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 相关文章推荐
当自定义数据属性为json格式字符串时jQuery的data api问题探讨
Feb 18 Javascript
Javascript selection的兼容性写法介绍
Dec 20 Javascript
jQuery中选择器小问题(新人难免遇到)
Mar 31 Javascript
对Js OOP编程 创建对象的一些全面理解
Jul 26 Javascript
微信小程序学习(4)-系统配置app.json详解
Jan 12 Javascript
基于vue组件实现猜数字游戏
May 28 Javascript
在vue里面设置全局变量或数据的方法
Mar 09 Javascript
详解vue-loader在项目中是如何配置的
Jun 04 Javascript
新手快速入门JavaScript装饰者模式与AOP
Jun 24 Javascript
js实现时间日期校验
May 26 Javascript
swiper4实现移动端导航栏tab滑动切换
Oct 16 Javascript
JavaScript事件概念详解(区分静态注册和动态注册)
Feb 05 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和Mysqlweb应用开发核心技术-第1部分 Php基础-2 php语言介绍
2011/07/03 PHP
php实现查询百度google收录情况(示例代码)
2013/08/02 PHP
TP5框架实现的数据库备份功能示例
2020/04/05 PHP
网站页面自动跳转实现方法PHP、JSP(上)
2010/08/01 Javascript
cookie.js 加载顺序问题怎么才有效
2013/07/31 Javascript
JavaScript的事件绑定(方便不支持js的时候)
2013/10/01 Javascript
浅谈bootstrap源码分析之scrollspy(滚动侦听)
2016/06/06 Javascript
JQuery Ajax 异步操作之动态添加节点功能
2017/05/24 jQuery
AngularJS使用ui-route实现多层嵌套路由的示例
2018/01/10 Javascript
vue-cli的工程模板与构建工具详解
2018/09/27 Javascript
如何优雅的在一台vps(云主机)上面部署vue+mongodb+express项目
2019/01/20 Javascript
js 获取扫码枪输入数据的方法
2020/06/10 Javascript
JavaScript实现点击出现子菜单效果
2021/02/08 Javascript
python实现登陆知乎获得个人收藏并保存为word文件
2015/03/16 Python
使用70行Python代码实现一个递归下降解析器的教程
2015/04/17 Python
简单说明Python中的装饰器的用法
2015/04/24 Python
在主机商的共享服务器上部署Django站点的方法
2015/07/22 Python
浅谈django中的认证与登录
2016/10/31 Python
python实现读取并显示图片的两种方法
2017/01/13 Python
python中urllib.unquote乱码的原因与解决方法
2017/04/24 Python
python实现定时提取实时日志程序
2018/06/22 Python
详解Python3的TFTP文件传输
2018/06/26 Python
python pptx复制指定页的ppt教程
2020/02/14 Python
python ffmpeg任意提取视频帧的方法
2020/02/21 Python
Python发送手机动态验证码代码实例
2020/02/28 Python
matplotlib 对坐标的控制,加图例注释的操作
2020/04/17 Python
python_matplotlib改变横坐标和纵坐标上的刻度(ticks)方式
2020/05/16 Python
PyChon中关于Jekins的详细安装(推荐)
2020/12/28 Python
CSS实现圆形放大镜狙击镜效果 只有圆圈里的放大
2012/12/10 HTML / CSS
2014年学习雷锋活动总结
2014/03/01 职场文书
党员自我对照检查材料
2014/08/19 职场文书
小学竞选班长演讲稿
2014/09/09 职场文书
警察群众路线整改措施
2014/09/26 职场文书
如何签定毕业生就业协议书
2014/09/28 职场文书
2015年百日安全活动总结
2015/03/26 职场文书
教师教育心得体会
2016/01/19 职场文书