Fragment in TabLayout only load when user slide Android

11,790

Solution 1

@Override public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
}

you could use above method within your fragment that is within your ViewPager Adapter

if(isVisibleToUser){//dosomething when the fragment is visible}
else{//dosomething else.}

be aware to do not initialize views there or anything rather, init your views within onViewCreated and call the method that you wanna execute on setUserVisibleHint. another ugly way is to add a scroll listener to your ViewPager and get the current item position and trigger an action that is within the fragment. to get the fragment from the ViewPager Adapter you can do such :

 MyFragment frag = (MyFragment) pager.getAdapter().instantiateItem(pager, position);

then you could call a method that is within MyFragment

Solution 2

The Viewpager by default loads the adjacent fragment to ensure make the app smooth, so that when the user swipe to the fragments (already loaded) it is there. To change is default behavior, use viewpager.setOffscreenPageLimit(int limit) where limit is how many fragment next to the one you are on will be preloaded. Hope this helps

Share:
11,790
Lê Khánh Vinh
Author by

Lê Khánh Vinh

Updated on July 26, 2022

Comments

  • Lê Khánh Vinh
    Lê Khánh Vinh almost 2 years

    Hi I'm making an app with A fragment and few child fragment inside it using tablayout and viewpager. The problem is all my child fragment (from Tablayout) always execute (load all the code inside whenever user click the parent fragment. How to get the child fragment only load whenever the the user slide to it (for example I have 2 tab, content in tab 2 only load when user slide to tab 2)

    Here is my parent fragment code

    public class ManageEventFragment extends Fragment {
    
    
        public ManageEventFragment() {
            // Required empty public constructor
        }
    
    
        TabLayout tabLayout;
        ViewPager viewPager;
    
        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View viewFragment = inflater.inflate(R.layout.fragment_manage_event, container, false);
    
            viewPager = (ViewPager) viewFragment.findViewById(R.id.viewPager);
    
            tabLayout = (TabLayout) viewFragment.findViewById(R.id.tabLayout);
    
            viewPager.setAdapter(new CustomAdapter(getChildFragmentManager(), getContext()));
            viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
    
            return viewFragment;
        }
    
        @Override
        public void onActivityCreated(Bundle savedInstanceState) {
    
            //        tabLayout.setupWithViewPager(viewPager);
            tabLayout.post(new Runnable() {
                @Override
                public void run() {
                    tabLayout.setupWithViewPager(viewPager);
                }
            });
    
            tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
                @Override
                public void onTabSelected(TabLayout.Tab tab) {
                    viewPager.setCurrentItem(tab.getPosition());
                }
    
                @Override
                public void onTabUnselected(TabLayout.Tab tab) {
                    viewPager.setCurrentItem(tab.getPosition());
                }
    
                @Override
                public void onTabReselected(TabLayout.Tab tab) {
                    viewPager.setCurrentItem(tab.getPosition());
                }
            });
    
            if (ViewCompat.isLaidOut(tabLayout)) {
                tabLayout.setupWithViewPager(viewPager);
            } else {
                tabLayout.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
                    @Override
                    public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                        tabLayout.setupWithViewPager(viewPager);
                        tabLayout.removeOnLayoutChangeListener(this);
                    }
                });
            }
    
            super.onActivityCreated(savedInstanceState);
    
        }
    
    
        //TabLayout and ViewPager class
        private class CustomAdapter extends FragmentPagerAdapter {
    
            private String fragments[] = {"Edit Event", "Create Event"};
    
            public CustomAdapter(FragmentManager fragmentManager, Context context) {
                super(fragmentManager);
            }
    
            @Override
            public Fragment getItem(int position) {
                switch (position) {
                    case 0:
                        return new EditEventFragment();
                    case 1:
                        return new CreateEventFragment();
                    default:
                        return null;
                }
            }
    
            @Override
            public int getCount() {
                return fragments.length;
            }
    
            @Override
            public CharSequence getPageTitle(int position) {
                return fragments[position];
            }
    
        }
    
    }
    

    And my child fragment code. I want these code only execute whenever the user slide to the child tab. Any help is much appreciate, Thanks

    @Override
        public void onActivityCreated(Bundle savedInstanceState) {
            super.onActivityCreated(savedInstanceState);
    
            //Initializing our listEvents list
            listEvents = new ArrayList();
    
            recyclerView.setHasFixedSize(true);
            layoutManager = new LinearLayoutManager(getContext());
            recyclerView.setLayoutManager(layoutManager);
    
            adapter = new EventAdapterEdit(getContext(),listEvents);
            recyclerView.setAdapter(adapter);
    
    
            requestQueue = Volley.newRequestQueue(getContext());
    
            adapter = new EventAdapterEdit(getContext(),listEvents);
            recyclerView.setAdapter(adapter);
    
            getEventDetailRespond(requestQueue);
    
    • Kosh
      Kosh over 8 years
      @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); }
    • Lê Khánh Vinh
      Lê Khánh Vinh over 8 years
      thanks for yrs rep. Can u describe a bit more detail. I need to put the above child fragment code on @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); }?
    • Zapnologica
      Zapnologica over 7 years
      When will android just add a callback to the tabView?
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    I tried yrs 1st method but does not seem to work. I move all the view code to OnCreateView and left only the method to fetch data getEventDetailRespond(requestQueue); inside @Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); } but got null pointer error (I have progressbar.setvisibillity inside the getEventDetailRespond
  • Kosh
    Kosh over 8 years
    instead of using getChildFragmentManager() could u call getActivity().getSupportFragmentManager() and see if that solve it? however i still encourage you to do some debugging on the answer i did provide.
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    seem to work with simple test Toast message but when I put my fetch data method. return null pointer. here is my method code and the error shown docs.google.com/document/d/…
  • Kosh
    Kosh over 8 years
    your issue is within this line ProgressBar.setVisibility(int) as i mentioned do initialize your views onViewCreated and setUserVisibleHint its called before onViewCreated so check against null stuff.
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    But the problem is that I need the progressBar to be visible whenever the method is fetching data from server. when receive the respond from server, the progress bar will be disappear.
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    thanks a lot. So by default if I have 3 fragment, only first 2 fragment will be loaded when user click parent fragment? where to put the viewsetOffscreenPageLimit(int limit) (on parent or child)? can give a bit detail how to implement this?
  • Tin Tran
    Tin Tran over 8 years
    I made a typo on my answer. already edited. You can call that method on the ViewPager.
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    I seem not to work. I have 2 child fragment. When I put viewpager.setOffscreenPageLimit(0) in my parent OnCreateView. all the code from child fragment 2nd tab is still loaded whenever user click parent fragment
  • Karakuri
    Karakuri over 8 years
    @LêKhánhVinh The minimum off screen page limit is 1. ViewPager is going to load stuff off screen so that it's ready when the user starts to scroll. You cannot avoid this.
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    thanks a lot. so If I have like 3 tab then the 3rd will not be automatic load when set is default 1?
  • Tin Tran
    Tin Tran over 8 years
    @LêKhánhVinh Yes Thats is true. Can I know why you want the system to not preload your fragment ?
  • Lê Khánh Vinh
    Lê Khánh Vinh over 8 years
    that because I want to pass the data get from the first child pass to the 2nd or 3rd child (like update data view based on user change)
  • Harish Vishwakarma
    Harish Vishwakarma about 7 years
    @LêKhánhVinh: I have a cameraview which gets activated even when am in another tab.