改变单一ClickableSpan的文本颜色时,pressed不会影响同一TextView的其他ClickableSpans文本、颜色、ClickableSpan、ClickableSpans

2023-09-12 22:38:09 作者:我会等你在人海中找到我

我在这多ClickableSpans一个TextView。当ClickableSpan是pressed,我希望它改变其文本的颜色。

我已经尝试设置一种颜色状态列表作为TextView中的textColorLink属性。这不会产生期望的结果,因为这会导致所有跨度改变颜色,当用户点击在TextView的任何地方

有趣的是,使用textColorHighlight改变背景颜色按预期工作:点击跨度变化的跨度只有背景颜色,点击任何其他地方的TextView什么也不做

我自己也尝试设置ForegroundColorSpans具有相同的边界在哪里传递相同的颜色状态列表,上面的颜色资源的ClickableSpans。这也不行。该跨度始终保持在颜色状态列表中的默认状态下的色彩,从来没有进入pressed状态。

有谁知道如何做到这一点?

这是颜色状态列表我用:

 <选择的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android>
  <项目的android:STATE_ pressed =真正的机器人:颜色=@色/ pressed_color/>
  <项目的android:颜色=@色/ normal_color/>
< /选择器>
 

解决方案

我终于找到了一个解决方案,做一切我想要的。正是基于这个答案。

怎样批量修改文本内容,文本格式为.ktr 可以用记事本打开

这是我修改LinkMovementMethod标志着一个跨度pssed上的触摸事件(MotionEvent.ACTION_DOWN)开始$ P $和取消标记它的触摸结束时或当触摸位置移出跨度。

 私有类LinkTouchMovementMethod扩展LinkMovementMethod {
    私人TouchableSpan米pressedSpan;

    @覆盖
    公共布尔的onTouchEvent(TextView的TextView的,Spannable spannable,MotionEvent事件){
        如果(event.getAction()== MotionEvent.ACTION_DOWN){
            米pressedSpan = GET pressedSpan(TextView的,spannable,事件);
            如果(M pressedSpan!= NULL){
                米pressedSpan.set pressed(真正的);
                Selection.setSelection(spannable,spannable.getSpanStart(M pressedSpan)
                        spannable.getSpanEnd(M pressedSpan));
            }
        }否则,如果(event.getAction()== MotionEvent.ACTION_MOVE){
            TouchableSpan touchedSpan = GET pressedSpan(TextView的,spannable,事件);
            如果(M pressedSpan = NULL和放大器;!&安培;!touchedSpan = M pressedSpan){
                米pressedSpan.set pressed(假);
                米pressedSpan = NULL;
                Selection.removeSelection(spannable);
            }
        } 其他 {
            如果(M pressedSpan!= NULL){
                米pressedSpan.set pressed(假);
                super.onTouchEvent(TextView的,spannable,事件);
            }
            米pressedSpan = NULL;
            Selection.removeSelection(spannable);
        }
        返回true;
    }

    私人TouchableSpan得到pressedSpan(TextView的TextView的,Spannable spannable,MotionEvent事件){

        INT X =(int)的event.getX();
        INT Y =(INT)event.getY();

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

        X + = textView.getScrollX();
        Y + = textView.getScrollY();

        布局布局= textView.getLayout();
        INT线= layout.getLineForVertical(Y);
        诠释关闭= layout.getOffsetForHorizo​​ntal(线,X);

        TouchableSpan []链接= spannable.getSpans(脱,脱,TouchableSpan.class);
        TouchableSpan touchedSpan = NULL;
        如果(link.length大于0){
            touchedSpan =链接[0];
        }
        返回touchedSpan;
    }

}
 

这需要被应用到TextView的,像这样:

  yourTextView.setMovementMethod(新LinkTouchMovementMethod());
 

这是修改后的ClickableSpan的编辑基础上,pressed状态的LinkTouchMovementMethod设置抽奖状态: (这也将删除链接下划线)

 公共抽象类TouchableSpan扩展ClickableSpan {
    私人布尔MIS pressed;
    私人诠释米pressedBackgroundColor;
    私人诠释mNormalTextColor;
    私人诠释米pressedTextColor;

    公共TouchableSpan(INT normalTextColor,诠释pressedTextColor,诠释pressedBackgroundColor){
        mNormalTextColor = normalTextColor;
        米pressedTextColor = pressedTextColor;
        米pressedBackgroundColor = pressedBackgroundColor;
    }

    公共无效套pressed(布尔isSelected){
        MIS pressed = isSelected;
    }

    @覆盖
    公共无效updateDrawState(TextPaint DS){
        super.updateDrawState(DS);
        ds.setColor(MIS pressed米pressedTextColor:mNormalTextColor);
        ds.bgColor = MIS pressed?米pressedBackgroundColor:0xffeeeeee;
        ds.setUnderlineText(假);
    }
}
 

I have a TextView with multiple ClickableSpans in it. When a ClickableSpan is pressed, I want it to change the color of its text.

I have tried setting a color state list as the textColorLink attribute of the TextView. This does not yield the desired result because this causes all the spans to change color when the user clicks anywhere on the TextView.

Interestingly, using textColorHighlight to change the background color works as expected: Clicking on a span changes only the background color of that span and clicking anywhere else in the TextView does nothing.

I have also tried setting ForegroundColorSpans with the same boundaries as the ClickableSpans where I pass the same color state list as above as the color resource. This doesn't work either. The spans always keep the color of the default state in the color state list and never enter the pressed state.

Does anyone know how to do this?

This is the color state list I used:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_pressed="true" android:color="@color/pressed_color"/>
  <item android:color="@color/normal_color"/>
</selector>

解决方案

I finally found a solution that does everything I wanted. It is based on this answer.

This is my modified LinkMovementMethod that marks a span as pressed on the start of a touch event (MotionEvent.ACTION_DOWN) and unmarks it when the touch ends or when the touch location moves out of the span.

    private class LinkTouchMovementMethod extends LinkMovementMethod {
    private TouchableSpan mPressedSpan;

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

    private TouchableSpan 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);

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

}

This needs to be applied to the TextView like so:

yourTextView.setMovementMethod(new LinkTouchMovementMethod());

And this is the modified ClickableSpan that edits the draw state based on the pressed state set by the LinkTouchMovementMethod: (it also removes the underline from the links)

public abstract class TouchableSpan extends ClickableSpan {
    private boolean mIsPressed;
    private int mPressedBackgroundColor;
    private int mNormalTextColor;
    private int mPressedTextColor;

    public TouchableSpan(int normalTextColor, int pressedTextColor, int pressedBackgroundColor) {
        mNormalTextColor = normalTextColor;
        mPressedTextColor = pressedTextColor;
        mPressedBackgroundColor = pressedBackgroundColor;
    }

    public void setPressed(boolean isSelected) {
        mIsPressed = isSelected;
    }

    @Override
    public void updateDrawState(TextPaint ds) {
        super.updateDrawState(ds);
        ds.setColor(mIsPressed ? mPressedTextColor : mNormalTextColor);
        ds.bgColor = mIsPressed ? mPressedBackgroundColor : 0xffeeeeee;
        ds.setUnderlineText(false);
    }
}

 
精彩推荐
图片推荐