这是我在开发app中的筛选需求,使用popupwindow显示筛选panel,在我的Android4.2系统中显示效果,popupwindow被状态栏statusBar挡住。
需求中这个筛选的界面需要显示在所有Activity的上层,包括TabActivity,如果不使用popupwindow那么可能会出现下面的情况。
解决上面的bug我能用的解决方式是1:Activity 2Popupwindow。由于不想动用activity(当然使用起来完全没有关系,我就偷个懒),所以我是用了popupwindow。第一张图片中代码为
if(null == mShaixuanPanel){
mShaixuanPanel = (RelativeLayout) View.inflate(this, R.layout.shaixuan_panel, null);
}
if (popupWindow == null) {
popupWindow = new PopupWindow(this);
popupWindow.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
popupWindow.setHeight(ViewGroup.LayoutParams.MATCH_PARENT);
popupWindow.setBackgroundDrawable(new BitmapDrawable());
popupWindow.setFocusable(true);
popupWindow.setOutsideTouchable(true);
popupWindow.setContentView(mShaixuanPanel);
}
popupWindow.showAtLocation(mTitlebar, Gravity.CENTER, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
mTitlebar为我自己的布局的标题栏。
那么如何解决问题呢?大家都知道popupwindow的显示方式有这几种:
showAtLocation(View parent, int gravity, int x, int y)
showAtLocation(IBinder token, int gravity, int x, int y)
showAsDropDown(View anchor)
showAsDropDown(View anchor, int xoff, int yoff)
showAsDropDown(View anchor, int xoff, int yoff, int gravity)
以前一直以为showAsDropDown是个动画效果,现在明白了,动画需要自己定义。
animRightin = AnimationUtils.loadAnimation(this, R.anim.slide_in_from_right);
animRightin.setDuration(200);
mShaixuanPanel.findViewById(R.id.shaixuan_view).startAnimation(animRightin);
所以上面几种显示方式的含义是这样的showAtLocation是作为父布局的一个子布局显示没具体显示位置自己定义,跟父布局无关。showAsDropDown是显示在某个view的旁边,作为同一级布局,具体位置可以根据offset调整。
比如
popupWindow.showAsDropDown(mTitlebar, 0, 0);
现在我的需求是显示在标题栏下面,找到标题栏就可以,标题栏是系统的控件,暂时不想这么麻烦,可以简单地在activity布局最上方设置个高度为0的控件,然后popupwindow在它下面就行了。
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_alignParentTop="true"
android:id="@+id/top_line"/>
mTopLine = findViewById(R.id.top_line);
popupWindow.showAsDropDown(mTopLine, 0, 0);
到这里任务算完成了。
另外,可以再popupwindow的布局的中间中设置paddingTop
android:paddingTop="?android:attr/actionBarSize"
但是这个是actionBar的高度,不是statusBar。
那么能获取statusBar高度吗?答案是可以。
2.获取状态栏高度:
decorView是window中的最顶层view,可以从window中获取到decorView,然后decorView有个getWindowVisibleDisplayFrame方法可以获取到程序显示的区域,包括标题栏,但不包括状态栏。
于是,我们就可以算出状态栏的高度了。
1
2
3
4
|
代码
Rect frame = new Rect();
getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
|
有时候获取到的高度是0,可以用另一种方法获取
在源码程序中获取状态栏高度代码:
height= getResources().getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
1
2
3
4
5
6
|
代码
class c = Class.forName("com.android.internal.R$dimen");
Object obj = c.newInstance();
Field field = c.getField("status_bar_height");
int x = Integer.parseInt(field.get(obj).toString());
int y = getResources().getDimensionPixelSize(x);
|