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 相关文章推荐
firefox下对ajax的onreadystatechange的支持情况分析
Dec 14 Javascript
第一个JavaScript入门基础 document.write输出
Feb 22 Javascript
JS Loading功能的简单实现
Nov 29 Javascript
借助javascript代码判断网页是静态还是伪静态
May 05 Javascript
JavaScript检测实例属性, 原型属性
Feb 04 Javascript
JavaScript父子窗体间的调用方法
Mar 31 Javascript
jQuery超精致图片轮播幻灯片特效代码分享
Sep 10 Javascript
javascript中call apply 与 bind方法详解
Mar 10 Javascript
xmlplus组件设计系列之选项卡(Tabbar)(5)
May 03 Javascript
ajax请求data遇到的问题分析
Jan 18 Javascript
使用Vue实现移动端左滑删除效果附源码
May 16 Javascript
Vue调用后端java接口的实例代码
Oct 28 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
预告映像公开!第1章续篇剧场版动画《Princess Principal Crown Handler》4月10日上映!
2020/03/06 日漫
B2K与车机的中波PK
2021/03/02 无线电
PHP弹出对话框技巧详细解读
2015/09/26 PHP
关于php unset对json_encode的影响详解
2018/11/14 PHP
js资料toString 方法
2007/03/13 Javascript
JQuery 动画卷页 返回顶部 动画特效(兼容Chrome)
2010/02/15 Javascript
jquery 无限级联菜单案例分享
2013/03/26 Javascript
jquery的flexigrid无法显示数据提示获取到数据
2013/07/19 Javascript
js鼠标及对象坐标控制属性详细解析
2013/12/14 Javascript
javascript使用闭包模拟对象的私有属性和方法
2016/10/05 Javascript
详解使用vue-router进行页面切换时滚动条位置与滚动监听事件
2017/03/08 Javascript
详解使用fetch发送post请求时的参数处理
2017/04/05 Javascript
详解JS数组Reduce()方法详解及高级技巧
2017/08/18 Javascript
详解使用Typescript开发node.js项目(简单的环境配置)
2017/10/09 Javascript
Vue Socket.io源码解读
2018/02/07 Javascript
vue监听键盘事件的快捷方法【推荐】
2018/07/11 Javascript
JavaScript实现正则去除a标签并保留内容的方法【测试可用】
2018/07/18 Javascript
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
vue实现前端分页完整代码
2020/06/17 Javascript
逐行分析鸿蒙系统的 JavaScript 框架(推荐)
2020/09/17 Javascript
[14:21]VICI vs EG (BO3)
2018/06/07 DOTA
python杀死一个线程的方法
2015/09/06 Python
python3 pandas 读取MySQL数据和插入的实例
2018/04/20 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
mvc框架打造笔记之wsgi协议的优缺点以及接口实现
2018/08/01 Python
Python自动化测试中yaml文件读取操作
2020/08/20 Python
俄罗斯在线水暖商店:Perfecto.ru
2019/10/25 全球购物
全神贯注教学反思
2014/02/03 职场文书
乌鸦喝水教学反思
2014/02/07 职场文书
学校节能减排倡议书
2014/05/16 职场文书
财政局党的群众路线教育实践活动整改方案
2014/09/21 职场文书
企业务虚会发言材料
2014/10/20 职场文书
荒岛余生观后感
2015/06/09 职场文书
回门宴新娘答谢词
2015/09/29 职场文书
严以用权专题学习研讨会发言材料
2015/11/09 职场文书
微信小程序结合ThinkPHP5授权登陆后获取手机号
2021/11/23 PHP