我需要一个可点击的跨度,在我的应用程序中同时具有正常点击和长按方法,我在这里(In Android - How can I register only long clicks using a ClickableSpan)发现我可以扩展LinkMovementMethod类和ClickableSpan类以允许这样做但是目前长短点击都有效,但长按一次而不是点击长按动作,当项目被按下的时间足够长时,它会等到你释放要射击的项目。这是扩展类的代码:
LinkMovementClass
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.view.MotionEvent;
import android.widget.TextView;
public class LongClickLinkMovementMethod extends LinkMovementMethod {
private Long lastClickTime = 0l;
private int lastX = 0;
private int lastY = 0;
@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();
lastX = x;
lastY = y;
int deltaX = Math.abs(x-lastX);
int deltaY = Math.abs(y-lastY);
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);
LongClickableSpan[] link = buffer.getSpans(off, off, LongClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
if (System.currentTimeMillis() - lastClickTime < 1000)
link[0].onClick(widget);
else if (deltaX < 10 && deltaY < 10)
link[0].onLongClick(widget);
} else if (action == MotionEvent.ACTION_DOWN) {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
lastClickTime = System.currentTimeMillis();
}
return true;
}
}
return super.onTouchEvent(widget, buffer, event);
}
public static MovementMethod getInstance() {
if (sInstance == null)
sInstance = new LongClickLinkMovementMethod();
return sInstance;
}
private static LongClickLinkMovementMethod sInstance;
}
LongClickableSpanClass
import android.text.style.ClickableSpan;
import android.view.View;
public abstract class LongClickableSpan extends ClickableSpan {
abstract public void onLongClick(View view);
}
实际实施
LongClickableSpan eruptionText = new LongClickableSpan() {
@Override
public void onClick(View tvEruptions) {
LinkFunctions.link_eruption_detail(getApplicationContext(),PostErupionID);
}
@Override
public void onLongClick(View tvEruptions) {
if(SignedInUserID != 0) {
DialogFragment newFragment = new Dialogs.QuickActionsDialogFragment();
// Supply num input as an argument.
Bundle args = new Bundle();
args.putLong("eruptionID", PostErupionID);
newFragment.setArguments(args);
newFragment.show(getFragmentManager(), "QuickActions");
}
}
};
ss.setSpan(eruptionText, startpos[(int) j], endpos[(int) j], Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
答案 0 :(得分:6)
我知道这个问题已经过时了,可能OP已经解决了这个问题,但我对原来的LongClickLinkMovementMethod进行了一些调整,以便在时间过后而不是在我们发布水龙头时触发:
import android.os.Handler;
import android.text.Layout;
import android.text.Selection;
import android.text.Spannable;
import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod;
import android.view.MotionEvent;
import android.widget.TextView;
public class LongClickLinkMovementMethod extends LinkMovementMethod {
private Handler mLongClickHandler;
private static int LONG_CLICK_TIME = 1000;
private boolean mIsLongPressed = false;
@Override
public boolean onTouchEvent(final TextView widget, Spannable buffer,
MotionEvent event) {
int action = event.getAction();
if(action == MotionEvent.ACTION_CANCEL){
if(mLongClickHandler!=null){
mLongClickHandler.removeCallbacksAndMessages(null);
}
}
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);
final LongClickableSpan[] link = buffer.getSpans(off, off, LongClickableSpan.class);
if (link.length != 0) {
if (action == MotionEvent.ACTION_UP) {
if(mLongClickHandler!=null){
mLongClickHandler.removeCallbacksAndMessages(null);
}
if(!mIsLongPressed) {
link[0].onClick(widget);
}
mIsLongPressed = false;
} else {
Selection.setSelection(buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0]));
mLongClickHandler.postDelayed(new Runnable() {
@Override
public void run() {
link[0].onLongClick(widget);
mIsLongPressed = true;
}
},LONG_CLICK_TIME);
}
return true;
}
}
return super.onTouchEvent(widget, buffer, event);
}
public static MovementMethod getInstance() {
if (sInstance == null) {
sInstance = new LongClickLinkMovementMethod();
sInstance.mLongClickHandler = new Handler();
}
return sInstance;
}
private static LongClickLinkMovementMethod sInstance;
}
所以基本上这使用Handler来在1000ms之后触发长按事件
答案 1 :(得分:3)
简单的方法是使用 View.setTag 。
代码示例:
tv.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
Toast.makeText(getApplicationContext(), "onLongClick", Toast.LENGTH_SHORT).show();
v.setTag("Test");
return true;
}
});
private static class NonLongClickableUrlSpan extends URLSpan {
public NonLongClickableUrlSpan(String url) {
super(url);
}
@Override
public void onClick(View widget) {
if (widget.getTag() != null) {
widget.setTag(null);
return;
}
super.onClick(widget);
}
}
答案 2 :(得分:0)
我使用最新的Kotlin语法编辑了Pedro Oliveira solution:
class LongClickLinkMovementMethod : LinkMovementMethod() {
private var longClickHandler: Handler? = null
private var isLongPressed = false
override fun onTouchEvent(
widget: TextView, buffer: Spannable,
event: MotionEvent
): Boolean {
val action = event.action
if (action == MotionEvent.ACTION_CANCEL) {
longClickHandler?.removeCallbacksAndMessages(null)
}
if (action == MotionEvent.ACTION_UP ||
action == MotionEvent.ACTION_DOWN
) {
var x = event.x.toInt()
var y = event.y.toInt()
x -= widget.totalPaddingLeft
y -= widget.totalPaddingTop
x += widget.scrollX
y += widget.scrollY
val layout = widget.layout
val line = layout.getLineForVertical(y)
val off = layout.getOffsetForHorizontal(line, x.toFloat())
val link = buffer.getSpans(
off, off,
LongClickableSpan::class.java
)
if (link.isNotEmpty()) {
if (action == MotionEvent.ACTION_UP) {
longClickHandler?.removeCallbacksAndMessages(null)
if (!isLongPressed) {
link[0].onClick(widget)
}
isLongPressed = false
} else {
Selection.setSelection(
buffer,
buffer.getSpanStart(link[0]),
buffer.getSpanEnd(link[0])
)
longClickHandler?.postDelayed({
link[0].onLongClick(widget)
isLongPressed = true
}, LONG_CLICK_TIME)
}
return true
}
}
return super.onTouchEvent(widget, buffer, event)
}
companion object {
private const val LONG_CLICK_TIME = 500L
val instance: MovementMethod?
get() {
if (sInstance == null) {
sInstance = LongClickLinkMovementMethod()
// Handler deprecated https://stackoverflow.com/a/62477706/4116924
sInstance!!.longClickHandler = Handler(Looper.getMainLooper())
}
return sInstance
}
private var sInstance: LongClickLinkMovementMethod? = null
}
}