Fragment re-created on bottom navigation view item selected

后端 未结 15 2545
长发绾君心
长发绾君心 2020-12-07 23:55

Following is my code for bottom navigation view item selected

bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationI         


        
相关标签:
15条回答
  • 2020-12-08 00:46

    With support library v26 you can do this

    FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
    
    Fragment curFrag = mFragmentManager.getPrimaryNavigationFragment();
    if (curFrag != null) {
        fragmentTransaction.detach(curFrag);
    }
    
    Fragment fragment = mFragmentManager.findFragmentByTag(tag);
    if (fragment == null) {
        fragment = new YourFragment();
        fragmentTransaction.add(container.getId(), fragment, tag);
    } else {
        fragmentTransaction.attach(fragment);
    }
    
    fragmentTransaction.setPrimaryNavigationFragment(fragment);
    fragmentTransaction.setReorderingAllowed(true);
    fragmentTransaction.commitNowAllowingStateLoss();
    
    0 讨论(0)
  • 2020-12-08 00:47

    This seemed to work well for me. Instead of attaching and detaching, i use show or hide to maintain fragment state.

        public void changeFragment(Fragment fragment, String tagFragmentName) {
    
            FragmentManager mFragmentManager = getSupportFragmentManager();
            FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
    
            Fragment currentFragment = mFragmentManager.getPrimaryNavigationFragment();
            if (currentFragment != null) {
                fragmentTransaction.hide(currentFragment);
            }
    
            Fragment fragmentTemp = mFragmentManager.findFragmentByTag(tagFragmentName);
            if (fragmentTemp == null) {
                fragmentTemp = fragment;
                fragmentTransaction.add(R.id.frame_layout, fragmentTemp, tagFragmentName);
            } else {
                fragmentTransaction.show(fragmentTemp);
            }
    
            fragmentTransaction.setPrimaryNavigationFragment(fragmentTemp);
            fragmentTransaction.setReorderingAllowed(true);
            fragmentTransaction.commitNowAllowingStateLoss();
        }
    

    And this is how i use it

         private void initViews() {
            BottomNavigationView bottomNavigationView = findViewById(R.id.navigation);
            bottomNavigationView.setOnNavigationItemSelectedListener
                    (new BottomNavigationView.OnNavigationItemSelectedListener() {
                        @Override
                        public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                            Fragment selectedFragment = null;
                            switch (item.getItemId()) {
                                case R.id.explore:
                                    changeFragment(new ExploreFragment(), ExploreFragment.class
                                            .getSimpleName());
                                    toggleViews(true, "");
                                    break;
                                case R.id.favorite:
                                    changeFragment(new FavoriteFragment(), FavoriteFragment.class
                                            .getSimpleName());
                                    toggleViews(false, "Favorites");
                                    break;
                                case R.id.venue:
                                    changeFragment(new VenueFragment(), VenueFragment.class.getSimpleName());
                                    toggleViews(false, "Venues");
                                    break;
                                case R.id.profile:
                                    changeFragment(new ProfileFragment(), ProfileFragment.class
                                            .getSimpleName());
                                    toggleViews(false, "Profile");
                                    break;
                            }
                            return true;
                        }
                    });
    
            //Manually displaying the first fragment - one time only
            changeFragment(new ExploreFragment(), ExploreFragment.class
                    .getSimpleName());
    
        }
    
    0 讨论(0)
  • 2020-12-08 00:47

    I wrote an Extension function in Kotlin for the same.

    fun FragmentManager.switch(containerId: Int, newFrag: Fragment, tag: String) {
    
    var current = findFragmentByTag(tag)
    beginTransaction()
        .apply {
    
            //Hide the current fragment
            primaryNavigationFragment?.let { hide(it) }
    
            //Check if current fragment exists in fragmentManager
            if (current == null) {
                current = newFrag
                add(containerId, current!!, tag)
            } else {
                show(current!!)
            }
        }
        .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
        .setPrimaryNavigationFragment(current)
        .setReorderingAllowed(true)
        .commitNowAllowingStateLoss()
    }
    
    0 讨论(0)
  • 2020-12-08 00:48

    Try this :

    bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
                    @Override
                    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                        Fragment fragment = null;
                        Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.container);
                        switch (item.getItemId()) {
                            case R.id.action_one:
                                // Switch to page one
                                if (!(currentFragment instanceof FragmentA)) {
                                    fragment = FragmentA.newInstance();
                                }
                                break;
                            case R.id.action_two:
                                // Switch to page two
                                if (!(currentFragment instanceof FragmentB)) {
                                    fragment = FragmentB.newInstance();
                                }
                                break;
                            case R.id.action_three:
                                // Switch to page three
                                if (!(currentFragment instanceof FragmentC)) {
                                    fragment = FragmentC.newInstance();
                                }
                                break;
                        }
                        getSupportFragmentManager().beginTransaction().replace(R.id.container, fragment, "TAG").commit();
                        return true;
                    }
                });
    

    That will get the current fragment in your container and if you click again on this fragment that will not re add the fragment.

    0 讨论(0)
  • 2020-12-08 00:51

    Be careful when using replace. Even if providing a fragment that already exists in memory, replace will restart the fragment's lifecycle. To avoid a restart, the transaction object's methods includes add, show, and hide, which can be used to show the correct fragment without restarting it.

    private fun switchFragment(selectedTabIndex: Int) {
        val previousTabIndex = this.currentTabIndex
        this.currentTabIndex = selectedTabIndex
    
        val transaction = supportFragmentManager.beginTransaction()
        val tag = fragments[this.currentTabIndex].tag
    
        // if the fragment has not yet been added to the container, add it first
        if (supportFragmentManager.findFragmentByTag(tag) == null) {
            transaction.add(R.id.container, fragments[this.currentTabIndex], tag)
        }
    
        transaction.hide(fragments[previousTabIndex])
        transaction.show(fragments[this.currentTabIndex])
        transaction.commit()
    }
    
    0 讨论(0)
  • 2020-12-08 00:55

    How To stop recreating Fragment when it is Already Visible Using BottomNavigationView

    Step 1--

         @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Fragment fragment = null;
        String valuestring;      
        **if (item.getItemId() == lastSelectedItemId) { // added this
            Log.e( "both id is same","LULL" );
            return true;
        }**
        switch (item.getItemId()) {
           case R.id.navigation_category:
          SetActioBarText( getString( R.string.label_actionbar_categories ) );
                fragment = new CategoryFragment();
                valuestring = "category";
                break;
            case R.id.navigation_favourite:
         SetActioBarText( getString( R.string.label_actionbar_favourites ) );
                fragment = new FavouriteFragment();
                valuestring = "favourites";
                break;
            default:
                throw new IllegalStateException( "Unexpected value: " +                  menuItem.getItemId() );
        }
        return loadFragment( fragment, valuestring ,menuItem);
    }
    

    Now Step 2---

        private boolean loadFragment(Fragment fragment, String argument,MenuItem item) {
      
        if (fragment != null) {
           
            transaction = fragmentManager.beginTransaction();
            transaction.addToBackStack( argument );
            transaction.setTransition( FragmentTransaction.TRANSIT_FRAGMENT_FADE );
            transaction.replace( R.id.frame_container, fragment,                         "demofragment").commitAllowingStateLoss();
    
         lastSelectedItemId= item.getItemId();
        
            return true;
        }
        return false;
    }
    
    0 讨论(0)
提交回复
热议问题