Javascript 当您不知道内容的大小时,如何在 react native 中设置高度动画?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/45633818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you animate the height in react native when you don't know the size of the content?
提问by Poyan
In react-native, how do you animate the size of a View when you dont know the size of it's contents?
在 react-native 中,当您不知道 View 内容的大小时,如何为 View 的大小设置动画?
Let's say the View's content height can be anywhere from 0-400pts, and the content can grow and shrink dynamically, and you want to animate any changes to the height.
假设 View 的内容高度可以在 0-400pts 之间的任何位置,并且内容可以动态增长和缩小,并且您希望对高度的任何变化进行动画处理。
Basically, I'm looking to reproduce the behaviour of LayoutAnimation without using LayoutAnimationbut using Animated.
基本上,我希望在不使用 LayoutAnimation而是使用 Animated 的情况下重现 LayoutAnimation 的行为。
I think what eludes me is I don't know how to animate towards a target height since I don't know the height of the content.
我认为我不知道的是我不知道如何朝着目标高度设置动画,因为我不知道内容的高度。
回答by Mahmoud Felfel
I use LayoutAnimationfor that, just before the state change that causes your component's height to change, add:
我使用LayoutAnimation它,就在导致组件高度更改的状态更改之前,添加:
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
You can use different presets:
您可以使用不同的预设:
- spring
- easeInEaseOut
linear
You can read more about it here https://facebook.github.io/react-native/docs/layoutanimation.html
- 春天
- 缓入缓出
线性
你可以在这里阅读更多关于它的信息https://facebook.github.io/react-native/docs/layoutanimation.html
回答by Tierna D. Hyman Lawless
You are going to have to add some kind of size scaling, probably with percentages for best effect.
您将不得不添加某种尺寸缩放,可能使用百分比以获得最佳效果。
First thing first you would need to use Animated.Viewinstead of View.
首先,您需要使用Animated.View而不是View.
Next you would need to apply a transform to the style of the view lets say it looks like below. This is the part that updates and changes and creates the 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.
]
}
]}
>
This next part is basically an animated API example, you would write something like this (custom to how you want) and when this script is called it will animate in whatever way you specify.
下一部分基本上是一个动画 API 示例,您可以编写这样的内容(根据您的需要自定义),当调用此脚本时,它将以您指定的任何方式进行动画处理。
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();
Lastly you will probably want to apply an interpolation to the value to make it look as custom as possible.
最后,您可能希望对值应用插值以使其看起来尽可能自定义。
(this will go into your render()function but before the return(). the ViewScaleValuewill go into the Animated.Viewtransform)
(这将进入您的render()功能,但在return().ViewScaleValue将进入Animated.View转换之前)
const ViewScaleValue = this.state.ViewScale.interpolate({
inputRange: [0, 25, 50, 75, 100],
outputRange: [0, .5, 0.75, 0.9, 1]
});
all of this code would make ViewScaleValue, a simple number, animate from 0-100, going fast and then slow (because of interpolation) and apply each iteration of the animation to the Animated.Viewtransform.
所有这些代码都会使ViewScaleValue,一个简单的数字,从 0 到 100 的动画,先快后慢(因为插值),并将动画的每次迭代应用于Animated.View变换。
Read the Animated API alongside this to get a good grasp on it.
阅读 Animated API 旁边的内容以更好地掌握它。
回答by sbearben
The method I've taken is to spend layout passes getting the height of the "truncated" component and the height of the "full size" component (you need a way for the truncated height to be deterministic, usually by knowing how to render a "row" of content). Essentially before you have those values, you render these as two separate views that are hidden:
我采用的方法是使用布局传递来获取“截断”组件的高度和“全尺寸”组件的高度(您需要一种方法来确定截断高度,通常是通过知道如何渲染内容的“行”)。基本上在获得这些值之前,将它们呈现为两个隐藏的独立视图:
hidden: {
position: 'absolute',
left: 0,
top: 0,
opacity: 0,
},
Use onLayout to capture their heights:
使用 onLayout 来捕捉它们的高度:
const onLayoutTruncated = ({nativeEvent}: LayoutChangeEvent) => {
if (!doneProcessing) {
truncatedHeight = nativeEvent.layout.height;
checkIfDoneProcessingLayout();
}
};
const onLayoutFull = ({nativeEvent}: LayoutChangeEvent) => {
if (!doneProcessing) {
fullHeight = nativeEvent.layout.height;
checkIfDoneProcessingLayout();
}
};
checkIfDoneProcessingLayout()will check if both truncatedHeightand fullHeightare set, and make a state change if they both are (doneProcessing = true).
checkIfDoneProcessingLayout()将检查truncatedHeight和fullHeight是否都设置,如果它们都设置,则更改状态(doneProcessing = true)。
From there you should unhide the truncated view and be able to animate between both height values using an Animated.Valueand interpolation:
从那里你应该取消隐藏被截断的视图,并能够使用Animated.Value和插值在两个高度值之间设置动画:
const expandingHeight = animatedValue.interpolate({
inputRange: [0, 1],
outputRange: [truncatedHeight, fullHeight],
});
Trigger the expanding/collapsing animation on click using Animated.timing
使用点击触发展开/折叠动画 Animated.timing
Animated.timing(animatedValue, {toValue: isExpanded ? 0 : 1, easing: SOME_EASING_FUNCTION, duration: SOME_DURATION}).start();

