我遇到了一个问题TextView.我可以使用它进行选择setTextIsSelectable(true),但是当我启用链接时setMovementMethod(LinkMovementMethod.getInstance()),它就不再可以选择了.
请注意,我并不是说可以点击原始链接,而是通过TextView使用类似的东西加载HTML标记来使实际单词可点击setText(Html.fromHtml("<a href='http://stackoverflow.com'>Hello World!</a>")).
小智 25
java.lang.IndexOutOfBoundsException: setSpan (-1 ... -1) starts before 0...
我查看了LinkMovementMethod中的onTouchEvent实现,发现当textview不包含链接时,它会删除选择.在这种情况下,当用户尝试更改时,选择从空值开始,应用程序崩溃.
...
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
} else {
Selection.removeSelection(buffer);
}
...
Run Code Online (Sandbox Code Playgroud)
所以我重写onTouchEvent方法,它工作正常.
public class CustomMovementMethod extends LinkMovementMethod {
@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) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN) {
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);
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
link[0].onClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
}
return true;
}
}
return Touch.onTouchEvent(widget, buffer, event);
}
}
Run Code Online (Sandbox Code Playgroud)
希望它对某人有所帮助.
oak*_*kes 14
我想到了.您需要子类化LinkMovementMethod并添加对文本选择的支持.真的很不幸的是它本身并不支持它.我只是推翻使用从该等价的相关方法的源代码的ArrowKeyMovementMethod.我想这是Android开源的一个好处!
public class CustomMovementMethod extends LinkMovementMethod {
@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());
}
}
}
Run Code Online (Sandbox Code Playgroud)
要使用它,只需直接实例化它,如下所示:
textView.setMovementMethod(new CustomMovementMethod());
Run Code Online (Sandbox Code Playgroud)