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 相关文章推荐
比较简单实用的使用正则三种版本的js去空格处理方法
Nov 18 Javascript
js时间日期和毫秒的相互转换
Feb 22 Javascript
js文件Cookie存取值示例代码
Feb 20 Javascript
在JavaScript中处理字符串之fontcolor()方法的使用
Jun 08 Javascript
javascript实现3D切换焦点图
Oct 16 Javascript
JavaScript如何调试有哪些建议和技巧附五款有用的调试工具
Oct 28 Javascript
浅析jquery与checkbox的checked属性的问题
Apr 27 Javascript
AngularJS 实现弹性盒子布局的方法
Aug 30 Javascript
JavaScript实现的选择排序算法实例分析
Apr 14 Javascript
使用ng-packagr打包Angular的方法示例
Sep 21 Javascript
深入解读VUE中的异步渲染的实现
Jun 19 Javascript
解决vue使用vant轮播组件swipe + flex时文字抖动问题
Jan 07 Vue.js
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中file_exists函数不支持中文名的解决方法
2014/07/26 PHP
浅析Yii2集成富文本编辑器redactor实例教程
2016/04/25 PHP
thinkphp3.x连接mysql数据库的方法(具体操作步骤)
2016/05/19 PHP
一个很简单的jquery+xml+ajax的无刷新树结构(无css,后台是c#)
2010/06/02 Javascript
textarea中的手动换行处理的jquery代码
2011/02/26 Javascript
关于火狐(firefox)及ie下event获取的两种方法
2012/12/27 Javascript
js触发select onchange事件的小技巧
2014/08/05 Javascript
对JavaScript的全文搜索实现相关度评分的功能的方法
2015/06/24 Javascript
jQuery插件pagewalkthrough实现引导页效果
2015/07/05 Javascript
BootStrap 下拉菜单点击之后不会出现下拉菜单(下拉菜单不弹出)的解决方案
2016/12/14 Javascript
JavaScript手风琴页面制作
2017/05/17 Javascript
简述jQuery Easyui一些用法
2017/08/01 jQuery
详解webpack3编译兼容IE8的正确姿势
2017/12/21 Javascript
Vue工程模板文件 webpack打包配置方法
2017/12/26 Javascript
微信小程序项目总结之点赞 删除列表 分享功能
2018/06/25 Javascript
npm scripts 使用指南详解
2018/10/08 Javascript
微信小程序使用wxParse解析html的方法示例
2019/01/17 Javascript
Vue 幸运大转盘实现思路详解
2019/05/06 Javascript
使用Easyui实现查询条件的后端传递并自动刷新表格的两种方法
2019/09/09 Javascript
[03:37]2016完美“圣”典 风云人物:Mikasa专访
2016/12/07 DOTA
[49:08]FNATIC vs Infamous 2019国际邀请赛小组赛 BO2 第二场 8.16
2019/08/18 DOTA
用python编写第一个IDA插件的实例
2018/05/29 Python
python实现决策树分类
2018/08/30 Python
深入浅析Python获取对象信息的函数type()、isinstance()、dir()
2018/09/17 Python
Python random模块制作简易的四位数验证码
2020/02/01 Python
Python3爬虫mitmproxy的安装步骤
2020/07/29 Python
使用HTML5 IndexDB存储图像和文件的示例
2018/11/05 HTML / CSS
潘多拉意大利官方网上商城:网上选购PANDORA珠宝
2018/10/07 全球购物
校园运动会广播稿
2014/10/06 职场文书
2014年质量工作总结
2014/11/22 职场文书
关于长城的导游词
2015/01/30 职场文书
幼儿园六一儿童节活动总结
2015/02/10 职场文书
趣味运动会加油词
2015/07/18 职场文书
煤矿安全生产管理协议书
2016/03/22 职场文书
oracle表分区的概念及操作
2021/04/24 Oracle
Python Django模型详解
2021/10/05 Python