Se me solicitó en un proyecto, mostrar una ventana de dialogo al usuario, cuando este hiciera clic en un link contenido en un TextView, con la idea de notificarle que el link va a ser abierto en otro programa (el browser) y confirmar que quiere abrirlo.
Me puse a buscar, y encontré que no es demasiado “hacky” a mi criterio.
Primero hay que crear una clase que herede de ClickableSpan para poder interceptar el clic en un “Span”
public class InternalURLSpan extends ClickableSpan { private OnClickListener mListener; public InternalURLSpan(OnClickListener listener) { mListener = listener; } @Override public void onClick(View view) { mListener.onClick(view); } }
Después solo toca asignar un SpannableString al TextView con el contenido HTML. Eso sí, nos tocará “buscar” los links, para ir asignando los diferentes “spans” que harán clickeable el link, utilizando nuestra clase, que nos permitirá al fin, interceptar el clic, y hacer con él lo que querramos.
Yo lo que hice fue implementar un método estático en una clase utiilitaria para poder utilizarlo en diferentes partes del proyecto.
public static void setHtmlText(TextView textview, String htmlStr, OnClickListener listener) { SpannableString f = new SpannableString(htmlStr);<br /><br /> int start = 0; int end = 0; int offset = 0;<br /><br /> while ((start = htmlStr.indexOf("http", offset)) != -1) { end = htmlStr.indexOf(" ", start); if (end == -1) { end = htmlStr.length(); //Llegamos al final del string original } f.setSpan(new InternalURLSpan(listener), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); offset = end; }<br /><br /> MovementMethod m = textview.getMovementMethod(); if (m == null || !(m instanceof LinkMovementMethod)) { if (textview.getLinksClickable()) { textview.setMovementMethod(LinkMovementMethod.getInstance()); } } textview.setText(f); }
Ahora solo nos falta “interpretar” ese click. Como se aprecia, solo vamos a saber que se hizo clic sobre el TextView. Por fortuna, al hacer clic sobre un link en un TextView, esto provoca que el link en sí mismo sea seleccionado, por lo que a la hora de interceptar el clic, solo se ocupa preguntarle al TextView cual es el área seleccionada para obtener el link y utilizarlo según convenga.
ViewUtil.setHtmlText(myTextView, "Esto es una prueba, consulte http://www.google.com o http://developer.android.com", new OnClickListener() { @Override public void onClick(View v) { if (v instanceof TextView){ TextView tv = (TextView) v; String url = tv.getText().subSequence(tv.getSelectionStart(), tv.getSelectionEnd()).toString(); Toast.makeText(context, url, Toast.LENGTH_SHORT).show(); } } });
Fuente: http://blog.elsdoerfer.name/2009/10/29/clickable-urls-in-android-textviews/