SystemUI手势操作隐藏显示导航栏

         在Android 12中,通过SystemUI手势操作来隐藏和显示导航栏主要涉及对系统UI的定制和编程控制。以下是一些实现这一功能的方法:

第一类. 使用WindowInsetsController

Android 12引入了一个新的WindowInsetsController类,它允许开发者更好地控制系统窗口的行为,包括导航栏的显示和隐藏。

1.1.步骤概述

  • AndroidManifest.xml文件中设置应用支持的最低SDK版本为Android 12(android:minSdkVersion="S")。
  • 在活动的onCreate方法中获取WindowInsetsController实例。
  • 使用hideshow方法来控制导航栏的显示和隐藏。

示例代码

import androidx.appcompat.app.AppCompatActivity;  
import android.os.Bundle;  
import androidx.core.view.WindowInsetsCompat;  
import androidx.core.view.WindowInsetsControllerCompat;  
  
public class MainActivity extends AppCompatActivity {  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
  
        WindowInsetsControllerCompat controller = WindowInsetsControllerCompat(getWindow(), getWindow().getDecorView());  
  
        // 隐藏导航栏  
        controller.hide(WindowInsetsCompat.Type.navigationBars());  
  
        // 在需要时显示导航栏  
        // controller.show(WindowInsetsCompat.Type.navigationBars());  
  
        // 检查导航栏是否可见  
        boolean isVisible = controller.isVisible(WindowInsetsCompat.Type.navigationBars());  
    }  
}

第二类、修改系统源码

1.可以通过修改系统源码实现底部导航栏 的控制涉及的类

Android10
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java


android12
frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController

2.DisplayPolicy源码分析

  mSystemGestures = new SystemGesturesPointerEventListener(mUiContext, mHandler,
                new SystemGesturesPointerEventListener.Callbacks() {
                    @Override
                    public void onSwipeFromTop() {
                        synchronized (mLock) {
                            if (mStatusBar != null) {
                                requestTransientBars(mStatusBar);
                            }
                            checkAltBarSwipeForTransientBars(ALT_BAR_TOP);
                        }
                    }

                    @Override
                    public void onSwipeFromBottom() {
                        synchronized (mLock) {
                            if (mNavigationBar != null
                                    && mNavigationBarPosition == NAV_BAR_BOTTOM) {
                                requestTransientBars(mNavigationBar);
                            }
                            checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
                        }
                    }

                    @Override
                    public void onSwipeFromRight() {
                        final Region excludedRegion = Region.obtain();
                        synchronized (mLock) {
                            mDisplayContent.calculateSystemGestureExclusion(
                                    excludedRegion, null /* outUnrestricted */);
                            final boolean excluded =
                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_RIGHT
                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
                                requestTransientBars(mNavigationBar);
                            }
                            checkAltBarSwipeForTransientBars(ALT_BAR_RIGHT);
                        }
                        excludedRegion.recycle();
                    }

                    @Override
                    public void onSwipeFromLeft() {
                        final Region excludedRegion = Region.obtain();
                        synchronized (mLock) {
                            mDisplayContent.calculateSystemGestureExclusion(
                                    excludedRegion, null /* outUnrestricted */);
                            final boolean excluded =
                                    mSystemGestures.currentGestureStartedInRegion(excludedRegion);
                            if (mNavigationBar != null && (mNavigationBarPosition == NAV_BAR_LEFT
                                    || !excluded && mNavigationBarAlwaysShowOnSideGesture)) {
                                requestTransientBars(mNavigationBar);
                            }
                            checkAltBarSwipeForTransientBars(ALT_BAR_LEFT);
                        }
                        excludedRegion.recycle();
                    }

                    @Override
                    public void onFling(int duration) {
                        if (mService.mPowerManagerInternal != null) {
                            mService.mPowerManagerInternal.setPowerBoost(
                                    Boost.INTERACTION, duration);
                        }
                    }

                    @Override
                    public void onDebug() {
                        // no-op
                    }

                    private WindowOrientationListener getOrientationListener() {
                        final DisplayRotation rotation = mDisplayContent.getDisplayRotation();
                        return rotation != null ? rotation.getOrientationListener() : null;
                    }

                    @Override
                    public void onDown() {
                        final WindowOrientationListener listener = getOrientationListener();
                        if (listener != null) {
                            listener.onTouchStart();
                        }
                    }

                    @Override
                    public void onUpOrCancel() {
                        final WindowOrientationListener listener = getOrientationListener();
                        if (listener != null) {
                            listener.onTouchEnd();
                        }
                    }

                    @Override
                    public void onMouseHoverAtTop() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_STATUS;
                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
                    }

                    @Override
                    public void onMouseHoverAtBottom() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                        Message msg = mHandler.obtainMessage(MSG_REQUEST_TRANSIENT_BARS);
                        msg.arg1 = MSG_REQUEST_TRANSIENT_BARS_ARG_NAVIGATION;
                        mHandler.sendMessageDelayed(msg, 500 /* delayMillis */);
                    }

                    @Override
                    public void onMouseLeaveFromEdge() {
                        mHandler.removeMessages(MSG_REQUEST_TRANSIENT_BARS);
                    }
                });

由于我们需要实现的是手势上滑隐藏导航栏,故只需关注onSwipeFromBottom方法,在其中触发事件时发送对应事件,然后载在SystemUI中接收对应事件实现隐藏显示效果。我直接在

                    @Override
                    public void onSwipeFromBottom() {
                        synchronized (mLock) {
                            if (mNavigationBar != null
                                    && mNavigationBarPosition == NAV_BAR_BOTTOM) {
										  //自定义上滑广播  
								mContext.sendBroadcast(new Intent("com.android.action.swipefrombottom")); //自定义上滑广播
								//自定义上滑广播

                                requestTransientBars(mNavigationBar);
                            }
                            checkAltBarSwipeForTransientBars(ALT_BAR_BOTTOM);
                        }
                    }

3.实现如下

--- a/frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java


import com.android.server.policy.WindowOrientationListener;
 import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.wallpaper.WallpaperManagerInternal;
 import com.android.server.wm.utils.InsetUtils;

+import android.util.Log;
 import java.io.PrintWriter;
 //unisoc: For Power Hint
 import android.os.PowerHintVendorSprd;

public class DisplayPolicy extends AbsDisplayPolicy {
                         if (mStatusBar != null) {
                             requestTransientBars(mStatusBar);
                         }
+   //mContext.sendBroadcast(new Intent("com.android.action.swipefromtop"));
                     }
 
 @Override
 public class DisplayPolicy extends AbsDisplayPolicy {
                                 updateShowHideNavSettings(true);
                             }
                         }
     //自定义上滑广播
+           mContext.sendBroadcast(new             
            Intent("com.android.action.swipefrombottom"));
+           Log.e("StatusBar","onSwipeFromBottom");
        }

3 StatusBar监听自定义广播然后实现导航栏显示和隐藏功能

--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -673,7 +673,7 @@ public class StatusBar extends SystemUI implements DemoMode,
             };
     private ActivityIntentHelper mActivityIntentHelper;
     private ShadeController mShadeController;
+    private boolean navigationBarState = false;
-
+    private RegisterStatusBarResult result = null;
     @Override
     public void onActiveStateChanged(int code, int uid, String packageName, boolean active) {
         Dependency.get(MAIN_HANDLER).post(() -> {
@@ -779,7 +779,6 @@ public class StatusBar extends SystemUI implements DemoMode,
         mCommandQueue = getComponent(CommandQueue.class);
         mCommandQueue.addCallback(this);
 
-        RegisterStatusBarResult result = null;
         try {
             result = mBarService.registerStatusBar(mCommandQueue);
         } catch (RemoteException ex) {
@@ -824,6 +823,8 @@ public class StatusBar extends SystemUI implements DemoMode,
         IntentFilter internalFilter = new IntentFilter();
         internalFilter.addAction(BANNER_ACTION_CANCEL);
         internalFilter.addAction(BANNER_ACTION_SETUP);
+        internalFilter.addAction("com.android.action.swipefrombottom");
         //internalFilter.addAction("com.android.action.swipefromtop");
         mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
                 null);
 
@@ -963,7 +964,7 @@ public class StatusBar extends SystemUI implements DemoMode,
         mNotificationLogger.setHeadsUpManager(mHeadsUpManager);
         putComponent(HeadsUpManager.class, mHeadsUpManager);
 
-        createNavigationBar(result);
+        //createNavigationBar(result);
 
         if (ENABLE_LOCKSCREEN_WALLPAPER) {
             mLockscreenWallpaper = new LockscreenWallpaper(mContext, this, mHandler);
@@ -4515,7 +4516,19 @@ public class StatusBar extends SystemUI implements DemoMode,
 
                     );
                 }
-            }
+            }else if("com.android.action.swipefrombottom".equals(action)){
+                 //上滑事件               android.util.Log.d("StatusBar","swipefrombottom-----");
 + if(!navigationBarState = false){
 + navigationBarState = true;
                   //加载导航栏
+                 createNavigationBar(result);
+                                mHandler.postDelayed(new Runnable() {
+                    @Override
+                    public void run() {
// 移除导航栏
+                       mNavigationBarController.removeNavigationBar(mDisplayId);
+                    }
+                 },3000);
+  }
+                       }else if("com.android.action.swipefromtop".equals(action)){
+                                android.util.Log.d("StatusBar","swipefromtop---");
+                 下滑事件
//mNavigationBarController.removeNavigationBar(mDisplayId);
+                       }
         }
     };

在 StatusBar的makeStatusBarView中去掉加载导航栏的方法createNavigationBar(result)而在start()方法中监听系统手势上滑的自定义广播,然后在收到自定义广播后,弹出系统导航栏,三秒钟后消失导航栏

4.修改隐藏导航栏方法

--- a/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
+++ b/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java
@@ -164,7 +164,7 @@ public class NavigationBarController implements Callbacks {
         });
     }
     //隐藏导航栏方法变为public 方便调用
-    private void removeNavigationBar(int displayId) {
+    public void removeNavigationBar(int displayId) {
         NavigationBarFragment navBar = mNavigationBars.get(displayId);
         if (navBar != null) {
             View navigationWindow = navBar.getView().getRootView();

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值