Want to start animation on viewpager page but pages are preloading

前端 未结 2 489
天命终不由人
天命终不由人 2021-01-21 21:58

In my projects I have several screen(Fragments) and I want to give animation to the fragments elements(views). I have used view pager and viewpager adapter and fragments. The ma

相关标签:
2条回答
  • 2021-01-21 22:27

    It is the default behavior of view-pager that it preload at-least 1 page from both side of current page. See following links

    ViewPager.setOffscreenPageLimit(0) doesn't work as expected

    So what you can do is Instead of starting animation onCreate start it from onPageScrolled callback

    viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
            //Loading fragment # position
    
            //Instead of starting animation from onCreate start it from here 
            //Only for the first time (for page 1) this callback will not trigger
        }
    
        @Override
        public void onPageSelected(int position) {
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
        }
    });
    

    See setOffscreenPageLimit

    Set the number of pages that should be retained to either side of the current page in the view hierarchy in an idle state. Pages beyond this limit will be recreated from the adapter when needed.

    This is offered as an optimization. If you know in advance the number of pages you will need to support or have lazy-loading mechanisms in place on your pages, tweaking this setting can have benefits in perceived smoothness of paging animations and interaction. If you have a small number of pages (3-4) that you can keep active all at once, less time will be spent in layout for newly created view subtrees as the user pages back and forth.

    You should keep this limit low, especially if your pages have complex layouts. This setting defaults to 1.

    0 讨论(0)
  • 2021-01-21 22:29

    Overriding setUserVisibleHint() in each of my pages/fragments worked for me. You can simply call view.startAnimation(animation) inside your setUserVisibleHint(). However, there is one problem with this approach:

    In fragments, setUserVisibleHint() gets called before onCreateView() and onViewCreated.

    The implication of this is that when the fragment starts for the first time and you call view.startAnimation(animation) inside setUserVisibleHint(), view and animation would both be null and the app would crash.


    How then can you fix this problem?

    In each of your pages/fragments, simply declare a global boolean (let's call it fresh_load), use this boolean to check whether the fragment is being loaded for the first time. Here's an illustration:

    boolean fresh_load = true;
    Animation move;
    ImageView car;
    
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_carousel_two, container, false);
    
        // init move and car variables
    
        if(fresh_load) {
            car.startAnimation(animation);
            fresh_load = false;
        }
    
        return view;
    }
    
    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
    
        if((isVisible() && animation != null) && !fresh_load) {
            car.startAnimation(move);
        }
    }
    

    I hope this helps. Merry coding!

    0 讨论(0)
提交回复
热议问题