使用ViewPager實(shí)現(xiàn)卡片疊加效果

我們來看一下效果圖:

背景

在開發(fā)項(xiàng)目時(shí),需要對 App的某個(gè)資源模塊進(jìn)行界面重構(gòu),其中在資源展示部分中新的交互以卡片疊加的效果替代了原來的資源組織樹門禁展示方式疾捍。在新的資源展示方式中羡洛,每一個(gè)新的卡片都是在最上面的,其順序以棧的形式存儲在內(nèi)存迫肖。卡片支持疊加效果攒驰,左右滑動切換到下一頁或上一頁蟆湖,且卡片中的資源是以列表的形式展示,支持上下滑動玻粪,上拉刷新隅津,下拉加載更多。目前網(wǎng)上存在的卡片布局第三方庫劲室,并不能滿足我們的項(xiàng)目需求伦仍,有的是無法達(dá)到疊加效果,有的會是卡片中不能有列表很洋,否則會產(chǎn)生View滑動事件沖突充蓝,導(dǎo)致列表無法滑動,因此考慮使用已有的知識,自己實(shí)現(xiàn)這樣的功能谓苟。

實(shí)現(xiàn)? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

在Android系統(tǒng)中官脓,沒有能直接能實(shí)現(xiàn)該效果的控件,可以實(shí)現(xiàn)左右滑動切換頁面的控件首先想到ViewPager娜谊,但ViewPager并不能直接實(shí)現(xiàn)頁面疊加效果确买,通過查閱資料,發(fā)現(xiàn)可以自定義ViewPager.PageTransformer接口去控制ViewPager中各個(gè)頁面的偏移顯示效果纱皆。

編碼嘗試:

1湾趾、創(chuàng)建基本界面結(jié)構(gòu):

首先我們先創(chuàng)建一個(gè)Activity,配置好頁面派草,就像以下效果搀缠。一個(gè)ViewPager,里面放View。還需要給ViewPager的setOffscreenPageLimit一個(gè)大一點(diǎn)的值近迁,這樣可以使Viewpager預(yù)加載多個(gè)頁面艺普。

正常情況下,ViewPager里面的內(nèi)容是水平排列的鉴竭,如下圖:

現(xiàn)在要做的第一步歧譬,就是將ViewPager里面所有的view都顯示在同一個(gè)位置,那么就需要自定義PageTransformer去實(shí)現(xiàn)了搏存。

自定義PageTransformer:

PageTransformer介紹瑰步,當(dāng)ViewPager中頁面滑動切換時(shí),將會回調(diào)方法transformPage(View page, float position)璧眠;該方法有兩個(gè)參數(shù)缩焦,第一個(gè)view當(dāng)然就是當(dāng)前正在滑動的頁面,第二個(gè)是一個(gè)float類型的值责静,不是我們平常見到的position位置袁滥,而是當(dāng)前滑動狀態(tài)的表示,相對于當(dāng)前position的position灾螃。它有三個(gè)臨界值-1 0 1题翻,0代表當(dāng)前屏幕顯示的view的position,1代表當(dāng)前view的下一個(gè)view所在的position腰鬼,-1代表當(dāng)前view的前一個(gè)view所在的position

當(dāng)前view左滑藐握、右滑時(shí)各個(gè)view positon的變化情況:

既然ViewPager里面的View默認(rèn)是水平排列的,那么只要將每個(gè)view的x軸坐標(biāo)更改為:view的寬度乘以下標(biāo)的負(fù)數(shù)垃喊,這樣就排列在一起了,為了方便起見袜炕,還給view增加了一個(gè)透明度本谜。代碼如下:

public void transformPage(View page, float position) {

??????? //設(shè)置透明度

??????? page.setAlpha(0.5f);

??????? //設(shè)置每個(gè)View在中間,即設(shè)置相對原位置偏移量

??????? page.setTranslationX((-page.getWidth() * position));?

}

具體效果如下:

卡片都疊加在了一起偎窘,說明X方向水平偏移達(dá)到了預(yù)期效果乌助,然后還需要實(shí)現(xiàn)卡片在Y方向垂直偏移溜在,和卡片大小的縮放操作,就可以實(shí)現(xiàn)疊加效果了他托,定義了一個(gè)變量mOffset表示偏移量掖肋,賦值為40px。

@Override

public?void?transformPage(View?page,?float?position)?{

if?(position?>?0){

//移動X軸坐標(biāo)赏参,使得卡片在同一坐標(biāo)

page.setTranslationX(-position?*?page.getWidth());

//縮放卡片并調(diào)整位置

float?scale?=?(page.getWidth()?-?mOffset?*?position)?/?page.getWidth();

page.setScaleX(scale);

page.setScaleY(scale);

//移動Y軸坐標(biāo)

page.setTranslationY(position?*?mOffset);

}

}

為啥這里只處理position>0的情況呢志笼,因?yàn)閿?shù)據(jù)源中最新的那個(gè)數(shù)據(jù)放在list中的第0個(gè),所以

要滑動下一個(gè)把篓,是用手指往右往左滑動的纫溃,那么我們只要把position>0的那些view都設(shè)置

translationX坐標(biāo)讓他們疊到第一個(gè)view的下面就行了,然后就設(shè)置他們的translationY

那我們怎么實(shí)現(xiàn)拿手勢從左往右滑看歷史呢韧掩,我們就要把數(shù)據(jù)源中最新的那條數(shù)據(jù)放到list的最后一個(gè)紊浩,

然后進(jìn)去后讓viewpager定位到最后一頁,然后我們要處理position<0的那些view就行了

public?class?CardTransformer?implements?ViewPager.PageTransformer?{

private?int?mOffset?=?40;

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

@Override

public?void?transformPage(View?page,?float?position)?{

if?(position?<=0)?{

page.setTranslationX(-position?*?page.getWidth());

//縮放卡片并調(diào)整位置

float?scale?=?(page.getWidth()?+?mOffset?*?position)?/?page.getWidth();

page.setScaleX(scale);

page.setScaleY(scale);

//移動Y軸坐標(biāo)

page.setTranslationY(-position?*?mOffset);

page.setTranslationZ(position);

}

}

}

這個(gè)translationZ是什么作用呢疗锐,其實(shí)是設(shè)置view的層級坊谁,translationZ越大,說明他的層級越高

所以position = -1的view的層級就比position=0的view的層級低滑臊,那么position=0的view就會疊在

position=-1的view的上面口芍,這樣就實(shí)現(xiàn)了效果

項(xiàng)目的代碼在https://github.com/nickgao1986/ViewPaperSwitch

如果喜歡這個(gè)效果,請幫忙點(diǎn)個(gè)贊简珠,謝謝

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末阶界,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子聋庵,更是在濱河造成了極大的恐慌膘融,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,729評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件祭玉,死亡現(xiàn)場離奇詭異氧映,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)脱货,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,226評論 3 399
  • 文/潘曉璐 我一進(jìn)店門岛都,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人振峻,你說我怎么就攤上這事臼疫。” “怎么了扣孟?”我有些...
    開封第一講書人閱讀 169,461評論 0 362
  • 文/不壞的土叔 我叫張陵烫堤,是天一觀的道長。 經(jīng)常有香客問我鸽斟,道長,這世上最難降的妖魔是什么富蓄? 我笑而不...
    開封第一講書人閱讀 60,135評論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮立倍,結(jié)果婚禮上灭红,老公的妹妹穿的比我還像新娘。我一直安慰自己帐萎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,130評論 6 398
  • 文/花漫 我一把揭開白布赁项。 她就那樣靜靜地躺著,像睡著了一般澈段。 火紅的嫁衣襯著肌膚如雪悠菜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,736評論 1 312
  • 那天败富,我揣著相機(jī)與錄音,去河邊找鬼兽叮。 笑死,一個(gè)胖子當(dāng)著我的面吹牛鹦聪,可吹牛的內(nèi)容都是我干的账阻。 我是一名探鬼主播泽本,決...
    沈念sama閱讀 41,179評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蒲牧!你這毒婦竟也來了赌莺?” 一聲冷哼從身側(cè)響起冰抢,我...
    開封第一講書人閱讀 40,124評論 0 277
  • 序言:老撾萬榮一對情侶失蹤晒屎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鼓鲁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體港谊,經(jīng)...
    沈念sama閱讀 46,657評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,723評論 3 342
  • 正文 我和宋清朗相戀三年燥狰,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了斜筐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,872評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡目代,死狀恐怖嗤练,靈堂內(nèi)的尸體忽然破棺而出榛了,到底是詐尸還是另有隱情煞抬,我是刑警寧澤,帶...
    沈念sama閱讀 36,533評論 5 351
  • 正文 年R本政府宣布战坤,位于F島的核電站残拐,受9級特大地震影響途茫,放射性物質(zhì)發(fā)生泄漏蹦骑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,213評論 3 336
  • 文/蒙蒙 一边败、第九天 我趴在偏房一處隱蔽的房頂上張望捎废。 院中可真熱鬧,春花似錦登疗、人聲如沸嫌蚤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,700評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽认罩。三九已至,卻和暖如春宦搬,著一層夾襖步出監(jiān)牢的瞬間劫拗,已是汗流浹背间校。 一陣腳步聲響...
    開封第一講書人閱讀 33,819評論 1 274
  • 我被黑心中介騙來泰國打工憔足, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留差购,地道東北人四瘫。 一個(gè)月前我還...
    沈念sama閱讀 49,304評論 3 379
  • 正文 我出身青樓找蜜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親洗做。 傳聞我的和親對象是個(gè)殘疾皇子彰居,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,876評論 2 361

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