[山东大学软件学院项目实训个人博客21]React Native 按钮动态效果实现

按压变色效果实现

1. 使用 TouchableOpacity 基础实现

<TouchableOpacity
  activeOpacity={0.7} // 按压时透明度变化
  style={styles.button}
  onPress={() => console.log('Pressed')}
>
  <Text style={styles.buttonText}>点击按钮</Text>
</TouchableOpacity>

2. 高级按压变色效果(使用 useState 和 Animated)

import React, { useState } from 'react';
import { Animated, TouchableWithoutFeedback, Text } from 'react-native';

const ColorChangingButton = () => {
  const [bgColor] = useState(new Animated.Value(0));
  
  const handlePressIn = () => {
    Animated.timing(bgColor, {
      toValue: 1,
      duration: 150,
      useNativeDriver: false
    }).start();
  };
  
  const handlePressOut = () => {
    Animated.timing(bgColor, {
      toValue: 0,
      duration: 250,
      useNativeDriver: false
    }).start();
  };
  
  const colorInterpolation = bgColor.interpolate({
    inputRange: [0, 1],
    outputRange: ['#4CAF50', '#388E3C'] // 从浅绿到深绿
  });
  
  return (
    <TouchableWithoutFeedback
      onPressIn={handlePressIn}
      onPressOut={handlePressOut}
    >
      <Animated.View style={[styles.button, { backgroundColor: colorInterpolation }]}>
        <Text style={styles.buttonText}>动态变色按钮</Text>
      </Animated.View>
    </TouchableWithoutFeedback>
  );
};

带特殊图标的按钮实现

1. 基础图标按钮

import { Ionicons } from '@expo/vector-icons';

<TouchableOpacity style={styles.iconButton}>
  <Ionicons name="ios-heart" size={24} color="red" />
  <Text style={styles.iconButtonText}>收藏</Text>
</TouchableOpacity>

2. 动态图标变化效果

import React, { useState } from 'react';
import { FontAwesome } from '@expo/vector-icons';

const LikeButton = () => {
  const [liked, setLiked] = useState(false);
  
  return (
    <TouchableOpacity 
      style={styles.likeButton}
      onPress={() => setLiked(!liked)}
    >
      <FontAwesome 
        name={liked ? "heart" : "heart-o"} 
        size={24} 
        color={liked ? "red" : "#333"} 
      />
      <Text style={styles.likeButtonText}>
        {liked ? '已点赞' : '点赞'}
      </Text>
    </TouchableOpacity>
  );
};

组合效果 - 按压变色+图标动画

import React, { useState } from 'react';
import { Animated, TouchableWithoutFeedback, Text, View } from 'react-native';
import { MaterialIcons } from '@expo/vector-icons';

const AnimatedIconButton = () => {
  const [scaleValue] = useState(new Animated.Value(1));
  const [iconColor] = useState(new Animated.Value(0));
  
  const handlePressIn = () => {
    Animated.parallel([
      Animated.spring(scaleValue, {
        toValue: 0.95,
        useNativeDriver: true
      }),
      Animated.timing(iconColor, {
        toValue: 1,
        duration: 150,
        useNativeDriver: false
      })
    ]).start();
  };
  
  const handlePressOut = () => {
    Animated.parallel([
      Animated.spring(scaleValue, {
        toValue: 1,
        friction: 3,
        tension: 40,
        useNativeDriver: true
      }),
      Animated.timing(iconColor, {
        toValue: 0,
        duration: 250,
        useNativeDriver: false
      })
    ]).start();
  };
  
  const colorInterpolation = iconColor.interpolate({
    inputRange: [0, 1],
    outputRange: ['#555', '#FF4081']
  });
  
  return (
    <TouchableWithoutFeedback
      onPressIn={handlePressIn}
      onPressOut={handlePressOut}
    >
      <Animated.View style={[
        styles.animatedButton,
        { transform: [{ scale: scaleValue }] }
      ]}>
        <Animated.View style={{ color: colorInterpolation }}>
          <MaterialIcons name="favorite" size={28} color={colorInterpolation} />
        </Animated.View>
        <Text style={styles.animatedButtonText}>喜欢</Text>
      </Animated.View>
    </TouchableWithoutFeedback>
  );
};

样式定义

const styles = StyleSheet.create({
  button: {
    padding: 15,
    borderRadius: 8,
    alignItems: 'center',
    justifyContent: 'center',
    backgroundColor: '#4CAF50',
    margin: 10,
  },
  buttonText: {
    color: 'white',
    fontSize: 16,
    fontWeight: 'bold',
  },
  iconButton: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 12,
    borderRadius: 6,
    backgroundColor: '#F5F5F5',
    margin: 10,
  },
  iconButtonText: {
    marginLeft: 8,
    fontSize: 16,
    color: '#333',
  },
  likeButton: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 10,
    borderRadius: 20,
    borderWidth: 1,
    borderColor: '#DDD',
    margin: 10,
  },
  likeButtonText: {
    marginLeft: 6,
    fontSize: 14,
  },
  animatedButton: {
    flexDirection: 'row',
    alignItems: 'center',
    padding: 12,
    borderRadius: 24,
    backgroundColor: 'white',
    margin: 10,
    shadowColor: '#000',
    shadowOffset: { width: 0, height: 2 },
    shadowOpacity: 0.1,
    shadowRadius: 4,
    elevation: 2,
  },
  animatedButtonText: {
    marginLeft: 8,
    fontSize: 16,
    color: '#555',
  },
});

技术要点总结

  1. 按压效果

    • 使用 TouchableOpacityactiveOpacity 属性实现简单效果
    • 使用 Animated API 实现更复杂的颜色和尺寸变化
  2. 图标集成

    • 使用 @expo/vector-icons 或其他图标库
    • 根据按钮状态动态改变图标
  3. 组合动画

    • 使用 Animated.parallel 同时运行多个动画
    • 结合缩放、颜色变化和透明度效果
  4. 性能优化

    • 尽可能使用 useNativeDriver: true
    • 避免在动画中使用复杂的布局计算
  5. 交互反馈

    • 提供清晰的视觉反馈增强用户体验
    • 保持动画快速流畅(通常在200-300ms之间)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值