设置消息输入

大约 9 分钟

设置消息输入

本文介绍如何通过消息输入组件 MessageInput 实现消息输入的自定义设置,包括发送文本、表情、文件、图片、语音等功能。

概述

MessageInput 组件用于发送文本、表情、文件、图片、语音等消息,是聊天界面的核心交互区域。你可以自定义发送菜单、扩展功能菜单,并添加自定义消息类型的发送入口。该组件通常与 MessageList 组件配合使用,构成完整的聊天界面。

MessageInput 通常作为 ConversationDetail 的内置组件使用,无需单独引入。通过 input 属性可对其进行配置和定制:

import { ConversationDetail, MessageInput } from 'react-native-chat-uikit';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  return (
    <ConversationDetail
      type="chat"
      convId={convId}
      convType={convType}
      input={{
        props: {
          // 传递给 MessageInput 的属性
          numberOfLines: 4,
          closeAfterSend: true,
          onChangeValue: (text) => {
            console.log('输入内容变化:', text);
          },
          onClickedSend: (value) => {
            console.log('发送消息:', value);
          },
        },
        // render: MessageInput, // 可选:使用自定义的 MessageInput 组件
        ref: messageInputRef, // 获取 MessageInput 的控制器
      }}
      onBack={() => navigation.goBack()}
    />
  );
}

MessageInput 组件的属性如下表所示:

属性类型是否必需描述
typeConversationDetailModelType消息输入组件的类型。
- chat:普通聊天页面。
- create_thread:创建话题页面。
- thread:话题聊天页面。
- search:搜索消息页面。
convIdstring会话 ID。
convTypeChatConversationType会话类型。
numberOfLinesnumber输入框的最大行数。默认为 4 行。详见 设置输入行数
topnumber键盘避让的顶部偏移量。
bottomnumber键盘避让的底部偏移量。
onClickedSend(value) => void点击发送按钮的回调。参数为发送的消息内容(文本、文件、图片、视频、语音或名片)。详见 处理发送事件
closeAfterSendboolean发送消息后是否关闭扩展菜单和表情面板。默认为 false
onHeightChange(height: number) => void输入组件高度变化时的回调。
onEditMessageFinished(model: MessageModel) => void编辑消息完成时的回调。
onInputMention(groupId: string) => void点击 @ 提及功能时的回调(群聊中)。
onClickedCardMenu() => void点击名片菜单时的回调。
onInitMenu(initItems) => InitMenuItemsType[]初始化扩展菜单时的回调,可以添加、修改或删除菜单项。详见自定义扩展菜单
emojiListstring[]自定义表情列表。
onChangeValue(text: string) => void输入内容变化时的回调。详见监听输入变化
selectTypeConversationSelectModeType消息选择模式。
- common(默认):普通模式。
- multi:多选模式。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。
multiSelectCountnumber多选模式下已选消息的数量。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。
onClickedMultiSelectDeleteButton() => void多选模式下点击删除按钮的回调。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。
onClickedMultiSelectShareButton() => void多选模式下点击分享按钮的回调。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。
unreadCountnumber未读消息数量。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。
onClickedUnreadCount() => void点击未读消息数量按钮的回调。
注意: 此属性主要用于内部组件之间通信,一般用户无需关注。

设置输入行数

通过 numberOfLines 属性控制输入框的最大行数,超过后自动出现滚动条:

<ConversationDetail
  type="chat"
  convId={convId}
  convType={convType}
  input={{
    props: {
      numberOfLines: 6, // 最多显示 6 行,默认为 4 行
    },
  }}
  onBack={() => navigation.goBack()}
/>

监听输入变化

通过 onChangeValue 回调监听输入内容的变化:

<ConversationDetail
  type="chat"
  convId={convId}
  convType={convType}
  input={{
    props: {
      onChangeValue: (text) => {
        console.log('当前输入内容:', text);

        // 可实现的功能:
        // 例如:显示正在输入状态、触发 @ 提及列表等
      },
    },
  }}
  onBack={() => navigation.goBack()}
/>

设置消息扩展菜单

消息扩展菜单提供发送附件类型消息(如图片、视频、文件)、位置消息以及自定义消息的快捷入口。点击文本输入框旁的 "+" 按钮即可展开。

设置菜单风格

风格描述
底部弹出菜单bottom-sheet默认风格。点击“+”号后,菜单从屏幕底部向上弹出,占用较大显示空间,适合展示较多功能项。
微信风格extension微信风格,通过布局组件实现。菜单在输入框上方直接展开,与输入区域融为一体,操作更加连贯。
  • 底部弹出菜单
import { UIKitContainer } from 'react-native-chat-uikit';

<UIKitContainer
  options={chatOptions}
  messageInputBarStyle="bottom-sheet"  // 底部弹出菜单(默认)
>
  {/* 你的应用内容 */}
</UIKitContainer>
  • 微信风格
import { UIKitContainer } from 'react-native-chat-uikit';

<UIKitContainer
  options={chatOptions}
  messageInputBarStyle="extension"  // 扩展面板样式:类似微信风格
>
  {/* 你的应用内容 */}
</UIKitContainer>

提示

messageInputBarStyle 是一个 全局配置,会影响应用中所有聊天页面的扩展菜单样式。为了保持用户体验一致性,建议在整个应用中统一使用同一种菜单风格,避免在不同页面之间切换造成用户困惑。

管理菜单项

通过 onInitMenu 回调添加、修改或删除菜单项:

<ConversationDetail
  type="chat"
  convId={convId}
  convType={convType}
  input={{
    props: {
      onInitMenu: (initItems) => {
        // initItems 是默认的菜单项列表
        console.log('默认菜单项:', initItems);

        // 1. 添加自定义菜单项
        const customItem = {
          name: 'custom',      // 菜单项名称
          isHigh: false,       // 是否高亮显示(通常用于警告操作)
          icon: 'star_fill',   // 菜单项图标
          onClicked: () => {
            console.log('点击自定义菜单项');
            // 实现自定义功能
          },
        };

        // 2. 修改现有菜单项
        const modifiedItems = initItems.map((item) => {
          if (item.name === 'Photo') {
            // 修改图片菜单项的图标
            return { ...item, icon: 'img' };
          }
          return item;
        });

        // 3. 删除特定菜单项
        const filteredItems = modifiedItems.filter(
          (item) => item.name !== 'File' // 删除文件选择菜单
        );

        // 返回新的菜单项列表
        return [...filteredItems, customItem];
      },
    },
  }}
  onBack={() => navigation.goBack()}
/>

菜单项类型定义

InitMenuItemsType 定义了扩展菜单项的数据结构,每个菜单项包含以下属性:

type InitMenuItemsType = {
  name: string; // 菜单项显示的文本
  isHigh: boolean; // 是否高亮显示(true 为警告样式)
  icon?: IconNameType; // 菜单项图标名称
  onClicked?: (name: string, others?: any) => void; // 点击回调
};

修改菜单图标

关于修改菜单项的图标,详见 自定义图标文档

处理发送事件

通过 onClickedSend 回调可以拦截或扩展消息发送逻辑:

<ConversationDetail
  type="chat"
  convId={convId}
  convType={convType}
  input={{
    props: {
      onClickedSend: (value) => {
        console.log('发送消息类型:', value.type);

        // 根据消息类型进行不同处理
        switch (value.type) {
          case 'text':
            const textValue = value as SendTextProps;
            console.log('文本内容:', textValue.content);
            break;
          case 'image':
            const imageValue = value as SendImageProps;
            console.log('图片路径:', imageValue.localPath);
            console.log('图片尺寸:', imageValue.imageWidth, imageValue.imageHeight);
            break;
          case 'video':
            const videoValue = value as SendVideoProps;
            console.log('视频路径:', videoValue.localPath);
            console.log('缩略图路径:', videoValue.thumbLocalPath);
            break;
          case 'voice':
            const voiceValue = value as SendVoiceProps;
            console.log('语音路径:', voiceValue.localPath);
            console.log('语音时长:', voiceValue.duration);
            break;
          case 'file':
            const fileValue = value as SendFileProps;
            console.log('文件路径:', fileValue.localPath);
            console.log('文件名:', fileValue.displayName);
            break;
          case 'card':
            const cardValue = value as SendCardProps;
            console.log('名片用户ID:', cardValue.userId);
            break;
        }

        // 如果需要自定义发送逻辑,可以在这里实现
        // 默认情况下,组件会自动处理消息发送
      },
    },
  }}
  onBack={() => navigation.goBack()}
/>

使用控制器

通过获取 MessageInputRef 引用,使用控制器方法实现更多高级功能。

关闭输入框

通过控制器的 close 方法可以关闭输入框(收起键盘、表情面板和扩展菜单):

import React, { useRef } from 'react';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  const handleCloseInput = () => {
    messageInputRef.current?.close();
  };

  return (
    <>
      <ConversationDetail
        type="chat"
        convId={convId}
        convType={convType}
        input={{
          ref: messageInputRef,
        }}
        onBack={() => navigation.goBack()}
      />
      <Button title="关闭输入框" onPress={handleCloseInput} />
    </>
  );
}

引用消息

通过控制器的 quoteMessage 方法可以引用(回复)消息,被引用的消息会显示在输入框上方,便于用户针对特定消息进行回复。

import React, { useRef } from 'react';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  const handleQuoteMessage = (messageModel: MessageModel) => {
    messageInputRef.current?.quoteMessage(messageModel);
  };

  return (
    <ConversationDetail
      type="chat"
      convId={convId}
      convType={convType}
      input={{
        ref: messageInputRef,
      }}
      list={{
        props: {
          onClickedItem: (id, model) => {
            if (model.modelType === 'message') {
              // 点击消息时引用该消息
              handleQuoteMessage(model as MessageModel);
              return false; // 阻止默认行为
            }
          },
        },
      }}
      onBack={() => navigation.goBack()}
    />
  );
}

编辑消息

通过控制器的 editMessage 方法可以实现消息编辑功能,允许用户修改已发送的消息内容。编辑完成后,消息会重新发送,并在列表中更新显示。

import React, { useRef } from 'react';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  const handleEditMessage = (messageModel: MessageModel) => {
    messageInputRef.current?.editMessage(messageModel);
  };

  return (
    <ConversationDetail
      type="chat"
      convId={convId}
      convType={convType}
      input={{
        ref: messageInputRef,
      }}
      onBack={() => navigation.goBack()}
    />
  );
}

显示/隐藏多选模式

通过控制器的 showMultiSelecthideMultiSelect 方法可以开启或关闭消息多选模式。多选模式允许用户批量选择多条消息进行统一操作,如批量删除或批量转发。

import React, { useRef } from 'react';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  const handleShowMultiSelect = () => {
    messageInputRef.current?.showMultiSelect();
  };

  const handleHideMultiSelect = () => {
    messageInputRef.current?.hideMultiSelect();
  };

  return (
    <>
      <ConversationDetail
        type="chat"
        convId={convId}
        convType={convType}
        input={{
          ref: messageInputRef,
        }}
        onBack={() => navigation.goBack()}
      />
      <View style={{ flexDirection: 'row' }}>
        <Button title="显示多选" onPress={handleShowMultiSelect} />
        <Button title="隐藏多选" onPress={handleHideMultiSelect} />
      </View>
    </>
  );
}

显示/隐藏遮罩层

通过控制器的 showMaskhideMask 方法可以控制输入区域遮罩层的显示与隐藏。遮罩层用于临时禁用输入框的交互,防止用户在特定状态下输入消息。

import React, { useRef } from 'react';
import type { MessageInputRef } from 'react-native-chat-uikit';

function ChatScreen({ route }) {
  const { convId, convType } = route.params;
  const messageInputRef = useRef<MessageInputRef>(null);

  const handleShowMask = () => {
    messageInputRef.current?.showMask();
  };

  const handleHideMask = () => {
    messageInputRef.current?.hideMask();
  };

  return (
    <ConversationDetail
      type="chat"
      convId={convId}
      convType={convType}
      input={{
        ref: messageInputRef,
      }}
      onBack={() => navigation.goBack()}
    />
  );
}

控制器方法

MessageInputRef 提供以下控制器方法:

方法名参数返回值描述
closevoid关闭输入框(收起键盘、表情面板和扩展菜单)。
quoteMessagemodel: MessageModelvoid引用(回复)指定消息。输入框上方会显示被引用的消息内容。
editMessagemodel: MessageModelvoid编辑指定消息。弹出编辑 UI 供用户修改消息内容。
showMultiSelectvoid显示多选模式。输入组件会显示删除和分享按钮。
hideMultiSelectvoid隐藏多选模式。恢复正常的输入框。
showMaskvoid显示遮罩层。通常用于置顶消息显示时,防止用户操作输入框。
hideMaskvoid隐藏遮罩层。恢复输入框的正常交互。

自定义事件监听

关于自定义消息输入区的事件监听,详见 自定义数据模型文档

自定义图标和文案

上次编辑于: