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

2024-05-05

在我的布局的底部有一个底部导航视图与三个片段。如果我单击后退按钮,片段将切换,但底部图标不会切换。我该如何修复它?

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

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

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

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

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

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

UPDATE: 由于您的要求不同。如您所愿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 大小为 3 。按回键时,它将弹出堆栈并转到该选项卡。如果堆栈中没有项目,它将退出活动。

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

更改单击后退按钮上的 BottomNavigationView 图标 的相关文章

随机推荐

  • IMAP CONDSTORE 是否得到广泛支持?

    我正在构建一个简单的网络邮件 我想使用 IMAP 的 CONDSTORE 扩展 它允许获取自某个日期以来已更改的所有内容 消息 标志等 这对于将电子邮件客户端同步到IMAP 服务器 但是我完全不知道大多数 IMAP 服务器是否真正支持此 I
  • ASP MVC4 - 通过视图模型传递列表以查看

    我有一个模型人物 其中包括出生日期等字段 我想将所有人的列表以及每个人的计算年龄传递给视图 因此 视图模型 public class vm PersonList public Person Person get set public int
  • 在没有事件的情况下从 HTML 执行 javascript 函数

    我希望从 HTML 页面调用 javascript 函数 并且我do not希望它依赖于任何事件 该函数位于单独的 js 文件中 因为我希望在许多网页中使用它 我也将变量传递给它 我试过这个 HTML fp footer2 js中的函数 f
  • 检查远程计算机上的进程所有者,并在所有者为 xyz 时将其终止

    嘿 我想在远程计算机上检查特定进程的进程所有者 并在所有者是 xyz 时杀死它 我已经成功地检查了它的主人 但我不知道当主人是 xyz 时如何杀死它 到目前为止我所拥有的 get wmiobject computername remoteP
  • PreferenceActivity 如何使用自定义首选项文件

    我第一次尝试偏好是在不了解PreferenceActivity 所以现在我有一个应用程序将所有用户首选项存储在特定的首选项文件中 我想迁移到使用 PreferenceActivity 但我也希望我的用户保留他们的偏好 有没有办法告诉我的 P
  • 如何使用 diff 排除多行模式?

    我想对两个 xml 文件进行比较 但忽略 2 3 行模式 例如 假设我想在比较下面的 xml 格式时忽略可用性和价格 这是我到目前为止所拥有的 diff I
  • 是否有与 SQL Server newsequentialid() 等效的 .NET

    我们使用 GUID 作为主键 您知道默认情况下它是集群的 将新行插入表中时 它将插入表中的随机页 因为 GUID 是随机的 这会对性能产生可衡量的影响 因为数据库始终会分割数据页 碎片 但我使用顺序 GUID 的主要原因是因为我希望将新行插
  • jQuery AJAX 或 XHR 请求从完成回调触发失败回调

    在我的 jQuery XHR 的完成处理程序 从 get 调用创建 中是否有一种方法可以查找响应中的问题 然后使用自定义错误消息触发注册的后续处理程序 即失败和始终 像这样的东西 get URL done function data sta
  • Gem .gemspec 中的本地依赖关系

    我正在开发一个 gem Gem A 它使用了我也编写的另一个 gem Gem B 到目前为止 Gem B 已添加到 Gem A 的 gemspec 中 gem add dependency gem a gt 0 0 4 但我现在发现需要使用
  • 在闪亮的应用程序中选择文件夹或文件夹目录

    我在使用闪亮时遇到问题 我想选择保存我要在应用程序中使用的所有文件的文件夹 方法是 1 将工作目录设置为该文件夹路径 或 2 将此文件夹内的所有 csv 数据上传到我的应用程序以进行进一步处理 1 我找到了shinyFiles包 但它非常非
  • 在 (PHP/GD) 中调整图像大小

    我正在寻找帮助 建议 以找到最有效的方法来使用以下方法将图像大小调整为尽可能小PHP GD同时保留原始图像的纵横比 但确保调整后的图像大于定义的最小宽度和高度 例如 调整大小后的图像必须具有宽度 gt 400 且高度 gt 300但应尽可能
  • FirebaseIndexRecyclerAdapter onDataChanged 被调用但 getItemCount() 始终返回 0

    我在用着FirebaseIndexRecyclerAdapter https github com firebase FirebaseUI Android blob master database src main java com fir
  • lambda 始终返回“1”

    有这样的代码 include
  • 如何根据 URL 路径添加 CSS 类?

    如何根据我所在的路径将 CSS 类添加到 div 中 包括如果我在其中包含 则不应该出现问题 div class popup ul li a href vs Example 1 a li li a href bod Example 2 a
  • xcodebuild 失败,返回代码:65 - 使用 CLI/Appcenter 但没有错误消息

    我已将 React Native 应用程序升级到 0 59 现在当我尝试使用 AppCenter 或 CLI 存档我的应 用程序时 我收到错误代码 65 但没有任何消息解释问题 当我直接从 Xcode 构建时 Xcode版本 10 2 1
  • C++ 最大非负整数

    以下内容是否会在所有平台 int 大小等上按预期工作 或者有更容易接受的方法吗 我做了以下的事情 define MAX NON NEGATIVE INT int unsigned int 1 2 我不会通过解释它在做什么来侮辱你的智商 编辑
  • 嵌套过滤器:$filter 数组,然后是 $filter 子数组

    本质上 我试图过滤掉已被 废弃 的子文档和子子文档 这是我的架构的精简版本 permitSchema id name feeClassifications new Schema id trashed name fees new Schema
  • 动态元素 ID 到 setId(int) - Android

    我看到了语法定义setId int and findViewByID int 但我们如何使用findViewById R id row1 我尝试使用这个 Object1 setId Integer parseInt repeat 它没有显示
  • 深层链接给出空路径

    我在实施 DeepLinks 时遇到问题 我可以从 myapp myapp com route 等 URL 打开该应用程序 但它不处理它的路径 它只是打开程序 我用以下命令打开它 this deeplinks route route Rou
  • 更改单击后退按钮上的 BottomNavigationView 图标

    在我的布局的底部有一个底部导航视图与三个片段 如果我单击后退按钮 片段将切换 但底部图标不会切换 我该如何修复它 addToBackStack 有效 也许您有一些关于美化代码的建议 在活动或片段中添加片段标签是一个好的做法吗 public