如何为Android BottomNavigation实现正确的反向导航

时间:2017-10-03 16:20:44

标签: android android-fragments

我花了一整天时间寻找答案,并没有找到适合这个问题的解决方案。

我正在寻找一种方法来创建类似于Instagram或PlayKiosk应用程序的BottomNavigation用法。碎片应仅添加到后堆栈一次。当按下后退按钮时,我希望应用程序跳回到最后访问的片段和BottomNavigation按钮以适合该片段。

目前我使用以下代码:

//BottomNavigationListener
private BottomNavigationView.OnNavigationItemSelectedListener buttonNavigationItemSelectedListener
        = new BottomNavigationView.OnNavigationItemSelectedListener() {

    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        FragmentManager fragmentManager = getSupportFragmentManager();
        switch (item.getItemId()) {
            case R.id.navigation_game:
                currentFragment = GameFragment.newInstance();
                fragmentManager.beginTransaction()
                        .addToBackStack(TAG_FRAGMENT_GAME)
                        .replace(R.id.content_frame, currentFragment, TAG_FRAGMENT_GAME)
                        .commit();
                break;
            case R.id.navigation_tournament:
                currentFragment = TournamentFragment.newInstance();
                fragmentManager.beginTransaction()
                        .addToBackStack(TAG_FRAGMENT_TOURNAMENT)
                        .replace(R.id.content_frame, currentFragment, TAG_FRAGMENT_TOURNAMENT)
                        .commit();
                break;
            case R.id.navigation_history:
                break;
        }
        return true;
    }

};

但是这导致了我可以按下BottomNavigation按钮几次的问题,对于每次点击,都会实例化一个新的片段。此外,BottomNavigation按钮不是根据片段设置的。

我找到了这个答案,但它没有解决Prevent The Same Fragment From Stacking More Than Once ( addToBackStack)

1 个答案:

答案 0 :(得分:0)

您可以使用以下结构来获得与Instagram相同的工作逻辑。

首先创建一个自定义有限的唯一队列类。它只保存最后N个项目,其中N是传递给其构造函数的限制数(或最大项目数)。而且,这种类型的队列只保留一个类的一个实例。如果A类的实例已经在队列中,并且要将另一个A类实例添加到队列中,则先删除前一个实例,然后插入新对象。

public class LimitedUniqueQueue<E> extends LinkedList<E> {

    private int limit;

    public LimitedUniqueQueue(int limit) {
        this.limit = limit;
    }

    @Override
    public boolean add(E o) {
        // For uniqueness
        for (int i = 0; i < super.size(); i++) {
            E item = super.get(i);
            if (item.getClass() == o.getClass()) {
                super.remove(i);
                break;
            }
        }
        boolean added = super.add(o);
        // For size limit
        while (added && size() > limit) {
            super.remove();
        }
        return added;
    }
}

然后按如下方式更新您的活动:

public class MainActivity extends AppCompatActivity {

    private BottomNavigationView navigation;
    private LimitedUniqueQueue<Fragment> queue;
    ...
    private BottomNavigationView.OnNavigationItemSelectedListener onNavigationItemSelectedListener
                = new BottomNavigationView.OnNavigationItemSelectedListener() {

        Fragment gameFragment;
        Fragment tournamentFragment;
        Fragment profileFragment;

        @Override
        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
            switch (item.getItemId()) {
                case R.id.navigation_game:
                    if (gameFragment == null) {
                        gameFragment = new GameFragment();
                    }
                    transaction.replace(R.id.content, gameFragment).commit();
                    queue.add(gameFragment);
                    return true;
                case R.id.navigation_tournament:
                    if (tournamentFragment == null) {
                        tournamentFragment = new TournamentFragment();
                    }
                    transaction.replace(R.id.content, tournamentFragment).commit();
                    queue.add(tournamentFragment);
                    return true;
                case R.id.navigation_profile:
                    if (profileFragment == null) {
                        profileFragment = new ProfileFragment();
                    }
                    transaction.replace(R.id.content, profileFragment).commit();
                    queue.add(profileFragment);
                    return true;
            }
            return false;
        }

    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        navigation = (BottomNavigationView) findViewById(R.id.navigation);
        queue = new LimitedUniqueQueue<>(navigation.getMenu().size());

        navigation.setOnNavigationItemSelectedListener(onNavigationItemSelectedListener);
        navigation.setSelectedItemId(R.id.navigation_game);
        ...
    }

    @Override
    public void onBackPressed() {
        if (queue.size() > 1) {
            queue.removeLast();
            Fragment previousFragment = queue.getLast();
            if (previousFragment instanceof GameFragment) {
                navigation.setSelectedItemId(R.id.navigation_game);
            } else if (previousFragment instanceof TournamentFragment) {
                navigation.setSelectedItemId(R.id.navigation_tournament);
            } else if (previousFragment instanceof ProfileFragment) {
                navigation.setSelectedItemId(R.id.navigation_profile);
            }
        } else {
            super.onBackPressed();
        }
    }

    ...
}