如何结合Activity与Fragment实现BottomNavigationView底部导航逻辑
底部导航混合切换Activity与Fragment实现方案
首先需明确底部导航菜单中各选项对应的跳转目标类型,提前建立菜单项ID与目标页面的映射关系,无需调整原有BottomAppBar+BottomNavigationView的布局结构,仅需补充内容承载容器即可:
第一步:修改基础布局
在你的CoordinatorLayout节点下新增FrameLayout作为Fragment的承载容器,避免内容被底部导航遮挡:
<androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 新增Fragment内容承载容器 --> <FrameLayout android:id="@+id/fl_content_container" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginBottom="?attr/actionBarSize" /> <com.google.android.material.bottomappbar.BottomAppBar android:id="@+id/bottom_app_bar" android:layout_width="match_parent" android:layout_height="wrap_content" app:fabAlignmentMode="center" app:contentInsetRight="0dp" app:contentInsetEnd="0dp" app:contentInsetStart="0dp" app:contentInsetLeft="0dp" android:layout_gravity="bottom|center" > <com.google.android.material.bottomnavigation.BottomNavigationView android:id="@+id/bottomNavigation" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:foregroundGravity="bottom" app:itemIconTint="@color/primary_icon_color" app:itemRippleColor="@color/primary_icon_color_super_light" app:itemTextColor="@color/primary_icon_color" app:labelVisibilityMode="labeled" app:menu="@menu/bottom_nav_menu" /> </com.google.android.material.bottomappbar.BottomAppBar> </androidx.coordinatorlayout.widget.CoordinatorLayout>
第二步:BaseActivity.java逻辑实现
import android.content.Intent; import android.os.Bundle; import android.util.SparseArray; import android.view.MenuItem; import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentTransaction; import com.google.android.material.bottomnavigation.BottomNavigationView; import com.google.android.material.navigation.NavigationBarView; public class BaseActivity extends AppCompatActivity { // 菜单项ID -> 对应Fragment类 映射表,按你的实际菜单ID替换 private final SparseArray<Class<? extends Fragment>> fragmentNavMap = new SparseArray<>(); // 菜单项ID -> 对应Activity类 映射表,按你的实际菜单ID替换 private final SparseArray<Class<? extends Activity>> activityNavMap = new SparseArray<>(); // 记录当前显示的Fragment,避免重复创建 private Fragment currentFragment; protected BottomNavigationView bottomNavigation; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 这里要替换为你自己的布局文件名 setContentView(R.layout.activity_base); initNavMap(); initBottomNavigation(); // 默认选中第一个菜单项,按需替换为你的首页ID if (savedInstanceState == null) { bottomNavigation.setSelectedItemId(R.id.nav_home); } } private void initNavMap() { // 按需配置映射关系 fragmentNavMap.put(R.id.nav_home, HomeFragment.class); fragmentNavMap.put(R.id.nav_discovery, DiscoveryFragment.class); activityNavMap.put(R.id.nav_message, MessageActivity.class); activityNavMap.put(R.id.nav_mine, MineActivity.class); } private void initBottomNavigation() { bottomNavigation = findViewById(R.id.bottomNavigation); bottomNavigation.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem item) { int itemId = item.getItemId(); // 优先匹配Activity跳转 Class<? extends Activity> targetActivity = activityNavMap.get(itemId); if (targetActivity != null) { startActivity(new Intent(BaseActivity.this, targetActivity)); // 如不需要保留当前Activity栈可加finish() return true; } // 匹配Fragment切换 Class<? extends Fragment> targetFragment = fragmentNavMap.get(itemId); if (targetFragment != null) { switchFragment(targetFragment); return true; } return false; } }); } private void switchFragment(Class<? extends Fragment> targetClazz) { FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction transaction = fragmentManager.beginTransaction(); // 隐藏当前活跃Fragment if (currentFragment != null) { transaction.hide(currentFragment); } String fragmentTag = targetClazz.getName(); Fragment targetFragment = fragmentManager.findFragmentByTag(fragmentTag); if (targetFragment == null) { // 未添加过则新建添加 try { targetFragment = targetClazz.newInstance(); transaction.add(R.id.fl_content_container, targetFragment, fragmentTag); } catch (IllegalAccessException | InstantiationException e) { e.printStackTrace(); return; } } else { // 已添加过直接显示 transaction.show(targetFragment); } transaction.commitAllowingStateLoss(); currentFragment = targetFragment; } }
注意事项
- 所有需要共用底部导航的Activity都需要继承BaseActivity,且在子类的
onCreate方法中主动设置对应选中状态,避免切换Activity后导航选中状态不匹配,示例:@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 对应MessageActivity的菜单ID bottomNavigation.setSelectedItemId(R.id.nav_message); } - 如需让Activity切换的体验更接近Fragment切换,可自定义Activity跳转动画消除页面跳变感。
内容的提问来源于stack exchange,提问作者arianwww
相关产品推荐
相关产品推荐

