简体   繁体   中英

Changing background color of a TextView when clicked

In some apps, such as Plaid or even the Chrome Browser, some portions of the text are underlined to convey the fact that they are a clickable link that will open a browser window or a new tab. When these links are clicked, the whole text's background color changes to that of the underline color. I've tried looking at Plaid's source to replicate this effect, without success. What I'm trying to accomplish is this effect:

在此输入图像描述

Create an XML resource file in res/drawable/my_background.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true" >
    <shape>
        <solid android:color="#343434" />
    </shape>
</item>
</selector>

And set it to your TextView as Background like

  <TextView
    android:id="@+id/tvMytv"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/my_background" />

I think this part of the code creates this effect:

https://github.com/nickbutcher/plaid/blob/61d59644d5ae9e373f93cef10e0438c50e2eea6d/app/src/main/java/io/plaidapp/util/LinkTouchMovementMethod.java

It's actually based on this question:

Change the text color of a single ClickableSpan when pressed without affecting other ClickableSpans in the same TextView

public class LinkTouchMovementMethod extends LinkMovementMethod {


private static LinkTouchMovementMethod instance;
private TouchableUrlSpan pressedSpan;

public static MovementMethod getInstance() {
    if (instance == null)
        instance = new LinkTouchMovementMethod();

    return instance;
}

@Override
public boolean onTouchEvent(TextView textView, Spannable spannable, MotionEvent event) {
    boolean handled = false;
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        pressedSpan = getPressedSpan(textView, spannable, event);
        if (pressedSpan != null) {
            pressedSpan.setPressed(true);
            Selection.setSelection(spannable, spannable.getSpanStart(pressedSpan),
                    spannable.getSpanEnd(pressedSpan));
            handled = true;
        }
    } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
        TouchableUrlSpan touchedSpan = getPressedSpan(textView, spannable, event);
        if (pressedSpan != null && touchedSpan != pressedSpan) {
            pressedSpan.setPressed(false);
            pressedSpan = null;
            Selection.removeSelection(spannable);
        }
    } else {
        if (pressedSpan != null) {
            pressedSpan.setPressed(false);
            super.onTouchEvent(textView, spannable, event);
            handled = true;
        }
        pressedSpan = null;
        Selection.removeSelection(spannable);
    }
    return handled;
}

private TouchableUrlSpan getPressedSpan(TextView textView, Spannable spannable, MotionEvent
        event) {

    int x = (int) event.getX();
    int y = (int) event.getY();

    x -= textView.getTotalPaddingLeft();
    y -= textView.getTotalPaddingTop();

    x += textView.getScrollX();
    y += textView.getScrollY();

    Layout layout = textView.getLayout();
    int line = layout.getLineForVertical(y);
    int off = layout.getOffsetForHorizontal(line, x);

    TouchableUrlSpan[] link = spannable.getSpans(off, off, TouchableUrlSpan.class);
    TouchableUrlSpan touchedSpan = null;
    if (link.length > 0) {
        touchedSpan = link[0];
    }
    return touchedSpan;
}

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM