单击后退按钮上的更改BottomNavigationView图标

时间:2017-09-20 14:51:07

标签: java android xml

在我的布局底部,我有一个带有三个片段的 BottomNavigationView 。如果我单击后退按钮,片段正在切换但不是底部图标。我该如何解决?

addToBackStack()有效。也许你有一些建议漂亮的代码。

在活动或片段中使用片段标签是一种好习惯吗?

public class MainActivity extends AppCompatActivity {

    private FragmentManager mFragmentManager;
    private BottomNavigationView mBottomNavigationView;
    private static final String HOME_FRAGMENT = "homeFragment";
    private static final String SEARCH_FRAGMENT = "searchFragment";
    private static final String SHARE_FRAGMENT = "shareFragment";
    private boolean isFirstFragment;
    private long mBackPressedTime;

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

            init();
            setBottomNavigationView();
        }

        private void init() {
            mBottomNavigationView = findViewById(R.id.bottomNavigationView);

            mFragmentManager = getSupportFragmentManager();
            mBackPressedTime = 0;
        }

        private void setBottomNavigationView() {
            setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
            isFirstFragment = true;
            mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
                @Override
                public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                    switch (item.getItemId()) {
                        case R.id.ic_home:
                            setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
                            return true;
                        case R.id.ic_search:
                            setFragment(SearchFragment.newInstance(), SEARCH_FRAGMENT);
                            return true;
                        case R.id.ic_circle:
                            setFragment(ShareFragment.newInstance(), SHARE_FRAGMENT);
                            return true;

                        default:
                            return false;
                    }
                }
            });
        }

        private void setFragment(Fragment fragment, String tag) {
            FragmentTransaction transaction = mFragmentManager.beginTransaction();
            transaction.replace(R.id.container, fragment, tag);
            if (isFirstFragment) {
                transaction.addToBackStack(tag);
            }
            transaction.commit();
        }

        @Override
        public void onBackPressed() {
            final long currentTimeMillis = System.currentTimeMillis();
            if (mFragmentManager.getBackStackEntryCount() > 0) {
                mFragmentManager.popBackStack();
            } else if (currentTimeMillis - mBackPressedTime > 2000) {
                mBackPressedTime = currentTimeMillis;
                Toast.makeText(this, getString(R.string.reach_homescreen), Toast.LENGTH_SHORT).show();
            } else {
                super.onBackPressed();
            }
        }
    }

3 个答案:

答案 0 :(得分:4)

@Hans Baum而不是将您的第一个片段添加到后台堆栈尝试此代码,

    @Override
    public void onBackPressed() {
        if(mBottomNavigationView.getSelectedItemId () != R.id.ic_home)
        {
            mBottomNavigationView.setSelectedItemId(R.id.ic_home);
        }
        else
        {
            super.onBackPressed();
        }     
    }

如果您在Home Fragment中,此代码将退出您的活动,否则如果您在任何其他片段中它将转到Home Fragment。 所以不需要addToBackStack()。所以你的serFragment()方法应该是,

  private void setFragment(Fragment fragment, String tag) {
        FragmentTransaction transaction = mFragmentManager.beginTransaction();
        transaction.replace(R.id.container, fragment, tag);
        transaction.commit();
    }
希望它有所帮助。 请注意,在您的代码中,您从未将isFirstFragment指定为false,因此我假设所有片段都添加到后台堆栈中,这非常耗费内存。

<强>更新: 由于您的要求不同。如您想要 Instagra 那样的标签,我希望此实施可以帮助您。

    Deque<Integer> mStack = new ArrayDeque<>();
    boolean isBackPressed  = false;

    private void setBottomNavigationView() {
        mBottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.ic_home:
                         if(!isBackPressed) {
                           pushFragmentIntoStack(R.id.ic_home);
                       }
                        isBackPressed = false
                        setFragment(HomeFragment.newInstance(), HOME_FRAGMENT);
                        return true;
                    case R.id.ic_search:
                        if(!isBackPressed) {
                           pushFragmentIntoStack(R.id.ic_search);
                       }
                        isBackPressed = false
                        setFragment(SearchFragment.newInstance(), SEARCH_FRAGMENT);
                        return true;
                    case R.id.ic_circle:
                        if(!isBackPressed) {
                           pushFragmentIntoStack(R.id.ic_circle);
                       }
                        isBackPressed = false
                        setFragment(ShareFragment.newInstance(), SHARE_FRAGMENT);
                        return true;

                    default:
                        return false;
                }
            }
        });
        mBottomNavigationView.setOnNavigationItemReselectedListener(new 
              BottomNavigationView.OnNavigationItemReselectedListener() {
            @Override
            public void onNavigationItemReselected(@NonNull MenuItem item) {

            }
        });
     mBottomNavigationView.setSelectedItemId(R.id.ic_home);
     pushFragmentIntoStack(R.id.ic_home);
    }

    private void pushFragmentIntoStack(int id)
    {
        if(mStack.size() < 3)
        {
            mStack.push(id);
        }
        else
        {
            mStack.removeLast();
            mStack.push(id);
        }
    }

    private void setFragment(Fragment fragment, String tag) {
        FragmentTransaction transaction = mFragmentManager.beginTransaction();
        transaction.replace(R.id.container, fragment, tag);
        transaction.commit();
    }

    @Override
    public void onBackPressed() {
        if(mStack.size() > 1)
        {
            isBackPressed = true;
            mStack.pop();
            mBottomNavigationView.setSelectedItemId(mStack.peek());
        }
        else 
        {
            super.onBackPressed();
        }
    }

我使用deque来存储单击选项卡的顺序因为有3个选项卡deque size是3.在后面按它会弹出堆栈并转到该选项卡。如果堆栈中没有项目,它将退出活动。

重要提示: 在这种情况下,不要将片段添加到backstack,因为当我切换选项卡时,backstack计数将继续增加,甚至可能导致MemoryOutOfBound异常。

问题2: 来到你的Fragment标签问题,最好将标签保存在片段中。由于片段可以在任何活动中重复使用,而不是在每个使用它的活动中添加标记,所以如果我们将它添加到片段本身中就很好。

答案 1 :(得分:0)

尝试一下:

@Override
public void onBackPressed() {
    if(navigation_bottom.getSelectedItemId () != R.id.action_home)
    {
        FragmentTransaction transaction = 
        ((HomeActivity)this).getSupportFragmentManager().beginTransaction();
        transaction.replace(R.id.frameLayout_home, new HomeFragment());
        transaction.commit();
        navigation_bottom.setSelectedItemId(R.id.action_home);
    }
    else
    {
        HomeActivity.this.finishAffinity();
    }     
}

答案 2 :(得分:0)

您可以通过片段事务在后台添加片段名称

        getFragmentManager()
            .beginTransaction()
            .replace(R.id.frame, YourCurrentFragment.newInstance())
            .addToBackStack(YourFragment.class.getName())
            .commit();

然后您可以添加onBackstackChangedListener以获得当前选定的片段

fragmentManager.addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            FragmentManager.BackStackEntry bse = fragmentManager.
                    getBackStackEntryAt(fragmentManager.getBackStackEntryCount() -1);
            //bse will be the backstack entry for current fragment
            if (bse.getName().equals(YourFragment.class.getName())) {
                navigationView.getMenu().getItem(0).setChecked(true);
            } else if (bse.getName().equals(YourSecondFragment.class.getName())) {
                navigationView.getMenu().getItem(1).setChecked(true);
            }
        }
    });