【发布时间】:2015-08-13 19:46:37
【问题描述】:
有人可以告诉我如何做到这一点,例如添加时将高度从 0 设置为动画,删除时将高度设置为 0?
【问题讨论】:
-
由于我的 listitem 是一个组件,我也可以将问题改写为:如何在组件卸载之前为其设置动画?
-
这是一个很好的问题,目前还没有回复。有没有办法在 Unmount 上为组件设置动画?
标签: react-native
有人可以告诉我如何做到这一点,例如添加时将高度从 0 设置为动画,删除时将高度设置为 0?
【问题讨论】:
标签: react-native
添加动画很简单,只需将 componentDidMount 中的 Animated 与您的 listRow 一起使用,例如:
componentDidMount = ()=> {
Animated.timing(this.state._rowOpacity, {
toValue: 1,
duration: 250,
}).start()
}
在卸载之前动画组件在 react-native 中要困难得多。您应该为ListView 设置一个处理程序。当dataSource改变时,diff数据,启动Animated来隐藏删除的行,并为ListView设置新的dataSource。
【讨论】:
在这里您可以获得不透明动画的完整工作示例:
import React from 'react-native';
export default class Cell extends React.Component {
constructor(props) {
super(props);
this.state = {
opacity: new React.Animated.Value(0)
};
}
componentDidMount() {
React.Animated.timing(this.state.opacity, {
toValue: 1,
duration: 250,
}).start();
}
render() {
return (
<React.Animated.View style={[styles.wrapper, {opacity: this.state.opacity}]}>
<React.Image source={{uri: 'http://placehold.it/150x150'}} style={styles.image}/>
<React.Text style={styles.text}>
Text
</React.Text>
</React.Animated.View>
);
}
}
const styles = React.StyleSheet.create({
wrapper: {
flex: 1,
flexDirection: 'row',
justifyContent: 'flex-start',
alignItems: 'center',
},
image: {
height: 40,
width: 40,
marginRight: 16,
backgroundColor: '#C9D5E6'
},
text: {
fontSize: 20
}
});
【讨论】:
如果您需要从列表中删除一个项目,以下是 ListRow 组件的操作方法:
class DynamicListRow extends Component {
// these values will need to be fixed either within the component or sent through props
_defaultHeightValue = 60;
_defaultTransition = 500;
state = {
_rowHeight : new Animated.Value(this._defaultHeightValue),
_rowOpacity : new Animated.Value(0)
};
componentDidMount() {
Animated.timing(this.state._rowOpacity, {
toValue : 1,
duration : this._defaultTransition
}).start()
}
componentWillReceiveProps(nextProps) {
if (nextProps.remove) {
this.onRemoving(nextProps.onRemoving);
} else {
// we need this for iOS because iOS does not reset list row style properties
this.resetHeight()
}
}
onRemoving(callback) {
Animated.timing(this.state._rowHeight, {
toValue : 0,
duration : this._defaultTransition
}).start(callback);
}
resetHeight() {
Animated.timing(this.state._rowHeight, {
toValue : this._defaultHeightValue,
duration : 0
}).start();
}
render() {
return (
<Animated.View
style={{height: this.state._rowHeight, opacity: this.state._rowOpacity}}>
{this.props.children}
</Animated.View>
);
}
}
我已在此博客文章中发布了有关此问题的完整教程。它逐步解释了您需要做什么来完成添加和删除项目并为该过程设置动画。 添加非常简单,但删除看起来有点复杂。 http://moduscreate.com/react-native-dynamic-animated-lists/
【讨论】:
这是高度和不透明度动画的完整示例。它支持添加和删除元素。关键是你需要在消失动画完成后重新设置高度和不透明度。然后您立即从源中删除该项目。
export const ListItem = (props: ListItemProps) => {
// Start the opacity at 0
const [fadeAnim] = useState(new Animated.Value(0));
// Start the height at 0
const [heightAnim] = useState(new Animated.Value(0));
/**
* Helper function for animating the item
* @param appear - whether the animation should cause the item to appear or disappear
* @param delay - how long the animation should last (ms)
* @param callback - callback to be called when the animation finishes
*/
const _animateItem = (appear: boolean = true, delay: number = 300, callback: () => void = () => null) => {
Animated.parallel([
Animated.timing(
fadeAnim,
{
toValue: appear ? 1 : 0,
duration: delay,
}
),
Animated.timing(
heightAnim,
{
toValue: appear ? 100 : 0,
duration: delay,
}
),
]).start(callback);
};
// Animate the appearance of the item appearing the first time it loads
// Empty array in useEffect results in this only occuring on the first render
React.useEffect(() => {
_animateItem();
}, []);
// Reset an item to its original height and opacity
// Takes a callback to be called once the reset finishes
// The reset will take 0 seconds and then immediately call the callback.
const _reset = (callback: () => void) => {
_animateItem(true,0, callback);
}
// Deletes an item from the list. Follows the following order:
// 1) Animate the item disappearing. On completion:
// 2) Reset the item to its original display height (in 0 seconds). On completion:
// 3) Call the parent to let it know to remove the item from the list
const _delete = () => {
_animateItem(false, 200, () => _reset(props.delete));
};
return (
<Animated.View
style={{height: heightAnim, opacity: fadeAnim, flexDirection: 'row'}}>
<Text>{props.text}</Text>
<Button onPress={() => _delete()}><Text>Delete</Text></Button>
</Animated.View>
);
}
【讨论】: