style配置了windowTranslucentStatus
<item name="android:windowTranslucentStatus">true</item>
会导致 顶部的状态栏和底部的虚拟按键区域浮起来,类似于FramLayout,DecorView在底层。这个时候在DecorView add的view就会被遮盖。
期待的效果如下
代码如下
decorView = (ViewGroup) activity.getWindow().getDecorView();
displayMetrics = activity.getResources().getDisplayMetrics();
viewParent = new LinearLayout(activity);
viewParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
loadingLayout = LayoutInflater.from(activity).inflate(R.layout.layout_loading_and_error, null,false);
int pointY = 0;
if (anchorView != null) {
int[] anchorLocation = new int[2];
anchorView.getLocationInWindow(anchorLocation);
pointY = anchorLocation[1] + anchorView.getHeight();
}
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(displayMetrics.widthPixels,displayMetrics.heightPixels - pointY);
layoutParams.width = displayMetrics.widthPixels;
layoutParams.height = displayMetrics.heightPixels - pointY;
layoutParams.gravity = Gravity.BOTTOM;
viewParent.removeView(loadingLayout);//先移除再添加,防止隐藏后,再次显示,导致loadingLayout重复添加
//添加视图
viewParent.addView(loadingLayout, layoutParams);
decorView.addView(viewParent);
其中anchorView是锚点的view,与PopWind中的类型,要显示在anchorView 下面。这里的anchorView 是ActionBar.
现在decorView中添加一个完全填充的LinearLaout viewParent,然后再在viewParent中添加真正的视图loadingLayout ,并控制loadingLayout的位置和宽高。
实际效果如下
发现有两处异常显示的问题
- Actionbar与下面网络图片直接有一个间距
- 底部黄色区域被遮盖住了一部分
这两个问题都是由于上面说的windowTranslucentStatus导致的。
通过分析发现,屏幕实际高度是1920px,displayMetrics.heightPixels=1812px,底部虚拟按键区域高度为108px,不在displayMetrics的区域内。
viewParent = new LinearLayout(activity);
viewParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT));
···
decorView.addView(viewParent);
这段代码是在decorView(1920px高度)中添加一个与它一样宽高的viewParent,所有viewParent占据了整个屏幕的大小。而windowTranslucentStatus=true,底部虚拟按键区域上浮,导致底部区域被覆盖。
而由于
int pointY = 0;
if (anchorView != null) {
int[] anchorLocation = new int[2];
anchorView.getLocationInWindow(anchorLocation);
pointY = anchorLocation[1] + anchorView.getHeight();
}
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(displayMetrics.widthPixels,displayMetrics.heightPixels - pointY);
layoutParams.width = displayMetrics.widthPixels;
layoutParams.height = displayMetrics.heightPixels - pointY;
layoutParams.gravity = Gravity.BOTTOM;
viewParent.removeView(loadingLayout);//先移除再添加,防止隐藏后,再次显示,导致loadingLayout重复添加
//添加视图
viewParent.addView(loadingLayout, layoutParams);
是想在viewParent的 displayMetrics的区域中添加一个loadingLayout,高度为displayMetrics.heightPixels - pointY。但是由于Gravity.BOTTOM+windowTranslucentStatus,导致本来预期的底部参考点由底部虚拟按键区域的顶部,变为屏幕的底部了,所以导致Actionbar与下面网络图片直接有一个间距,刚好是底部虚拟按键区域的高度108px。
解决方案
viewParent.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, displayMetrics.heightPixels));
在添加viewParent时,将其高度设置为displayMetrics.heightPixels,这样viewParent的底部刚好与虚拟区域的顶部对齐,这样就完美解决上面的问题了。