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

在React Native中使用RenderHtml实现文本复制功能遇阻

解决React Native中RenderHtml文本长按无法复制的问题

问题根源

你当前代码的核心问题是外层包裹的TouchableOpacity拦截了文本的长按触摸事件,导致RenderHtml内部的文本无法触发原生文本选择菜单,自然无法完成复制操作。另外,RenderHtml本身提供了文本选择和自定义交互的配置,不需要通过外层TouchableOpacity来实现复制功能。

解决方案步骤

1. 移除外层TouchableOpacity

直接去掉包裹RenderHtml的TouchableOpacity,避免它拦截触摸事件,让文本能够响应长按选择。

2. 开启RenderHtml的文本选择功能

给RenderHtml添加enableSelectable={true}属性,开启原生文本选择支持。

3. 自定义复制交互(两种方式)

方式一:原生选择菜单+复制提示

开启文本选择后,原生会弹出包含“复制”的菜单,选择后通过copyToClipboard函数显示Toast提示。

方式二:监听选择变化自动复制

通过RenderHtml的onSelectionChange回调获取选中的文本内容,自动执行复制并显示提示,无需手动点击菜单。

4. 保留“点击复制全部文本”功能(可选)

如果需要保留点击整个邮件内容复制全部文本的功能,直接给RenderHtml添加onPress回调即可。

修改后的代码示例

import Clipboard from "@react-native-clipboard/clipboard";
import RenderHtml, {
  HTMLContentModel,
  HTMLElementModel,
} from 'react-native-render-html'
import { View } from 'react-native';

const copyToClipboard = (text) => {
  Clipboard.setString(text);
  Toast.show({
    type: "info",
    position: "bottom",
    text1: "Copied to clipboard",
    text2: "",
    visibilityTime: 3000,
    autoHide: true,
    topOffset: 30,
    bottomOffset: 40,
    onShow: () => {},
    onHide: () => {},
    onPress: () => {},
  });
};

const renderEmailBody = (emailItem) => {
  const regex = new RegExp("On .+ wrote:", "g");
  if (regex.test(emailItem.body)) {
    const editBody = emailItem.body.replace(/On .+ wrote:/g, (str) => {
      return str + "<p><extend-button>&#8226&#8226&#8226</extend-button></p>";
    });
    const editBodySplit = editBody.split(
      "<p><extend-button>&#8226&#8226&#8226</extend-button></p>"
    );
    const header =
      editBodySplit[0] +
      "<p><extend-button>&#8226&#8226&#8226</extend-button></p>";

    return (
      <View
        style={[
          Gutters.smallTMargin,
          Gutters.largeHPadding,
          { paddingBottom: wp(1) },
        ]}
      >
        {emailItem?.body ? (
          <>
            {!!editBodySplit[0] && (
              <RenderHtml
                contentWidth={width}
                source={{ html: header }}
                enableCSSInlineProcessing={false}
                enableExperimentalBRCollapsing={true}
                enableExperimentalGhostLinesPrevention={true}
                enableExperimentalMarginCollapsing={true}
                customHTMLElementModels={customHTMLElementModels}
                // 开启文本选择
                enableSelectable={true}
                // 监听文本选择变化,自动复制选中内容
                onSelectionChange={(selection) => {
                  if (selection.type === 'selected' && selection.text) {
                    copyToClipboard(selection.text);
                  }
                }}
                renderersProps={{
                  a: {
                    onPress: (event, href) => {
                      navigate("WebView", href);
                    },
                  },
                }}
                // 点击复制全部文本(可选)
                onPress={() => copyToClipboard(emailItem?.body)}
              />
            )}
            {showBodyMess && !!editBodySplit[1] && (
              <RenderHtml
                contentWidth={width}
                source={{ html: editBodySplit[1] }}
                enableCSSInlineProcessing={false}
                enableExperimentalBRCollapsing={true}
                enableExperimentalGhostLinesPrevention={true}
                enableExperimentalMarginCollapsing={true}
                customHTMLElementModels={customHTMLElementModels}
                enableSelectable={true}
                onSelectionChange={(selection) => {
                  if (selection.type === 'selected' && selection.text) {
                    copyToClipboard(selection.text);
                  }
                }}
                renderersProps={{
                  a: {
                    onPress: (event, href) => {
                      navigate("WebView", href);
                    },
                  },
                }}
                onPress={() => copyToClipboard(emailItem?.body)}
              />
            )}
          </>
        ) : null}
      </View>
    );
  }
  return (
    <View
      style={[
        Gutters.smallTMargin,
        Gutters.largeHPadding,
        { paddingBottom: wp(1) },
      ]}
    >
      {emailItem?.body ? (
        <RenderHtml
          contentWidth={width}
          source={{ html: emailItem?.body }}
          enableCSSInlineProcessing={false}
          enableExperimentalBRCollapsing={true}
          enableExperimentalGhostLinesPrevention={true}
          enableExperimentalMarginCollapsing={true}
          customHTMLElementModels={customHTMLElementModels}
          enableSelectable={true}
          onSelectionChange={(selection) => {
            if (selection.type === 'selected' && selection.text) {
              copyToClipboard(selection.text);
            }
          }}
          renderersProps={{
            a: {
              onPress: (event, href) => {
                navigate("WebView", href);
              },
            },
          }}
          onPress={() => copyToClipboard(emailItem?.body)}
        />
      ) : null}
    </View>
  );
};

额外说明

如果需要完全自定义选择菜单样式(和示例图一致),可以结合第三方菜单组件(如react-native-menu),在onSelectionChange触发时弹出自定义菜单,点击菜单选项执行复制操作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:35:22