https://www.2cto.com/kf/201703/605854.html
如上述网址所述,有两种通用的方法。第二中方法其实没有必要新建一个服务。
其实可以直接这样用:
优化方案一:
1、onCreate的时候:
private void initStatusBarHelperView() { WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mStatusBarHelperView = new View(mContext); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; lp.gravity = Gravity.LEFT | Gravity.TOP; lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; lp.format = PixelFormat.TRANSLUCENT; wm.addView(mStatusBarHelperView, lp); }
2、onDestory的时候:
public void removeStatusBarHelperView() { WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.removeView(mStatusBarHelperView); mStatusBarHelperView = null; }
3、需要高度的时候:
public int getStatusBarHeight() { int[] windowParams = new int[2]; int[] screenParams = new int[2]; mStatusBarHelperView.getLocationInWindow(windowParams); mStatusBarHelperView.getLocationOnScreen(screenParams); return screenParams[1] - windowParams[1]; }
上面的方法亲测已经满足。
优化方案二:
考虑到如果在服务中,只在destory才remove,新建的view一直存在也不太好。所以在onstart和onpusue调用对应的方法比较合适,但是如果频繁的调用又有性能问题,故最终采用在remove的时候延迟执行。最后写了一个工具类,直接调用如下三个方法即可:
StatusBarHelper.getInstance().getStatusBarHeight()
StatusBarHelper.getInstance().addStatusBarHelperView();
StatusBarHelper.getInstance().removeStatusBarHelperView();
工具类如下:
package com.smartisanos.ime.util; import android.content.Context; import android.graphics.PixelFormat; import android.os.Handler; import android.os.Message; import android.view.Gravity; import android.view.View; import android.view.WindowManager; import com.smartisanos.ime.IMEApp; public class StatusBarHelper { private Context mContext; private View mStatusBarHelperView; private static StatusBarHelper mStatusBarHelper = new StatusBarHelper(); private static final int MSG_INIT_STATUS_BAR = 1; private static final int MSG_REMOVE_STATUS_BAR = 2; private static final long MSG_REMOVE_DELAY_TIME = 500L; private Handler mStatusBarHandler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case MSG_INIT_STATUS_BAR: mStatusBarHandler.removeMessages(MSG_REMOVE_STATUS_BAR); initStatusBarHelperView(); break; case MSG_REMOVE_STATUS_BAR: WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); wm.removeView(mStatusBarHelperView); mStatusBarHelperView = null; break; } } }; private StatusBarHelper() { mContext = IMEApp.getContext(); } public static StatusBarHelper getInstance() { return mStatusBarHelper; } /* //由于在本类的构造方法中并没有耗时操作,所以不需要在getInstance()中进行new操作,可以直接在定义变量时直接new。故没有用下面的方法 public static StatusBarHelper getInstance() { if (mStatusBarHelper == null) { mStatusBarHelper = new StatusBarHelper(); } return mStatusBarHelper; } */ private void initStatusBarHelperView() { if (mStatusBarHelperView != null) { return; } WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); mStatusBarHelperView = new View(mContext); WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; lp.gravity = Gravity.LEFT | Gravity.TOP; lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; lp.format = PixelFormat.TRANSLUCENT; wm.addView(mStatusBarHelperView, lp); } public void addStatusBarHelperView() { Message message = mStatusBarHandler.obtainMessage(StatusBarHelper.MSG_INIT_STATUS_BAR); mStatusBarHandler.sendMessage(message); } public void removeStatusBarHelperView() { Message message = mStatusBarHandler.obtainMessage(StatusBarHelper.MSG_REMOVE_STATUS_BAR); mStatusBarHandler.sendMessageDelayed(message, StatusBarHelper.MSG_REMOVE_DELAY_TIME); } public int getStatusBarHeight() { if (mStatusBarHelperView == null) { return 0; } int[] windowParams = new int[2]; int[] screenParams = new int[2]; mStatusBarHelperView.getLocationInWindow(windowParams); mStatusBarHelperView.getLocationOnScreen(screenParams); return screenParams[1] - windowParams[1]; } }
20190806更新
注意:适配8.0时,需initStatusBarHelperView()方法中,要修改两处
1、要给window设置不获取焦点:FLAG_NOT_FOCUSABLE
2、Android8.0时,要用TYPE_APPLICATION_OVERLAY
1 private void initStatusBarHelperView() { 2 boolean isShown = ServiceManager.getInstance().getInputMethodService().isInputViewShown(); 3 Log.d(TAG, "initStatusBarHelperView: isShown="+isShown+" mStatusBarHelperView="+mStatusBarHelperView); 4 if (mStatusBarHelperView != null || !isShown) { 5 return; 6 } 7 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); 8 mStatusBarHelperView = new View(mContext); 9 WindowManager.LayoutParams lp = new WindowManager.LayoutParams(); 10 lp.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL 11 | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE 12 | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE; 13 lp.gravity = Gravity.LEFT | Gravity.TOP; 14 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { 15 lp.type = WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; 16 } else { 17 lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; 18 } 19 lp.format = PixelFormat.TRANSLUCENT; 20 lp.width = 1; 21 wm.addView(mStatusBarHelperView, lp); 22 }
后来的优化代码见博客:
https://www.cnblogs.com/longjunhao/p/9055087.html