Android 8中LANDSCAPE切换至REVERSE_LANDSCAPE时如何判断导航栏位置
解决Android 8导航栏位置判断与旋转监听问题
嘿,我来帮你搞定这个导航栏位置判断的问题!你遇到的横屏/反向横屏切换时,旧的判断逻辑没及时更新导致异常的情况,其实有几个很实用的解决方案,一起来看看:
一、监听屏幕旋转回调,及时刷新判断逻辑
当屏幕旋转时,咱们可以通过重写Activity的onConfigurationChanged方法,主动触发导航栏位置的重新判断,步骤很简单:
先在Manifest里配置Activity的configChanges
这样系统不会在旋转时重启你的Activity,而是回调onConfigurationChanged方法,咱们就能在里面更新逻辑了:<activity android:name=".YourActivity" android:configChanges="orientation|screenSize|smallestScreenSize" />重写Activity的onConfigurationChanged方法
把你的导航栏位置判断逻辑封装成一个方法,在这个回调里重新调用它:@Override public void onConfigurationChanged(@NonNull Configuration newConfig) { super.onConfigurationChanged(newConfig); // 旋转发生时,重新检查导航栏位置 checkNavigationBarPosition(); } private void checkNavigationBarPosition() { View rootView = getWindow().getDecorView().getRootView(); int deviceScreenWidth = getResources().getDisplayMetrics().widthPixels; if (rootView.getWidth() == deviceScreenWidth) { // 平板导航栏在底部,或者三星设备无导航栏 } else if (rootView.getLocationOnScreen()[0] == 0) { // 导航栏在左侧 } else { // 导航栏在右侧 } }要是你是在Fragment里处理,直接重写Fragment的
onConfigurationChanged方法,同样调用这个判断逻辑就行。
二、用更靠谱的系统API判断导航栏位置
比起通过根View的尺寸和位置判断,直接用系统提供的API会更准确,还能自动响应布局变化,推荐两个方案:
方案1:通过屏幕旋转方向直接判断
Android的Display类能拿到当前屏幕的旋转状态,结合Android 8的导航栏行为,咱们可以直接映射导航栏位置:
import android.view.Surface; import android.view.WindowManager; private void judgeNavigationBarByRotation() { int rotation = ((WindowManager) getSystemService(WINDOW_SERVICE)).getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_90: // LANDSCAPE横屏状态,导航栏在右侧 break; case Surface.ROTATION_270: // REVERSE_LANDSCAPE反向横屏,导航栏在左侧 break; case Surface.ROTATION_0: case Surface.ROTATION_180: // 竖屏状态,导航栏在底部(手机)或者侧边(平板) break; } }
方案2:监听WindowInsets获取导航栏Insets
WindowInsets是官方推荐的获取系统UI占据空间的方式,不管屏幕怎么旋转,甚至导航栏动态显示隐藏,它都能实时返回最新的空间数据:
import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; private void setupNavigationBarListener() { View rootView = getWindow().getDecorView(); ViewCompat.setOnApplyWindowInsetsListener(rootView, (v, insets) -> { WindowInsetsCompat navInsets = insets.getInsets(WindowInsetsCompat.Type.navigationBars()); int leftInset = navInsets.left; int rightInset = navInsets.right; if (leftInset > 0) { // 导航栏在左侧 } else if (rightInset > 0) { // 导航栏在右侧 } else { // 导航栏在底部或者已经隐藏 } return insets; }); }
这个方法的好处是完全不用手动监听旋转,只要导航栏的位置或状态变了,它就会自动触发判断,从根源上避免了逻辑滞后的问题。
三、总结一下
- 如果你想继续用原来的判断逻辑,只需要加上
onConfigurationChanged回调,在旋转时重新执行判断就可以解决异常; - 更推荐用WindowInsets监听的方法,兼容性更好,还能处理更多边缘情况,比如用户手动隐藏导航栏的场景。
内容的提问来源于stack exchange,提问作者SIMMORSAL
相关产品推荐
相关产品推荐

