android完美解决ClickableSpan中点击后ListView中item的长按冲突的问题

项目中碰到一个问题,情景是这样的:

有一个ListView,每个item中有一个TextView,textview实现了LongClick事件 实现复制文本的功能 ,这个TextView中又添加了ClickableSpan,实现了方法onClick。

我的需求是点击ClickableSpan,则响应ClickableSpan事件;长按ClickableSpan效果跟长按TextView应该一样,都响应TextView的LongClick事件。


研究了一下代码,解决方法如下:


package com.youxiake.controls;

import android.app.AlertDialog;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.DialogInterface;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.TextView;
import android.widget.Toast;

import com.youxiake.util.MyLog;

public class TextViewFixTouchConsume extends TextView {
   boolean dontConsumeNonUrlClicks = true;
   int linkHit;

   public OnClickListener onclick;


   public void setMyOnClickListener(OnClickListener onclick){
      this.onclick=onclick;
   }

   @Override
   public boolean hasFocusable() {
      return false;
   }

   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 void setOnLongClickListener(OnLongClickListener l) {
   //
   // ClipboardManager cmb =
   // (ClipboardManager)getContext().getSystemService(Context.CLIPBOARD_SERVICE);
   // cmb.setText(getText().toString().trim());
   // Toast.makeText(getContext(), "已复制", Toast.LENGTH_SHORT).show();
   //
   // };

   @Override
   public boolean onTouchEvent(MotionEvent event) {

      //MyLog.debug_s("onTouchEvent:begin");

      boolean res = super.onTouchEvent(event);

      //MyLog.debug_s("onTouchEvent:"+res+",linkHit="+linkHit);

      return res;
   }


   public static class DialogCopy {

      private static View.OnLongClickListener onLongClickListener;

      public static View.OnLongClickListener getInstance() {
         if (onLongClickListener == null) {
            onLongClickListener = new View.OnLongClickListener() {
               @Override
               public boolean onLongClick(final View v) {
                  AlertDialog.Builder builder = new AlertDialog.Builder(v.getContext());
                  builder.setItems(new String[]{"复制"}, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int which) {
                        if (which == 0) {
                           TextView textView = (TextView) v;
                           Context context = v.getContext();
                           String txt = textView.getText().toString();

                           ClipboardManager cmb = (ClipboardManager) context.getSystemService(context.CLIPBOARD_SERVICE);
                           if(txt!=null){
                              cmb.setText(txt);
                           }
                           Toast.makeText(context, "已复制", Toast.LENGTH_SHORT).show();
                        }
                     }
                  }).show();

                  return true;
               }
            };
         }

         return onLongClickListener;
      }
   }


   public static class LocalLinkMovementMethod extends LinkMovementMethod {
      static LocalLinkMovementMethod sInstance;

      public static LocalLinkMovementMethod getInstance() {
         if (sInstance == null)
            sInstance = new LocalLinkMovementMethod();

         return sInstance;
      }


      private long mActionDownTime = 0;

      @Override
      public boolean onTouchEvent(TextView widget, Spannable buffer,
                           MotionEvent event) {
         int action = event.getAction();

         MyLog.debug_s("action:"+action);

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

            MyLog.debug_s("off:"+off+",link:"+link.length);

            if (link.length != 0) {
               if (action == MotionEvent.ACTION_UP) {
                  if (System.currentTimeMillis() - mActionDownTime < ViewConfiguration.getLongPressTimeout()) {
                     //MyLog.debug_s("ACTION_UP");
                     link[0].onClick(widget);
                  }

               } else if (action == MotionEvent.ACTION_DOWN) {
                  //MyLog.debug_s("ACTION_DOWN");
                  Selection.setSelection(buffer,
                        buffer.getSpanStart(link[0]),
                        buffer.getSpanEnd(link[0]));
                  mActionDownTime = System.currentTimeMillis();

               }else if (action == MotionEvent.ACTION_MOVE) {
                  //MyLog.debug_s("ACTION_MOVE");
               }

               return true;
            } else {
               Selection.removeSelection(buffer);
               // MyLog.debug_s("Selection.removeSelection(buffer);");
               //Touch.onTouchEvent(widget, buffer, event);
               if (action == MotionEvent.ACTION_UP) {
                  if (System.currentTimeMillis() - mActionDownTime < ViewConfiguration.getLongPressTimeout()) {
                     if (widget instanceof TextViewFixTouchConsume) {
                        if(((TextViewFixTouchConsume) widget).onclick!= null){

                           ((TextViewFixTouchConsume) widget).onclick.onClick(widget);
                        }
                     }
                  }

               } else if (action == MotionEvent.ACTION_DOWN) {
                  mActionDownTime = System.currentTimeMillis();
               }

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

   }

}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值