You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用React Native FlatList实现带日期分隔的WhatsApp风格聊天UI

实现React Native FlatList消息中插入日期分隔(仿WhatsApp)

核心思路

先把原始消息数组转换成包含日期分隔项的混合数组,再让FlatList根据项的类型分别渲染日期或消息内容。


步骤1:处理原始消息数据

写一个工具函数,遍历消息数组,对比当前消息和上一条消息的日期,若日期不同则插入日期分隔项。这里用原生Intl.DateTimeFormat格式化日期,无需额外依赖:

// 格式化时间戳为日期字符串(仅年月日部分)
const formatDate = (timestamp) => {
  return new Intl.DateTimeFormat('zh-CN', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }).format(new Date(timestamp));
};

// 处理消息数组,插入日期分隔项
const processMessagesWithDates = (messages) => {
  if (!messages.length) return [];
  
  const processed = [];
  let lastDate = null;

  messages.forEach((msg) => {
    const currentDate = formatDate(msg.timestamp);
    // 如果当前消息日期和上一条不同,插入日期项
    if (currentDate !== lastDate) {
      processed.push({
        type: 'date',
        content: currentDate
      });
      lastDate = currentDate;
    }
    // 加入原始消息,标记类型为message
    processed.push({
      type: 'message',
      content: msg
    });
  });

  return processed;
};

步骤2:用FlatList渲染混合数组

在组件中调用处理函数,让FlatList根据item的类型渲染不同内容:

import { View, Text, FlatList, StyleSheet } from 'react-native';

const ChatScreen = ({ messages }) => {
  const processedData = processMessagesWithDates(messages);

  const renderItem = ({ item }) => {
    if (item.type === 'date') {
      // 渲染日期分隔组件
      return (
        <View style={styles.dateContainer}>
          <Text style={styles.dateText}>{item.content}</Text>
        </View>
      );
    }
    // 渲染普通消息组件(替换成你自己的消息UI即可)
    const msg = item.content;
    return (
      <View style={msg.isMine ? styles.myMessage : styles.otherMessage}>
        <Text style={msg.isMine ? styles.myText : styles.otherText}>{msg.content}</Text>
        <Text style={styles.timeText}>
          {new Intl.DateTimeFormat('zh-CN', { hour: '2-digit', minute: '2-digit' }).format(new Date(msg.timestamp))}
        </Text>
      </View>
    );
  };

  return (
    <FlatList
      data={processedData}
      renderItem={renderItem}
      keyExtractor={(item, index) => index.toString()}
      contentContainerStyle={styles.listContainer}
      inverted={true} // 消息底部最新时开启反转
    />
  );
};

// 仿WhatsApp风格的样式参考
const styles = StyleSheet.create({
  listContainer: {
    paddingVertical: 10,
    paddingHorizontal: 15,
  },
  dateContainer: {
    alignItems: 'center',
    marginVertical: 12,
  },
  dateText: {
    backgroundColor: '#e9e9eb',
    color: '#666',
    paddingVertical: 4,
    paddingHorizontal: 12,
    borderRadius: 8,
    fontSize: 12,
  },
  myMessage: {
    alignSelf: 'flex-end',
    backgroundColor: '#dcf8c6',
    borderRadius: 18,
    padding: 10,
    marginVertical: 4,
    maxWidth: '75%',
  },
  otherMessage: {
    alignSelf: 'flex-start',
    backgroundColor: '#fff',
    borderRadius: 18,
    padding: 10,
    marginVertical: 4,
    maxWidth: '75%',
  },
  myText: {
    fontSize: 14,
    color: '#000',
  },
  otherText: {
    fontSize: 14,
    color: '#000',
  },
  timeText: {
    fontSize: 11,
    color: '#666',
    alignSelf: 'flex-end',
    marginTop: 4,
  },
});

注意事项

  • 如果消息是按时间倒序排列,开启inverted属性后,建议先反转原始数组处理日期,再反转回倒序,避免日期判断逻辑出错。
  • 若要更精准判断跨天边界,可以把时间戳转换为当天0点的时间戳来对比,避免时分秒差异导致的误判。
  • 样式可根据自身UI需求调整,核心是保证日期项居中显示的布局逻辑。

内容的提问来源于stack exchange,提问作者React_Coder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 18:05:27