android--判断两个view是否有重叠(微信最新表情面板回退按钮效果)

android–判断两个view是否有重叠

  • 有时我们需要判断两个view是否有重叠,例如实现以下微信emoji表情面板这个回退按钮的效果
  • 在这里插入图片描述
  • 如果要做到这个效果,我的思路是获取这个回退按钮在屏幕中的位置,然后在滚动时判断每个itemview的位置是否和回退按钮有交叉,有的话就根据交叉情况设置透明度
  • 那么怎么拿到位置呢,可以通过View.getGlobalVisibleRect获得当前view在屏幕中的矩形坐标
  • 之后通过Rect.containsRect.intersects即可判断连个Rect是包含还是交叉
  • 值得注意的是,当判断是否交叉的时候我们要用Rect.intersects这个静态方法,而不是Rect.intersect
  • 得到交叉区域我们要用Rect.intersect这个方法,两个方法名只有一个字母只差
  • 然后你就需要给RecyclerView添加一个滑动监听器(RecyclerView.addOnScrollListener),在监听器里实现上面的思路
  • 如果你想根据交叉区域的大小设置透明度,则需要用到Rect.intersect,调用后,这个Rect对象就变成交叉区域的部分了,这个要好好理解一下,例如矩形a.intersect(b)调用后,那么a就变成a和b的交叉部分了,不再是原来那个a了
  • 参考代码如下
	/**
     * 
     * @param recyclerView
     * @param panelRect 表情面板的位置矩形,主要是为了优化比较的次数,没有就传一个空矩形即可
     * @param deleteRect 删除按钮的位置矩形
     */
    private void handleChildView(@NotNull RecyclerView recyclerView, @NonNull Rect panelRect, @NotNull Rect deleteRect) {
        RecyclerView.LayoutManager manager = recyclerView.getLayoutManager();
        if (manager == null) {
            return;
        }
        Rect tmp = new Rect();
        int count = manager.getChildCount();
        for (int i = 0; i < count; i++) {
            View child = manager.getChildAt(i);
            tmp.setEmpty();
            child.getGlobalVisibleRect(tmp);
            if (!panelRect.isEmpty() && !panelRect.contains(tmp)) {
                continue;
            }
            if (deleteRect.contains(tmp)) {
                child.setAlpha(0.0f);
            } else if (Rect.intersects(deleteRect, tmp)) {
                //计算交叉占比
                float scale = getRatio(tmp, deleteRect);
                if (scale > 0.5f) {
                    child.setAlpha(0.0f);
                } else {
                    child.setAlpha(1 - scale);
                }
            } else {
                child.setAlpha(1.0f);
            }
        }
    }
	/**
     * 获得两个矩形的交叉部分占r1的比例
     *
     * @param r1
     * @param r2
     * @return
     */
    private float getRatio(@NotNull Rect r1, @NotNull Rect r2) {
        if (r1.isEmpty()) {
            return 0;
        }
        Rect tmp = new Rect(r1.left, r1.top, r1.right, r1.bottom);
        int sourceSize = tmp.width() * tmp.height();//原本的大小
        tmp.intersect(r2);//调用后tmp即变为交叉部分了
        int intersectSize = tmp.width() * tmp.height();//交叉部分的大小
        float scale = intersectSize * 1.0f / sourceSize;
        return scale;
    }

参考

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值