使用reactnative的panResponder組件
實現手勢響應的一系列函數
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
});
this._previousHeight = 0;
this._circleStyles = {
style: {
height: this._previousHeight,
backgroundColor: 'green',
}
};
}
重點來寫這兩個函數
onPanResponderMove: this._handlePanResponderMove,
響應過程中觸發
this.show來表示圖片view層的顯示狀態
如果this.show == false,手指向下滑動圖片層高度漸變跟隨手指,如果this.show == true手指向下滑動則不響應,
向上滑動也是同理
_handlePanResponderMove = (e: Object, gestureState: Object) =>{
if(this.show && gestureState.dy < 0 || !this.show && gestureState.dy > 0){
this._circleStyles.style.height = this._previousHeight + gestureState.dy;
this._updateNativeStyles();
}
}
和
onPanResponderRelease: this._handlePanResponderEnd,
響應結束時觸發
以50為界限,如果this.show == false,向下滑動距離超過50則顯示,show = true,小於50或向上滑動不響應
如過this.show == true,向上滑動距離超過50隱藏,show = false,小於50或向下滑動不響應
_handlePanResponderEnd = (e: Object, gestureState: Object) =>{
this._unHighlight();
if( gestureState.dy <= -50 && this.show){
this._circleStyles.style.height = 0;
this.show = false;
this._updateNativeStyles();
}else if( gestureState.dy >= 50 && !this.show){
this._circleStyles.style.height = height;
this.show = true;
this._updateNativeStyles();
}else{
this._circleStyles.style.height = this.show?height:0;
this._updateNativeStyles();
}
this._previousHeight = this._circleStyles.style.height;
}
效果如圖:

完整代碼如下:
'use strict';
import React,{Component} from 'react';
import {
PanResponder,
StyleSheet,
View,
Button,
Image,
Dimensions,
} from 'react-native';
var img = require('../img/r.jpg');
let {width,height} = Dimensions.get('window');
class PanResponderExample extends Component{
constructor(props){
super(props);
this.statics ={
title: 'PanResponder Sample',
description: 'Shows the use of PanResponder to provide basic gesture handling.',
};
this._panResponder = {};
this._previousHeight = 0;
this._circleStyles = {};
this.circle = (null : ?{ setNativeProps(props: Object): void });
this.show = false;
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: this._handleStartShouldSetPanResponder,
onMoveShouldSetPanResponder: this._handleMoveShouldSetPanResponder,
onPanResponderGrant: this._handlePanResponderGrant,
onPanResponderMove: this._handlePanResponderMove,
onPanResponderRelease: this._handlePanResponderEnd,
onPanResponderTerminate: this._handlePanResponderEnd,
});
this._previousHeight = 0;
this._circleStyles = {
style: {
height: this._previousHeight,
backgroundColor: 'green',
}
};
}
componentDidMount(){
this._updateNativeStyles();
}
render(){
return (
<View
style={styles.container}
{...this._panResponder.panHandlers}>
<View style={styles.circle}
ref={(circle) => {
this.circle = circle;
}}
>
<Image
source={img}
style = {{width:200,height:200,borderRadius:100}}
/>
</View>
</View>
);
}
_highlight(){
this._circleStyles.style.backgroundColor = 'rgba(0,0,0,0.03)';
this._updateNativeStyles();
}
_unHighlight(){
this._circleStyles.style.backgroundColor = 'transparent';
this._updateNativeStyles();
}
_updateNativeStyles(){
this.circle && this.circle.setNativeProps(this._circleStyles);
}
_handleStartShouldSetPanResponder = (e: Object, gestureState: Object): boolean => {
// Should we become active when the user presses down on the circle?
return true;
}
_handleMoveShouldSetPanResponder = (e: Object, gestureState: Object): boolean =>{
// Should we become active when the user moves a touch over the circle?
return true;
}
_handlePanResponderGrant = (e: Object, gestureState: Object) =>{
this._highlight();
}
_handlePanResponderMove = (e: Object, gestureState: Object) =>{
if(this.show && gestureState.dy < 0 || !this.show && gestureState.dy > 0){
this._circleStyles.style.height = this._previousHeight + gestureState.dy;
this._updateNativeStyles();
}
}
_handlePanResponderEnd = (e: Object, gestureState: Object) =>{
this._unHighlight();
if( gestureState.dy <= -50 && this.show){
this._circleStyles.style.height = 0;
this.show = false;
this._updateNativeStyles();
}else if( gestureState.dy >= 50 && !this.show){
this._circleStyles.style.height = height;
this.show = true;
this._updateNativeStyles();
}else{
this._circleStyles.style.height = this.show?height:0;
this._updateNativeStyles();
}
this._previousHeight = this._circleStyles.style.height;
}
}
var styles = StyleSheet.create({
circle: {
justifyContent:'center',
width:width,
height:height,
position:'absolute',
top:0,
left:0,
elevation:10,
alignItems:'center',
},
container: {
flex: 1,
backgroundColor:'pink',
alignItems:'stretch',
flexDirection:'column',
elevation:1,
},
});
module.exports = PanResponderExample;