ViewPager的基本用法不必多說(shuō),這都很簡(jiǎn)單,我們可以在ViewPager中加載一個(gè)ImageView,也可以加載一個(gè)Fragment愧哟,這都是目前非常常見(jiàn)的用法。那么我今天說(shuō)的是ViewPager中的PageTransformer屬性哼蛆,用好這個(gè)屬性可以讓我們的應(yīng)用更加出彩蕊梧,OK,那我們就開(kāi)始吧腮介!
本文將從如下幾方面來(lái)介紹:
1.clipChildren屬性
2.一個(gè)頁(yè)面顯示多個(gè)ViewPager的Item
3.初識(shí)PagerTransformer
4.進(jìn)一步了解PagerTransformer
5.ViewPager結(jié)合CardView
1.clipChildren屬性
clipChildren屬性表示是否限制子控件在該容器所在的范圍內(nèi)肥矢,clipChildren屬性配合layout_gravity屬性,可以用來(lái)設(shè)置多余部分的顯示位置,我這里舉一個(gè)簡(jiǎn)單的例子甘改,比如喜馬拉雅FM這個(gè)應(yīng)用的首頁(yè):
大家注意看這個(gè)應(yīng)用底部導(dǎo)航欄中中間一個(gè)是要比另外四個(gè)高的旅东,這種效果很多人就會(huì)想到使用一個(gè)RelativeLayout布局來(lái)實(shí)現(xiàn),其實(shí)不用那么麻煩十艾,這種效果一個(gè)clipChildren屬性就能實(shí)現(xiàn)抵代,示例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>
大家看只需要在根節(jié)點(diǎn)添加clipChildren屬性,然后在第三個(gè)ImageView上添加layout_gravity屬性即可忘嫉,layout_gravity屬性值為bottom表示控件大小超出后控件底部對(duì)齊荤牍。效果如下:
OK,上面是對(duì)clipChildren屬性一個(gè)簡(jiǎn)單介紹庆冕,算是一個(gè)鋪墊康吵,接下來(lái)我們來(lái)看看ViewPager。
2.一個(gè)頁(yè)面顯示多個(gè)ViewPager的Item
我們要來(lái)解決的第一個(gè)問(wèn)題是如何在一個(gè)頁(yè)面上顯示ViewPager的多個(gè)item访递,一共有兩種解決方案晦嵌,第一種就是我們上文所說(shuō)的clipChildren屬性,第二種是clipToPadding屬性拷姿,我們先來(lái)看看使用第一種屬性設(shè)置的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設(shè)置左右兩個(gè)margin,使其不致于把整個(gè)屏幕占滿响巢,就是這么簡(jiǎn)單描滔,我們?cè)賮?lái)看看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);
}
}
最后再來(lái)看看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多了兩行代碼,一個(gè)是setOffscreenPageLimit抵乓,這個(gè)是設(shè)置預(yù)加載的頁(yè)數(shù)伴挚,我們知道默認(rèn)情況下這個(gè)參數(shù)為1靶衍,也就是左右各預(yù)加載一頁(yè)灾炭,但是我們這里要讓左右各預(yù)加載兩頁(yè),原因一會(huì)再說(shuō)颅眶,另外一個(gè)PageMargin就好說(shuō)了蜈出,就是設(shè)置ViewPager中兩頁(yè)之間的距離。OK涛酗,那我們來(lái)看看顯示效果:
OK铡原,就是這么簡(jiǎn)單,這樣商叹,我們現(xiàn)在已經(jīng)可以在一個(gè)頁(yè)面上來(lái)顯示多個(gè)ViewPager中的item燕刻,接下來(lái)我們先來(lái)看看PageTransformer的簡(jiǎn)單使用。
3.初識(shí)PagerTransformer
我們知道可以給ViewPager設(shè)置一個(gè)setPagerTransformer屬性剖笙,設(shè)置時(shí)候需要我們自己來(lái)實(shí)現(xiàn)PagerTransformer接口卵洗,實(shí)現(xiàn)這個(gè)接口的時(shí)候要實(shí)現(xiàn)該接口中的方法,transformPage弥咪,該方法接收兩個(gè)參數(shù)过蹂,其中一個(gè)是position十绑,如果你直接打印position出來(lái)可能會(huì)看得你云里霧里,實(shí)際上position表示的是第一個(gè)參數(shù)View的position酷勺,把這兩個(gè)參數(shù)一起打印出來(lái)就可以找到規(guī)律了:
比如從第1頁(yè)滑動(dòng)到第2頁(yè):
第一頁(yè)position的變化為 [0,-1]
第二頁(yè)position的變化為 [1,0]
知道了這個(gè)我們就可以寫(xiě)一個(gè)簡(jiǎn)單的切換動(dòng)畫(huà)了本橙,我希望頁(yè)面上正中間的item是正常的,兩邊的item都有一點(diǎn)透明度脆诉。那我們可以使用如下方式來(lái)定義:
public class AlphaTransformer implements ViewPager.PageTransformer {
private float MINALPHA = 0.5f;
/**
* position取值特點(diǎn):
* 假設(shè)頁(yè)面從0~1甚亭,則:
* 第一個(gè)頁(yè)面position變化為[0,-1]
* 第二個(gè)頁(yè)面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));
}
}
}
}
定義好了之后再設(shè)置給ViewPager即可:
viewPager.setPageTransformer(false, new AlphaTransformer());
我們?cè)賮?lái)看看運(yùn)行效果:
4.進(jìn)一步了解PagerTransformer
上面是一個(gè)簡(jiǎn)答的效果,遵循這個(gè)思路库说,我們可以做出更多的效果狂鞋,比如下面這個(gè)效果:
這是一個(gè)非常常見(jiàn)的效果,實(shí)現(xiàn)思路和前文一致潜的,就是讓ImageView動(dòng)態(tài)縮放骚揍。那我們來(lái)看看這里的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設(shè)置相應(yīng)的PagerTransformer:
viewPager.setPageTransformer(false, new ScaleTransformer());
就是這么簡(jiǎn)單。其它復(fù)雜的旋轉(zhuǎn)平移等都是按照這個(gè)思路來(lái)實(shí)現(xiàn)啰挪,這里不再贅述信不。
5.ViewPager結(jié)合CardView
如果你還不會(huì)使用CardView,可以參考我之前的文章Android5.0之CardView的使用亡呵,那今天我們來(lái)看看ViewPager結(jié)合CardView會(huì)產(chǎn)生怎樣的效果呢抽活?
那么在這之前,我想先介紹一個(gè)屬性锰什,那就是clipToPadding下硕,這個(gè)屬性是什么意思呢?它表示是否允許ViewGroup在ViewGroup的padding中進(jìn)行繪制汁胆,默認(rèn)情況下該屬性的值為true梭姓,即不允許在ViewGroup的padding中進(jìn)行繪制。那如果我設(shè)置了false呢嫩码?我們來(lái)看看:
<?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誉尖,那這個(gè)clipToPadding屬性是我們?cè)谝粋€(gè)頁(yè)面中顯示多個(gè)ViewPager item的第二種方式。這個(gè)CardView式的ViewPager我們就使用這種方式來(lái)實(shí)現(xiàn)铸题。先來(lái)看看效果圖:
整體思路和上文其實(shí)是一致的铡恕,我們來(lái)看看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中每一個(gè)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="我是一個(gè)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="我是一個(gè)按鈕"/>
</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));
最后再來(lái)看看我們定義的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);
}
}
}
}
原文鏈接
http://blog.csdn.net/u012702547/article/details/52334161