android–判断两个view是否有重叠
- 有时我们需要判断两个view是否有重叠,例如实现以下微信emoji表情面板这个回退按钮的效果
- 如果要做到这个效果,我的思路是获取这个回退按钮在屏幕中的位置,然后在滚动时判断每个itemview的位置是否和回退按钮有交叉,有的话就根据交叉情况设置透明度
- 那么怎么拿到位置呢,可以通过View.getGlobalVisibleRect获得当前view在屏幕中的矩形坐标
- 之后通过Rect.contains和Rect.intersects即可判断连个Rect是包含还是交叉
- 值得注意的是,当判断是否交叉的时候我们要用Rect.intersects这个静态方法,而不是Rect.intersect
- 得到交叉区域我们要用Rect.intersect这个方法,两个方法名只有一个字母只差
- 然后你就需要给RecyclerView添加一个滑动监听器(RecyclerView.addOnScrollListener),在监听器里实现上面的思路
- 如果你想根据交叉区域的大小设置透明度,则需要用到Rect.intersect,调用后,这个Rect对象就变成交叉区域的部分了,这个要好好理解一下,例如矩形a.intersect(b)调用后,那么a就变成a和b的交叉部分了,不再是原来那个a了
- 参考代码如下
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);
}
}
}
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);
int intersectSize = tmp.width() * tmp.height();
float scale = intersectSize * 1.0f / sourceSize;
return scale;
}
参考