1. 程式人生 > >安卓隱藏手機虛擬按鍵

安卓隱藏手機虛擬按鍵

我的實現思路是,通過監聽根佈局的檢視高度的變化,來判斷虛擬按鍵的隱藏和顯示

1. 在oncreate中View.getWidth和View.getHeight無法獲得一個view的高度和寬度,這是因為View元件佈局要在onResume回撥後完成。所以現在需要使用getViewTreeObserver().addOnGlobalLayoutListener()來獲得根佈局的高度。

2. OnGlobalLayoutListener 是ViewTreeObserver的內部類,當一個檢視樹的佈局發生改變時,可以被ViewTreeObserver監聽到,這是一個註冊監聽檢視樹的觀察者(observer),在檢視樹的全域性事件改變時得到通知。ViewTreeObserver不能直接例項化,而是通過getViewTreeObserver()獲得。

3. 獲取到當前佈局的高度和activity跟佈局的高度,進行對比

程式碼如下:

//隱藏虛擬按鍵
rootView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

    @Override
public void onGlobalLayout() {

        //比較Activity根佈局與當前佈局的大小
int heightDiff = rootView.getRootView().getHeight() - rootView.getHeight();
if (heightDiff > 100) { //大小超過100時,一般為顯示虛擬鍵盤事件 rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE); } else { //大小小於100時,為不顯示虛擬鍵盤或虛擬鍵盤隱藏 rootView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION); } } });

第一種方法存在一些問題,更完美的解決方案,簡單粗暴,請看下面的方法

第二種方法

  1. /**  
  2.  * 隱藏虛擬按鍵,並且設定成全屏  
  3.  */  
  4. private void hideBottomState(){  
  5.     if (Build.VERSION.SDK_INT > 11 && Build.VERSION.SDK_INT <19) { // lower api  
  6.         View v = this.getWindow().getDecorView();  
  7.         v.setSystemUiVisibility(View.GONE);  
  8.     } else if (Build.VERSION.SDK_INT >= 19) {  
  9.         //for new api versions.  
  10.         View decorView = getWindow().getDecorView();  
  11.         int uiOptions = View.SYSTEM_UI_FLAG_LAYOUT_STABLE  
  12.                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION  
  13.                 | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN  
  14.                 | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar  
  15.                   | View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar  
  16.                 | View.SYSTEM_UI_FLAG_IMMERSIVE;  
  17.         decorView.setSystemUiVisibility(uiOptions);  
  18.         getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);  
  19.     }  

擴充套件功能

  1. /**  
  2.      * 檢查是否存在虛擬按鍵欄  
  3.      * @param context  
  4.      * @return  
  5.      */  
  6.     public static boolean hasNavBar(Context context) {  
  7.         Resources res = context.getResources();  
  8. //這種方式一定要注意寫法要正確,內部應該是通過反射去呼叫的。
  9.         int resourceId = res.getIdentifier("config_showNavigationBar", "bool", "android");  
  10.         if (resourceId != 0) {  
  11.             boolean hasNav = res.getBoolean(resourceId);  
  12.             // check override flag  
  13.             String sNavBarOverride = getNavBarOverride();  
  14.             if ("1".equals(sNavBarOverride)) {  
  15.                 hasNav = false;  
  16.             } else if ("0".equals(sNavBarOverride)) {  
  17.                 hasNav = true;  
  18.             }  
  19.             return hasNav;  
  20.         } else { // fallback  
  21.             return !ViewConfiguration.get(context).hasPermanentMenuKey();  
  22.         }  
  23.     }  
  24.     /**  
  25.      * 判斷虛擬按鍵欄是否重寫  
  26.      * @return  
  27.      */  
  28.     private static String getNavBarOverride() {  
  29.         String sNavBarOverride = null;  
  30.         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {  
  31.             try {  
  32.                 Class c = Class.forName("android.os.SystemProperties");  
  33.                 Method m = c.getDeclaredMethod("get", String.class);  
  34.                 m.setAccessible(true);  
  35.                 sNavBarOverride = (String) m.invoke(null, "qemu.hw.mainkeys");  
  36.             } catch (Throwable e) {  
  37.             }  
  38.         }  
  39.         return sNavBarOverride;  
  40.     }