1. 程式人生 > >popupwindow全螢幕顯示被狀態列擋住如何解決+Android獲取狀態列高度

popupwindow全螢幕顯示被狀態列擋住如何解決+Android獲取狀態列高度

這是我在開發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在它下面就行了。

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
    <View
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);