单击后退按钮上的更改 BottomNavigationView 图标 [英] Change BottomNavigationView Icons on Back Button clicked

查看:30
本文介绍了单击后退按钮上的更改 BottomNavigationView 图标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

addToBackStack() 有效.也许您有一些关于美化代码的建议.

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

At the bottom of my layout I have a BottomNavigationView with three fragments. If I click the back button the fragment is switching but not the bottom icons. How can I fix it?

addToBackStack() works. Maybe you have some advise to pretty the code.

Is it good practise to have the fragment tags in the activity or fragment?

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();
            }
        }
    }

推荐答案

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

@Hans Baum instead of adding your first fragment to back stack try this code,

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

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

This code will exit your activity if you are in Home Fragment else if you are in any other Fragment it will go to Home Fragment. So no addToBackStack() needed. So your serFragment() method should be,

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

希望有帮助.请注意,在您的代码中,您从未将 false 分配给 isFirstFragment,因此我假设所有片段都添加到非常消耗内存的后台堆栈中.

hope it helps. Note that in your code you never assigned false to isFirstFragment so i assume all fragments are added to backstack which is very memory consuming.

更新:由于您的要求不同.如果您希望 Instagram 喜欢标签,我希望此实现对您有所帮助.

UPDATE: Since your requirement is different.As you want Instagram like tabs, i hope this implementation helps you .

    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 大小是 3 .按下后它将弹出堆栈并转到该选项卡.如果堆栈中没有项目,它将退出活动.

I have used deque to store the order in which the tabs are clicked Since there are 3 tabs deque size is 3 .On back press it will pop the stack and go to that tab. If no item in stack it will quit the activity.

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

IMPORTANT NOTE: Do not add fragments to backstack in this scenario because as i switch the tabs the backstack count will keep increasing and may even lead to MemoryOutOfBound exception.

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

To Question 2: Coming to your Fragment tag question , It is good to save tag in fragment . As the fragment is reusable in any activity instead adding tag in every activity it is used , it is good if we add it in fragment itself.

这篇关于单击后退按钮上的更改 BottomNavigationView 图标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆