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

原文地址:http://halohoop.com/2017/06/06/cookies-android-touchdelegate/

开门撞山:

今天我要记录的是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,无伤大雅。

顺便说一下,科学上网之后浏览本站文章可以评论。

好的,这是一个典型的贪心算法问题。假设有m个孩子和n个饼干,每个孩子都有一个贪心因子g[i],每个饼干都有一个大小s[j]。我们需要将饼干分配给孩子,使得满足贪心条件的孩子个数最大。具体的思路如下: 1. 将孩子和饼干按照贪心因子和大小从小到大排序。 2. 从第一个孩子和第一个饼干开始,依次比较孩子的贪心因子和饼干的大小,如果饼干的大小可以满足孩子的贪心因子,就将这个饼干分配给这个孩子,并且继续考虑下一个孩子和下一个饼干;否则就考虑下一个饼干是否可以满足这个孩子的贪心因子,直到找到一个合适的饼干或者没有合适的饼干为止。 3. 继续考虑下一个孩子和下一个饼干,直到所有的孩子都被分配了饼干或者没有合适的饼干为止。 下面是一个可运行的C++代码实现: ```cpp #include <iostream> #include <vector> #include <algorithm> using namespace std; int findContentChildren(vector<int>& g, vector<int>& s) { sort(g.begin(), g.end()); sort(s.begin(), s.end()); int i = 0, j = 0; while (i < g.size() && j < s.size()) { if (g[i] <= s[j]) { i++; } j++; } return i; } int main() { vector<int> g = {1, 2, 3}; vector<int> s = {1, 1}; cout << findContentChildren(g, s) << endl; // 输出1 g = {1, 2}; s = {1, 2, 3}; cout << findContentChildren(g, s) << endl; // 输出2 return 0; } ``` 其中,g为贪心因子数组,s为饼干大小数组,函数返回可以满足的孩子个数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值