React Native实现地址挑选器功能


Posted in Javascript onOctober 24, 2017

本文实例为大家分享了React Native地址挑选器的实现代码,供大家参考,具体内容如下

产品经理:“你明白吧,这里向右划可以出菜单,然后需要一个闪烁的动画,还有,我想这个tab可以拉下来,你懂吧?

设计师:“别废话,把你要抄的产品给我看下。”


接下来,我们仿一下别人家的地址挑选器

React Native实现地址挑选器功能

import React, { Component, PropTypes } from 'react';
import {
 ViewPropTypes,
 StyleSheet,
 View,
 TouchableOpacity,
 TouchableNativeFeedback,
 Platform,
 Animated,
 Text
} from 'react-native';

export default class SelectCityTabBar extends Component {
 //属性声名
 static propTypes = {
  goToPage: PropTypes.func,
  activeTab: PropTypes.number,
  tabs: PropTypes.array,
  backgroundColor: PropTypes.string,
  activeTextColor: PropTypes.string,
  inactiveTextColor: PropTypes.string,
  textStyle: Text.propTypes.style,
  tabStyle: ViewPropTypes.style,
  renderTab: PropTypes.func,
  underlineStyle: ViewPropTypes.style,
 };
 //默认属性
 static defaultProps = {
  activeTextColor: '#FA3D4F',
  inactiveTextColor: 'black',
  backgroundColor: null,
 }

 renderTab(name, page, isTabActive, onPressHandler) {
  const { activeTextColor, inactiveTextColor, textStyle, } = this.props;
  const textColor = isTabActive ? activeTextColor : inactiveTextColor;
  const fontWeight = isTabActive ? 'bold' : 'normal';
  const viewStyle = isTabActive ? [styles.tab, { borderBottomWidth: Constant.sizeDividerLarge, borderColor: Constant.colorPrimary }] : styles.tab;

  if (Platform.OS !== 'ios') {
   return <TouchableNativeFeedback
    delayPressIn={0}
    background={TouchableNativeFeedback.SelectableBackground()}
    key={name + page}
    accessible={true}
    accessibilityLabel={name}
    accessibilityTraits='button'
    onPress={() => onPressHandler(page)}
   >
    <View style={viewStyle}>
     <Text style={[{ color: textColor, fontWeight, }, textStyle,]}>
      {name}
     </Text>
    </View>
   </TouchableNativeFeedback>
  }

  return <TouchableOpacity
   key={name + page}
   accessible={true}
   accessibilityLabel={name}
   accessibilityTraits='button'
   onPress={() => onPressHandler(page)}
  >
   <View style={viewStyle}>
    <Text style={[{ color: textColor, fontWeight, }, textStyle,]}>
     {name}
    </Text>
   </View>
  </TouchableOpacity>;
 }

 render() {
  return (
   <View style={{ flexDirection: 'row', borderBottomWidth: Constant.sizeDividerNormal, borderColor: Constant.colorDivider }}>
    {this.props.tabs.map((name, page) => {
     const isTabActive = this.props.activeTab === page;
     const renderTab = this.props.renderTab || this.renderTab;
     return this.renderTab(name, page, isTabActive, this.props.goToPage);
    })}
   </View>
  );
 }
}



const styles = StyleSheet.create({
 tab: {
  alignItems: 'center',
  justifyContent: 'center',
  paddingBottom: 10,
  marginLeft: 10,
 },
 tabs: {
  height: 50,
  flexDirection: 'row',
  justifyContent: 'space-around',
  borderWidth: 1,
  borderTopWidth: 0,
  borderLeftWidth: 0,
  borderRightWidth: 0,
  borderColor: '#ccc',
 },
});

npm react-native-scrollable-tab-view 组件

import React, { Component } from 'react';
import {
 StyleSheet,
 View,
 ScrollView,
 Dimensions,
 TouchableOpacity,
 InteractionManager,
 Platform,
 UIManager,
 Text
} from 'react-native';
import ScrollableTabView from 'react-native-scrollable-tab-view';
import SelectCityTabBar from './SelectCityTabBar'
import AREA_JSON from '../../util/area.json';
const { height, width } = Dimensions.get('window');

export default class AddressSelect extends Component {

 static defaultProps = {
  commitFun: function (value) {
   console.log(value);
  },
  dissmissFun: function () {

  },
  lastAddress: null,
 };

 constructor(props) {
  super(props);
  if (Platform.OS === 'android') {
   UIManager.setLayoutAnimationEnabledExperimental(true)
  }
  const { lastAddress } = props;
  let selectAddress = this.initAddress(lastAddress);
  this.state = {
   selectAddress
  }
 }

 initAddress(lastAddress) {
  let selectAddress = [
   {
    value: null,
    label: null,
    children: AREA_JSON,
   }, {
    value: null,
    label: null,
    children: null,
   }, {
    value: null,
    label: null,
    children: null,
   }];
  let array = null;

  function fun(array, value) {
   for (let item of array) {
    if (item.value + '' === value + '') {
     return item;
    }
   }
  }
  try {
   selectAddress = selectAddress.map((item, index) => {
    let result = fun(array ? array : AREA_JSON, lastAddress[index].value);
    if (result.children) {
     array = result.children;
    }
    return result;
   });
  } catch (e) {
   console.log('-----e-', e);
  }
  return selectAddress
 }


 /**
  * 列表行
  * @param item
  * @param i
  * @returns {XML}
  */
 renderListItem(item, i) {
  let itemStyle = styles.itemStyle;
  let textStyle = styles.itemText;
  let { selectAddress } = this.state;
  if (item.label === selectAddress[i].label) {
   itemStyle = [itemStyle];
   textStyle = [textStyle, { color: 'red' }]
  }
  return (
   <TouchableOpacity
    style={itemStyle}
    key={i + item.label}
    onPress={() => {
     this.pressItem(item, i)
    }}
   >
    <Text style={textStyle}>{item.label}</Text>
   </TouchableOpacity>
  )
 }

 /**
  * 点击列表事件
  * @param item 选中数据
  * @param i 选中行数
  */
 pressItem(item, i) {
  let { selectAddress } = this.state;
  const initObj = {
   value: null,
   label: null,
   children: null,
  }
  let tempIndex = 0;
  if (i === 0) {
   selectAddress[0] = item;
   selectAddress[1] = initObj;
   selectAddress[2] = initObj;
   tempIndex = 1
  } else if (i === 1) {
   selectAddress[1] = item;
   selectAddress[2] = initObj;
   tempIndex = 2
  } else {
   selectAddress[2].value = item.value;
   selectAddress[2].label = item.label;
   tempIndex = 2
   let address = [
    {
     label: selectAddress[0].label,
     value: selectAddress[0].value
    },
    {
     label: selectAddress[1].label,
     value: selectAddress[1].value
    },
    {
     label: selectAddress[2].label,
     value: selectAddress[2].value
    }
   ]
   this.props.commitFun && this.props.commitFun(address);
   this.props.dissmissFun && this.props.dissmissFun();
   return null;

  }
  this.setState({ selectAddress });
  InteractionManager.runAfterInteractions(() => {
   this.tabView.goToPage(tempIndex)
  })

 }

 render() {
  const { selectAddress } = this.state;
  return (
   <View style={styles.container}>
    <View style={{ width: width, height: 40, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', }}>
     <Text>所在地区</Text>
    </View>
    <ScrollableTabView
     ref={(tabView) => {
      this.tabView = tabView;
     }}
     renderTabBar={() => <SelectCityTabBar />}
    >
     {selectAddress.map((obj, i) => {
      let array = (i === 0) ? AREA_JSON : selectAddress[i - 1].children;
      if (array) {
       return (
        <ScrollView
         key={i}
         tabLabel={obj.label || '请选择'}
         style={styles.scrollStyleList}
        >
         {array && array.map((obj2, j) => {
          return this.renderListItem(obj2, i)
         })}
        </ScrollView>
       )
      }
     })}
    </ScrollableTabView>
   </View>
  );
 }
}

const styles = StyleSheet.create({
 container: {
  height: height * 0.6,
  backgroundColor: '#F5FCFF',
 },
 scrollStyleList: {
  width: width,
  marginBottom: Constant.sizeMarginDefault,
  marginTop: Constant.sizeMarginDefault,
 },
 itemStyle: {
  marginTop: 5,
  width: width,
  height: 35,
  marginLeft: Constant.sizeMarginDefault,
  justifyContent: 'center'
 },
 itemText: {
  fontSize: 15,
  color: '#333333'
 },

使用方法:

import React, {Component} from 'react';
import {
 StyleSheet,
 View,
 TouchableOpacity,
 Alert,
 ScrollView,
 ART,
 TouchableHighlight,
 ListView,
 Dimensions,
 Text
} from 'react-native';

import {ReactNavComponent, Widget} from 'rn-yunxi';
import AddressSelect from '../../app-widget/address-select/index'

export default class extends React.Component {

 render() {
  return (
   <TouchableOpacity style={{flex:1, justifyContent:'center', alignItems:'center'}} onPress={() => this.openAddressSelect()}>
    <Text >地址选择</Text>
   </TouchableOpacity>
  );

 }

 openAddressSelect() {

  Widget.Popup.show( // 这边使用自己封装的modal嵌套地址选择器
   <AddressSelect
    commitFun={(area) => this.onSelectArea(area)}
    dissmissFun={() => Widget.Popup.hide()}
   />,
   {
    animationType: 'slide-up', backgroundColor: '#00000000', onMaskClose: () => {
    Widget.Popup.hide()
   }
   })
 }

 onSelectArea = (area) => {
  Log(area)
 }
};

数据类型格式

[
 {
  "value": "110000000000",
  "children": [
   {
    "value": "110100000000",
    "children": [
     {
      "value": "110101000000",
      "label": "东城区"
     },
     {
      "value": "110102000000",
      "label": "西城区"
     },
     {
      "value": "110105000000",
      "label": "朝阳区"
     },
     {
      "value": "110106000000",
      "label": "丰台区"
     },
     {
      "value": "110107000000",
      "label": "石景山区"
     },
     {
      "value": "110108000000",
      "label": "海淀区"
     },
     {
      "value": "110109000000",
      "label": "门头沟区"
     },
     {
      "value": "110111000000",
      "label": "房山区"
     },
     {
      "value": "110112000000",
      "label": "通州区"
     },
     {
      "value": "110113000000",
      "label": "顺义区"
     },
     {
      "value": "110114000000",
      "label": "昌平区"
     },
     {
      "value": "110115000000",
      "label": "大兴区"
     },
     {
      "value": "110116000000",
      "label": "怀柔区"
     },
     {
      "value": "110117000000",
      "label": "平谷区"
     },
     {
      "value": "110118000000",
      "label": "密云区"
     },
     {
      "value": "110119000000",
      "label": "延庆区"
     }
    ],
    "label": "北京市"
   }
  ],
  "label": "北京市"
 }
]

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
完美解决js传递参数中加号和&amp;号自动改变的方法
Oct 11 Javascript
Bootstrap下拉菜单样式
Feb 07 Javascript
AngularJS Toaster使用详解
Feb 24 Javascript
canvas仿iwatch时钟效果
Mar 06 Javascript
Vue computed计算属性的使用方法
Jul 14 Javascript
基于原生js运动方式关键点的总结(推荐)
Oct 01 Javascript
使用Vue-Router 2实现路由功能实例详解
Nov 14 Javascript
使用Vue动态生成form表单的实例代码
Apr 26 Javascript
vue.js引入外部CSS样式和外部JS文件的方法
Jan 06 Javascript
详解Jest结合Vue-test-utils使用的初步实践
Jun 27 Javascript
JS Thunk 函数的含义和用法实例总结
Apr 08 Javascript
JavaScript, select标签元素左右移动功能实现
May 14 Javascript
Angular js 实现添加用户、修改密码、敏感字、下拉菜单的综合操作方法
Oct 24 #Javascript
React Native 通告消息竖向轮播组件的封装
Aug 25 #Javascript
Vue v2.5 调整和更新不完全问题
Oct 24 #Javascript
Vue.js 2.5新特性介绍(推荐)
Oct 24 #Javascript
Vue 2.5 Level E 发布了: 新功能特性一览
Oct 24 #Javascript
浅谈在vue项目中如何定义全局变量和全局函数
Oct 24 #Javascript
Angularjs添加排序查询功能的实例代码
Oct 24 #Javascript
You might like
PHP通过header实现文本文件下载的代码
2010/08/08 PHP
php判断linux下程序问题实例
2015/07/09 PHP
PHP的邮件群发系统phplist配置方法详细总结
2016/03/30 PHP
yii2.0实现创建简单widgets示例
2016/07/18 PHP
php+js实现裁剪任意形状图片
2018/10/31 PHP
Javascript new关键字的玄机 以及其它
2010/08/25 Javascript
JQuery实现鼠标移动到图片上显示边框效果
2014/01/09 Javascript
详解js闭包
2014/09/02 Javascript
jquery+html5制作超酷的圆盘时钟表
2015/04/14 Javascript
json格式数据的添加,删除及排序方法
2016/01/21 Javascript
JavaScript每天必学之事件
2016/09/18 Javascript
深入理解JavaScript中的for循环
2017/02/07 Javascript
js实现音频控制进度条功能
2017/04/01 Javascript
bootstrap suggest下拉框使用详解
2017/04/10 Javascript
jQuery开源组件BootstrapValidator使用详解
2017/06/29 jQuery
js排序与重组的实例讲解
2017/08/28 Javascript
Vue2.0权限树组件实现代码
2017/08/29 Javascript
vue项目总结之文件夹结构配置详解
2017/12/13 Javascript
js 计算图片内点个数的示例代码
2019/04/04 Javascript
详解Vue中CSS样式穿透问题
2019/09/12 Javascript
Python的爬虫程序编写框架Scrapy入门学习教程
2016/07/02 Python
用Python进行简单图像识别(验证码)
2018/01/19 Python
使用pandas对矢量化数据进行替换处理的方法
2018/04/11 Python
PyTorch搭建多项式回归模型(三)
2019/05/22 Python
python学生信息管理系统实现代码
2019/12/17 Python
Python3.9又更新了:dict内置新功能
2020/02/28 Python
pyCharm 设置调试输出窗口中文显示方式(字符码转换)
2020/06/09 Python
将HTML5 Canvas的内容保存为图片借助toDataURL实现
2013/05/20 HTML / CSS
个人自我鉴定总结
2014/03/25 职场文书
协议书与合同的区别
2014/04/18 职场文书
法制宣传月活动方案
2014/05/11 职场文书
助理政工师申报材料
2014/06/03 职场文书
购房委托书范本
2014/09/18 职场文书
办公室行政主管岗位职责
2015/04/09 职场文书
MySQL中utf8mb4排序规则示例
2021/08/02 MySQL
Spring中bean集合注入的方法详解
2022/07/07 Java/Android