How to determine when Fragment becomes visible in ViewPager

后端 未结 26 1321
心在旅途
心在旅途 2020-11-22 00:24

Problem: Fragment onResume() in ViewPager is fired before the fragment becomes actually visible.

For example, I have 2 fragments with

26条回答
  •  鱼传尺愫
    2020-11-22 00:44

    setUserVisibleHint() gets called sometimes before onCreateView() and sometimes after which causes trouble.

    To overcome this you need to check isResumed() as well inside setUserVisibleHint() method. But in this case i realized setUserVisibleHint() gets called only if Fragment is resumed and visible, NOT when Created.

    So if you want to update something when Fragment is visible, put your update function both in onCreate() and setUserVisibleHint():

    @Override
    public View onCreateView(...){
        ...
        myUIUpdate();
        ...        
    }
      ....
    @Override
    public void setUserVisibleHint(boolean visible){
        super.setUserVisibleHint(visible);
        if (visible && isResumed()){
            myUIUpdate();
        }
    }
    

    UPDATE: Still i realized myUIUpdate() gets called twice sometimes, the reason is, if you have 3 tabs and this code is on 2nd tab, when you first open 1st tab, the 2nd tab is also created even it is not visible and myUIUpdate() is called. Then when you swipe to 2nd tab, myUIUpdate() from if (visible && isResumed()) is called and as a result,myUIUpdate() may get called twice in a second.

    The other problem is !visible in setUserVisibleHint gets called both 1) when you go out of fragment screen and 2) before it is created, when you switch to fragment screen first time.

    Solution:

    private boolean fragmentResume=false;
    private boolean fragmentVisible=false;
    private boolean fragmentOnCreated=false;
    ...
    
    @Override
    public View onCreateView(...){
        ...
        //Initialize variables
        if (!fragmentResume && fragmentVisible){   //only when first time fragment is created
            myUIUpdate();
        }
        ...        
    }
    
    @Override
    public void setUserVisibleHint(boolean visible){
        super.setUserVisibleHint(visible);
        if (visible && isResumed()){   // only at fragment screen is resumed
            fragmentResume=true;
            fragmentVisible=false;
            fragmentOnCreated=true;
            myUIUpdate();
        }else  if (visible){        // only at fragment onCreated
            fragmentResume=false;
            fragmentVisible=true;
            fragmentOnCreated=true;
        }
        else if(!visible && fragmentOnCreated){// only when you go out of fragment screen
            fragmentVisible=false;
            fragmentResume=false;
        }
    }
    

    Explanation:

    fragmentResume,fragmentVisible: Makes sure myUIUpdate() in onCreateView() is called only when fragment is created and visible, not on resume. It also solves problem when you are at 1st tab, 2nd tab is created even if it is not visible. This solves that and checks if fragment screen is visible when onCreate.

    fragmentOnCreated: Makes sure fragment is not visible, and not called when you create fragment first time. So now this if clause only gets called when you swipe out of fragment.

    Update You can put all this code in BaseFragment code like this and override method.

提交回复
热议问题