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

如何在Android端用JavaScript+Cordova检测单词语本选中操作

检测Android Cordova中单词文本选中的完成事件

问题背景

我需要在Android端用Cordova和JavaScript检测用户完成文本选中的操作。目前已有检测多词选中的方案(见下方parthibeyond提供的代码),但无法检测单词选中的情况。

长按单词发起选中时,事件触发顺序为:

  1. selectstart
  2. contextmenu
  3. selectionchange
  4. touchcancel

此时用户有两种操作:要么抬起手指仅选中初始单词,要么移动手指选中更多单词。我需要检测第一种仅选中单个单词的情况。

touchcancel会阻止touchend事件触发,定时器方案也不可行——因为用户可能在移动手指选多词前长时间按住屏幕。系统会在选中文本两端添加“抓取手柄”来提示手指已离开、选中结束(单词和多词选中均是如此),但目前找不到在JavaScript中捕获这个状态的方法。我试过的临时方案是在touchstart事件中调用event.preventDefault(),但这会移除所有文本选中和滚动功能,不符合需求。

原多词选中结束事件代码,感谢parthibeyond

function customisedSelectListener(el = document, callbackFn) {
  // events to be listened - 'selectstart', 'selectionchange', 'contextmenu'
  let eventSequence = [];

  el.addEventListener('selectstart', function() {
    eventSequence = [];
    eventSequence.unshift(event.type);
  })

  el.addEventListener('selectionchange', function() {
    if (eventSequence[0] != 'selectionchange') {
      eventSequence.unshift(event.type);
    }
  })

  el.addEventListener('contextmenu', function() {
    eventSequence.unshift(event.type);
    if (eventSequence[1] == 'selectionchange') {
      callbackFn.call();
    }
  })
}

使用示例:

customisedSelectListener(document, function (){
  alert('Text Selection Completed !!');
})

解决方案:结合选中范围与事件序列检测单词选中完成

核心思路是通过跟踪选中状态、记录初始选中范围,在touchcancel或contextmenu事件触发时校验当前选中内容是否未发生变化且为单个单词,以此判断用户完成了单词语句选中。

实现代码

function detectSingleWordSelection(el = document, callbackFn) {
  let isSelecting = false;
  let initialSelectionRange = null;

  el.addEventListener('selectstart', () => {
    isSelecting = true;
    initialSelectionRange = null;
  });

  el.addEventListener('selectionchange', () => {
    if (!isSelecting) return;
    const selection = window.getSelection();
    if (selection.rangeCount === 1) {
      const range = selection.getRangeAt(0);
      // 记录首次选中的范围(单个单词的初始状态)
      if (!initialSelectionRange) {
        initialSelectionRange = {
          startContainer: range.startContainer,
          startOffset: range.startOffset,
          endContainer: range.endContainer,
          endOffset: range.endOffset
        };
      } else {
        // 选中范围变化,说明用户在选多词,重置标记
        initialSelectionRange = null;
      }
    }
  });

  el.addEventListener('touchcancel', () => {
    if (!isSelecting || !initialSelectionRange) return;
    const selection = window.getSelection();
    // 校验当前选中范围是否和初始一致
    if (selection.rangeCount === 1) {
      const currentRange = selection.getRangeAt(0);
      const isRangeUnchanged = 
        currentRange.startContainer === initialSelectionRange.startContainer &&
        currentRange.startOffset === initialSelectionRange.startOffset &&
        currentRange.endContainer === initialSelectionRange.endContainer &&
        currentRange.endOffset === initialSelectionRange.endOffset;
      
      if (isRangeUnchanged) {
        const selectedText = selection.toString().trim();
        // 验证选中内容为单个单词(可根据需求调整正则规则)
        if (/^\w+$/.test(selectedText)) {
          callbackFn.call(null, selectedText);
        }
      }
    }
    // 重置选中状态
    isSelecting = false;
    initialSelectionRange = null;
  });

  // 兼容上下文菜单触发的场景
  el.addEventListener('contextmenu', (e) => {
    e.preventDefault(); // 阻止默认菜单,避免干扰选中判断
    if (isSelecting && initialSelectionRange) {
      const selection = window.getSelection();
      const selectedText = selection.toString().trim();
      if (/^\w+$/.test(selectedText)) {
        callbackFn.call(null, selectedText);
      }
    }
    isSelecting = false;
    initialSelectionRange = null;
  });
}

使用示例

detectSingleWordSelection(document, (selectedWord) => {
  alert(`单个单词选中完成:${selectedWord}`);
});

关键说明

  1. 状态跟踪:用isSelecting标记是否处于文本选中状态,initialSelectionRange记录首次选中的范围,若选中范围变化则重置标记,排除多词选中的情况。
  2. 事件校验:在touchcancel(手指离开触发)和contextmenu(长按弹出菜单触发)事件中,对比当前选中范围与初始范围,确认未发生变化,再通过正则验证选中内容为单个单词。
  3. 保留原生功能:未在touchstart中调用preventDefault(),保留了原生的文本选中、滚动等功能,避免影响用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 08:19:54