《React-Native系列》40、刨根问底Picker组件
来源:互联网 发布:rbf神经网络 python 编辑:程序博客网 时间:2024/06/05 03:24
最近做一个需求,需求里需要实现一个类似Picker组件的效果,如下图所示,页面布局很简单,上面一个View 包含两个Text或者Touch*组件,下面放置一个Picker组件。
这个组件在app中已经存在,本来打算直接桥接native的,觉得这样基础的组件,还是使用RN的吧,这样就开始了我的Picker刨根之路。
布局代码如下:
- <Animated.View style={[styles.tip , {transform: [{
- translateY: this.state.offset.interpolate({
- inputRange: [0, 1],
- outputRange: [height, (height-aHeight)]
- }),
- }]
- }]}>
- <View style={styles.tipTitleView} >
- <Text style={styles.cancelText} onPress={this.cancel.bind(this)}>取消</Text>
- <Text style={styles.okText} onPress={this.ok.bind(this)} >确定</Text>
- </View>
- <Picker
- style={styles.picker}
- mode={Picker.MODE_DIALOG}
- itemStyle={styles.itempicker}
- selectedValue={this.state.choice}
- onValueChange={choice => this.setState({choice: choice})}>
- {this.options.map((aOption) => <Picker.Item color='#b5b9be' label={aOption} value={aOption} key={aOption} /> )}
- </Picker>
- </Animated.View>
那么问题来了,当我给Picker的style属性设置height为161的时候,发现Picker的高度确实是161,背景色为green,但是滚动轮的height确不是161,如下图所示:
在上面的一个View部分,还是可以点击Picker的item选项,当我点击取消和确定的时候,Picker.item还是可以点击,这是不是Picker的bug?
我是先在iOS上实现的,后来了解,Picker在原生iOS中height系统默认是216,好像还不能修改,what ?
难道又要和UI妥协,让修改下height。有点...
好吧,还是看下RN的源码看看是怎么回事!
搜索找到PickerIOS 这个类。有问题多看看源码,绝大多数问题都可以在源码中找到答案!
发现下面2段代码:
代码片段1:
代码片段2:
看到这儿,似乎找到了我想要的答案。
Picker有如下两个属性:
那么想要实现我们的效果,设置itemStyle的属性,覆盖默认的height不就可以了吗。
经过实现,确实解决了问题,这里也说明系统默认的Picker的216的高度也是可以修改的。
该组件实现功能
1、动画效果,点击时,组件从手机下面弹出,有遮罩层
2、布局效果见本文开始处
源码如下:
- 'use strict';
- import React, { Component } from 'react';
- import {
- StyleSheet,
- View,
- Image,
- Text,
- TouchableHighlight,
- Animated,
- Easing,
- Dimensions,
- Picker,
- TouchableOpacity,
- } from 'react-native';
-
- const {width, height} = Dimensions.get('window');
- const navigatorH = 64;
- const [aWidth, aHeight] = [width, 214];
- const [left, top] = [0, 0];
-
- const styles = StyleSheet.create({
- container: {
- position:"absolute",
- width:width,
- height:height,
- left:left,
- top:top,
- },
- mask: {
- justifyContent:"center",
- backgroundColor:"#383838",
- opacity:0.8,
- position:"absolute",
- width:width,
- height:height,
- left:left,
- top:top,
- },
- tip: {
- width:aWidth,
- height:aHeight,
-
- backgroundColor:"#fff",
- alignItems:"center",
- justifyContent:"space-between",
- },
- tipTitleView: {
- height:53,
- width:aWidth,
- flexDirection:'row',
- alignItems:'center',
- justifyContent:'space-between',
- borderBottomWidth:0.5,
- borderColor:"#f0f0f0",
-
- },
- cancelText:{
- color:"#e6454a",
- fontSize:16,
- paddingLeft:30,
- },
- okText:{
- color:"#e6454a",
- fontSize:16,
- paddingRight:27,
- fontWeight:'bold',
- },
- picker:{
- justifyContent:'center',
-
- width:aWidth,
- },
- itempicker:{
- color:'#e6454a',
- fontSize:19,
- height:161
- }
- });
-
- export default class PickerWidget extends Component {
-
- constructor(props) {
- super(props);
- this.state = {
- offset: new Animated.Value(0),
- opacity: new Animated.Value(0),
- choice:this.props.defaultVal,
- hide: true,
- };
- this.options = this.props.options;
- this.callback = function () {};
- this.parent ={};
- }
-
- componentWillUnMount(){
- this.timer && clearTimeout(this.timer);
- }
-
- render() {
- if(this.state.hide){
- return (<View />)
- } else {
- return (
- <View style={styles.container} >
- <Animated.View style={ styles.mask } >
- </Animated.View>
-
- <Animated.View style={[styles.tip , {transform: [{
- translateY: this.state.offset.interpolate({
- inputRange: [0, 1],
- outputRange: [height, (height-aHeight)]
- }),
- }]
- }]}>
- <View style={styles.tipTitleView} >
- <Text style={styles.cancelText} onPress={this.cancel.bind(this)}>取消</Text>
- <Text style={styles.okText} onPress={this.ok.bind(this)} >确定</Text>
- </View>
- <Picker
- style={styles.picker}
- mode={Picker.MODE_DIALOG}
- itemStyle={styles.itempicker}
- selectedValue={this.state.choice}
- onValueChange={choice => this.setState({choice: choice})}>
- {this.options.map((aOption) => <Picker.Item color='#b5b9be' label={aOption} value={aOption} key={aOption} /> )}
- </Picker>
- </Animated.View>
- </View>
- );
- }
- }
-
- componentDidMount() {
- }
-
-
- in() {
- Animated.parallel([
- Animated.timing(
- this.state.opacity,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0.8,
- }
- ),
- Animated.timing(
- this.state.offset,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 1,
- }
- )
- ]).start();
- }
-
-
- out(){
- Animated.parallel([
- Animated.timing(
- this.state.opacity,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0,
- }
- ),
- Animated.timing(
- this.state.offset,
- {
- easing: Easing.linear,
- duration: 500,
- toValue: 0,
- }
- )
- ]).start();
-
- this.timer = setTimeout(
- () => this.setState({hide: true}),
- 500
- );
- }
-
-
- cancel(event) {
- if(!this.state.hide){
- this.out();
- }
- }
-
-
- ok() {
- if(!this.state.hide){
- this.out();
- this.callback.apply(this.parent,[this.state.choice]);
- }
- }
-
- show(obj:Object,callback:Object) {
- this.parent = obj;
- this.callback = callback;
- if(this.state.hide){
- this.setState({ hide: false}, this.in);
- }
- }
- }
0 0