Dans react-native, comment animer la taille d'une vue sans connaître la taille de son contenu?
Supposons que la hauteur du contenu de la vue puisse être comprise entre 0 et 400 points, que le contenu puisse être agrandi et réduit de façon dynamique et que vous souhaitiez animer les modifications apportées à la hauteur.
En gros, je cherche à reproduire le comportement de LayoutAnimation sans utiliser LayoutAnimation mais en utilisant Animated.
Je pense que ce qui m'échappe, c'est que je ne sais pas comment animer vers une hauteur cible car je ne connais pas la hauteur du contenu.
J'utilise LayoutAnimation
pour cela, juste avant le changement d'état qui provoque la modification de la hauteur de votre composant, ajoutez:
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
Vous pouvez utiliser différents préréglages:
linéaire
Vous pouvez en savoir plus à ce sujet ici https://facebook.github.io/react-native/docs/layoutanimation.html
Vous allez devoir ajouter une sorte d’échelle de taille, probablement avec des pourcentages pour obtenir le meilleur effet.
Tout d’abord, vous devez utiliser Animated.View
Au lieu de View
.
Ensuite, vous devrez appliquer une transformation au style de la vue, ce qui signifie que celle-ci ressemble à celle ci-dessous. C'est la partie qui met à jour et change et crée la motion.
<Animated.View style={[ styles.someStyleYouMade,
{
transform: [
// scaleX, scaleY, scale, theres plenty more options you can find online for this.
{ scaleX: ViewScaleValue } // this would be the result of the animation code below and is just a number.
]
}
]}
>
Cette partie suivante est fondamentalement un exemple d’API animée, vous écririez quelque chose comme ceci (personnalisé selon votre choix) et lorsque ce script sera appelé, il s'animera de la manière que vous spécifiez.
Animated.timing( // Animate over time
this.state.ViewScale, // The animated value to drive, this would be a new Animated.Value(0) object.
{
toValue: 100, // Animate the value
duration: 5000, // Make it take a while
}
).start();
Enfin, vous souhaiterez probablement appliquer une interpolation à la valeur pour la rendre aussi personnalisée que possible.
(cela ira dans votre fonction render()
mais avant la return()
. le ViewScaleValue
ira dans la transformation Animated.View
)
const ViewScaleValue = this.state.ViewScale.interpolate({
inputRange: [0, 25, 50, 75, 100],
outputRange: [0, .5, 0.75, 0.9, 1]
});
tout ce code ferait ViewScaleValue
, un nombre simple, animer de 0 à 100, aller vite puis ralentir (à cause de l'interpolation) et appliquer chaque itération de l'animation à la transformation Animated.View
.
Lisez l'API animée à côté de ceci pour bien le comprendre.
La méthode que j’ai choisie consiste à passer des passes de présentation à obtenir la hauteur du composant "tronqué" et celle du composant "taille réelle" (vous avez besoin d’un moyen de déterminer la hauteur tronquée, généralement en sachant rendre un "rangée" de contenu). Essentiellement, avant d'avoir ces valeurs, vous les présentez sous la forme de deux vues distinctes qui sont masquées:
hidden: {
position: 'absolute',
left: 0,
top: 0,
opacity: 0,
},
Utilisez onLayout pour capturer leurs sommets:
const onLayoutTruncated = ({nativeEvent}: LayoutChangeEvent) => {
if (!doneProcessing) {
truncatedHeight = nativeEvent.layout.height;
checkIfDoneProcessingLayout();
}
};
const onLayoutFull = ({nativeEvent}: LayoutChangeEvent) => {
if (!doneProcessing) {
fullHeight = nativeEvent.layout.height;
checkIfDoneProcessingLayout();
}
};
checkIfDoneProcessingLayout()
vérifie si truncatedHeight
et fullHeight
sont définis et modifie leur état s'ils le sont (doneProcessing = true).
À partir de là, vous devriez afficher la vue tronquée et pouvoir animer les deux valeurs de hauteur à l'aide d'un Animated.Value
Et d'une interpolation:
const expandingHeight = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [truncatedHeight, fullHeight],
});
Déclenchez l’animation de développement/réduction en cliquant sur en utilisant Animated.timing
Animated.timing(animatedValue, {toValue: isExpanded ? 0 : 1, easing: SOME_EASING_FUNCTION, duration: SOME_DURATION}).start();