android的clickable功能,android ClickableSpan拦截点击事件

您的问题的第一个答案是,您没有在您的TextView上设置一个点击监听器,该消息是以user2558882指出的方式消耗点击事件.在您的TextView上设置了一个点击监听器后,您将看到ClickableSpans触摸区域之外的区域将按预期工作.但是,您会发现当您点击其中一个ClickableSpans时,TextView的onClick回调也将被触发.如果两个火都是你的一个问题,那会导致我们遇到一个困难的问题. user2558882的回复不能保证您的ClickableSpan的onClick回调将在您的TextView之前被触发.这里有一些

a similar thread的解决方案可以更好地实现,并从源代码中解释.线程应该适用于大多数设备的接受答案,但该答案的评论提到某些设备有问题.看起来像一些具有自定义操作符/制造商用户界面的设备是责怪的,但这是猜测.

那么为什么你不能保证onClick回调顺序?如果你看看TextView(Android 4.3)的源码,你会注意到在onTouchEvent方法中,boolean superResult = super.onTouchEvent(event); (super is View)被调用before | = mMovement.onTouchEvent(this,(Spannable)mText,event);这是调用您的移动方法,然后调用您的ClickableSpan的onClick.看看超级(View)onTouchEvent(..),你会注意到:

// Use a Runnable and post this rather than

// performClick directly. This lets other visual

// of the view update before click actions start.

if (mPerformClick == null) {

mPerformClick = new PerformClick();

}

if (!post(mPerformClick)) { //

performClick(); // it'll fallback to calling it directly

}

performClick()调用click listener集,在这种情况下,它是我们的TextView的点击监听器.这意味着,你不会知道你的onClick回调将以什么顺序触发.你所知道的是,您的ClickableSpan和TextView点击监听器将被调用.我之前提到的线程的解决方案有助于确保顺序,以便您可以使用标志.

如果确保与许多设备的兼容性是优先考虑的,那么最好先看看您的布局,看看是否可以避免被困在这种情况.通常有很多布局选项来像这样的裙子.

编辑评论答案:

当您的TextView执行onTouchEvent时,它会调用您的LinkMovementMethod的onTouchEvent,以便它可以处理对各种ClickableSpan的onClick方法的调用.您的LinkMovementMethod在其onTouchEvent中执行以下操作:

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

}

return true;

} else {

Selection.removeSelection(buffer);

}

}

return super.onTouchEvent(widget, buffer, event);

}

您会注意到,运动MotionEvent将获取动作(ACTION_UP:提升手指,ACTION_DOWN:按下手指),触发起始位置的x和y坐标,然后找到哪个行号和偏移量(文本中的位置)触摸命中.最后,如果有ClickableSpans包含这一点,它们将被检索,并且它们的onClick方法被调用.因为我们想要传递任何触摸到你的父布局,你可以调用你的布局onTouchEvent,如果你想要做它做的一切,当触摸,或者你可以称之为点击监听器,如果它实现了你所需的功能.这里是哪里:

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

}

return true;

} else {

Selection.removeSelection(buffer);

// Your call to your layout's onTouchEvent or it's

//onClick listener depending on your needs

}

}

所以要查看,您将创建一个扩展LinkMovementMethod的新类,覆盖它的onTouchEvent方法,将该源复制并粘贴到正确的位置,并将其粘贴到我所评论的正确位置,确保将TextView的移动方法设置为新的子类,你应该设置

再次编辑可能的副作用避免看看ScrollingMovementMethod的源(LinkMovementMethod的父),你会看到它是一个委托方法,它调用一个静态方法返回Touch.onTouchEvent(widget,buffer,event);这意味着您可以将其添加为方法中的最后一行,并避免调用super(LinkMovementMethod)onTouchEvent实现,这将重复您要粘贴的内容,其他事件可能按预期方式崩溃.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值