淺談 Android ViewPager 切換動畫

這篇文章不是我自己寫的, 是 Stew 寫的,我發在我的簡書,為了公眾賬號可以有一個原文鏈接,因為公眾賬號比較看代碼不方便。


應部門大神邀請,寫一篇關于 Android 動畫方面的小記,也算是一種鍛煉吧,自知菜鳥,學識淺陋,有錯提之。

?ViewPager 是谷歌官方給我們提供的一個向下兼容包(Android-support-v4.jar)里面的一個類。我可以用其做簡單的app引導頁,也可以做一些復雜的頁菜單(類似網易新聞,簡書等app的頁面菜單)。不熟悉 ViewPager 的同學可以參照如下鏈接進行學習:

  1. http://blog.csdn.net/harvic880925/article/details/38453725 (harvic 大神寫的基礎篇)
  2. http://developer.android.com/reference/android/support/v4/view/ViewPager.html ViewPager 對應官方文檔地址

具體細節不再敖述,下面我們直接進入主題—— Viewpager 切換動畫

ViewPager 是從 Android 3.0 開始支持自定義動畫的,官方給出了 PageTransformer 接口和其唯一的方法 transformPage(View view, float position) ,所以只要實現該接口就可以了。

    /**
     * A PageTransformer is invoked whenever a visible/attached page is scrolled.
     * This offers an opportunity for the application to apply a custom transformation
     * to the page views using animation properties.
     *
     * <p>As property animation is only supported as of Android 3.0 and forward,
     * setting a PageTransformer on a ViewPager on earlier platform versions will
     * be ignored.</p>
     */
    public interface PageTransformer {
        /**
         * Apply a property transformation to the given page.
         *
         * @param page Apply the transformation to this page
         * @param position Position of page relative to the current front-and-center
         *                 position of the pager. 0 is front and center. 1 is one full
         *                 page position to the right, and -1 is one page position to the left.
         */
        public void transformPage(View page, float position);
    }

從官方文檔可以看出,在 transformPage 方法中, 會傳遞兩個參數, page 即當前界面,以及該 page 對應的 position。重點在于參數 position ,其意思是當前界面的位置相對于屏幕中心的偏移量。在滑動界面時,參數 position 是實時變化的,具體規律如下:

  1. 開始或活動結束:

當position = 0 :當前界面位于屏幕中心

當position = 1 :當前Page剛好滑出屏幕,位于屏幕右側

當position = -1 :當前Page剛好滑出屏幕,位于屏幕左側

  1. 滑動過程中:

滑動過程中涉及到兩個 page ,當前 page 和下一個 page(一個滑出屏幕,一個滑入屏幕),且都會執行 transformPage 方法。舉個簡單例子:從前往后有 A、B、C 3個界面的引導頁,開始顯示 A 界面,然后手指向左滑動,A 界面開始向左滑出屏幕,B 界面開始向左滑入屏幕,A 界面的 position0 漸變到 -1 ,B 界面的 position 從 1 漸變到 0 。

可以想象到兩者的 position 的絕對值相加一直是1。同學們可以將 position 用日志打出來觀察其具體的變化規律。掌握了position的變化規律,就不難理解,為什么可以將 position 運用到我們的切換動畫中了。我們可以對 page 本身設置 setAlpha() , setTranslationX() , setTranslationY() , setScaleX() , setScaleY() 方法,也可以對 page 中的內容設置動畫,前提是通過 page 找到 page 中的內容。

下面舉一個 我自己做的 Demo ( page 有動畫,page 中的內容也有動畫)

效果如下:

Viewpager 動畫效果

核心代碼如下:

@Override
        public void transformPage(View page, float position) {
            RelativeLayout backgroundView = (RelativeLayout) page.findViewById(R.id.simple_pager_bg);
            View text_head = page.findViewById(R.id.slide_fragment_text_1);
            View text_content = page.findViewById(R.id.slide_fragment_text_2);
            View welcomeImage01 = page.findViewById(R.id.slide_pic_1);
            View welcomeImage02 = page.findViewById(R.id.slide_pic_2);
            View welcomeImage03 = page.findViewById(R.id.slide_pic_3);
            View welcomeImage04 = page.findViewById(R.id.slide_pic_4);
            if (0 <= position && position < 1) {
                ViewHelper.setTranslationX(page, pageWidth * -position);
            }
            if (-1 < position && position < 0) {
                ViewHelper.setTranslationX(page, pageWidth * -position);
            }
            if (position <= -1.0f || position >= 1.0f) {
                    //當前界面已經向左或者向右滑出屏幕
            }
            else if (position == 0.0f) {
                    //當前界面未滑動或者滑動結束
            }
            else {
                    //滑動過程中
                if (backgroundView != null) {
                    ViewHelper.setAlpha(backgroundView, 1.0f - Math.abs(position));
                }
                if (text_head != null) {
                    ViewHelper.setTranslationX(text_head, pageWidth * position);
                    ViewHelper.setAlpha(text_head, 1.0f - Math.abs(position));
                }
                if (text_content != null) {
                    ViewHelper.setTranslationX(text_content, pageWidth * position);
                    ViewHelper.setAlpha(text_content, 1.0f - Math.abs(position));
                }
                if (welcomeImage01 != null) {
                    ViewHelper.setRotationY(welcomeImage01, 90 * position);
                    ViewHelper.setAlpha(welcomeImage01, 1.0f - Math.abs(position));
                }
                if (welcomeImage02 != null) {
                    ViewHelper.setRotationY(welcomeImage02, 90 * position);
                    ViewHelper.setAlpha(welcomeImage02, 1.0f - Math.abs(position));
                }
                if (welcomeImage03 != null) {
                    ViewHelper.setRotationY(welcomeImage03, 90 * position);
                    ViewHelper.setAlpha(welcomeImage03, 1.0f - Math.abs(position));
                }
                if (welcomeImage04 != null) {
                    ViewHelper.setRotationY(welcomeImage04, 90 * position);
                    ViewHelper.setAlpha(welcomeImage04, 1.0f - Math.abs(position));
                }
            }
        }

Github上類似的效果有很多

https://github.com/daimajia/AndroidImageSlider(代碼家寫的動畫庫,強烈推薦!)

https://github.com/prolificinteractive/ParallaxPager

https://github.com/flavienlaurent/discrollview

https://github.com/andraskindler/parallaxviewpager

主要是以前沒研究過 PageTransformer ,其實實現起來很簡單,但是功能很強大,如果能善于運用position參數,可以做出非常炫酷的效果。

其實對于上述 Viewpagerpage 切換動畫可以有2種方式(只考慮 page ),不僅可以用 transformPage 方式,也可以用 onPageScrolled 方式。具體細節可以參照 AndroidImageSliderJazzyViewPager 的兩種實現。下一篇我也會給出這兩種方式的具體實現思路,敬請期待。

其實對于上述 Viewpagerpage 切換動畫可以有2種方式(只考慮 page ),不僅可以用 transformPage 方式,也可以用 onPageScrolled 方式。具體細節可以參照 AndroidImageSliderJazzyViewPager 的兩種實現。下一篇我也會給出這兩種方式的具體實現思路,敬請期待。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 173,462評論 25 708
  • afinalAfinal是一個android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,568評論 2 45
  • 英國一直都是我很喜歡的國家之一,最大的原因應該就是英倫音樂了吧,喜歡的好多歌手都是英國人有被很多人熟知的也有偏冷門...
    熊大俠是怪女生閱讀 966評論 0 2
  • 今天起風了,還夾雜著小雨,心情有點不好,因為我似乎又做錯事情,把一個包裹發錯地方了,真的很不好。我自認為自己責任心...
    地瓜222閱讀 184評論 0 0
  • 埋藏了一冬的思緒 隨著一列火車 飛速蔓延 瞧著天上混亂了的 灰白的云 太陽在其間穿梭 與我同一個速度 飛快的穿梭 ...
    王子騫閱讀 213評論 2 2