React Native开发React Native开发经验集React Native实践

ReactNative手势上滑隐藏下滑显示

2019-04-03  本文已影响16人  Huangrong_000

一、实现效果

demo.gif

二、实现方式

1 使用RN的panResponder组件来实现手势滑动###

2 在constructor中初始可变组件的属性值和stytle###

constructor(props) {
    super(props);
    this.thresholdMin = 5;
    this.thresholdMax = 20;
    this.sapceInitHeight = 330;
    this.spaceHeight = 330;
    this.imageInitHeight =180;
    this.imageHeight = 180;
    this.imageInitOpacity = 1;
    this.imageOpacity = 1;
    this._spaceStyles = {};
    this.space = (null: ?{ setNativeProps(props: Object): void });
    this._imageStyles = {};
    this.image = (null: ?{ setNativeProps(props: Object): void });
    this.show = true;
}

3 在render中绑定this._panResponder手势处理handler,并通过ref关联组件对应的stytle###

render() {
    return (
        <View style={styles.container} {...this._panResponder.panHandlers}>
            <View style={styles.space}
                  ref={(space) => {
                      this.space = space;
                  }}
            >
                <Image style={styles.image}
                       ref={(image) => {
                           this.image = image;
                       }}
                       source={require('../../../res/img/home/space_img.png')}/>
            </View>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        backgroundColor: color.transparent,
    },
    space: {
        height: 330,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: color.transparent,
    },
    image: {
        opacity:1,
        width: 238,
        height: 180,
        marginBottom: 35,
        resizeMode: 'contain'
    }
});

4 在componentWillMount实现手势响应的一系列函数,并给stytle属性重新赋值###

componentWillMount() {
    this._panResponder = PanResponder.create({
        // 要求成为响应者:
        //this.refs[RefsConstant.HOME_DEV_LIST].setRefreshFunc(false);
        onStartShouldSetPanResponder: (evt, gestureState) => false,
        onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
        onMoveShouldSetPanResponder: (evt, gestureState) => false,
        onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
            if (Math.abs(gestureState.dx) < this.thresholdMin && Math.abs(gestureState.dy) < this.thresholdMin) {
                return false;
            } else {
                if ((this.show && gestureState.dy < 0) || (!this.show && gestureState.dy > 0)) {
                    return true;
                } else {
                    return false;
                }
            }
        },

        onPanResponderGrant: (evt, gestureState) => {
            // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
            console.log('onPanResponderGrant');
            // gestureState.{x,y} 现在会被设置为0
        },
        onPanResponderMove: (evt, gestureState) => {
            // 最近一次的移动距离为gestureState.move{X,Y}
            console.log('onPanResponderMove');
            console.log('滑动参数:dx='+gestureState.dx +',dy='+gestureState.dy + '可见吗='+this.show);
            // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
            if ((this.show && gestureState.dy < 0) || (!this.show && gestureState.dy > 0)) {
                this._spaceStyles.style.height = this.sapceInitHeight + gestureState.dy;
                this._imageStyles.style.height = this._spaceStyles.style.height * this.imageHeight / this.spaceHeight;
                this._imageStyles.style.opacity = this._spaceStyles.style.height / this.spaceHeight;
                if (this._spaceStyles.style.height >= 0 && this._spaceStyles.style.height <= this.spaceHeight) {
                    this._updateNativeStyles();
                }
            }
        },
        //是否可以释放响应者角色让给其他组件
        onPanResponderTerminationRequest: (evt, gestureState) => true,
        onPanResponderRelease: (evt, gestureState) => {
            // 用户放开了所有的触摸点,且此时视图已经成为了响应者。
            console.log('onPanResponderRelease');
            // 一般来说这意味着一个手势操作已经成功完成。
            if (gestureState.dy <= -1 * this.thresholdMax && this.show) {
                this._spaceStyles.style.height = 0;
                this._imageStyles.style.height = 0;
                this._imageStyles.style.opacity = 0;
                this.show = false;
                console.log('隐藏');
                this._updateNativeStyles();
            } else if (gestureState.dy >= this.thresholdMax && !this.show) {
                this._spaceStyles.style.height = this.spaceHeight;
                this._imageStyles.style.height = this.imageHeight;
                this._imageStyles.style.opacity = this.imageOpacity;
                this.show = true;
                console.log('显示');
                this._updateNativeStyles();
            } else {
                this._spaceStyles.style.height = this.show ? this.spaceHeight : 0;
                this._imageStyles.style.height = this.show ? this.imageHeight : 0;
                this._imageStyles.style.opacity = this.show ? this.imageOpacity : 0;
                console.log('不变');
                this._updateNativeStyles();
            }
            this.sapceInitHeight = this._spaceStyles.style.height;
            this.imageInitHeight = this._imageStyles.style.height;
            this.imageInitOpacity = this._imageStyles.style.opacity;
        },
        onPanResponderTerminate: (evt, gestureState) => {
            // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
            console.log('onPanResponderTerminate');
        },
        onShouldBlockNativeResponder: (evt, gestureState) => {
            // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
            // 默认返回true。目前暂时只支持android。
            return true;
        },
    });

    this._spaceStyles = {
        style: {
            height: this.sapceInitHeight,
        }
    };
    this._imageStyles = {
        style: {
            height: this.imageInitHeight,
            opacity: this.imageInitOpacity,
        }
    };

5 在componentDidMount实现更新组件stytle的函数###

componentDidMount() {
    this.updateNativeStyles();
}
updateNativeStyles() {
    this.space && this.space.setNativeProps(this._spaceStyles);
    this.image && this.image.setNativeProps(this._imageStyles);
}

三、React Native 触摸事件处理详解

参考:https://www.race604.com/react-native-touch-event/

上一篇 下一篇

猜你喜欢

热点阅读