manejar el enlace de vista de texto, haga clic en mi aplicación de Android

Resuelto David Hedlund asked hace 54 años • 13 respuestas

Actualmente estoy renderizando la entrada HTML en un TextView de esta manera:

tv.setText(Html.fromHtml("<a href='test'>test</a>"));

El HTML que se muestra me lo proporciona a través de un recurso externo, por lo que no puedo cambiar las cosas como lo haría, pero puedo, por supuesto, alterar algunas expresiones regulares del HTML para cambiar el valor href, por ejemplo, a otra cosa.

Lo que quiero es poder manejar un clic en un enlace directamente desde la aplicación, en lugar de que el enlace abra una ventana del navegador. ¿Es esto algo alcanzable? Supongo que sería posible configurar el protocolo del valor href en algo como "myApp://" y luego registrar algo que permita a mi aplicación manejar ese protocolo. Si esta es realmente la mejor manera, me gustaría saber cómo se hace, pero espero que haya una manera más fácil de simplemente decir "cuando se hace clic en un enlace en esta vista de texto, quiero generar un evento que reciba el valor href del enlace como parámetro de entrada"

David Hedlund avatar Jan 01 '70 08:01 David Hedlund
Aceptado

Llegando a esto casi un año después, hay una manera diferente en la que resolví mi problema particular. Como quería que el enlace fuera manejado por mi propia aplicación, existe una solución que es un poco más simple.

Además del filtro de intención predeterminado, simplemente dejo que mi actividad objetivo escuche las ACTION_VIEWintenciones y, específicamente, aquellas con el esquemacom.package.name

<intent-filter>
    <category android:name="android.intent.category.DEFAULT" />
    <action android:name="android.intent.action.VIEW" />
    <data android:scheme="com.package.name" />  
</intent-filter>

Esto significa que los enlaces que comienzan con com.package.name://serán manejados por mi actividad.

Entonces todo lo que tengo que hacer es construir una URL que contenga la información que quiero transmitir:

com.package.name://action-to-perform/id-that-might-be-needed/

En mi actividad objetivo, puedo recuperar esta dirección:

Uri data = getIntent().getData();

En mi ejemplo, podría simplemente verificar datasi hay valores nulos, porque cuando no sean nulos, sabré que fueron invocados mediante dicho enlace. A partir de ahí, extraigo las instrucciones que necesito de la URL para poder mostrar los datos adecuados.

David Hedlund avatar Aug 10 '2010 20:08 David Hedlund

De otra forma, toma prestado un poco de Linkify pero te permite personalizar su manejo.

Clase de tramo personalizada:

public class ClickSpan extends ClickableSpan {

    private OnClickListener mListener;

    public ClickSpan(OnClickListener listener) {
        mListener = listener;
    }

    @Override
    public void onClick(View widget) {
       if (mListener != null) mListener.onClick();
    }

    public interface OnClickListener {
        void onClick();
    }
}

Función auxiliar:

public static void clickify(TextView view, final String clickableText, 
    final ClickSpan.OnClickListener listener) {

    CharSequence text = view.getText();
    String string = text.toString();
    ClickSpan span = new ClickSpan(listener);

    int start = string.indexOf(clickableText);
    int end = start + clickableText.length();
    if (start == -1) return;

    if (text instanceof Spannable) {
        ((Spannable)text).setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
    } else {
        SpannableString s = SpannableString.valueOf(text);
        s.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        view.setText(s);
    }

    MovementMethod m = view.getMovementMethod();
    if ((m == null) || !(m instanceof LinkMovementMethod)) {
        view.setMovementMethod(LinkMovementMethod.getInstance());
    }
}

Uso:

 clickify(textView, clickText,new ClickSpan.OnClickListener()
     {
        @Override
        public void onClick() {
            // do something
        }
    });
Jonathan S. avatar Apr 15 '2011 20:04 Jonathan S.

si hay varios enlaces en la vista de texto. Por ejemplo, la vista de texto tiene "https://" y "tel no". Podemos personalizar el método LinkMovement y manejar clics para palabras según un patrón. Adjunto se encuentra el método de movimiento de enlaces personalizado.

public class CustomLinkMovementMethod extends LinkMovementMethod
{

private static Context movementContext;

private static CustomLinkMovementMethod linkMovementMethod = new CustomLinkMovementMethod();

public boolean onTouchEvent(android.widget.TextView widget, android.text.Spannable buffer, android.view.MotionEvent event)
{
    int action = event.getAction();

    if (action == MotionEvent.ACTION_UP)
    {
        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);

        URLSpan[] link = buffer.getSpans(off, off, URLSpan.class);
        if (link.length != 0)
        {
            String url = link[0].getURL();
            if (url.startsWith("https"))
            {
                Log.d("Link", url);
                Toast.makeText(movementContext, "Link was clicked", Toast.LENGTH_LONG).show();
            } else if (url.startsWith("tel"))
            {
                Log.d("Link", url);
                Toast.makeText(movementContext, "Tel was clicked", Toast.LENGTH_LONG).show();
            } else if (url.startsWith("mailto"))
            {
                Log.d("Link", url);
                Toast.makeText(movementContext, "Mail link was clicked", Toast.LENGTH_LONG).show();
            }
            return true;
        }
    }

    return super.onTouchEvent(widget, buffer, event);
}

public static android.text.method.MovementMethod getInstance(Context c)
{
    movementContext = c;
    return linkMovementMethod;
}

Esto debe llamarse desde la vista de texto de la siguiente manera:

textViewObject.setMovementMethod(CustomLinkMovementMethod.getInstance(context));
Arun avatar May 20 '2013 07:05 Arun