React Native聊天应用自定义音频气泡实现方法咨询(View尝试未果)
React Native 自定义音频消息气泡实现方案
下面是针对你需求的具体实现步骤和代码,完全匹配你提供的参考样式:
1. 依赖准备
首先安装需要的第三方库:
npm install react-native-linear-gradient # iOS 额外执行 cd ios && pod install && cd ..
这个库用来实现气泡的渐变背景,如果你不需要渐变,也可以直接用普通View的backgroundColor替代。
2. 完整组件代码
import React, { useState, useRef, useEffect } from 'react'; import { View, Text, TouchableOpacity, Animated, StyleSheet } from 'react-native'; import LinearGradient from 'react-native-linear-gradient'; const AudioMessageBubble = ({ isMe, duration, onPressPlay, isPlaying }) => { // 波形动画控制 const bar1Anim = useRef(new Animated.Value(1)).current; const bar2Anim = useRef(new Animated.Value(0.6)).current; const bar3Anim = useRef(new Animated.Value(0.8)).current; useEffect(() => { if (isPlaying) { // 播放时循环动画 const animateWave = () => { Animated.sequence([ Animated.parallel([ Animated.timing(bar1Anim, { toValue: 0.6, duration: 300, useNativeDriver: false }), Animated.timing(bar2Anim, { toValue: 1, duration: 300, useNativeDriver: false }), Animated.timing(bar3Anim, { toValue: 0.6, duration: 300, useNativeDriver: false }), ]), Animated.parallel([ Animated.timing(bar1Anim, { toValue: 0.8, duration: 300, useNativeDriver: false }), Animated.timing(bar2Anim, { toValue: 0.6, duration: 300, useNativeDriver: false }), Animated.timing(bar3Anim, { toValue: 1, duration: 300, useNativeDriver: false }), ]), ]).start(() => animateWave()); }; animateWave(); } else { // 暂停时重置波形 Animated.parallel([ Animated.timing(bar1Anim, { toValue: 1, duration: 200, useNativeDriver: false }), Animated.timing(bar2Anim, { toValue: 0.6, duration: 200, useNativeDriver: false }), Animated.timing(bar3Anim, { toValue: 0.8, duration: 200, useNativeDriver: false }), ]).start(); } }, [isPlaying]); return ( <View style={[styles.container, isMe ? styles.myMsgWrapper : styles.otherMsgWrapper]}> {/* 气泡主体 */} <LinearGradient colors={isMe ? ['#6366F1', '#8B5CF6'] : ['#E5E7EB', '#D1D5DB']} style={[styles.bubble, isMe ? styles.myBubble : styles.otherBubble]} > <TouchableOpacity onPress={onPressPlay} style={styles.playBtn}> <Text style={styles.playIcon}>{isPlaying ? '⏸' : '▶'}</Text> </TouchableOpacity> {/* 动态波形 */} <View style={styles.waveContainer}> <Animated.View style={[styles.waveBar, { transform: [{ scaleY: bar1Anim }] }]} /> <Animated.View style={[styles.waveBar, { transform: [{ scaleY: bar2Anim }] }]} /> <Animated.View style={[styles.waveBar, { transform: [{ scaleY: bar3Anim }] }]} /> </View> {/* 时长文本 */} <Text style={[styles.durationTxt, isMe ? styles.myTxt : styles.otherTxt]}> {duration}'' </Text> </LinearGradient> {/* 气泡三角箭头 */} <View style={[styles.triangle, isMe ? styles.myTriangle : styles.otherTriangle]} /> </View> ); }; const styles = StyleSheet.create({ container: { flexDirection: 'row', marginVertical: 8, marginHorizontal: 12, alignItems: 'center', }, myMsgWrapper: { justifyContent: 'flex-end', }, otherMsgWrapper: { justifyContent: 'flex-start', }, bubble: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, paddingHorizontal: 16, borderRadius: 20, minWidth: 120, }, myBubble: { borderTopRightRadius: 8, // 自己发的气泡右上角改成小圆角 }, otherBubble: { borderTopLeftRadius: 8, // 对方发的气泡左上角改成小圆角 }, playBtn: { marginRight: 12, }, playIcon: { fontSize: 20, color: '#fff', }, waveContainer: { flexDirection: 'row', alignItems: 'flex-end', height: 24, flex: 1, justifyContent: 'center', marginRight: 12, }, waveBar: { width: 4, backgroundColor: '#fff', marginHorizontal: 2, borderRadius: 2, }, durationTxt: { fontSize: 14, }, myTxt: { color: '#fff', }, otherTxt: { color: '#374151', }, triangle: { width: 0, height: 0, position: 'absolute', top: 10, }, myTriangle: { right: -8, borderTopWidth: 8, borderLeftWidth: 8, borderBottomWidth: 8, borderLeftColor: '#6366F1', borderTopColor: 'transparent', borderBottomColor: 'transparent', }, otherTriangle: { left: -8, borderTopWidth: 8, borderRightWidth: 8, borderBottomWidth: 8, borderRightColor: '#E5E7EB', borderTopColor: 'transparent', borderBottomColor: 'transparent', }, }); export default AudioMessageBubble;
3. 使用方式
在聊天列表中直接引入组件,根据消息发送者传入对应参数:
// 自己发送的音频消息 <AudioMessageBubble isMe={true} duration={15} onPressPlay={() => { /* 播放音频的逻辑 */ }} isPlaying={false} /> // 对方发送的音频消息 <AudioMessageBubble isMe={false} duration={22} onPressPlay={() => { /* 播放音频的逻辑 */ }} isPlaying={false} />
4. 自定义调整建议
- 颜色调整:修改
LinearGradient的colors数组,替换成你需要的渐变配色;三角箭头的颜色要和渐变边缘色保持一致。 - 波形优化:如果需要更细腻的波形,可以用
react-native-svg绘制SVG波形,结合Animated实现更复杂的动画效果。 - 图标替换:把示例中的文本图标(▶/⏸)换成你项目中的图标组件(比如react-native-vector-icons)。
内容的提问来源于stack exchange,提问作者Riaz Yousaf
相关产品推荐
相关产品推荐

