Можно ли выбрать TextView и содержать ссылки?
У меня возникла проблема с TextView
. Я могу сделать его доступным с помощью setTextIsSelectable(true)
, но когда я включаю ссылки, которые нужно щелкнуть через setMovementMethod(LinkMovementMethod.getInstance())
, он больше не может быть выбран.
Обратите внимание: я не имею в виду, что ссылки на исходные ссылки можно кликать, а вместо того, чтобы делать текущие слова интерактивными, загружая TextView
с помощью HTML-разметки, используя что-то вроде setText(Html.fromHtml("<a href='http://stackoverflow.com'>Hello World!</a>"))
.
Ответы
Ответ 1
Я понял это. Вам нужно подклассировать 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());
}
}
}
Чтобы использовать его, просто создайте его прямо так:
textView.setMovementMethod(new CustomMovementMethod());
Ответ 2
Ответ на вопрос oakes вызывает двойное нажатие на textview
java.lang.IndexOutOfBoundsException: setSpan (-1 ... -1) starts before 0...
Я просмотрел реализацию onTouchEvent в LinkMovementMethod и обнаружил, что он удаляет выделение, когда 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);
}
...
Итак, я переопределяю метод 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);
}
}
Надеюсь, что это будет полезно для кого-то.
Ответ 3
LinkMovementMethod()
не поддерживает выбор текста очень хорошо, даже мы можем выбрать текст, но после прокрутки текстового поля выбор будет потерян.
Лучшая реализация распространяется от ArrowKeyMovementMethod
, которая очень хорошо поддерживает выбор текста.
Подробнее см. в здесь
Ответ 4
XML TextView не должен иметь никакой ссылки или каких-либо атрибутов, которые можно выбрать:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Затем установите все программно, соблюдая следующий порядок:
textView.setText(Html.fromHtml(myHtml));
Linkify.addLinks(textView, Linkify.WEB_URLS);
textView.setTextIsSelectable(true); // API-11 and above
textView.setMovementMethod(LinkMovementMethod.getInstance());
Ответ 5
можно ли связать TextView с URL-адресом?
У вас есть 10 TextView и 10 URL-адресов, поэтому просто написать код, который, если щелкнуть TextView [3], уволит намерение веб-браузера (или браузера) с URL [3]