问题
接到一个需求,需要点击一个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