【问题标题】:scaling a react-native button with animated用动画缩放反应原生按钮
【发布时间】:2020-05-20 08:11:52
【问题描述】:

我正在创建一个可触摸的按钮来响应原生动画。按下按钮时,它应该按比例缩小一点。当压力释放时,它应该会恢复正常。

这是我的代码:

export const TouchableButton = (props) => {

    const { onPress, text, icon } = props

    const animatedValue = new Animated.Value(0)

    const animatedValueInterpolateScale = animatedValue.interpolate({
        inputRange: [0, 1],
        outputRange: [1, 0.95]
    })

    const pressInHandler = () => {
        Animated.timing(
            animatedValue,
            {
                toValue: 1,
                duration: 150
            }
        ).start()
    }

    const pressOutHandler = () => {
        Animated.timing(
            animatedValue,
            {
                toValue: 0,
                duration: 150
            }
        ).start()
    }

return (
    <TouchableWithoutFeedback onPress={onPress} onPressIn={pressInHandler} onPressOut={pressOutHandler}>
        <View style={{ alignItems: 'center' }}>
            <Animated.View style={{ width: '100%', height: 40, borderRadius: 5, overflow: 'hidden', transform: [{ scaleX: animatedValueInterpolateScale }, { scaleY: animatedValueInterpolateScale }] }}>
                <View style={{ flex: 1, alignItems: 'center', justifyContent: 'center', backgroundColor: Color.GrayLight }}>
                    <Text style={{ marginTop: 2.5, fontFamily: 'AlegreyaSans-Medium', fontSize: 15, color: Color.White }}>{text}</Text>
                    <View style={{ position: 'absolute', left: 12.5, top: 12.5 }}>
                        <Icon lib={icon.lib} icon={icon.icon} color={Color.White} size={15} />
                    </View>
                </View>
            </Animated.View>
        </View>
    </TouchableWithoutFeedback>
)
}

当按钮被按下时,pressInHandler 中的动画被启动,并且缩放从 1 到 0.95 的动画。这行得通。但是当我释放压力(调用 onPressOut)时,比例会迅速回到 1,而没有平滑的动画。似乎 pressOutHandler(以及其中的动画)从未被调用过。

我有另一个具有相同属性的按钮,但我设置了背景颜色而不是缩放,这就像它应该的那样工作。

【问题讨论】:

  • 哦,是的,我明白了。也许它与我的模拟器有关。我正在IOS模拟器上进行测试。我将在真实设备上进行测试以检查。感谢您的意见!

标签: react-native react-animated


【解决方案1】:

让它变得简单。

注意:始终使用 useNativeDriver: true

const App = () => {
  const animation = new Animated.Value(0);
  const inputRange = [0, 1];
  const outputRange = [1, 0.8];
  const scale = animation.interpolate({inputRange, outputRange});

  const onPressIn = () => {
    Animated.spring(animation, {
      toValue: 1,
      useNativeDriver: true,
    }).start();
  };
  const onPressOut = () => {
    Animated.spring(animation, {
      toValue: 0,
      useNativeDriver: true,
    }).start();
  };

  return (
    <View style={styles.container}>
      <Animated.View style={[styles.button, {transform: [{scale}]}]}>
        <TouchableOpacity
          style={styles.btn}
          activeOpacity={1}
          onPressIn={onPressIn}
          onPressOut={onPressOut}>
          <Text style={styles.btnText}>BUTTON</Text>
        </TouchableOpacity>
      </Animated.View>
    </View>
  );
};

export default App;

const styles = StyleSheet.create({
  container: {flex: 1, alignItems: 'center', justifyContent: 'center'},
  button: {
    height: 70,
    width: 200,
    backgroundColor: 'red',
    marginBottom: 20,
    borderRadius: 10,
  },
  btn: {
    flex: 1,
    alignItems: 'center',
    justifyContent: 'center',
  },
  btnText: {
    color: '#fff',
    fontSize: 25,
  },
});

【讨论】:

    【解决方案2】:

    这是一个非常简单的解决方案,没有任何动画,看起来几乎是原生的(至少在 iOS 上):

    import React from "react"
    import { Pressable, PressableProps, StyleProp, ViewStyle } from "react-native"
    
    type TouchableButtonProps = PressableProps & {
      scale?: number;
      style?: StyleProp<ViewStyle>;
    }
    
    const PressableScale: React.FC<TouchableButtonProps> = ({ scale, style, children, ...otherProps }) => {
      return (
        <Pressable style={({ pressed }) => [style, { transform: [{ scale: pressed ? (scale ?? 0.98) : 1 }] }]} {...otherProps}>
          {children}
        </Pressable>
      )
    }
    

    用法:

    <PressableScale style={{ flex: 1, justifyContent: 'center', alignContent: 'center', backgroundColor: 'black', padding: 50, borderRadius: 12 }}>
      <Text style={{ color: 'white' }}>This is pressable button</Text>
    </PressableScale>
    

    【讨论】:

      猜你喜欢
      • 2023-03-29
      • 2021-10-20
      • 2017-03-09
      • 2016-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-07
      • 2022-01-19
      相关资源
      最近更新 更多