盒子
盒子
文章目录
  1. 开门撞山:
  2. 场景:
  3. Don’t do:
  4. What should do (How to use TouchDelegate):
    1. 直接上菜:
  5. 实际应用场景
  6. 总结

[饼干]安卓小秘密-不扩大view宽高增加其可触控范围

声明:博文未经授权一律不允转载

开门撞山:

今天我要记录的是TouchDelegate,有很多人应该都不知道还有这个东西,知道的孩子都没你们事了,都散了散了吧,不知道的请往下看。其实也不算什么秘密,只要你仔细的走过神迹一样的事件分发的源码,很容易发现的。

场景:

如下图,有这样一个场景,View a 需要有这么大,比如可以是一个按钮,UI要求显示View a的黑框部分,但是为了更好的用户体验,我们一般会增大其触控范围,比如点击绿框中都能够触发a的事件,咋做?(说好的不卖关子的呢?)

demo0

Don’t do:

  • 增加a的Padding?
    • 后期如果修改bgColor,那么不好了,绿色框内全变色。
  • 套多一层透明的FrameLayout?
    • 增加布局复杂度,我TM一脚飞死你。
  • 自定义view限制绘制区域?
    • 写完了?你很棒!但是你可以收拾包袱走人了。

What should do (How to use TouchDelegate):

要学会站在巨人的肩膀,要知道,“你遇到的,巨人也会遇到”,巨人给我们留下了TouchDelegate

直接上菜:

注意方法ViewGroup.setTouchDelegate(Rect,View)

以下代码出自我一个自定义View—UsoppBubble.java

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
    super.onLayout(changed, left, top, right, bottom);
    if (changed) {
        float largedSize = (bottom - top) * mTouchAreaLargerRatio;//乘以放大倍数
        int deltaY = (int) (largedSize - (bottom - top));
        int deltaX = largedSize > (right - left) ? (int) (largedSize - (right - left)) : 0;
        ViewGroup vg = (ViewGroup) getParent();
        Rect rect = new Rect(left - deltaX, top - deltaY, right + deltaX, bottom + deltaY);
        //构建出来的Rect对象就相当于绿色框框,而this就是这个view的实例。
        vg.setTouchDelegate(new TouchDelegate(rect, this));
    }
}

相信上述代码是极度容易的,ViewGroup.setTouchDelegate(Rect,View)接受两个参数:

  • 可触控区域。
  • 谁(哪个子view)需要用这个可触控区域。

实际应用场景

  • QQ消息气泡可触控区域

demo1

demo2

  • 小米贴边悬浮球点击唤醒

demo3

  • 锤子的闪念胶囊贴边点击唤醒

demo4

总结

  • View.setTouchDelegate(Rect,View),这句还不够吗?还要我怎样?
  • 你遇到的,巨人也会遇到,如果换位思考一下,你就是“巨人”,那么子View获取到的触摸事件是从ViewGroup分发下来的,那么如果在分发之前加一些条件判断,比如区域什么的,那么TouchDelegate这玩意儿是不是就出来了呢?
  • Stay hungry stay foolish!

仅作知识点记录,如有疏漏,全(欢)都(迎)怪(指)你(正)。


确保这文章被看完了,我在上面留了一个无伤大雅的bug,不知道有人发现没有,那就是:

setTouchDelegate其实是View的方法。而ViewGroup : View,无伤大雅。

支持一下
扫一扫,支持Halohoop