如何让Bottom Navigation Bar在Activity切换时保持固定不移动?
你当前的问题根源是多Activity架构下,页面切换动画会作用于整个Activity窗口,包括每个Activity里的Bottom Navigation Bar,所以切换时导航栏会跟着动。最合理的解决方案是改用单Activity + Fragment架构,把三个页面做成Fragment,导航栏固定在主Activity中,只切换Fragment内容区域。
具体实现步骤
1. 将原Activity改为Fragment
把SettingsActivity和StatsActivity重构为SettingsFragment、StatsFragment,示例代码:
class SettingsFragment : Fragment() { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { return inflater.inflate(R.layout.fragment_settings, container, false) } }
2. 调整主Activity布局
让Bottom Navigation Bar固定在底部,上方用Fragment容器承载页面内容(示例布局activity_main.xml):
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <!-- Fragment容器,占满除导航栏外的所有空间 --> <androidx.fragment.app.FragmentContainerView android:id="@+id/fragment_container" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> <!-- 固定在底部的导航栏 --> <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottom_navigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="?android:attr/windowBackground" app:menu="@menu/bottom_nav_menu" /> </LinearLayout>
3. 修改主Activity代码,实现Fragment切换
不再启动新Activity,而是切换Fragment,并给Fragment切换添加动画:
class MainActivity : AppCompatActivity() { private lateinit var navbar: BottomNavigationView override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) navbar = findViewById(R.id.bottom_navigation) // 初始化默认加载首页Fragment if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.fragment_container, HomeFragment()) .commit() } navbar.setOnItemSelectedListener { item -> val transaction = supportFragmentManager.beginTransaction() // 根据切换方向设置Fragment动画 transaction.setCustomAnimations( when (item.itemId) { R.id.ic_settings -> R.anim.slide_from_left R.id.ic_stats -> R.anim.slide_from_right else -> 0 }, when (item.itemId) { R.id.ic_settings -> R.anim.slide_to_right R.id.ic_stats -> R.anim.slide_to_left else -> 0 } ) // 替换对应Fragment when (item.itemId) { R.id.ic_home -> transaction.replace(R.id.fragment_container, HomeFragment()) R.id.ic_settings -> transaction.replace(R.id.fragment_container, SettingsFragment()) R.id.ic_stats -> transaction.replace(R.id.fragment_container, StatsFragment()) } transaction.commit() true } } }
为什么这个方案有效?
- 主Activity中的Bottom Navigation Bar属于固定布局,不会参与Fragment的切换动画,始终保持在底部不动。
- 只有Fragment容器内的内容会执行滑动动画,完全符合你的需求。
备选方案(不推荐)
如果实在不想重构为Fragment,可以尝试修改动画文件,指定动画仅作用于Activity的内容区域:
- 给每个Activity的内容区域设置唯一ID(比如
content_container)。 - 修改动画文件,添加
android:targetId="@id/content_container",示例slide_from_left.xml:
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:fromXDelta="-100%" android:toXDelta="0%" android:duration="300" android:interpolator="@android:anim/decelerate_interpolator" android:targetId="@id/content_container" />
这种方式需要每个Activity都调整布局和动画,维护成本高,且可能存在窗口切换的细微痕迹,不如Fragment架构优雅。
内容的提问来源于stack exchange,提问作者Kiss Gergő
相关产品推荐
相关产品推荐

