解决textview.setMovementMethod后Listview的OnItemClickListener点击失效问题

当在ListView的item中设置TextView的setMovementMethod为LinkMovementMethod.getInstance()后,会导致ListView的点击事件失效。本文介绍了三种解决方法,包括自定义TextView和重写其onTouchEvent方法,以确保链接可点击同时不阻止ListView的点击事件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



listview中在item里的textview设置了setMovementMethod(LinkMovementMethod.getInstance());后,
list的clickitem失效问题解决办法

参考:http://stackoverflow.com/questions/8558732/listview-textview-with-linkmovementmethod-makes-list-item-unclickable

方法一、二:

public class TextViewFixTouchConsume extends TextView {
    boolean dontConsumeNonUrlClicks = true;
    boolean linkHit;
    public TextViewFixTouchConsume(Context context) {
        super(context);
    }
    public TextViewFixTouchConsume(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public TextViewFixTouchConsume(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 一、 listview    setOnItemLongClickListener  BUG
        // linkHit = false;
        // boolean res = super.onTouchEvent(event);
        //
        // if (dontConsumeNonUrlClicks)
        // return linkHit;
        // return res;
       
         // 二、有误触textview内链接BUG
        if (getMovementMethod() == null) {
            boolean result = super.onTouchEvent(event);
            return result;
        }
        MovementMethod m = getMovementMethod();
        setMovementMethod(null);
        boolean mt = m.onTouchEvent(this, (Spannable) getText(), event);
        if (mt && event.getAction() == MotionEvent.ACTION_DOWN) {
            event.setAction(MotionEvent.ACTION_UP);
            mt = m.onTouchEvent(this, (Spannable) getText(), event);
            event.setAction(MotionEvent.ACTION_DOWN);
        }
        boolean st = super.onTouchEvent(event);
        setMovementMethod(m);
        setFocusable(false);
        return mt || st;
    }
    @Override
    public boolean hasFocusable() {
        return false;
    }
    public static class LocalLinkMovementMethod extends LinkMovementMethod {
        static LocalLinkMovementMethod sInstance;
        public static LocalLinkMovementMethod getInstance() {
            if (sInstance == null)
                sInstance = new LocalLinkMovementMethod();
            return sInstance;
        }
        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                MotionEvent event) {
            int action = event.getAction();
            if (action == MotionEvent.ACTION_UP
                    || action == MotionEvent.ACTION_DOWN) {
                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);
                ClickableSpan[] link = buffer.getSpans(off, off,
                        ClickableSpan.class);
                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        link[0].onClick(widget);
                    } else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer,
                                buffer.getSpanStart(link[0]),
                                buffer.getSpanEnd(link[0]));
                    }
                    if (widget instanceof TextViewFixTouchConsume) {
                        ((TextViewFixTouchConsume) widget).linkHit = true;
                    }
                    return true;
                } else {
                    Selection.removeSelection(buffer);
                    Touch.onTouchEvent(widget, buffer, event);
                    return false;
                }
            }
            return Touch.onTouchEvent(widget, buffer, event);
        }
    }
}  



使用:

<com.TextViewFixTouchConsume
            android:id="@+id/bc_con"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:lineSpacingExtra="5dp"
            android:textColor="@color/tvcolor_w"
            android:textSize="16sp" /> 
h.tvContent.setMovementMethod(LocalLinkMovementMethod.getInstance()); 



方法三:
    BUG:textview的setOnClickListener 失效
public class TextViewFixTouchConsume extends TextView {
    boolean dontConsumeNonUrlClicks = true;
    boolean linkHit;
    public TextViewFixTouchConsume(Context context) {
        super(context);
        init();
    }
    public TextViewFixTouchConsume(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }
    public TextViewFixTouchConsume(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
        init();
    }
    
    private void init() {
        setOnTouchListener(new OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    boolean ret = false;
                    CharSequence text = ((TextView) v).getText();
                    Spannable stext = Spannable.Factory.getInstance().newSpannable(text);
                    TextView widget = (TextView) v;
                    int action = event.getAction();
                    if (action == MotionEvent.ACTION_UP ||
                            action == MotionEvent.ACTION_DOWN) {
                        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);
                        ClickableSpan[] link = stext.getSpans(off, off, ClickableSpan.class);
                        if (link.length != 0) {
                            if (action == MotionEvent.ACTION_UP) {
                                link[0].onClick(widget);
                            }
                            ret = true;
                        }
                    }
                    return ret;
                }
            });
    }
    
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (getMovementMethod() == null) {
            boolean result = super.onTouchEvent(event);
            return result;
        }
        MovementMethod m = getMovementMethod();
        setMovementMethod(null);
        boolean mt = m.onTouchEvent(this, (Spannable) getText(), event);
        if (mt && event.getAction() == MotionEvent.ACTION_DOWN) {
            event.setAction(MotionEvent.ACTION_UP);
            mt = m.onTouchEvent(this, (Spannable) getText(), event);
            event.setAction(MotionEvent.ACTION_DOWN);
        }
        boolean st = super.onTouchEvent(event);
        setMovementMethod(m);
        setFocusable(false);
        return mt || st;
    }
    @Override
    public boolean hasFocusable() {
        return false;
    }
   
}  

使用:
<com.TextViewFixTouchConsume
            android:id="@+id/bc_con"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:lineSpacingExtra="5dp"
            android:textColor="@color/tvcolor_w"
            android:textSize="16sp" /> 

h.tvContent.setMovementMethod(LinkMovementMethod.getInstance());  


呵呵,始终没有完美解决方案,等待大神!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值