有次在工作上遇到需要在安卓APP中,防止上方狀態列被使用者下拉展開的需求,一開始聽到毫無頭緒,怎麼想都不會有API提供直接的方式,了不起就是隱藏起來不顯示而已,因為一直沒想到確切的關鍵字,所以一直google不到解法,沒想到老闆居然找到了一篇stackoverflow的問題,裡面的一篇回答解決了這個問題
主要原理是產生一個透明並且和狀態列等高的view,攔截觸控事件,用WindowManager放在畫面上方,因此view會壓在畫面的最上層,剛好蓋住狀態列,即使可以拉下來看到狀態列,但第二次在下拉想展開就沒用了。用的真巧妙,就這樣成功達成需求了,不過原文的作法比較繁瑣,還要自定義一個繼承ViewGroup的class,後來我把它簡化成以下程式碼,直接在onCreate使用就可以了
//狀態列遮罩,防止跳出,僅在上下跳出時才顯示,記得需要權限也要一併添加
private ViewGroup topOverlay;
WindowManager manager;
WindowManager.LayoutParams topOverlayLayoutParams;
@Override
protected void onCreate(Bundle savedInstanceState) {
manager = ((WindowManager)getApplicationContext().getSystemService(Context.WINDOW_SERVICE));
topOverlay = new ViewGroup(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) { return true; }
};
topOverlayLayoutParams = new WindowManager.LayoutParams();
topOverlayLayoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
topOverlayLayoutParams.gravity = Gravity.TOP;
topOverlayLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
// this is to enable the notification to receive touch events
WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL |
// Draws over status bar
WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
topOverlayLayoutParams.width = WindowManager.LayoutParams.MATCH_PARENT;
topOverlayLayoutParams.height = (int) (50 * getResources()
.getDisplayMetrics().scaledDensity);
topOverlayLayoutParams.format = PixelFormat.TRANSPARENT;
manager.addView(topOverlay, topOverlayLayoutParams);
}
@Override
protected void onDestroy(){
//程式結束時移除掉,不然即使退出回到桌面了,也無法展開XD
manager.removeView(topOverlay);
super.onDestroy();
}
注意此功能需要權限 android.permission.SYSTEM_ALERT_WINDOW ,並且6.0以上需要檢查及要求,否則用戶取消權限後,一進入APP就會閃退。
只能說想到對的關鍵字真的很重要,畢竟許多問題都有人遇過並且解答了,能不能找到又是另一門學問。
參考來源
發表迴響