扩大控件点击区域

以下为通用方法,默认将控件上下左右各扩大 3dp 的点击区域,读者可以自行将 3dp 修改为自己想要的数值:

         void increaseHotArea(View view) {
                Rect delegateArea = new Rect();

                view.getHitRect(delegateArea);

                final int _3DP = dp2px(view.getContext(), 3);
                delegateArea.left -= _3DP;
                delegateArea.top -= _3DP;
                delegateArea.right += _3DP;
                delegateArea.bottom += _3DP;

                TouchDelegate touchDelegate = new TouchDelegate(delegateArea, view);

                if (View.class.isInstance(view.getParent())) {
                    ((View) view.getParent()).setTouchDelegate(touchDelegate);
                }
            }

            int dp2px(Context context, float dp) {
                if (context == null) {
                    return (int) dp;
                }
                DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
                return (int) (dp * (displayMetrics != null ? displayMetrics.density : 3));
            }

其中需要注意的是,调用 increaseHotArea() 的方法,直接调用因为目标控件还未绘制完成导致获取目标区域失败,正确的方式应该是:

view.post(new Runnable() {
                @Override
                public void run() {
                    increaseHotArea(view);
                }
            });

另一个需要注意的点是,同时给同一个父控件设置多个子控件的 TouchDelegate,可能会出现点击事件错乱的现象。比如下面这个布局:

————————
| A B |
|______________|

一个父控件里面有两个子控件,分别扩大 A 和 B 的点击区域:

increaseHotArea(A);
increaseHotArea(B);

你会发现你一个奇怪的现象:点击 A 周围的区域,会触发 B 的点击事件。这是因为一个 View/ViewGroup 中只有一个 TouchDelegate,故 A 的 TouchDelegate 其实被 B 的覆盖了,从而失效。

你可能感兴趣的:(Android,UI,开发)