如果要实现微信这样底部一个导航栏,实现中间的内容部分切换,大部分人想到的就是Activity+底部导航栏+Fragment或者Activity+底部导航栏+ViewPager+Fragment然而很多人不喜欢这样的结构,更喜欢把每个主体页面放在一个单独的Activity中这时候就产生了一种新的实现方式的思考
目标
- 点击底部导航栏的各个图标时视觉效果上看不出来是开启了新的Activity
- 避免无限循环,也就是Activity1->Activity2->Activity1,此时第二次打开的Activity1必须跟第一次打开的Activity1是同一个实例
- 在任意一级界面(即导航栏图标点击后的视觉一级界面),按返回键能直接关闭APP
实现
第一步:各个一级界面的XML布局文件中都放置导航栏
<com.wuadam.appbaselibrary.widget.NavigationView android:id="@+id/navigation" android:layout_width="match_parent" android:layout_height="56dp" app:layout_constraintBottom_toBottomOf="parent" />
第二步:各个一级界面的代码中得到导航栏对象后,手动点亮各自在导航栏中的图标
NavigationView.Item itemHome = new NavigationView.Item(R.drawable.ic_home_0, R.drawable.ic_home_1, R.string.navi_home_page); NavigationView.Item itemBodyData = new NavigationView.Item(R.drawable.ic_body_data_0, R.drawable.ic_body_data_1, R.string.navi_body_data); NavigationView.Item itemFood = new NavigationView.Item(R.drawable.ic_food_0, R.drawable.ic_food_1, R.string.navi_food); NavigationView.Item itemProfile = new NavigationView.Item(R.drawable.ic_profile_0, R.drawable.ic_profile_1, R.string.navi_profile); navigationView.addItem(itemHome); navigationView.addItem(itemBodyData); navigationView.addItem(itemFood); navigationView.addItem(itemProfile); navigationView.lockItem(2); navigationView.setOnItemSelectListener(new NavigationView.OnItemSelectListener() { @Override public void onSelect(int position, NavigationView.Item item) { if (item.equals(itemBodyData)) { Intent intent = new Intent(FoodTypeActivity.this, BodyDataActivity.class); startActivity(intent); } else if (item.equals(itemHome)) { Intent intent = new Intent(FoodTypeActivity.this, HomePageActivity.class); startActivity(intent); } else if (item.equals(itemProfile)) { Intent intent = new Intent(FoodTypeActivity.this, MeActivity.class); startActivity(intent); } } });
第三步:关闭一级Activity进入和退出时的动画
在style中定义动画为null
<item name="android:windowAnimationStyle">@null</item>
至此已经实现了目标一,下面实现目标二
第四步:在所有一级Activity的Manifest声明中定义launchMode为singleTask
android:launchMode="singleTask"
至此实现了目标二,下面实现目标三
第五步:在各个Activity的父类也就是自定义的BaseActivity中添加如下方法
private static String action_finish = BaseActivity.class.getName() + "_action_finish";
public static void finishActivities(Context context) { context.getApplicationContext().sendBroadcast(new Intent(action_finish)); }
private BroadcastReceiver finishReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (intent == null || intent.getAction() == null) { return; } String action = intent.getAction(); if (action.equals(action_finish)) { finish(); } } };
protected boolean shouldFinishOnReceiveBroadcast() { return true; }
这样任意一级界面在关闭时调用finishActivities(Context context)方法就能关闭所有界面,从而实现了目标三
而如果某个Activity不想这样被关闭,只需要Override shouldFinishOnReceiveBroadcast()方法并return false
缺点
- 通过点击导航栏图标进入新的界面时没有Fragment方案流畅
- Activity1->Activity2->Activity1->Activity2,第一次Activity2的状态得到保存,因为第二次的Activity2是一个新的实例