单击时更改 TextView 的背景颜色

Changing background color of a TextView when clicked

在某些应用程序中,例如 Plaid 甚至 Chrome 浏览器,文本的某些部分带有下划线以表明它们是可点击的 link浏览器 window 或新标签页。单击这些 link 时,整个文本的背景颜色变为下划线颜色。我试过查看 Plaid 的来源来复制这种效果,但没有成功。我想要完成的是这个效果:

在 res/drawable/my_background 中创建一个 XML 资源文件。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>

并将其设置为您的 TextView 作为背景,例如

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

我认为这部分代码产生了这种效果:

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

其实是基于这个问题:

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;
}

}