ViewPager翻页动画失效详解

在工作中遇到了在一些复杂的场景下,androidx下的ViewPager在调用setCurrentItem时翻页动画失效,令人很是无语,并且第一次失效,再后来就又有了动画,如果你不仔细看,都不会发现会有这个问题,对于有强迫着症追求完美主义的我怎么能放过这个BUG呢,结合demo详细分析一下。

在demo中,营造场景尽量复杂,在RecyclerView中嵌入ViewPager,并且在华东过程中让ViewPager所在视图被回收再滑回来进入页面,此时翻页失效,请看demo。

在demo中,RecyclerView添加头部内容为ViewPager,其他以Button形式展示:

ViewPager翻页动画失效详解

ViewPager翻页动画失效详解

此时在向下滑动的过程中再次展示Viewpager时,点击按钮时,ViewPager的页面切换丢失了动画,直接切页了。

那么缘由是什么呢?我们知道在RecyclerView滑动的过程中ViewPager是被回收了,再次展示是又重新被拿了出来,对于ViewPager来说最起码是重新走了onDetachedFromWindow 和onAttachedToWindow两个方法,那么我们跟随源码进去看看到底是怎么回事。

可以看出在ViewPager调用onAttachedToWindow时只是将成员变量mIsFirstLayout置为true,

ViewPager翻页动画失效详解

从字段命名我们也能看出,是都是第一次layout的意思,我们继续搜索这个字段在哪些可疑的地方使用,发目前setCurrentItemInternal中判断如果是true时会赋值给成员变量mCurItem并请求重新layout,而在layout中跳转到指定页面是没有动画的;在false时会平滑地滑动到指定页,而向上追溯setCurrentItemInternal是被setCurrentItem调用,一切终于真相大白了,但是ViewPager的源码对普通的应用来说是无法更改的,这该怎么办呢?

别慌别急,我们可以从mIsFirstLayout这个字段下手,我们看看它在什么时候会被置为false呢?搜索发目前这个成员变量会在onLayout之后变为false,这也就解释了为什么RecyclerView滑回去第一次动画失效,继续再翻页时,动画又回来了。由于此时的mIsFirstLayout已经为false,走的是下面平滑翻页的逻辑。所以我们可以直接从这个字段着手了。

第一我们想到的就是直接改变这个成员变量的值,在ViewPager重新看见的时候直接置为true,我们想到的就是反射,直接暴力,不过,不过这种方法肯定是不好的,万一哪天谷歌在源码中把这个字段重新命名了,你哭都哭不出来了。我们可以从layout方法入手,由于在onLayout方法中是会将该字段置为false,我们想办法触发onLayout不就可以了?!事不宜迟,我们加上看看:

ViewPager翻页动画失效详解

重新requestLayout

当然这种在第一次的时候会触发没有意义,降低了效率,读者可以声明个成员变量记住是否第一次展示就可以,运行起来,完美解决BUG!DONE!

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容