[Android]防止上方狀態列展開

有次在工作上遇到需要在安卓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就會閃退。

只能說想到對的關鍵字真的很重要,畢竟許多問題都有人遇過並且解答了,能不能找到又是另一門學問。

參考來源

發表留言

在 WordPress.com 建立網站或網誌

向上 ↑