如何实现屏幕旋转时BottomNavigationView固定位置并旋转图标?
要实现竖屏时顶部导航、横屏时左侧导航且图标文字适配旋转的效果,可通过布局资源适配+代码动态调整视图属性来完成,具体步骤如下:
1. 配置横竖屏布局资源
Android支持按屏幕方向加载不同布局,我们分别创建两种布局:
竖屏布局(res/layout/activity_main.xml)
保持BottomNavigationView在顶部,宽度铺满屏幕:
<com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/transparent" app:elevation="0dp" app:itemBackground="@color/transparent" app:itemIconTint="@drawable/selector" app:itemTextColor="@drawable/selector" app:labelVisibilityMode="labeled" app:menu="@menu/nav_menu" />
横屏布局(res/layout-land/activity_main.xml)
将BottomNavigationView放在左侧,高度铺满屏幕,后续通过代码处理旋转:
<com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/nav_bar" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@color/transparent" app:elevation="0dp" app:itemBackground="@color/transparent" app:itemIconTint="@drawable/selector" app:itemTextColor="@drawable/selector" app:labelVisibilityMode="labeled" app:menu="@menu/nav_menu" />
2. 代码动态处理视图旋转与布局
在Activity中监听屏幕方向变化,调整导航栏的旋转角度和布局参数,同时添加平滑过渡动画:
步骤1:配置Activity监听方向变化
在AndroidManifest.xml对应Activity中添加属性,避免旋转时重建页面:
<activity android:name=".MainActivity" android:configChanges="orientation|screenSize"> </activity>
步骤2:实现方向变化逻辑
在Activity中重写onConfigurationChanged方法:
override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) val navBar = findViewById<BottomNavigationView>(R.id.nav_bar) val targetRotation = if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) 270f else 0f val layoutParams = navBar.layoutParams // 平滑旋转动画 ObjectAnimator.ofFloat(navBar, View.ROTATION, navBar.rotation, targetRotation).apply { duration = 300 interpolator = AccelerateDecelerateInterpolator() start() } // 调整布局参数 if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) { layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT // 若使用ConstraintLayout,设置约束到左侧、顶部、底部 (layoutParams as? ConstraintLayout.LayoutParams)?.apply { startToStart = ConstraintLayout.LayoutParams.PARENT_ID topToTop = ConstraintLayout.LayoutParams.PARENT_ID bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID endToEnd = ConstraintLayout.LayoutParams.UNSET } } else { layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT (layoutParams as? ConstraintLayout.LayoutParams)?.apply { topToTop = ConstraintLayout.LayoutParams.PARENT_ID startToStart = ConstraintLayout.LayoutParams.PARENT_ID endToEnd = ConstraintLayout.LayoutParams.PARENT_ID bottomToBottom = ConstraintLayout.LayoutParams.UNSET } } navBar.layoutParams = layoutParams // 保存并恢复选中状态,避免旋转后丢失 val selectedItemId = navBar.selectedItemId navBar.selectedItemId = selectedItemId }
3. 优化菜单项显示(可选)
默认菜单项在旋转后文字方向可能不符合预期,可自定义item布局调整显示逻辑:
创建res/layout/custom_bottom_nav_item.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <ImageView android:id="@+id/icon" android:layout_width="24dp" android:layout_height="24dp" android:scaleType="centerInside"/> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="12sp" android:layout_marginTop="4dp"/> </LinearLayout>
在Activity的onCreate中设置自定义布局:
val navBar = findViewById<BottomNavigationView>(R.id.nav_bar) for (i in 0 until navBar.menu.size()) { navBar.setItemView(i, LayoutInflater.from(this).inflate(R.layout.custom_bottom_nav_item, navBar, false)) }
4. 关键注意点
- 若使用Java,将上述Kotlin代码转换为对应语法即可
- 测试不同分辨率设备,避免布局错位
- 若需要更精细的文字方向控制,可在自定义item布局中根据屏幕方向动态调整文字旋转角度
内容的提问来源于stack exchange,提问作者Do Ji
相关产品推荐
相关产品推荐

