为什么我无法在 React Native 的 Animated.event() 中触发 nativeEvent 回调?



拖动框时,为什么nativeEvent回调不在我的Animated.event调用中触发?

我的最终目标是实现逻辑,以防止可拖动的手势控制组件离开屏幕,但在我弄清楚为什么所需的回调永远不会触发之前,我无法做到这一点。

我为<PanGestureHandler />组件设置了一个onGestureEvent回调,并向它传递了一个带有nativeEvent回调的Animated.event()调用(有关如何执行此操作的示例,请参阅他们的文档(。

我知道nativeEvent回调没有启动,因为Animated.block()中的debug和console.log调用没有向控制台输出任何内容(我使用Expo-debug链接运行它(。此外,Animate.block()调用中的set(_translateX, translationX)行也从未执行过,否则我希望看到框在拖动时移动(而不是在释放触摸时(。

请注意,如果取消对以下块的注释,并在其后面直接删除{ nativeEvent: function... }对象,则动画将按预期工作:

{
nativeEvent: {translationX: _translateX}
},

我觉得我错过了一些非常简单的东西,但我不知道它是什么。

以下是用于调试的世博链接:https://snack.expo.io/d8xCeHhtj

这是我的代码:

import React, { Component } from 'react';
import {
Dimensions,
StyleSheet,
Text,
View,
Button,
Animated
} from 'react-native';
import {
PanGestureHandler,
ScrollView,
State,
} from 'react-native-gesture-handler';
const {
and,
block,
clockRunning,
set,
Clock,
cond,
eq,
debug,
Extrapolate,
max,
lessThan,
greaterOrEq,
Value,
startClock,
timing,
call,
stopClock,
} = Animated;
function Slider({color, width, height}) {
const screenWidth = Dimensions.get('window').width;
const _translateX = new Animated.Value(0);
const _lastOffset = {x: 0};
const cmpStyles = StyleSheet.create({
box: {
width: width,
height: height,
alignSelf: 'center',
backgroundColor: color,
margin: 30,
zIndex: 200,
color: color,
transform: [
{translateX: _translateX},
],
},
});
const _onGestureEvent = Animated.event(
[
// Uncomment this block to see the original animation
/*
{
nativeEvent: {translationX: _translateX}
},
*/
// Comment the following object when uncommenting the previous section
{
nativeEvent: function({ translationX, absoluteX }) {
return block([
debug('x', translationX),
call([], () => console.log('the code block was executed')),
set(_translateX, translationX),
])
}
},
// ------------------------------
],
{
useNativeDriver: true,
listener: (event, gestureState) => {
const {absoluteX, translationX} = event.nativeEvent;
//console.log('translationX' + translationX);
//console.log('dest' + _translateX._value);
}
}
);
const _onHandlerStateChange = event => {
const {
oldState,
translationX,
absoluteX,
} = event.nativeEvent;
if (oldState === State.ACTIVE) {
//if (absoluteX + translationX > screenWidth) {
//console.log("translationX: " + translationX);
//console.log("screenWidth" + screenWidth);
// Set the slider to correct position when gesture is released
_lastOffset.x += translationX;
_translateX.setOffset(_lastOffset.x);
_translateX.setValue(0);
}
};
return (
<PanGestureHandler
onGestureEvent={_onGestureEvent}
onHandlerStateChange={_onHandlerStateChange}
>
<Animated.View style={cmpStyles.box} />
</PanGestureHandler>
);
}
export default function Example() {
const width = 60;
const height = 60;
return (
<View style={styles.scrollView}>
<Slider color={'red'} width={width} height={height} />
<Slider color={'blue'} width={width} height={height} />
<Slider color={'green'} width={width} height={height} />
<Slider color={'orange'} width={width} height={height} />
</View>
);
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
marginTop: 120,
},
})

谢谢你的帮助。

您可以使用react native reactivated中的动画

因为当我们从react native导入动画时,nativeEvent调用不起作用

import React, { Component } from "react";
import { Dimensions, StyleSheet, Text, View, Button } from "react-native";
import { PanGestureHandler, State } from "react-native-gesture-handler";
import Animated from "react-native-reanimated";
const {
and,
block,
clockRunning,
set,
Clock,
cond,
eq,
debug,
Extrapolate,
max,
lessThan,
greaterOrEq,
Value,
startClock,
timing,
call,
stopClock,
event,
} = Animated;
function Slider({ color, width, height }) {
const screenWidth = Dimensions.get("window").width;
const _translateX = new Value(0);
const _lastOffset = { x: 0 };
const cmpStyles = StyleSheet.create({
box: {
width: width,
height: height,
alignSelf: "center",
backgroundColor: color,
margin: 30,
zIndex: 200,
color: color,
transform: [{ translateX: _translateX }],
},
});
const _onGestureEvent = event(
[
// Uncomment this block to see the original animation
/*
{
nativeEvent: {translationX: _translateX}
},
*/
// Comment the following object when uncommenting the previous section
{
nativeEvent: ({ translationX: x, translationY: y, state }) =>
block([
// debug('x', _translateX),
call([], () => console.log("the code block was executed")),
set(_translateX, x),
]),
},
],
// ------------------------------
{
useNativeDriver: true,
listener: (event, gestureState) => {
const {absoluteX, translationX} = event.nativeEvent;
//console.log('translationX' + translationX);
//console.log('dest' + _translateX._value);
}
}
);
const _onHandlerStateChange = (event) => {
const { oldState, translationX, absoluteX } = event.nativeEvent;
if (oldState === State.ACTIVE) {
//if (absoluteX + translationX > screenWidth) {
//console.log("translationX: " + translationX);
//console.log("screenWidth" + screenWidth);
// Set the slider to correct position when gesture is released
_lastOffset.x += translationX;
_translateX.setValue(_lastOffset.x);
}
};
return (
<PanGestureHandler
onGestureEvent={_onGestureEvent}
onHandlerStateChange={_onHandlerStateChange}
>
<Animated.View style={cmpStyles.box} />
</PanGestureHandler>
);
}
export default function Example() {
const width = 60;
const height = 60;
return (
<View style={styles.scrollView}>
<Slider color={"red"} width={width} height={height} />
<Slider color={"blue"} width={width} height={height} />
<Slider color={"green"} width={width} height={height} />
<Slider color={"orange"} width={width} height={height} />
</View>
);
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
marginTop: 120,
},
});

编写类似的处理程序函数

handleSctoll = (e) => {
console.log(e.nativeEvent.contentOffset.y);
}

你可以添加像这个这样的监听器

Animated.event(
[{ nativeEvent: { contentOffset: { y: this.state.scrollY } } }],
{ listener: (event) => this.handleSctoll(event) }
)

最新更新