React Native自定义控件底部抽屉菜单的示例


Posted in Javascript onFebruary 08, 2018

一、需求分析

原生开发中,自定义View可谓是屡见不鲜的事情,往往系统的控件总不能满足现实的需求。五花八门的产品设计需要我们做出不同的View。关于自定义View的内容网上已经有很多的博文,本篇博客要和大家分享如何在React Native中自定义组件实现抽屉菜单控件效果。分享功能在App中的重要性想必是不言而喻的,那么RN中如何实现这种效果呢?

React Native 系统库中只提供了IOS的实现,即ActionSheetIOS.该控件的显示方式有两种实现:

(1)showActionSheetWithOptions

(2)showShareActionSheetWithOptions

第一种是在iOS设备上显示一个ActionSheet弹出框。第二种实现是在iOS设备上显示一个分享弹出框。借用官方的图片说明如下:

React Native自定义控件底部抽屉菜单的示例  React Native自定义控件底部抽屉菜单的示例

IOS设备上的实现系统已经提供了,接下来我们就需要如何适配Android。在原生开发中,自定义View也是有基本的流程:

(1)自定义控件类,继承View或系统控件。

(2)自定义属性

(3)获取自定义属性,并初始化一系列工具类

(4)重写onMeasure方法,对控件进行测量

(5)如果是自定义布局,还需要重写onLayout进行布局

在React Native中自定义组件的思路基本和原生自定义相似。所以按照这个流程,我们一步步实现即可。

二、功能实现

1、自定义组件,实现Component

export default class AndroidActionSheet extends Component

2、自定义属性

// 1.声明所需要的属性 
static propTypes= { 
  title: React.PropTypes.string, // 标题 
  content: React.PropTypes.object, // 内容 
  show: React.PropTypes.func, // 显示 
  hide: React.PropTypes.func, // 隐藏 
}
constructor(props) { 
  super(props); 
  this.translateY = 150; 
  this.state = { 
    visible: false, 
    sheetAnim: new Animated.Value(this.translateY) 
  } 
  this.cancel = this.cancel.bind(this); 
}

3、实现基本布局

/** 
* Modal为最外层,ScrollView为内容层 
*/ 
render() { 
    const { visible, sheetAnim } = this.state; 
    return( 
      <Modal 
      visible={ visible } 
      transparent={ true } 
      animationType="none" 
      onRequestClose={ this.cancel } 
      > 
      <View style={ styles.wrapper }> 
              <TouchableOpacity style={styles.overlay} onPress={this.cancel}></TouchableOpacity> 
          <Animated.View 
            style={[styles.bd, {height: this.translateY, transform: [{translateY: sheetAnim}]}]}> 
            { this._renderTitle() } 
            <ScrollView 
                      horizontal={ true } 
                      showsHorizontalScrollIndicator={ false }> 
              {this._renderContainer()} 
            </ScrollView> 
          </Animated.View> 
        </View> 
      </Modal> 
    ) 
}

可以看到上面我们定义了基本的布局,布局中使用_renderTitle()方法来渲染标题部分,内容区域为ScrollView,并且为横向滚动,即当菜单项超过屏幕宽度时,可以横向滑动选择。在内部调用了renderContainer方法来渲染菜单:

/** 
* 标题 
*/ 
_renderTitle() { 
  const { title,titleStyle } = this.props; 
  if (!title) { 
    return null 
  } 
    // 确定传入的是不是一个React Element,防止渲染的时候出错 
  if (React.isValidElement(title)) { 
    return ( 
      <View style={styles.title}>{title}</View> 
    ) 
  } 
  return ( 
    <Text style={[styles.titleText,titleStyle]}>{title}</Text> 
  ) 
} 
 
/** 
* 内容布局 
*/ 
_renderContainer() { 
    const { content } = this.props; 
    return ( 
      <View style={styles.container}> 
        { content } 
      </View> 
    ) 
  }

当我们需要点击Modal,进行关闭时,还需要处理关闭操作,Modal并没有为我们提供外部关闭处理,所以需要我们单独实现,从布局代码中我们看到TouchableOpacity作为遮罩层,并添加了单机事件,调用cancel来处理:

/** 
 * 控制Modal点击关闭,Android返回键关闭 
 */ 
 cancel() { 
  this.hide(); 
}

4、自定义方法,对外调用

在外部我们需要控制控件的显示和隐藏,所以需要对外公开显示、关闭的方法:

/** 
 * 显示 
 */ 
show() { 
  this.setState({visible: true}) 
  Animated.timing(this.state.sheetAnim, { 
    toValue: 0, 
    duration: 250 
  }).start(); 
}
/** 
 * 隐藏 
 */ 
hide() { 
   this.setState({ visible: false }) 
   Animated.timing(this.state.sheetAnim, { 
    toValue: this.translateY, 
    duration: 150 
   }).start(); 
}

5、使用

<ActionSheet 
 ref='sheet' 
 title='分享' 
 content={this._renderContent()} 
/>

至此,我们自定义组件就完成了。整体来看,基本的原理还是很简单的,主要利用了自定义属性,传参,动画,就可以轻松的实现了。本篇博客重点不是为了让大家知道怎么去写出这个效果,而是让大家明白,当我们遇到一个需要自定义的实现时,该如何去一步步实现。

三、效果图

React Native自定义控件底部抽屉菜单的示例

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
网页中实现浏览器的最大,最小化和关闭按钮
Mar 12 Javascript
常用简易JavaScript函数
Apr 09 Javascript
jquery的ajax从纯真网(cz88.net)获取IP地址对应地区名
Dec 02 Javascript
Ext.MessageBox工具类简介
Dec 10 Javascript
js ondocumentready onmouseover onclick onmouseout 样式
Jul 22 Javascript
浅谈js构造函数的方法与原型prototype
Jul 04 Javascript
JavaScript之map reduce_动力节点Java学院整理
Jun 29 Javascript
详解vue中点击空白处隐藏div的实现(用指令实现)
Apr 19 Javascript
JavaScript设计模式之构造函数模式实例教程
Jul 02 Javascript
4 种滚动吸顶实现方式的比较
Apr 09 Javascript
基于原生js实现九宫格算法代码实例
Jul 03 Javascript
Vue 实现创建全局组件,并且使用Vue.use() 载入方式
Aug 11 Javascript
vue 使用ref 让父组件调用子组件的方法
Feb 08 #Javascript
Vuejs 2.0 子组件访问/调用父组件的方法(示例代码)
Feb 08 #Javascript
web前端页面生成exe可执行文件的方法
Feb 08 #Javascript
ajax前台后台跨域请求处理方式
Feb 08 #Javascript
详解自定义ajax支持跨域组件封装
Feb 08 #Javascript
微信小程序实现验证码获取倒计时效果
Feb 08 #Javascript
ES6 迭代器(Iterator)和 for.of循环使用方法学习(总结)
Feb 08 #Javascript
You might like
php+mysql事务rollback&amp;commit示例
2010/02/08 PHP
跟我学Laravel之请求(Request)的生命周期
2014/10/15 PHP
3种php生成唯一id的方法
2015/11/23 PHP
PHP中字符串长度的截取用法示例
2017/01/12 PHP
详解PHP字符串替换str_replace()函数四种用法
2017/10/13 PHP
判断iframe是否加载完成的完美方法
2010/01/07 Javascript
JavaScript NaN和Infinity特殊值 [译]
2012/09/20 Javascript
Javascript排序算法之合并排序(归并排序)的2个例子
2014/04/04 Javascript
实例详解jQuery Mockjax 插件模拟 Ajax 请求
2016/01/12 Javascript
如何使用AngularJs打造权限管理系统【简易型】
2016/05/09 Javascript
javaScript封装的各种写法
2017/08/14 Javascript
微信小程序picker组件下拉框选择input输入框的实例
2017/09/20 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
基于D3.js实现时钟效果
2018/07/17 Javascript
如何通过setTimeout理解JS运行机制详解
2019/03/23 Javascript
.netcore+vue 实现压缩文件下载功能
2020/09/24 Javascript
python文件操作整理汇总
2014/10/21 Python
整理Python中的赋值运算符
2015/05/13 Python
Python装饰器基础详解
2016/03/09 Python
Python微信企业号开发之回调模式接收微信端客户端发送消息及被动返回消息示例
2017/08/21 Python
python中requests库session对象的妙用详解
2017/10/30 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
python list转矩阵的实例讲解
2018/08/04 Python
Python 运行.py文件和交互式运行代码的区别详解
2019/07/02 Python
python将邻接矩阵输出成图的实现
2019/11/21 Python
django 读取图片到页面实例
2020/03/27 Python
python开发入门——set的使用
2020/09/03 Python
python urllib和urllib3知识点总结
2021/02/08 Python
经济系大学生求职信
2013/10/01 职场文书
新法人代表任命书
2014/06/06 职场文书
我的梦想演讲稿1000字
2014/08/21 职场文书
团拜会主持词
2015/07/04 职场文书
趣味运动会加油词
2015/07/18 职场文书
运动会通讯稿100字
2015/07/20 职场文书
退休欢送会致辞
2015/07/31 职场文书
redis通过6379端口无法连接服务器(redis-server.exe闪退)
2021/05/08 Redis