TextView 分词点击弹窗

问题

接到一个需求,需要点击一个textview 中具体的某一个单词,取出这个单词,查询,然后将查询结果弹出。然后网上查了一下,零零碎碎,没有比较具体的解决方法。然后自己弄了一个

解决办法

主要分成两大块

a 分词 添加clickspan,根据需求使用正则表达式进行单词拆分,拆分完单词后对每一个单词添加clickspan

/**
 * 分词并且添加点击事件
 */
public void SplitWord() {
    Spannable spans = (Spannable) mTextView.getText();
    Matcher matcher = Pattern.compile(mRegular, Pattern.CASE_INSENSITIVE).matcher(spans);
    while (matcher.find()) {
        ClickableSpan clickSpan = clickableSpan();
        spans.setSpan(clickSpan, matcher.start(0), matcher.end(0), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    }
}

/**
 * 创建点击事件
 */
private ClickableSpan clickableSpan() {
    return new ClickableSpan() {

        @Override
        public void onClick(@NonNull View widget) {
            try {
                TextView tv = (TextView) widget;
                String s = tv.getText().subSequence(tv.getSelectionStart(), tv.getSelectionEnd()).toString();
                setSelectedSpan((TextView) widget);
                Log.d("tapped on:", s);
                int[] array = new int[4];
                meaurePosition(this, widget, array);
                if (mWordClick != null) {
                    mWordClick.onWordClick(s, (TextView) widget, array[0], array[1], array[2], array[3], SplitTextViewHelper.this);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void updateDrawState(@NonNull TextPaint ds) {
            ds.setUnderlineText(false);
        }
    };
}

 

 

 

2 点击单词的定位问题

/**
 * 单词点击位置
 */
public void meaurePosition(ClickableSpan spanned, View widget, int[] array) {
    TextView parentTextView = (TextView) widget;
    Rect parentTextViewRect = new Rect();
    // Initialize values for the computing of clickedText position
    SpannableString completeText = (SpannableString) parentTextView.getText();
    Layout textViewLayout = parentTextView.getLayout();
    int startOffsetOfClickedText = completeText.getSpanStart(spanned);
    int endOffsetOfClickedText = completeText.getSpanEnd(spanned);
    float startXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(startOffsetOfClickedText);
    float endXCoordinatesOfClickedText = textViewLayout.getPrimaryHorizontal(endOffsetOfClickedText);
    // Get the rectangle of the clicked text
    int currentLineStartOffset = textViewLayout.getLineForOffset(startOffsetOfClickedText);
    int currentLineEndOffset = textViewLayout.getLineForOffset(endOffsetOfClickedText);
    boolean keywordIsInMultiLine = currentLineStartOffset != currentLineEndOffset;
    textViewLayout.getLineBounds(currentLineStartOffset, parentTextViewRect);
    // Update the rectangle position to his real position on screen
    int[] parentTextViewLocation = new int[2];
    parentTextView.getLocationOnScreen(parentTextViewLocation);
    int parentTextViewTopAndBottomOffset = (parentTextViewLocation[1] - parentTextView.getScrollY() + parentTextView.getCompoundPaddingTop());
    parentTextViewRect.top += parentTextViewTopAndBottomOffset;
    parentTextViewRect.bottom += parentTextViewTopAndBottomOffset;
    parentTextViewRect.left += (parentTextViewLocation[0] +
            startXCoordinatesOfClickedText +
            parentTextView.getCompoundPaddingLeft() - parentTextView.getScrollX());
    parentTextViewRect.right = (int) (parentTextViewRect.left + endXCoordinatesOfClickedText - startXCoordinatesOfClickedText);
    int x = parentTextViewRect.left;
    int y = parentTextViewRect.bottom;
    if (keywordIsInMultiLine) {
        x = parentTextViewRect.left;
    }
    array[0] = x;
    array[1] = y;
    array[2] = parentTextViewRect.width();
    array[3] = parentTextViewRect.height();
}

 

效果

通过对单词的点击取词和定位,就可以进行查词和弹窗位置的控制 如图

 

放个连接吧,希望可以帮助有需要的人:github https://github.com/wanghaibao123/SplitText

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值