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源码分析


Android10源代码  
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);
                    }
                });




Android12源代码


 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);
                            }
							
							// 新增
							mContext.sendBroadcast(new Intent("com.android.action.swipefrombottom")); //自定义上滑广播
						 
                            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中接收对应事件实现隐藏显示效果。我直接在onSwipeFromBottom发送广播。

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

3.实现如下

        在向上滑动onSwipeFromBottom方法中发送广播,来通知navigarbar显示隐藏。

mContext.sendBroadcast(new Intent("com.android.action.swipefrombottom")); //自定义上滑广播

类路径:frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java



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

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

代码内容

frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java

 第一步 修改变量
 +代表新增的意思

+    private boolean navigationBarState = false;
+    private RegisterStatusBarResult result = null;

  // 注释局部变量改成全局变量
  // RegisterStatusBarResult result = null;

第二步 注释NavigationBar

  //createNavigationBar(result); //注释


第三步 注册广播 internalFilter.addAction全局搜索
   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);



第四步 接收广播mBannerActionBroadcastReceiver系统自动

    private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
                NotificationManager noMan = (NotificationManager)
                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
                noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage.
                        NOTE_HIDDEN_NOTIFICATIONS);

                Settings.Secure.putInt(mContext.getContentResolver(),
                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
                if (BANNER_ACTION_SETUP.equals(action)) {
                    mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
                            true /* force */);
                    mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

                    );
                }
            }


            // 新增代码
			// 分割线
			else if("com.android.action.swipefrombottom".equals(action)){
	            //上滑事件
			     Log.d("StatusBar","swipefrombottom---666--");
			  if(!navigationBarState){
			        navigationBarState = true;
			        //加载导航栏
			        createNavigationBar(result);
			        mHandler.postDelayed(new Runnable() {
			                @Override
			                public void run() {
							  navigationBarState = false;
							// 移除导航栏
		                      mNavigationBarController.removeNavigationBar(mDisplayId);
			                }
			            },6000);
			  }
		    }else if("com.android.action.swipefromtop".equals(action)){
			     Log.d("StatusBar","swipefromtop--666-");
			//下滑事件
			   mNavigationBarController.removeNavigationBar(mDisplayId);
		   }
            // 新增代码
			// 分割线


        }
    };

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

4.修改隐藏导航栏方法

Android10 路径
frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/NavigationBarController.java

Android12 路径
frameworks/base/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBarController

public class NavigationBarController implements Callbacks {
     
     
    //隐藏导航栏方法变为public 方便调用
-   void removeNavigationBar(int displayId) {

   // 变成公布方法
+  public void removeNavigationBar(int displayId) {
        NavigationBar navBar = mNavigationBars.get(displayId);
        if (navBar != null) {
            navBar.setAutoHideController(/* autoHideController */ null);
            navBar.destroyView();
            mNavigationBars.remove(displayId);
        }
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值