2

我正在尝试为我的应用创建一个 InputAccessoryView。它有一个 TextInput 和一个 Pressable 按钮。

我想做的是,当 TextInput 有空值时隐藏按钮,否则使用反应原生动画显示按钮。

我想出了按预期工作的工作组件。对于我正在使用的动画useNativeDriver: true

但是,有一个问题:

  1. 当 text 为空并且我输入一个单词然后pause时,显示的动画动画流畅。(如下图所示)

在此处输入图像描述

  1. 但是当文本为空并且我连续输入时,显示的动画就会以一种笨拙的方式进行动画处理。(如下图所示)

在此处输入图像描述

这是代码,也是世博小吃的链接:

export default function App() {
  const [text, setText] = React.useState('');
  const translateY = React.useRef(new Animated.Value(0)).current;

  React.useEffect(() => {
    if (text.length > 0) {
      // animate the add button to show by coming up
      _animateShowAddButton();
    } else {
      // animate the add button to hide by going down
      _animateHideAddButton();
    }
    // return null
  }, [text]);

  const _animateShowAddButton = () => {
    Animated.timing(translateY, {
      toValue: 0,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };

  const _animateHideAddButton = () => {
    Animated.timing(translateY, {
      toValue: 100,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };

  const onPressFunction = () => {
    console.log('onPressFunction');
  };

  return (
    <View style={styles.container}>
      <Text style={styles.paragraph}>Some text view</Text>
      <View style={styles.myInputAccessory}>
        <TextInput
          placeholder="Enter text"
          style={styles.textInputStyle}
          onChangeText={(text) => setText(text)}
        />
        <Animated.View
          style={[
            {
              transform: [
                {
                  translateY: translateY,
                },
              ],
            },
          ]}>
          <Pressable style={styles.buttonStyle} onPress={onPressFunction}>
            <Ionicons name="send" size={24} color="white" />
          </Pressable>
        </Animated.View>
      </View>
    </View>
  );
}

每当文本更改时,动画似乎都会暂停(并再次动画)。你能帮我当文本不为空时如何为按钮设置动画以平滑显示吗?

4

1 回答 1

2

问题是useEffect由于第二个参数而在每次文本更改时触发[text]。因此,动画在每次文本更改时开始。

您可以通过使用一些状态“锁定”动画来防止这种情况。以下是您的组件的相关更改:

function App() {
  const [isAnimating, setIsAnimating] = useState(false);
  const [isVisible, setIsVisible] = useState(false);

  useEffect(() => {
    // only start a new animation if we're not currently animating
    if (!isAnimating) {
      // only animate show if currently invisible
      if (!isVisible && text.length > 0) {
        _animateShowAddButton();
      // only animate hide if currently visible
      } else if (isVisible && text.length === 0) {
        _animateHideAddButton();
      }
    }
  // check if we need to animate whenever text changes
  // also check whenever animation finishes
  }, [text, isAnimating]);

  const _animateShowAddButton = () => {
    // secure the lock so another animation can't start
    setIsAnimating(true);
    setIsVisible(true);
    Animated.timing(translateY, {
      toValue: 0,
      duration: 300,
      useNativeDriver: true,
    // release the lock on completion
    }).start(() => setIsAnimating(false));
  };

  const _animateHideAddButton = () => {
    // secure the lock so another animation can't start
    setIsAnimating(true);
    setIsVisible(false);
    Animated.timing(translateY, {
      toValue: 100,
      duration: 300,
      useNativeDriver: true,
    // release the lock on completion
    }).start(() => setIsAnimating(false));
  };
}
于 2021-06-15T20:16:39.857 回答