Android 处理带有可选文本的可点击范围的点击需要双击
我有一个Android 处理带有可选文本的可点击范围的点击需要双击,android,clickable,focusable,clickablespan,Android,Clickable,Focusable,Clickablespan,我有一个文本视图,其中每个单词都是可点击span。单击时,该单词将变为粗体,该单词的词典定义将显示在另一个文本视图中。在我将TextView中的文本设置为可选之前,该应用程序可以正常工作。当文本可选择时,定义在单击时显示,但单词在双击时仅为粗体。双击或长按可选择文本(但长按不会使单词加粗) 我的猜测是,问题与操作处理过程中的绘制状态更新有关,但我无法找到修复方法。我尝试设置TextViewfocusable=“false”,但没有任何更改。相关代码如下 curSpan = new WordSpa
文本视图
,其中每个单词都是可点击span
。单击时,该单词将变为粗体,该单词的词典定义将显示在另一个文本视图中。在我将TextView中的文本设置为可选之前,该应用程序可以正常工作。当文本可选择时,定义在单击时显示,但单词在双击时仅为粗体。双击或长按可选择文本(但长按不会使单词加粗)
我的猜测是,问题与操作处理过程中的绘制状态更新有关,但我无法找到修复方法。我尝试设置TextView
focusable=“false”
,但没有任何更改。相关代码如下
curSpan = new WordSpan(index) {
@Override
public void onClick(View view) {
handleWordClick(index,this); // handles code to display definition
setMarking(true);
view.invalidate();
tvText.invalidate();
}
};
spannableStringBuilder.setSpan(curSpan, totalLength, totalLength + strWord, Spanned.SPAN_COMPOSING);
以及单词范围定义:
class WordSpan extends ClickableSpan
{
int id;
private boolean marking = false;
public WordSpan(int id) {
this.id = id;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLACK);
ds.setUnderlineText(false);
if (marking) {
ds.setTypeface(Typeface.create(myFont,Typeface.BOLD));
}
}
@Override
public void onClick(View v) {}
public void setMarking(boolean m) {
marking = m;
}
}
设置TextView的移动方法:
private MovementMethod createMovementMethod ( Context context ) {
final GestureDetector detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp ( MotionEvent e ) {
return true;
}
@Override
public boolean onSingleTapConfirmed ( MotionEvent e ) {
return true;
}
});
return new ScrollingMovementMethod() {
@Override
public boolean canSelectArbitrarily () {
return true;
}
@Override
public void initialize(TextView widget, Spannable text) {
Selection.setSelection(text, text.length());
}
@Override
public void onTakeFocus(TextView view, Spannable text, int dir) {
if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
if (view.getLayout() == null) {
// This shouldn't be null, but do something sensible if it is.
Selection.setSelection(text, text.length());
}
} else {
Selection.setSelection(text, text.length());
}
}
@Override
public boolean onTouchEvent ( TextView widget, Spannable buffer, MotionEvent event ) {
// check if event is a single tab
boolean isClickEvent = detector.onTouchEvent(event);
// detect span that was clicked
if (isClickEvent) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
WordSpan[] link = buffer.getSpans(off, off, WordSpan.class);
if (link.length != 0) {
// execute click only for first clickable span
// can be a for each loop to execute every one
if (event.getAction() == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
}
}
// let scroll movement handle the touch
return super.onTouchEvent(widget, buffer, event);
}
};
}
编辑:
我刚刚发现了一个新的怪癖,可能有助于解决这个问题。如果我双击但在两次单击之间更改单词(点击一个单词,然后快速切换另一个单词),第一次点击时会显示该单词的定义,第二次点击时会显示第一个单词的粗体,但第二个单词会被选中(高亮显示),并且第一个单词的定义仍会显示
例如,如果我双击“first”和“second”,当我点击
“first”将显示“first”的定义,当我触摸时
“第二个”单词“第一个”是粗体,单词“第二个”是突出显示的
但是定义没有改变(仍然显示
“第一”)
将
createMovementMethod
替换为以下内容。如果您遇到错误,请修复它并编辑此答案
private MovementMethod createMovementMethod (final Context context ) {
return new ScrollingMovementMethod() {
public MotionEvent event;
public Spannable buffer;
public TextView widget;
final GestureDetector detector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp ( MotionEvent e ) {
return true;
}
@Override
public boolean onSingleTapConfirmed ( MotionEvent e ) {
triggerClick();
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
triggerClick();
return true;
}
private boolean triggerClick() {
int x = (int) event.getX();
int y = (int) event.getY();
x -= widget.getTotalPaddingLeft();
y -= widget.getTotalPaddingTop();
x += widget.getScrollX();
y += widget.getScrollY();
Layout layout = widget.getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
WordSpan[] link = buffer.getSpans(off, off, WordSpan.class);
if (link.length != 0) {
// execute click only for first clickable span
// can be a for each loop to execute every one
if (event.getAction() == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (event.getAction() == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
}
return true;
}
});
@Override
public boolean canSelectArbitrarily () {
return true;
}
@Override
public void initialize(TextView widget, Spannable text) {
Selection.setSelection(text, text.length());
}
@Override
public void onTakeFocus(TextView view, Spannable text, int dir) {
if ((dir & (View.FOCUS_FORWARD | View.FOCUS_DOWN)) != 0) {
if (view.getLayout() == null) {
// This shouldn't be null, but do something sensible if it is.
Selection.setSelection(text, text.length());
}
} else {
Selection.setSelection(text, text.length());
}
}
@Override
public boolean onTouchEvent (TextView widget, Spannable buffer, MotionEvent event ) {
// check if event is a single tab
boolean isClickEvent = detector.onTouchEvent(event);
//record this for GestureDetector
this.widget = widget;
this.buffer = buffer;
this.event = event;
// detect span that was clicked
if (isClickEvent) {
//ignore click here
return true;
}
// let scroll movement handle the touch
return super.onTouchEvent(widget, buffer, event);
}
};
}
嘿我理解这个问题对吗。如何处理文本视图上的双击,并使用不同的可点击文本的可点击字符串?它应该是一次单击而不是双击。当用户单击一个单词时,它应该加粗该单词并显示其定义。双击不应该做任何事情。感谢您的回复,但这并不能纠正问题,并增加了一个额外的问题,即在触摸时选择了错误的单词。此外,双击不会触发onDoubleTap()。它只在我双击的时候起作用,但是这个方法没有被触发,所以我不能像这个答案尝试的那样捕捉它和重定向。是的,我知道,需要类似的东西。它没有经过测试,您需要修复它并编辑答案本身。谢谢