Fragment in TabLayout only load when user slide Android
Asked Answered
A

2

9

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);
Ambivert answered 28/12, 2015 at 1:58 Comment(3)
@Override public void setUserVisibleHint(boolean isVisibleToUser) { super.setUserVisibleHint(isVisibleToUser); }Lyse
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); }?Fleischer
When will android just add a callback to the tabView?Wilhelmina
L
5
@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

Lyse answered 28/12, 2015 at 2:14 Comment(5)
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 getEventDetailRespondFleischer
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.Lyse
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/…Fleischer
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.Lyse
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.Fleischer
E
4

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

Expostulation answered 28/12, 2015 at 3:22 Comment(9)
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?Fleischer
I made a typo on my answer. already edited. You can call that method on the ViewPager.Expostulation
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 fragmentFleischer
@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.Preventer
thanks a lot. so If I have like 3 tab then the 3rd will not be automatic load when set is default 1?Fleischer
@LêKhánhVinh Yes Thats is true. Can I know why you want the system to not preload your fragment ?Expostulation
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)Fleischer
@LêKhánhVinh: I have a cameraview which gets activated even when am in another tab.Begotten
i was searching so many sites, books to find out why the adjucent fragements are called but i did't found any answer. but now thanks to " TIn Tan " i understood it.Jude

© 2022 - 2024 — McMap. All rights reserved.