部分内容参考http://blog.csdn.net/peidonghui/article/details/49583263,在此对原作者表示感谢。
在某些需求下,需要判断某一个View是否被遮挡,比如ListView的headerView中某一个View在ListView向上滑动到开始不可见时,在页面顶部固定显示一个View。在刚开始时,处理方式是在ListView的onScroll()中判断该View距离屏幕顶部的距离,来作为判断条件,网上好不容易找到解决方法,但测试的妹纸却在android 6.0的手机上测出兼容性BUG ,害得我周末跟妹纸约会都在想这个问题该怎么办,看来还是要仔细系统的研究一下自定义View和ViewGroup的相关问题
废话不多说,直接上代码。
1.当Android 的版本为6.0以下时
pullListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
Rect rect = new Rect();
line.getGlobalVisibleRect(rect);
if ((rect.top < statusBarHeight + DimenUtil.dip2px(mContext, 97)) ) {
if (rl_choosed_tag.getVisibility() == View.INVISIBLE)
rl_choosed_tag.setVisibility(View.VISIBLE);
} else {
if (rl_choosed_tag.getVisibility() == View.VISIBLE)
rl_choosed_tag.setVisibility(View.INVISIBLE);
}
}
});
以上line为listView的headerView布局中的一个view,通过line.getGlobalVisibleRect(rect);来判断该view距离屏幕顶部的距离是否小于指定值(此处该临界值为
statusBarHeight + DimenUtil.dip2px(mContext, 97))来作为另外一个View是否显示的条件
2.当Android 的S版本为6.0时
在onScroll()中这样处理
if (Build.VERSION.SDK_INT >= 23) {
if (isViewCovered(mSortFlowLayout)) {
if (rl_choosed_tag.getVisibility() == View.VISIBLE)
rl_choosed_tag.setVisibility(View.INVISIBLE);
} else {
if (rl_choosed_tag.getVisibility() == View.INVISIBLE)
rl_choosed_tag.setVisibility(View.VISIBLE);
}
}
涉及的isViewCovered()函数如下:
public boolean isViewCovered(final View view) {
View currentView = view;
Rect currentViewRect = new Rect();
boolean partVisible = currentView.getGlobalVisibleRect(currentViewRect);
boolean totalHeightVisible = (currentViewRect.bottom - currentViewRect.top) >= view.getMeasuredHeight();
boolean totalWidthVisible = (currentViewRect.right - currentViewRect.left) >= view.getMeasuredWidth();
boolean totalViewVisible = partVisible && totalHeightVisible && totalWidthVisible;
if (!totalViewVisible)//if any part of the view is clipped by any of its parents,return true
return true;
while (currentView.getParent() instanceof ViewGroup) {
ViewGroup currentParent = (ViewGroup) currentView.getParent();
if (currentParent.getVisibility() != View.VISIBLE)//if the parent of view is not visible,return true
return true;
int start = indexOfViewInParent(currentView, currentParent);
for (int i = start + 1; i < currentParent.getChildCount(); i++) {
Rect viewRect = new Rect();
view.getGlobalVisibleRect(viewRect);
View otherView = currentParent.getChildAt(i);
Rect otherViewRect = new Rect();
otherView.getGlobalVisibleRect(otherViewRect);
if (Rect.intersects(viewRect, otherViewRect))//if view intersects its older brother(covered),return true
return true;
}
currentView = currentParent;
}
return false;
}
private int indexOfViewInParent(View view, ViewGroup parent) {
int index;
for (index = 0; index < parent.getChildCount(); index++) {
if (parent.getChildAt(index) == view)
break;
}
return index;
}
虽然一个简单的判断却还需要分版本不同单独处理,不过应该有更加简洁优雅的解决方案,欢迎各位给出指导。