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 相关文章推荐
一个很简单的办法实现TD的加亮效果.
Jun 29 Javascript
Javascript-Mozilla和IE中的一个函数直接量的问题
Jan 09 Javascript
js获得鼠标的坐标值的方法
Mar 13 Javascript
DOM基础教程之模型中的模型节点
Jan 19 Javascript
JS+CSS实现美化的下拉列表框效果
Aug 11 Javascript
JS实现弹性菜单效果代码
Sep 07 Javascript
JS实现点击登录弹出窗口同时背景色渐变动画效果
Mar 25 Javascript
逻辑表达式中与或非的用法详解
Jun 06 Javascript
使用BootStrap实现悬浮窗口的效果
Dec 13 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
Apr 02 Javascript
详解Element-UI中上传的文件前端处理
Aug 07 Javascript
js简单粗暴的发布订阅示例代码
Jan 23 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实现的连贯操作、链式操作实例
2014/07/08 PHP
PHP常用字符串操作函数实例总结(trim、nl2br、addcslashes、uudecode、md5等)
2016/01/09 PHP
php使用glob函数遍历文件和目录详解
2016/09/23 PHP
php如何实现不借助IDE快速定位行数或者方法定义的文件和位置
2017/01/17 PHP
用PHP去掉文件头的Unicode签名(BOM)方法
2017/06/22 PHP
一段效率很高的for循环语句使用方法
2007/08/13 Javascript
JavaScript中的数学运算介绍
2014/12/29 Javascript
浅析javascript中函数声明和函数表达式的区别
2015/02/15 Javascript
JS实现在页面随时自定义背景颜色的方法
2015/02/27 Javascript
vue.js绑定class和style样式(6)
2016/12/09 Javascript
基于Vue如何封装分页组件
2016/12/16 Javascript
jQuery向webApi提交post json数据
2017/01/16 Javascript
微信小程序上传图片功能(附后端代码)
2020/06/19 Javascript
Element UI 自定义正则表达式验证方法
2018/09/04 Javascript
Nodejs调用Dll模块的方法
2018/09/17 NodeJs
浅谈webpack 四个核心概念之Entry
2019/06/12 Javascript
webpack3.0升级4.0的方法步骤
2020/04/02 Javascript
[46:37]LGD vs TNC 2019国际邀请赛小组赛 BO2 第二场 8.15
2019/08/16 DOTA
Python构造函数及解构函数介绍
2015/02/26 Python
Python循环语句中else的用法总结
2016/09/11 Python
pytorch对可变长度序列的处理方法详解
2018/12/08 Python
详解Python requests 超时和重试的方法
2018/12/18 Python
Python集中化管理平台Ansible介绍与YAML简介
2019/06/12 Python
python多进程使用函数封装实例
2020/05/02 Python
Numpy中的数组搜索中np.where方法详细介绍
2021/01/08 Python
浅谈css3中的渐进增强和优雅降级
2017/12/01 HTML / CSS
Speedo速比涛中国官方网站:全球领先泳装运动品牌
2018/04/24 全球购物
美国医生配方营养补充剂供应商:Healthy Directions
2019/07/10 全球购物
中学生获奖感言
2014/02/04 职场文书
电子商务专业学生职业生涯规划
2014/03/07 职场文书
安全生产一岗双责责任书
2014/07/28 职场文书
我们的节日国庆活动方案
2014/08/19 职场文书
《狼牙山五壮士》教学反思
2016/02/17 职场文书
Java移除无效括号的方法实现
2021/08/07 Java/Android
MySQL库表太大怎么办? 数据库分库分表项目实践
2022/04/11 MySQL
MySQL实现用逗号进行拼接、以逗号进行分割
2022/12/24 MySQL