通过纯Activity而不是Fragment实现类似微信的Tab切换效果

如果要实现微信这样底部一个导航栏,实现中间的内容部分切换,大部分人想到的就是Activity+底部导航栏+Fragment或者Activity+底部导航栏+ViewPager+Fragment然而很多人不喜欢这样的结构,更喜欢把每个主体页面放在一个单独的Activity中这时候就产生了一种新的实现方式的思考

目标

  1. 点击底部导航栏的各个图标时视觉效果上看不出来是开启了新的Activity
  2. 避免无限循环,也就是Activity1->Activity2->Activity1,此时第二次打开的Activity1必须跟第一次打开的Activity1是同一个实例
  3. 在任意一级界面(即导航栏图标点击后的视觉一级界面),按返回键能直接关闭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

缺点

  1. 通过点击导航栏图标进入新的界面时没有Fragment方案流畅
  2. Activity1->Activity2->Activity1->Activity2,第一次Activity2的状态得到保存,因为第二次的Activity2是一个新的实例
Share

You may also like...

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注