Interceptar “clics” de un link en un TextView

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/

CB002 – Instalando el Android SDK

En el caso de que tenga instalado Eclipse u otro IDE, es necesario que tenga el SDK de Android. Si no se tiene ningún IDE, se recomienda bajar el Bundle, que viene con una version de Eclipse optimizada para desarrollar en Android.

Android SDK

Música:

Every Single Word You’ve Ever Said (Featuring Mark Ingraham) (Just Plain Ant) / CC BY-NC-ND 3.0
Monkies In the Temple (krackatoa) / CC BY-NC 3.0
Strobe On Torso (The Womb) / CC BY-NC-SA 3.0

CB001 – Instalando Eclipse

Para poder desarrollar para Android, es buena idea utilizar algún IDE para aumentar la productividad y utilizar las herramientas que facilitan el desarrollo. Eclipse es el IDE “oficial” y en este tutorial, se detallan los pasos necesarios para instalarlo en sistema operativo Windows.