在数据源中添加/删除列表视图项时为其设置动画

时间:2015-08-13 19:46:38

标签: react-native

有人可以告诉我如何做到这一点,例如在添加时将高度从0设为动画,在删除时返回0?

4 个答案:

答案 0 :(得分:6)

添加动画很简单,只需在Animated中使用listRow componentDidMount,例如:

componentDidMount = ()=> {
    Animated.timing(this.state._rowOpacity, {
        toValue: 1,
        duration: 250,
    }).start()
}

在卸载之前为组件设置动画在本地反应中要困难得多。您应该为ListView设置处理程序。当dataSource更改时,将数据差异化,启动Animated以隐藏已删除的行,并为ListView设置新的dataSource。

答案 1 :(得分:6)

在这里,您可以获得不透明度动画的完整工作示例:

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
    }
});

答案 2 :(得分:2)

如果您需要从列表中删除项目,请按以下步骤操作ListRow组件:

&#13;
&#13;
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>
       );
   }
}
&#13;
&#13;
&#13;

我已在此博客文章中发布了此问题的完整教程。并且它逐步解释了您需要做什么来完成添加和删除项目以及为此过程设置动画。 对于添加非常简单,但是为了删除它看起来有点复杂。 http://moduscreate.com/react-native-dynamic-animated-lists/

答案 3 :(得分:0)

这是高度和不透明度动画的完整示例。它支持添加和删除元素。关键是您需要在消失的动画完成后重新设置高度和不透明度。然后,您立即从源中删除该项目。

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>
  );
}