android自定义控件跟随手指移动及view事件分发机制

 我们都知道自定义控件流程onmeasure(),onlayout(),ondraw(),那么是不是所有得自定义都要重写这三个方法呐,肯定不是的,onmeasure()只是测量控件大小,onlayout(),测量大小后需要控件显示位置,最后通过ondraw()进行绘制.

言归正算自定义控件让控件跟随手指移动,很明显只需要监听手指移动,来改变控件位置,而不需要去重写其他方法:这里我举一个FloatingActionButton的例子:

  

//自定义悬浮按钮
class CustomFloatingActionButton(context: Context, attr: AttributeSet) : FloatingActionButton(context, attr) {
    var down_x = 0f
    var down_y = 0f
//    var move_x = 0f
//    var move_y = 0f
    override fun onTouchEvent(ev: MotionEvent?): Boolean {
        when (ev!!.action) {
            MotionEvent.ACTION_DOWN -> {
                down_x = ev.rawX
                down_y = ev.rawY
//                move_x = ev.rawX
//                move_y = ev.rawY
            }
            MotionEvent.ACTION_MOVE -> {
                layout(
                    (ev.rawX - down_x + left).toInt(),
                    (ev.rawY - down_y + top).toInt(),
                    (ev.rawX - down_x + right).toInt(),
                    (ev.rawY - down_y + bottom).toInt()
                )

                down_x = ev.rawX
                down_y = ev.rawY
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
//                if (abs(down_x - move_x) < 5f && abs(down_y - move_y) <= 5f) {
//                    performClick()
                    isPressed = true
//                    return super.onTouchEvent(ev)
//                }
            }
        }

        return true//如果返回true,从手指接触屏幕到手指离开屏幕,将不会触发点击事件。
    }


}

通过代码我们可以看到,重写ontouchevent()方法,监听手势,通过滑动初始位置来设置控件位置,最后调用invalidate()重新绘制.

写在最后:可以看到我们的ontouchevent()最后返回的是true,根据注解返回true就不会执行onclick事件,这是为什么呐?额这就设计到view的事件分发了,在android中事件分发机制主要在activity,viewgroup,view中,今天我就讲下view的事件分发(子view)

在了解view事件分发时你必须知道三个函数,dispatchTouchevent(),onintercepTouchEvent(),ontouchevent(),然而我们今天讲的view事件分发就不存在onintercepTouchEvent()方法了,这个很好理解一个子view要么处理事件要么不处理事件,根本不存在事件拦截之说,dispatchTouchevent()事件分发,这个函数一般我们都不会重写他,并且都是默认返回super.dispatchTouchevent.内部交给ontouchevent处理.但是如果返回true就表明事件消耗了,不再向下分发,如果返回false就表明此view不消耗此次事件,返回上一级viewgroup处理.

注:如果dispatchTouchevent()返回super.dispatchTouchevent,由于view事件分发顺序是ontouch-ontouchevent-onclick

如果我们view中没用ontouch事件,那么默认返回的return super.ontouch..,默认值就是false,此时才会执行ontouchevent事件,如果设置了ontouch事件并且返回的true,那么就不会执行,ontouchevent更别说什么Onclick了。

那么ontouchevent中默认返回的super.ontouchevent也是false,但是我们可以看他源码是实现了onclick的,(通过源码可看到实现onclick是有一些列条件的).如果ontouchevent返回true就表明消耗此时事件,不向下分发也就是不走onclick方法了.当然我们可以在ontouchevent里面直接调用.performclick(),可以监听onclick事件,流程可能不是那么清晰.但是对于对事件分发有一定基础的应该不难理解

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值