• Android——解决BottomNavigationView+Fragment重建与重叠问题


    简介

    在BottomNavigationView+多个Fragment框架下,进行Fragment切换时,会导致Fragment重建,也会出现同级Fragment未hide,导致重叠

    解决方法

    第一步

    初始化一个默认需要显示的Fragment页面

    public void InitFragment(Bundle savedInstanceState) {
            //判断activity是否重建,如果不是,则不需要重新建立fragment.
            if (savedInstanceState == null) {
                fragmentManager = getSupportFragmentManager();
                fragmentTransaction = fragmentManager.beginTransaction();
                if (mMovie == null) {
                    mMovie = new HomeFragment();
                }
                CurrentFragment = mMovie;
                fragmentTransaction.replace(R.id.nav_host_fragment_activity_main, mMovie).commit();//fragment parent layout id
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第二步

    监听BottomNavigationView切换事件

     binding.navView.setOnNavigationItemSelectedListener(listener);
    
    • 1

    对同级每一个Fragment进行监听,当进行切换的时候,对其状态进行show或者hide

    private BottomNavigationView.OnNavigationItemSelectedListener listener = new BottomNavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull @NotNull MenuItem item) {
                switch (item.getItemId()) {
                    case R.id.navigation_home:
                        if (mMovie == null) {
                            mMovie = new HomeFragment();
                        }
                        switchContent(CurrentFragment, mMovie);
                        return true;
                    case R.id.navigation_dashboard:
                        if (mExplore == null) {
                            mExplore = new ExploreFragment();
                        }
                        switchContent(CurrentFragment, mExplore);
                        return true;
                    case R.id.navigation_notifications:
                        if (mLibrary == null) {
                            mLibrary = new LibraryFragment();
                        }
                        switchContent(CurrentFragment, mLibrary);
                        return true;
                    case R.id.navigation_member:
                        if (mMember == null) {
                            mMember = new MemberFragment();
                        }
                        switchContent(CurrentFragment, mMember);
                        return true;
                }
                return false;
            }
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    第三步

    此为对原Fragment进行隐藏,对要跳转的Fragment进行show,防止页面重叠

    public void switchContent(Fragment from, Fragment to) {
            if (from == null || to == null) return;
    
            if (CurrentFragment != to) {
                CurrentFragment = to;
                fragmentManager = getSupportFragmentManager();
                fragmentTransaction = fragmentManager.beginTransaction();
                if (!to.isAdded()) {  
                    //fragment parent layout id
                    fragmentTransaction.hide(from).add(R.id.nav_host_fragment_activity_main, to).commit(); 
                } else {
                    fragmentTransaction.hide(from).show(to).commit(); 
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    使用

        private FragmentManager fragmentManager;
        private FragmentTransaction fragmentTransaction;
        private HomeFragment mMovie = null;
        private ExploreFragment mExplore = null;
        private LibraryFragment mLibrary = null;
        private MemberFragment mMember = null;
        private Fragment CurrentFragment = null;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
      InitFragment(savedInstanceState);
     binding.navView.setOnNavigationItemSelectedListener(listener);
    
    • 1
    • 2

    同级Fragment跳转

    当BottomNavigationView中的同级Fragment需要进行跳转时,可使用EventBus进行跨进程通信实现,然后拿到BottomNavigationView实例进行切换即可,此id为需要跳转的Fragment 页面ID

     @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
        public void OnEvent(ChangeFragBean bean) {
            binding.navView.setSelectedItemId(R.id.navigation_dashboard);
        }
    
    • 1
    • 2
    • 3
    • 4

    Activity跳转到Fragment

    同样使用EventBus,从一个Activity跳转到BottomNavigationView的某个Fragment时,需要加一个延迟执行,因为Activity可能未销毁,延迟时间,根据具体手机性能决定,大致在300-500毫秒即可

     @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
        public void OnEvent(MermberBean bean) {
            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    /**
                     *要执行的操作
                     */
                    binding.navView.setSelectedItemId(R.id.navigation_member);
                }
            }, 250);//3秒后执行Runnable中的run方法
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    centos7部署Canal与Canal集成使用
    4种方法!怎么把电脑上的音频传到苹果手机上?
    HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效——错误代码:0x8007000d
    【AI必备利器】GPU白嫖指南
    C语言--每日五道选择题--Day20
    SpringBoot关闭Tomcat容器,SpringBoot使用Jetty容器
    python配置到系统环境中
    scrapy框架——架构介绍、安装、项目创建、目录介绍、使用、持久化方案、集成selenium、去重规则源码分析、布隆过滤器使用、redis实现分布式爬虫
    qt day6 人脸识别
    JavaScript面试经,offer拿到手软
  • 原文地址:https://blog.csdn.net/News53231323/article/details/126015892