一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!
ViewPager的基本用法不必多說,這都很簡單,我們可以在ViewPager中載入一個ImageView,也可以載入一個Fragment,這都是目前非常常見的用法。那麼我今天說的是ViewPager中的PageTransformer屬性,用好這個屬性可以讓我們的應用更加出彩,OK,那我們就開始吧!
本文將從如下幾方面來介紹:
1.clipChildren屬性
2.一個頁面顯示多個ViewPager的Item
3.初識PagerTransformer
4.進一步瞭解PagerTransformer
5.ViewPager結合CardView
1.clipChildren屬性
clipChildren屬性表示是否限制子控制元件在該容器所在的範圍內,clipChildren屬性配合layout_gravity屬性,可以用來設定多餘部分的顯示位置,我這裡舉一個簡單的例子,比如喜馬拉雅FM這個應用的首頁:
大家注意看這個應用底部導航欄中中間一個是要比另外四個高的,這種效果很多人就會想到使用一個RelativeLayout佈局來實現,其實不用那麼麻煩,這種效果一個clipChildren屬性就能實現,示例Demo如下:
程式碼:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:clipChildren="false" tools:context="org.lenve.clipchildren.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="48dp" android:layout_alignParentBottom="true" android:background="#03b9fc" android:orientation="horizontal"> <ImageView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@mipmap/ic_launcher"/> <ImageView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@mipmap/ic_launcher"/> <ImageView android:layout_width="0dp" android:layout_height="72dp" android:layout_gravity="bottom" android:layout_weight="1" android:src="@mipmap/ic_launcher"/> <ImageView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@mipmap/ic_launcher"/> <ImageView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:src="@mipmap/ic_launcher"/> </LinearLayout> </RelativeLayout>
大家看只需要在根節點新增clipChildren屬性,然後在第三個ImageView上新增layout_gravity屬性即可,layout_gravity屬性值為bottom表示控制元件大小超出後控制元件底部對齊。效果如下:
OK,上面是對clipChildren屬性一個簡單介紹,算是一個鋪墊,接下來我們來看看ViewPager。
2.一個頁面顯示多個ViewPager的Item
我們要來解決的第一個問題是如何在一個頁面上顯示ViewPager的多個item,一共有兩種解決方案,第一種就是我們上文所說的clipChildren屬性,第二種是clipToPadding屬性,我們先來看看使用第一種屬性設定的ViewPager:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
tools:context="org.lenve.myviewpagercards.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginLeft="60dp"
android:layout_marginRight="60dp"
android:clipChildren="false"></android.support.v4.view.ViewPager>
</RelativeLayout>
只需要在父容器和ViewPager中都新增上clipChildren屬性,然後給ViewPager設定左右兩個margin,使其不致於把整個螢幕佔滿,就是這麼簡單,我們再來看看ViewPager的Adapter:
public class MyVpAdater extends PagerAdapter {
private List<Integer> list;
private Context context;
public MyVpAdater(Context context, List<Integer> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(context);
iv.setImageResource(list.get(position));
container.addView(iv);
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
最後再來看看Activity中的程式碼:
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setPageMargin(80);
viewPager.setOffscreenPageLimit(3);
List<Integer> list = new ArrayList<>();
list.add(R.drawable.p001);
list.add(R.drawable.p002);
list.add(R.drawable.p003);
list.add(R.drawable.p004);
list.add(R.drawable.p005);
MyVpAdater adater = new MyVpAdater(this, list);
viewPager.setAdapter(adater);
比我們一般使用ViewPager多了兩行程式碼,一個是setOffscreenPageLimit,這個是設定預載入的頁數,我們知道預設情況下這個引數為1,也就是左右各預載入一頁,但是我們這裡要讓左右各預載入兩頁,原因一會再說,另外一個PageMargin就好說了,就是設定ViewPager中兩頁之間的距離。OK,那我們來看看顯示效果:
OK,就是這麼簡單,這樣,我們現在已經可以在一個頁面上來顯示多個ViewPager中的item,接下來我們先來看看PageTransformer的簡單使用。
3.初識PagerTransformer
我們知道可以給ViewPager設定一個setPagerTransformer屬性,設定時候需要我們自己來實現PagerTransformer介面,實現這個介面的時候要實現該介面中的方法,transformPage,該方法接收兩個引數,其中一個是position,如果你直接列印position出來可能會看得你雲裡霧裡,實際上position表示的是第一個引數View的position,把這兩個引數一起打印出來就可以找到規律了:
比如從第1頁滑動到第2頁:
第一頁position的變化為 [0,-1]
第二頁position的變化為 [1,0]
知道了這個我們就可以寫一個簡單的切換動畫了,我希望頁面上正中間的item是正常的,兩邊的item都有一點透明度。那我們可以使用如下方式來定義:
public class AlphaTransformer implements ViewPager.PageTransformer {
private float MINALPHA = 0.5f;
/**
* position取值特點:
* 假設頁面從0~1,則:
* 第一個頁面position變化為[0,-1]
* 第二個頁面position變化為[1,0]
*
* @param page
* @param position
*/
@Override
public void transformPage(View page, float position) {
if (position < -1 || position > 1) {
page.setAlpha(MINALPHA);
} else {
//不透明->半透明
if (position < 0) {//[0,-1]
page.setAlpha(MINALPHA + (1 + position) * (1 - MINALPHA));
} else {//[1,0]
//半透明->不透明
page.setAlpha(MINALPHA + (1 - position) * (1 - MINALPHA));
}
}
}
}
定義好了之後再設定給ViewPager即可:
viewPager.setPageTransformer(false, new AlphaTransformer());
我們再來看看執行效果:
OK,透明度的效果已經有了。很簡單吧!
4.進一步瞭解PagerTransformer
上面是一個簡答的效果,遵循這個思路,我們可以做出更多的效果,比如下面這個效果:
這是一個非常常見的效果,實現思路和前文一致,就是讓ImageView動態縮放。那我們來看看這裡的PagerTransformer:
public class ScaleTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.70f;
private static final float MIN_ALPHA = 0.5f;
@Override
public void transformPage(View page, float position) {
if (position < -1 || position > 1) {
page.setAlpha(MIN_ALPHA);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
} else if (position <= 1) { // [-1,1]
float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));
if (position < 0) {
float scaleX = 1 + 0.3f * position;
Log.d("google_lenve_fb", "transformPage: scaleX:" + scaleX);
page.setScaleX(scaleX);
page.setScaleY(scaleX);
} else {
float scaleX = 1 - 0.3f * position;
page.setScaleX(scaleX);
page.setScaleY(scaleX);
}
page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));
}
}
}
然後給ViewPager設定相應的PagerTransformer:
viewPager.setPageTransformer(false, new ScaleTransformer());
就是這麼簡單。其它複雜的旋轉平移等都是按照這個思路來實現,這裡不再贅述。
5.ViewPager結合CardView
如果你還不會使用CardView,可以參考我之前的文章Android5.0之CardView的使用,那今天我們來看看ViewPager結合CardView會產生怎樣的效果呢?
那麼在這之前,我想先介紹一個屬性,那就是clipToPadding,這個屬性是什麼意思呢?它表示是否允許ViewGroup在ViewGroup的padding中進行繪製,預設情況下該屬性的值為true,即不允許在ViewGroup的padding中進行繪製。那如果我設定了false呢?我們來看看:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.lenve.myviewpagercards2.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="200dp"
android:clipToPadding="false"
android:paddingBottom="24dp"
android:paddingLeft="48dp"
android:paddingRight="48dp"
android:paddingTop="24dp"></android.support.v4.view.ViewPager>
</RelativeLayout>
ViewPager的Adapter如下:
public class MyAdapter extends PagerAdapter {
private List<Integer> list;
private Context context;
public MyAdapter(Context context, List<Integer> list) {
this.context = context;
this.list = list;
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView iv = new ImageView(context);
iv.setImageResource(list.get(position));
container.addView(iv);
return iv;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
Activity中的程式碼:
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
List<Integer> list = new ArrayList<>();
list.add(R.drawable.p001);
list.add(R.drawable.p002);
list.add(R.drawable.p003);
list.add(R.drawable.p004);
list.add(R.drawable.p005);
MyAdapter adapter = new MyAdapter(this, list);
viewPager.setAdapter(adapter);
viewPager.setPageMargin(20);
顯示效果如下:
OK,那這個clipToPadding屬性是我們在一個頁面中顯示多個ViewPager item的第二種方式。這個CardView式的ViewPager我們就使用這種方式來實現。先來看看效果圖:
整體思路和上文其實是一致的,我們來看看activity的佈局:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.lenve.myviewpagercards2.MainActivity">
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="300dp"
android:clipToPadding="false"
android:paddingBottom="24dp"
android:paddingLeft="80dp"
android:paddingRight="80dp"
android:paddingTop="24dp"></android.support.v4.view.ViewPager>
</RelativeLayout>
ViewPager中每一個item的佈局:
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView android:id="@+id/cardview"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:cardCornerRadius="10dp">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="300dp">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:text="我是一個TextView"/>
<Button
android:layout_width="96dp"
android:layout_height="36dp"
android:textColor="#ffffff"
android:layout_below="@id/tv"
android:layout_centerHorizontal="true"
android:layout_marginTop="12dp"
android:background="@color/colorAccent"
android:text="我是一個按鈕"/>
</RelativeLayout>
</android.support.v7.widget.CardView>
Adapter:
public class MyAdapter extends PagerAdapter {
private List<Integer> list;
private Context context;
private LayoutInflater inflater;
public MyAdapter(Context context, List<Integer> list) {
this.context = context;
this.list = list;
inflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View view = inflater.inflate(R.layout.vp_item, container, false);
container.addView(view);
return view;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
Activity中的程式碼:
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
List<Integer> list = new ArrayList<>();
list.add(R.drawable.p001);
list.add(R.drawable.p002);
list.add(R.drawable.p003);
list.add(R.drawable.p004);
list.add(R.drawable.p005);
MyAdapter adapter = new MyAdapter(this, list);
viewPager.setAdapter(adapter);
viewPager.setPageMargin((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
48, getResources().getDisplayMetrics()));
viewPager.setPageTransformer(false, new ScaleTransformer(this));
最後再來看看我們定義的PageTransformer:
public class ScaleTransformer implements ViewPager.PageTransformer {
private Context context;
private float elevation;
public ScaleTransformer(Context context) {
this.context = context;
elevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
20, context.getResources().getDisplayMetrics());
}
@Override
public void transformPage(View page, float position) {
if (position < -1 || position > 1) {
} else {
if (position < 0) {
((CardView) page).setCardElevation((1 + position) * elevation);
} else {
((CardView) page).setCardElevation((1 - position) * elevation);
}
}
}
}
很簡單,我只是對CardView的陰影做了處理 ,其他屬性都沒改,這樣就有了我們剛才看到的效果。
參考資料:
以上。
相關推薦
一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!
ViewPager的基本用法不必多說,這都很簡單,我們可以在ViewPager中載入一個ImageView,也可以載入一個Fragment,這都是目前非常常見的用法。那麼我今天說的是ViewPager中的PageTransformer屬性,用好這個屬性可以讓我們的應用更加出彩
一個簡單的例子,帶你理解haproxy!
如果你對haproxy啥都不懂,這篇文章將對你有很大的幫助。大神請繞行! haproxy是一個性能不輸於nginx的工具。和nginx功能類似,可以實現負載均衡。他與nginx不同的是,haproxy既可以實現基於http的七層架構,又可以實現基於tcp/udp的四層架構。 [[email&
ET錢包帶你玩轉糖果,秒變現!
之前跟大家分享過如何在ET錢包中通過PRA糖果盒領取糖果代幣,今天跟大家聊一聊如何將ET錢包賬戶中的糖果代幣變現成EOS代幣。我們選擇在【Newdex交易所】交易。 Newdex交易所是什麼? Newdex是目前全球成交量最大的,基於EOS主鏈搭建的去中心化交易所。 玩家在近期上
帶你玩轉Android中的反射機制,再也不怕private修飾了
前言 在前面寫一些Android原始碼分析的文章中,比如fork程序,SystemServer啟動服務,ActivityThread載入等都會涉及到反射的大量運用,讓我覺得很有必要針對反射機制寫一篇部落格進行總結 相關知識點 在講解反射前先說明一些知識點以做鋪
應用之星帶你玩轉H5頁面和app開發,不懂技術的看過來
智慧手機更新換代日新月異,其功能已經滿足我們的日常需求了,那麼手機內的應用程式是不是還沒有徹底滿足你的個性化需求?沒有一款按照你意願發展的app?如果是的話,那麼恭喜你,今天的這篇文章就是為你而準備。看完這篇文章後,相信你完全可以定製一款屬於自己的專屬應用app,而且這個
公開課 | 獨家首發:微軟Hackathon冠軍隊帶你玩轉新零售,堪比外掛的祕笈分享
大家好,文摘菌又來搞事情啦~本次公開課,大資料文摘邀請到了【微軟大中華區 零售解決方案新創業黑客鬆】大賽上海站冠軍團隊成員之一、觀遠資料合夥人周遠(位元組)。他將從賽題背景、資料探索、特徵工程、模型調優
【宇哥帶你玩轉MySQL】索引篇(一)索引揭祕,看他是如何讓你的查詢效能指數提升的
場景復現,一個索引提高600倍查詢速度? 首先準備一張books表 create table books( id int not null primary key auto_increment, name varchar(255) not null, author va
【幹貨篇】步步為營,帶你輕松掌握jQuery!
red submit 所有 onf rec 選中 jquer 分別是 綁定 寫在前面: 經過系統的學習了原生JS之後,會發現其具有以下三個特點: 1、是一種解釋性腳本語言(代碼不進行預編譯)。 2、主要用來向 HTML 頁面添加交互行為。 3、可以直接嵌入 HTML
1分鐘帶你玩轉Kafka
Kafka 分布式 消息服務 說起Kafka,許多使用者對它是又愛又恨。Kafka是一種分布式的、基於發布/訂閱的消息系統,其極致體驗讓人欲罷不能,但操心的運維、復雜的安全策略、可靠性易用性的缺失、算不上極致的性能發揮、並不豐富的消息服務功能,仍需要使用者付出諸多的背後工作。即使你是Kafka老手
資深程序員帶你玩轉深度學習中的正則化技術(附Python代碼)!
c51 進行 ros batch num 簡單的 oat 深度學習 repr 目錄 1. 什麽是正則化? 2. 正則化如何減少過擬合? 3. 深度學習中的各種正則化技術: L2和L1正則化 Dropout 數據增強(Data augmentation) 提前停止(Ear
百曉生帶你玩轉linux系統服務搭建系列----DNS服務的搭建一(正向解析)
home 主配置文件 baidu 安裝環境 圖片 搭建 href ace eid DNS正向解析的搭建 實驗環境系統環境:centos6.5 安裝DNS環境軟件包rpm -ivh /mnt/Packages/bind-9.8.2-0.17.rc1.el6_4.6.x86_
百曉生帶你玩轉linux系統服務搭建系列----pxe遠程安裝服務器的搭建及無人值守安裝
conf fig ces sys 鏡像文件 mount size set blog 實驗環境系統環境:centos6.5:程安裝服務器WIN7:客戶端一、pxe遠程安裝服務器的搭建 安裝並開啟需要的服務,tftp,ftp,dhcp。1) yum -y install t
百曉生帶你玩轉linux系統服務搭建系列----SSH遠程訪問及控制
登入 conf rsa nag 系列 配置 上傳 我們 shel 實驗環境:linux centos 6.5*2實驗目的:用戶登錄控制及密鑰對驗證 sshd服務默認允許root用戶登錄,當在Internet中使用時這是非常不安全的。普遍的做法是先以普通用戶遠程登入,進入安全
百曉生帶你玩轉linux系統服務搭建系列----構建虛擬ApacheWeb主機
ESS host mon conf 圖片 common roo echo 端口 虛擬Web主機指的是在同一臺服務器中運行多個Web站點,其中的每一個站點實際上並不獨自占用整個服務器,因此被稱為“虛擬”Web主機。通過Web主機服務可以充分利用服務器的硬件資源,從而大大降低網
架構師帶你玩轉分布式鎖
src 效率 獲取鎖 當我 mysql 代碼 red 目錄 在線 大多數互聯網系統都是分布式部署的,分布式部署確實能帶來性能和效率上的提升,但為此,我們就需要多解決一個分布式環境下,數據一致性的問題。 當某個資源在多系統之間,具有共享性的時候,為了保證大家訪問這個資
帶你玩轉Logview: MaxCompute Logview參數詳解和問題排查
磁盤 兩種 同時 col mage proc ins NPU 優化 摘要: 對於Logview上的諸多參數信息,究竟應該怎麽“撥開雲霧”,發現問題所在呢?又如何通過Logview了解每個instance、task運行狀態及資源占用情況,如何分析執行計劃,分析query存在問
亞洲誠信帶你玩轉[2018國家網絡安全宣傳周]上海地區活動!
新的 信息安全 信用卡 對手 禮物 徹底 應用程序 活動 通話 為提升全社會的網絡安全意識和安全防護技能,根據中央網信辦統一部署,2018年國家網絡安全宣傳周於9月17日至23日在全國範圍內舉辦,此次宣傳周主題為“網絡安全為人民,網絡安全靠人民”。上海地區的活動由市委網信
六天帶你玩轉mysql資料庫--第四天筆記
回顧: 列屬性:主鍵,自增長,唯一鍵 關係:一對一,一對多,多對多 正規化:規範資料庫的設計,三層正規化 1NF:欄位設計必須符合原子性 2NF:不存在部分依賴(沒有複合主鍵) 3NF:不存在傳遞依賴(實體單獨建表) 逆規範化:效率與磁碟空間的博弈 高階資料操作: 新增資料:主
六天帶你玩轉mysql資料庫-- 第三天筆記(下)
資料的高階操作: 資料操作:增刪改查 新增資料: 基本語法: insert into 表名 [(欄位列表)] values(值列表); 在資料插入的時候,假設主鍵對應的值已經存在,插入一定會失敗。 主鍵衝突: 當主鍵存在衝突的時候(Duplicate ke
六天帶你玩轉mysql資料庫--第三天筆記(中)
索引: 幾乎所有的索引都是建立在欄位之上。 索引:系統根據某種演算法將已有的資料(未來可能新增的資料),單獨建立一個檔案,檔案能夠實現快速的匹配資料, 並且能夠快速的找到對應表中的記錄。索引的意義在於: 1.提升查詢資料的效率 2.約束資料的有效性(唯一性等) 增加索引有前提條件:索引本