Pourquoi le rappel nativeEvent
ne se déclenche-t-il pas dans mon appel Animated.event
Lorsqu'une boîte est déplacée?
Mon objectif ultime est d'implémenter une logique pour empêcher les composants contrôlés par des gestes déplaçables de sortir de l'écran, mais je ne peux pas le faire tant que je n'aurai pas compris pourquoi le rappel souhaité ne se déclenche jamais.
J'ai défini un rappel onGestureEvent
pour un composant <PanGestureHandler />
, Et je lui passe un appel Animated.event()
avec un rappel nativeEvent
( voir leurs documents pour un exemple de la façon de procéder ).
Je sais que le rappel nativeEvent ne se déclenche pas car les appels debug et console.log dans Animated.block()
ne sortent rien vers la console (je l'exécute en utilisant Expo -- lien de débogage ici ). De plus, la ligne set(_translateX, translationX)
dans l'appel Animate.block()
ne s'exécute jamais non plus, sinon je m'attendrais à voir les boîtes bouger tout en les faisant glisser (au lieu de quand une touche est relâchée).
Notez que si vous décommentez le bloc suivant et supprimez l'objet { nativeEvent: function... }
Directement après lui, l'animation fonctionne comme prévu:
{
nativeEvent: {translationX: _translateX}
},
J'ai l'impression de manquer quelque chose de très simple mais je ne sais pas ce que c'est.
Voici un lien expo Expo pour le débogage: https://snack.expo.io/d8xCeHhtj
Voici mon code:
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,
},
})
Merci de votre aide.
vous pouvez utiliser Animé from react-native-reanimated.
car l'appel nativeEvent ne fonctionne pas lorsque nous importons Animated from react-native
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,
},
});