项目中碰到一个问题,情景是这样的:
有一个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); } } }