Android 使用自定義PageTransformer實(shí)現(xiàn)ViewPager切換動(dòng)畫

本文沒有提供酷炫的動(dòng)畫實(shí)現(xiàn)掩缓,而是分析理解如何使用自定義PageTransformer完成要想的效果。

1蓄诽、PageTransformer之position分析

從3.0開始功偿,ViewPager開始支持自定義切換動(dòng)畫,官方提供的接口為PageTransformer座慰,因此只要實(shí)現(xiàn)該接口即可陨舱,PageTransformer非常簡單,它只有一個(gè)方法:

/** 
 * 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 view, float position)

transformPage()方法的關(guān)鍵在于position的理解版仔,從doc注釋來看游盲,當(dāng)前選中的item的position永遠(yuǎn)是0(這與ViewPagerOnPageChangeListener回調(diào)方法中的position不同)误墓,被選中item的前一個(gè)為-1,被選中item的后一個(gè)為1益缎。** 其實(shí)這里文檔的描述并不是完全正確的驶臊,前后item position為-1和1的前提是你沒有給ViewPager設(shè)置pageMargin(通過調(diào)用viewPager.setPageMargin(int)方法設(shè)置)**。如果你設(shè)置了pageMargin哟沫,前后item的position需要分別加上(或減去遗淳,前減后加)一個(gè)偏移量(偏移量的計(jì)算方式為pageMargin / pageWidth)。
在用戶滑動(dòng)界面的時(shí)候令哟,position是動(dòng)態(tài)變化的恼琼,下面以左滑為例:

  • 選中item position:0->-1 - offset (pageMargin / pageWidth)
  • 前一個(gè)item position:-1 - offset (pageMargin / pageWidth) -> -2 - offset (pageMargin / pageWidth),再往前就以此類推
  • 后一個(gè)item position:1 + offset (pageMargin / pageWidth) -> 0屏富,再往后就以此類推

因此我們可以將position的值應(yīng)用于setAlpha(), setTranslationX(), 或者 setScaleY()等等方法晴竞,從而實(shí)現(xiàn)自定義的動(dòng)畫效果。

2狠半、示例代碼

2.1 布局文件

先看下布局噩死,只有一個(gè)RelativeLayout,內(nèi)部放置了一個(gè)ViewPager神年。

<RelativeLayout
    android:id="@+id/viewpager_container"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_centerVertical="true"
    android:clipChildren="false">

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="200dp"
        android:layout_height="280dp"
        android:clipChildren="false"
        android:layout_centerInParent="true">
    </android.support.v4.view.ViewPager>
</RelativeLayout>

為了ViewPager可以展示多個(gè)Item已维,這里分別設(shè)置其以及其父布局的clipChildren屬性為false。

2.2 滑動(dòng)技巧

ViewPager滑動(dòng)還有一個(gè)小技巧瘤袖,我們都知道默認(rèn)情況下ViewPager本身滑動(dòng)才可以切換頁面衣摩,所以就算屏幕上顯示了多個(gè)item,當(dāng)你滑動(dòng)未被選中的item時(shí)捂敌,ViewPager也是無法切換頁面的艾扮。如果想擴(kuò)大滑動(dòng)區(qū)域可以給ViewPager的父布局設(shè)置觸摸監(jiān)聽,并將觸摸事件交給ViewPager處理占婉,這樣即使滑動(dòng)觸摸位置為未選中item泡嘴,ViewPager仍然可以相應(yīng)滑動(dòng)了。代碼如下:

relativeLayout = (RelativeLayout) view.findViewById(R.id.viewpager_container);
relativeLayout.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return viewPager.onTouchEvent(event);
    }
});

2.3 自定義PageTransformer

class MyPageTransform implements ViewPager.PageTransformer {

    final float SCALE_MAX = 0.8f;
    final float ALPHA_MAX = 0.5f;

    @Override
    public void transformPage(View page, float position) {
        float scale = (position < 0)
                ? ((1 - SCALE_MAX) * position + 1)
                : ((SCALE_MAX - 1) * position + 1);
        float alpha = (position < 0)
                ? ((1 - ALPHA_MAX) * position + 1)
                : ((ALPHA_MAX - 1) * position + 1);
        //為了滑動(dòng)過程中逆济,page間距不變酌予,這里做了處理
        if(position < 0) {
            ViewCompat.setPivotX(page, page.getWidth());
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        } else {
            ViewCompat.setPivotX(page, 0);
            ViewCompat.setPivotY(page, page.getHeight() / 2);
        }
        ViewCompat.setScaleX(page, scale);
        ViewCompat.setScaleY(page, scale);
        ViewCompat.setAlpha(page, Math.abs(alpha));
    }
}

2.3 實(shí)現(xiàn)效果

device-2016-08-07-153455.gif

自定義PageTransformer實(shí)現(xiàn)ViewPager切換動(dòng)畫的分析到此結(jié)束,知道原理后其他炫酷動(dòng)畫效果自然就簡單了奖慌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末抛虫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子简僧,更是在濱河造成了極大的恐慌建椰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岛马,死亡現(xiàn)場離奇詭異棉姐,居然都是意外死亡屠列,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門伞矩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來笛洛,“玉大人,你說我怎么就攤上這事乃坤】寥茫” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵侥袜,是天一觀的道長蝌诡。 經(jīng)常有香客問我,道長枫吧,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任宇色,我火速辦了婚禮九杂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘宣蠕。我一直安慰自己例隆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布抢蚀。 她就那樣靜靜地躺著镀层,像睡著了一般。 火紅的嫁衣襯著肌膚如雪皿曲。 梳的紋絲不亂的頭發(fā)上唱逢,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天,我揣著相機(jī)與錄音屋休,去河邊找鬼坞古。 笑死,一個(gè)胖子當(dāng)著我的面吹牛劫樟,可吹牛的內(nèi)容都是我干的痪枫。 我是一名探鬼主播,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼叠艳,長吁一口氣:“原來是場噩夢啊……” “哼奶陈!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起附较,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤吃粒,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后翅睛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體声搁,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡黑竞,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疏旨。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片很魂。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖檐涝,靈堂內(nèi)的尸體忽然破棺而出遏匆,到底是詐尸還是另有隱情,我是刑警寧澤谁榜,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布幅聘,位于F島的核電站,受9級(jí)特大地震影響窃植,放射性物質(zhì)發(fā)生泄漏帝蒿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一巷怜、第九天 我趴在偏房一處隱蔽的房頂上張望葛超。 院中可真熱鬧,春花似錦延塑、人聲如沸绣张。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侥涵。三九已至,卻和暖如春宋雏,著一層夾襖步出監(jiān)牢的瞬間芜飘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來泰國打工好芭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留燃箭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓舍败,卻偏偏與公主長得像招狸,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子邻薯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容