Контроль onclicklistener в текстовом режиме с поддержкой автозапуска
Я использую TextView, для которого я установил свойство autolink="web"
в файле XML. Я также внедрил onClickListener
для этого TextView. Проблема в том, что текст TextView содержит гиперссылку, и если я коснусь этой ссылки, ссылка открывается в браузере, но одновременно триггеры onClickListener
тоже. Я не хочу этого.
То, что я хочу, если я коснусь гиперссылки, не должен срабатывать clickListener. Он должен срабатывать только при касании части текста, который не является гиперссылкой. Любое предложение?
Ответы
Ответ 1
Вы можете добиться этого, используя работу в функциях getSelectionStart() и getSelectionEnd() класса Textview,
tv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClassroomLog.log(TAG, "Textview Click listener ");
if (tv.getSelectionStart() == -1 && tv.getSelectionEnd() == -1) {
//This condition will satisfy only when it is not an autolinked text
//Fired only when you touch the part of the text that is not hyperlinked
}
}
});
Это может быть поздний ответ, но может быть полезен тем, кто ищет решение.
Ответ 2
один из сообщений @CommonsWare помогает перехватить событие autolink OnClick
.
private void fixTextView(TextView tv) {
SpannableString current = (SpannableString) tv.getText();
URLSpan[] spans =
current.getSpans(0, current.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = current.getSpanStart(span);
int end = current.getSpanEnd(span);
current.removeSpan(span);
current.setSpan(new DefensiveURLSpan(span.getURL()), start, end,
0);
}
}
public static class DefensiveURLSpan extends URLSpan {
private String mUrl;
public DefensiveURLSpan(String url) {
super(url);
mUrl = url;
}
@Override
public void onClick(View widget) {
// openInWebView(widget.getContext(), mUrl); // intercept click event and do something.
// super.onClick(widget); // or it will do as it is.
}
}
Применить выше код, как показано ниже. Он пройдет через все связующие тексты и заменит события click на обработчик событий.
fixTextView(textViewContent);
Ответ 3
Вы можете установить свойство android: linksClickable = "false" в вашем TextView, в сочетании с android: autoLink = "web"; это делает ссылки видимыми, но не кликабельными.
Ответ 4
Используйте textView.getSelectionStart() и textView.getSelectionEnd(). Если вы щелкните любой текст, отличный от ссылки textView.getSelectionStart(), а textView.getSelectionEnd() будет -1. Так используя условие if в onClickListner, вы можете блокировать действие onClick при нажатии ссылки.
//inside onClickListner
if(textView.getSelectionStart()==-1&&textView.getSlectionEnd==-1){
//onClick action
}
Ответ 5
если вы хотите, вы можете использовать следующий код, который позволяет настраивать кликабельные ссылки в строке (на основе этого сообщения):
использование:
final TextView textView = (TextView) findViewById(R.id.textView);
final Spanned text = Html.fromHtml(getString(...));
textView.setText(text);
textView.setMovementMethod(new LinkMovementMethodExt());
LinkMovementMethodExt.java
public class LinkMovementMethodExt extends LinkMovementMethod {
private static LinkMovementMethod sInstance;
public static MovementMethod getInstance() {
if (sInstance == null)
sInstance = new LinkMovementMethodExt();
return sInstance;
}
@Override
public boolean onTouchEvent(final TextView widget, final Spannable buffer, final MotionEvent event) {
final int action = event.getAction();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
final int x = (int) event.getX() - widget.getTotalPaddingLeft() + widget.getScrollX();
final int y = (int) event.getY() - widget.getTotalPaddingTop() + widget.getScrollY();
final Layout layout = widget.getLayout();
final int line = layout.getLineForVertical(y);
final int off = layout.getOffsetForHorizontal(line, x);
final ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
//do something with the clicked item...
return true;
}
}
return super.onTouchEvent(widget, buffer, event);
}
}
Ответ 6
private void fixTextView(TextView tv) {
SpannableString current = (SpannableString) tv.getText();
URLSpan[] spans =
current.getSpans(0, current.length(), URLSpan.class);
for (URLSpan span : spans) {
int start = current.getSpanStart(span);
int end = current.getSpanEnd(span);
current.removeSpan(span);
current.setSpan(new DefensiveURLSpan(span.getURL()), start, end,
0);
}
}
public static class DefensiveURLSpan extends URLSpan {
public final static Parcelable.Creator<DefensiveURLSpan> CREATOR =
new Parcelable.Creator<DefensiveURLSpan>() {
@Override
public DefensiveURLSpan createFromParcel(Parcel source) {
return new DefensiveURLSpan(source.readString());
}
@Override
public DefensiveURLSpan[] newArray(int size) {
return new DefensiveURLSpan[size];
}
};
private String mUrl;
public DefensiveURLSpan(String url) {
super(url);
mUrl = url;
}
@Override
public void onClick(View widget) {
// openInWebView(widget.getContext(), mUrl); // intercept click event and do something.
// super.onClick(widget); // or it will do as it is.
}
}
Затем вы вызовете fixTextView(textViewContent);
в представлении после его объявления (через инфляцию или findViewById
) или добавьте в окно (через addView
)
Это относится к отсутствующему требованию установить CREATOR при расширении Parcelable.
Он был предложен как редактирование, но отклонен. К сожалению, теперь будущим пользователям нужно будет узнать, что оригинал сначала неполный. Хороший, рецензенты!
Ответ 7
Вместо использования onClickListener вы можете попробовать это.
private void addLink() {
tvLink = (TextView) findViewById(R.id.tvInfo2);
String strURL = UrlLoader.getCodeUrl();
// Make the url string clicable and take action in its onclick
SpannableString spanUrl = SpannableString.valueOf(strURL);
spanUrl.setSpan(new InternalURLSpan(new OnClickListener() {
public void onClick(View v) {
//Do Some action
}
}), 0, spanUrl.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tvLink.setText(spanUrl);
// We probably also want the user to jump to your link by moving the
// focus (e.g. using the trackball), which we can do by setting the
// proper movement method:
MovementMethod m = tvLink.getMovementMethod();
if ((m == null) || !(m instanceof LinkMovementMethod)) {
if (tvLink.getLinksClickable()) {
tvLink.setMovementMethod(LinkMovementMethod.getInstance());
}
}
}
Также в XML файле макета не забудьте добавить
<TextView android:layout_width="wrap_content" android:linksClickable="true"
android:layout_height="wrap_content" android:id="@+id/tvInfo2" android:text="@string/url_link" />
Ответ 8
Просто добавив
textView.setMovementMethod(CustomLinkMovementMethod.getInstance());
to @binary ответ для тех, чей метод не с ними работал