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 相关文章推荐
jquery DOM操作 基于命令改变页面
May 06 Javascript
Javascript基础教程之函数对象和属性
Jan 18 Javascript
JavaScript获得页面base标签中url的方法
Apr 03 Javascript
JavaScript使用Replace进行字符串替换的方法
Apr 14 Javascript
高性能JavaScript DOM编程(1)
Aug 11 Javascript
React.js入门学习第一篇
Mar 30 Javascript
实例解析jQuery中proxy()函数的用法
May 24 Javascript
jquery uploadify如何取消已上传成功文件
Feb 08 Javascript
jquery submit()不能提交表单的解决方法
Apr 24 jQuery
基于Vue的SPA动态修改页面title的方法(推荐)
Jan 02 Javascript
安装vue-cli的简易过程
May 22 Javascript
vue实现pdf导出解决生成canvas模糊等问题(推荐)
Oct 18 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
一个odbc连mssql分页的类
2006/10/09 PHP
PHP自带方法验证邮箱、URL、IP是否合法的函数
2016/12/08 PHP
Laravel程序架构设计思路之使用动作类
2018/06/07 PHP
实例介绍PHP删除数组中的重复元素
2019/03/03 PHP
Json对象与Json字符串互转(4种转换方式)
2013/03/27 Javascript
Jquery实现由下向上展开效果的例子
2014/12/08 Javascript
jQuery中add()方法用法实例
2015/01/08 Javascript
Javascript中的方法链(Method Chaining)介绍
2015/03/15 Javascript
使用AngularJS实现可伸缩的页面切换的方法
2015/06/19 Javascript
Jquery基础之事件操作详解
2016/06/14 Javascript
js实现九宫格拼图小游戏
2017/02/13 Javascript
vue+vuex+axios实现登录、注册页权限拦截
2018/03/09 Javascript
vue2.0学习之axios的封装与vuex介绍
2018/05/28 Javascript
angular6 利用 ngContentOutlet 实现组件位置交换(重排)
2018/11/02 Javascript
layui-table获得当前行的上/下一行数据的例子
2019/09/24 Javascript
vue element自定义表单验证请求后端接口验证
2019/12/11 Javascript
node.js使用stream模块实现自定义流示例
2020/02/13 Javascript
微信小程序自定义tabBar的踩坑实践记录
2020/11/06 Javascript
python通过floor函数舍弃小数位的方法
2015/03/17 Python
浅谈Python处理PDF的方法
2017/11/10 Python
Python输出各行命令详解
2018/02/01 Python
使用Python 自动生成 Word 文档的教程
2020/02/13 Python
Python中qutip用法示例详解
2020/10/02 Python
Python页面加载的等待方式总结
2021/02/28 Python
中级会计职业生涯规划书
2014/03/01 职场文书
党员承诺书内容
2014/03/26 职场文书
库房保管员岗位职责
2014/04/07 职场文书
师范生免费教育协议书范本
2014/10/09 职场文书
民事赔偿协议书
2014/11/02 职场文书
2014年英语教学工作总结
2014/12/17 职场文书
2015年公务员试用期工作总结
2015/05/28 职场文书
初中英语教学随笔
2015/08/15 职场文书
Redis高并发防止秒杀超卖实战源码解决方案
2021/11/01 Redis
VUE之图片Base64编码使用ElementUI组件上传
2022/04/09 Vue.js
python中的random模块和相关函数详解
2022/04/22 Python
使用Cargo工具高效创建Rust项目
2022/08/14 Javascript