React native React本机pan应答器设置边界,有时不工作
我正在尝试使用react nativeReact native React本机pan应答器设置边界,有时不工作,react-native,React Native,我正在尝试使用react nativePanResponder 在用户平移时,我使用动画.ValueXY值更新动画.View,当用户点击左边框或右边框时,我想停止移动此动画.View我以某种方式管理了它,但当用户滑动更快时,该视图不会在边框上停止,并且超出了限制 我怎样才能解决这个问题 这是完整的代码 import React, { useRef, useEffect } from 'react' import { Platform, View, PanResponder
PanResponder
在用户平移时,我使用动画.ValueXY
值更新动画.View
,当用户点击左边框或右边框时,我想停止移动此动画.View
我以某种方式管理了它,但当用户滑动更快时,该视图不会在边框上停止,并且超出了限制
我怎样才能解决这个问题
这是完整的代码
import React, { useRef, useEffect } from 'react'
import {
Platform,
View,
PanResponder,
Animated,
Dimensions,
StyleSheet
} from 'react-native';
import PropTypes from 'prop-types';
function usePanResponders({ parentWidth, reverse, width, values, onMoving}) {
const endXPos = parentWidth - width;
const _values = useRef({...values}).current;
const pan = useRef(new Animated.ValueXY({...values})).current
useEffect(() => {
pan.addListener((values) => {
_values.x = values.x
});
return () => {
pan.removeAllListeners();
}
}, [])
return [useRef(PanResponder.create({
onMoveShouldSetPanResponder: () => true,
onMoveShouldSetPanResponderCapture: (_, { dx }) => Math.abs(dx) > 20,
onPanResponderGrant: () => {
if(!reverse) {
console.log(reverse)
pan.setOffset({x: _values.x, y: _values.y});
pan.setValue({x: 0, y: 0});
}
},
onPanResponderMove: (e, gestureState) => {
const isMovingLeft = gestureState.dx > 0;
// this is how i stops right border
if((_values.x >= endXPos) && isMovingLeft) return null;
// left border
if(!isMovingLeft && _values.x <= 0) return null;
return Animated.event(
[ null,
{dx: pan.x}
],
{listener: null}
)(e, gestureState);
},
onPanResponderRelease: () => onMoving(_values)
})).current, pan];
}
function useCss({width, height, color}) {
return [
Platform.select({
ios: {
zIndex: 999,
position: 'absolute',
},
android: {
position: 'absolute',
}
}),
{
backgroundColor: color,
width,
height
}
]
}
function AsyncDraggable({x, y, width, height, color, parentWidth, reverse, onDragEnd}) {
const [position, item] = useCss({width, height, color})
const onMoving = (v) => {
console.log(v)
}
const values = {x, y}
console.log('Rendering...')
const [panresponder, pan] = usePanResponders({parentWidth, reverse, width, pan, values, onMoving})
return (
<View style={{...position}}>
<Animated.View
{...panresponder.panHandlers}
style={[pan.getLayout()]}>
<View
style={{...item}}
>
</View>
</Animated.View>
</View>
)
}
AsyncDraggable.prototype = {
width: PropTypes.number,
height: PropTypes.number,
color: PropTypes.string,
parentWidth:PropTypes.number.isRequired,
onDragEnd: PropTypes.func,
onMove: PropTypes.func,
x:PropTypes.number,
y:PropTypes.number
}
AsyncDraggable.defaultProps = {
x : 0,
y : 0,
reverse : false,
onMove: () => {}
}
const margin = {
top: 10,
bottom: 20,
left: 50,
right: 15
};
const screenWidth = Dimensions.get('window').width;
function Scroller({width, height, panWidth}){
const computedWidth = width - (margin.left + margin.right);
const _height = height || 70
return (
<View style={{
marginLeft: margin.left,
marginRight: margin.right,
marginTop: margin.top,
width: computedWidth,
overflow: 'hidden',
height,
backgroundColor: 'rgba(255,255,255,0.04)'}}>
<AsyncDraggable x={10} color={'yellow'} parentWidth={computedWidth} width={panWidth} height={_height}/>
</View>
)
}
Scroller.prototype = {
height: PropTypes.number,
width: PropTypes.number,
}
Scroller.defaultProps = {
height: 70,
width: screenWidth,
panWidth: 60
}
export default class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Scroller/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
padding: 8
}
});
import React,{useRef,useffect}来自“React”
进口{
平台,
看法
应答器,
有生气的
尺寸,
样式表
}从“反应本机”;
从“道具类型”导入道具类型;
函数usePanResponders({parentWidth,reverse,width,values,onMoving}){
const endXPos=parentWidth-width;
const_values=useRef({…values}).current;
const pan=useRef(新的动画.ValueXY({…values})).current
useffect(()=>{
pan.addListener((值)=>{
_values.x=values.x
});
return()=>{
pan.removeAllListeners();
}
}, [])
return[useRef(PanResponder.create({
onMoveShouldSetPanResponder:()=>true,
onMoveShouldSetPanResponderCapture:(u,{dx})=>Math.abs(dx)>20,
onPanResponderGrant:()=>{
如果(!反向){
console.log(反向)
setOffset({x:_values.x,y:_values.y});
集值({x:0,y:0});
}
},
onPanResponderMove:(e,手势状态)=>{
常数isMovingLeft=gestureState.dx>0;
//这就是我如何停止右边界
if((_values.x>=endXPos)和&isMovingLeft)返回null;
//左边框
如果(!isMovingLeft&&&u values.x onMoving(\u values)
})).当前,pan];
}
函数useCss({宽度、高度、颜色}){
返回[
Platform.select({
ios:{
zIndex:999,
位置:'绝对',
},
安卓:{
位置:'绝对',
}
}),
{
背景颜色:颜色,
宽度,
高度
}
]
}
函数AsyncDraggable({x,y,width,height,color,parentWidth,reverse,onDragEnd}){
const[position,item]=useCss({宽度,高度,颜色})
移动常数=(v)=>{
控制台日志(v)
}
常量值={x,y}
console.log('Rendering…'))
const[panresponder,pan]=usepanresponder({parentWidth,reverse,width,pan,values,onMoving})
返回(
)
}
AsyncDragTable.prototype={
宽度:PropTypes.number,
高度:PropTypes.number,
颜色:PropTypes.string,
parentWidth:PropTypes.number.isRequired,
onDragEnd:PropTypes.func,
onMove:PropTypes.func,
x:PropTypes.number,
y:PropTypes.number
}
AsyncDragTable.defaultProps={
x:0,,
y:0,
反面:错,
onMove:()=>{}
}
常量边距={
前10名,
底数:20,
左:50,,
右:15
};
const screenWidth=Dimensions.get('window').width;
函数滚动条({width,height,panWidth}){
const computedWidth=宽度-(margin.left+margin.right);
常数|高度=高度| 70
返回(
)
}
Scroller.prototype={
高度:PropTypes.number,
宽度:PropTypes.number,
}
Scroller.defaultProps={
身高:70,
宽度:屏幕宽度,
窗格宽度:60
}
导出默认类App扩展React.Component{
render(){
返回(
);
}
}
const styles=StyleSheet.create({
容器:{
填充:8
}
});
正如你在代码上看到的
if((_values.x >= endXPos) && isMovingLeft) return null;
if(!isMovingLeft && _values.x <= 0) return null;
if((_values.x>=endXPos)和&isMovingLeft)返回null;
如果(!isMovingLeft&&&_values.x,如果它超出边界,您可以做一件事,您可以在onPanResponderRelease回调上检查它,并将标记位置重置或更新到边界限制