TouchableOpacity with parent PanResponder
TouchableOpacity with parent PanResponder
我有一个 parent PanResponder
和 child TouchableOpacity。
发生的情况是 TouchableOpacity
不响应点击,因为 PanResponder
接受了点击。
我试图遵循本指南但没有成功:
http://browniefed.com/blog/react-native-maintain-touchable-items-with-a-parent-panresponder/
这是我的代码:
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
return gestureState.dx != 0 && gestureState.dy != 0;
},
onPanResponderGrant: (evt, gestureState) => {
let isFirst = gestureState.y0 > 164 ? false : true;
this.setState({animObj: isFirst, isUsingCurtain: true});
},
onPanResponderMove: (evt, gestureState) => {
//let Y = this.state.animObj ? gestureState.moveY - this.state.currentHeaderHeight : gestureState.moveY - this.state.currentHeaderHeight ;// - this.state.currentHeaderHeight;
let Y = gestureState.moveY - this.state.currentHeaderHeight + 20
if (Y < 0) {
return false
}
this.state.animCurtain.setValue(Y);
gestureState.moveY > height / 2 ? this.setState({curtainOnMiddle: true}) : this.setState({curtainOnMiddle: false})
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
if (((height / 2) > gestureState.moveY)) {//slide back up1
this._CurtainAnimation(0, false);
} else {//slide to bottom
let val = height - calcSize(180);
this._CurtainAnimation(val, true);
}
},
onPanResponderTerminate: (evt, gestureState) => {
},
onPanResponderStart: (e, gestureState) => {
},
});
这是我的观点:
<Animated.View
style={[styles.bottomHPHeader, TopArroOpacity ? {opacity: TopArroOpacity} : ""]} {...this._panResponder.panHandlers}>
<TouchableOpacity onPress={() => this._animateAutoCurtain()}>
{this.state.curtainOnMiddle ?
<AIIcon image={require('../../../../assets/images/homepage/close_drawer_arrow.png')}
boxSize={30}/>
: <AIIcon image={require('../../../../assets/images/homepage/open_drawer_arrow.png')}
boxSize={30}/>}
</TouchableOpacity></Animated.View>
谢谢
我的案例的解决方案是修改 onMoveShouldSetPanResponder
onMoveShouldSetPanResponder: (evt, gestureState) => {
//return true if user is swiping, return false if it's a single click
return !(gestureState.dx === 0 && gestureState.dy === 0)
}
我遇到了类似的问题,但对我来说,有一个包含内部平移视图的容器视图,同时将按钮置于绝对位置并将其保持在平移视图上方确实有所帮助。它可能不适合所有人,但对于按钮可以绝对定位的情况(比如我的),它是有效的。
以下是具有平移视图和按钮的组件的示例代码。
import React, { Component } from "react";
import {
Animated,
View,
Text,
StyleSheet,
PanResponder,
TouchableOpacity
} from "react-native";
export class ToolRuler extends Component {
constructor(props) {
super(props);
this.state = {
moveX: 0,
moveY: 0
};
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
// anything
},
onPanResponderMove: (evt, gestureState) => {
this.setState({
moveX: gestureState.moveX,
moveY: gestureState.moveY
});
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.setState({
moveX: gestureState.moveX,
moveY: gestureState.moveY
});
},
onPanResponderTerminate: (evt, gestureState) => {},
onPanResponderStart: (e, gestureState) => {}
});
}
render() {
return (
<View
style={{
flex: 1,
position: "relative",
alignItems: "center",
justifyContent: "center"
}}
>
<Animated.View
{...this._panResponder.panHandlers}
style={{ flex: 1, width: "100%", backgroundColor: "#ccc" }}
>
<Text style={{ marginTop: 200, textAlign: "center" }}>
x: {this.state.moveX}, y: {this.state.moveY}
</Text>
</Animated.View>
<TouchableOpacity
style={{
position: "absolute"
}}
onPress={() => alert("I am tapped!")}
>
<Text>Click Me</Text>
</TouchableOpacity>
</View>
);
}
}
this.panResponder = PanResponder.create({
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
});
完美!我只是因为敏感而需要调整。
onMoveShouldSetPanResponder: (evt, gestureState) => {
const { dx, dy } = gestureState
return dx > 2 || dx < -2 || dy > 2 || dy < -2
}
我对 Android 的解决方案。所有其他人 return false
onMoveShouldSetPanResponder: (evt, { dx, dy }) => dx !== 0 || dy !== 0,
我遇到了完全相同的问题。该解决方案是上述解决方案的组合。必须为 onMoveShouldSetPanResponder 和 onMoveShouldSetPanResponderCapture 添加条件。这是我所做的。
onMoveShouldSetPanResponder: (_, gestureState) => {
const { dx, dy } = gestureState
return (dx > 2 || dx < -2 || dy > 2 || dy < -2)
},
onMoveShouldSetPanResponderCapture: (_, gestureState) => {
const { dx, dy } = gestureState
return (dx > 2 || dx < -2 || dy > 2 || dy < -2)
},
似乎每个人的情况都略有不同...这里是对我有用的 PanResponder.create
属性的组合(我试图允许点击子元素,但使用 PanResponder 捕获移动:
onStartShouldSetPanResponder: ( e, state ) => false,
onStartShouldSetPanResponderCapture: ( e, state ) => false,
onMoveShouldSetPanResponder: ( e, state ) => true,
onMoveShouldSetPanResponderCapture: ( e, state ) => true,
我希望这对其他人有帮助,并且它不会以某种方式回来困扰我!
以上修复对我不起作用,但以下修复 -
在PanResponder.create
中将onStartShouldSetPanResponderCapture
设置为false
下面是我的panResponder代码
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
// We need this code to listen for onPress vs pan events
onStartShouldSetPanResponderCapture: () => false,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onPanResponderMove: (e, gestureState) => {
if (gestureState.dy > 0) {
Animated.event([null, { dy: pan.y }], { useNativeDriver: false })(
e,
gestureState,
);
}
},
onPanResponderRelease: (evt, gestureState) => {
// If pulled down far enough, dismiss modal
if (gestureState.dy > SWIPE_DISTANCE) onCancel();
else {
// If not dismissed slide back to standard height
Animated.spring(pan, {
toValue: { x: 0, y: 0 },
useNativeDriver: false,
}).start();
}
},
onShouldBlockNativeResponder: () => true,
}),
).current;
我有一个 parent PanResponder
和 child TouchableOpacity。
发生的情况是 TouchableOpacity
不响应点击,因为 PanResponder
接受了点击。
我试图遵循本指南但没有成功:
http://browniefed.com/blog/react-native-maintain-touchable-items-with-a-parent-panresponder/
这是我的代码:
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => {
return gestureState.dx != 0 && gestureState.dy != 0;
},
onPanResponderGrant: (evt, gestureState) => {
let isFirst = gestureState.y0 > 164 ? false : true;
this.setState({animObj: isFirst, isUsingCurtain: true});
},
onPanResponderMove: (evt, gestureState) => {
//let Y = this.state.animObj ? gestureState.moveY - this.state.currentHeaderHeight : gestureState.moveY - this.state.currentHeaderHeight ;// - this.state.currentHeaderHeight;
let Y = gestureState.moveY - this.state.currentHeaderHeight + 20
if (Y < 0) {
return false
}
this.state.animCurtain.setValue(Y);
gestureState.moveY > height / 2 ? this.setState({curtainOnMiddle: true}) : this.setState({curtainOnMiddle: false})
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
if (((height / 2) > gestureState.moveY)) {//slide back up1
this._CurtainAnimation(0, false);
} else {//slide to bottom
let val = height - calcSize(180);
this._CurtainAnimation(val, true);
}
},
onPanResponderTerminate: (evt, gestureState) => {
},
onPanResponderStart: (e, gestureState) => {
},
});
这是我的观点:
<Animated.View
style={[styles.bottomHPHeader, TopArroOpacity ? {opacity: TopArroOpacity} : ""]} {...this._panResponder.panHandlers}>
<TouchableOpacity onPress={() => this._animateAutoCurtain()}>
{this.state.curtainOnMiddle ?
<AIIcon image={require('../../../../assets/images/homepage/close_drawer_arrow.png')}
boxSize={30}/>
: <AIIcon image={require('../../../../assets/images/homepage/open_drawer_arrow.png')}
boxSize={30}/>}
</TouchableOpacity></Animated.View>
谢谢
我的案例的解决方案是修改 onMoveShouldSetPanResponder
onMoveShouldSetPanResponder: (evt, gestureState) => {
//return true if user is swiping, return false if it's a single click
return !(gestureState.dx === 0 && gestureState.dy === 0)
}
我遇到了类似的问题,但对我来说,有一个包含内部平移视图的容器视图,同时将按钮置于绝对位置并将其保持在平移视图上方确实有所帮助。它可能不适合所有人,但对于按钮可以绝对定位的情况(比如我的),它是有效的。
以下是具有平移视图和按钮的组件的示例代码。
import React, { Component } from "react";
import {
Animated,
View,
Text,
StyleSheet,
PanResponder,
TouchableOpacity
} from "react-native";
export class ToolRuler extends Component {
constructor(props) {
super(props);
this.state = {
moveX: 0,
moveY: 0
};
}
componentWillMount() {
this._panResponder = PanResponder.create({
onStartShouldSetPanResponder: (evt, gestureState) => true,
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
onMoveShouldSetResponderCapture: () => true,
onMoveShouldSetPanResponder: (evt, gestureState) => true,
onMoveShouldSetPanResponderCapture: (evt, gestureState) => true,
onPanResponderGrant: (evt, gestureState) => {
// anything
},
onPanResponderMove: (evt, gestureState) => {
this.setState({
moveX: gestureState.moveX,
moveY: gestureState.moveY
});
},
onPanResponderTerminationRequest: (evt, gestureState) => true,
onPanResponderRelease: (evt, gestureState) => {
this.setState({
moveX: gestureState.moveX,
moveY: gestureState.moveY
});
},
onPanResponderTerminate: (evt, gestureState) => {},
onPanResponderStart: (e, gestureState) => {}
});
}
render() {
return (
<View
style={{
flex: 1,
position: "relative",
alignItems: "center",
justifyContent: "center"
}}
>
<Animated.View
{...this._panResponder.panHandlers}
style={{ flex: 1, width: "100%", backgroundColor: "#ccc" }}
>
<Text style={{ marginTop: 200, textAlign: "center" }}>
x: {this.state.moveX}, y: {this.state.moveY}
</Text>
</Animated.View>
<TouchableOpacity
style={{
position: "absolute"
}}
onPress={() => alert("I am tapped!")}
>
<Text>Click Me</Text>
</TouchableOpacity>
</View>
);
}
}
this.panResponder = PanResponder.create({
onStartShouldSetPanResponderCapture: (evt, gestureState) => false,
});
完美!我只是因为敏感而需要调整。
onMoveShouldSetPanResponder: (evt, gestureState) => {
const { dx, dy } = gestureState
return dx > 2 || dx < -2 || dy > 2 || dy < -2
}
我对 Android 的解决方案。所有其他人 return false
onMoveShouldSetPanResponder: (evt, { dx, dy }) => dx !== 0 || dy !== 0,
我遇到了完全相同的问题。该解决方案是上述解决方案的组合。必须为 onMoveShouldSetPanResponder 和 onMoveShouldSetPanResponderCapture 添加条件。这是我所做的。
onMoveShouldSetPanResponder: (_, gestureState) => {
const { dx, dy } = gestureState
return (dx > 2 || dx < -2 || dy > 2 || dy < -2)
},
onMoveShouldSetPanResponderCapture: (_, gestureState) => {
const { dx, dy } = gestureState
return (dx > 2 || dx < -2 || dy > 2 || dy < -2)
},
似乎每个人的情况都略有不同...这里是对我有用的 PanResponder.create
属性的组合(我试图允许点击子元素,但使用 PanResponder 捕获移动:
onStartShouldSetPanResponder: ( e, state ) => false,
onStartShouldSetPanResponderCapture: ( e, state ) => false,
onMoveShouldSetPanResponder: ( e, state ) => true,
onMoveShouldSetPanResponderCapture: ( e, state ) => true,
我希望这对其他人有帮助,并且它不会以某种方式回来困扰我!
以上修复对我不起作用,但以下修复 -
在PanResponder.create
onStartShouldSetPanResponderCapture
设置为false
下面是我的panResponder代码
const panResponder = React.useRef(
PanResponder.create({
onStartShouldSetPanResponder: () => true,
// We need this code to listen for onPress vs pan events
onStartShouldSetPanResponderCapture: () => false,
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: () => true,
onPanResponderTerminationRequest: () => true,
onPanResponderMove: (e, gestureState) => {
if (gestureState.dy > 0) {
Animated.event([null, { dy: pan.y }], { useNativeDriver: false })(
e,
gestureState,
);
}
},
onPanResponderRelease: (evt, gestureState) => {
// If pulled down far enough, dismiss modal
if (gestureState.dy > SWIPE_DISTANCE) onCancel();
else {
// If not dismissed slide back to standard height
Animated.spring(pan, {
toValue: { x: 0, y: 0 },
useNativeDriver: false,
}).start();
}
},
onShouldBlockNativeResponder: () => true,
}),
).current;