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