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

Han*_*aum 3 java xml android

在我的布局底部,我有一个包含三个片段的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();
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

Vel*_*n V 5

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

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

如果您在 Home Fragment 中,此代码将退出您的活动,否则如果您在任何其他 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();
    }
Run Code Online (Sandbox Code Playgroud)

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

更新:由于您的要求不同。因为您想要像标签一样的Instagra m,我希望此实现对您有所帮助。

    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();
        }
    }
Run Code Online (Sandbox Code Playgroud)

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

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

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