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的陰影做了處理 ,其他屬性都沒改,這樣就有了我們剛才看到的效果。
Demo下載下傳:http://download.csdn.net/detail/u012702547/9615195
參考資料:
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1030/1870.html
以上。
轉載于:https://www.cnblogs.com/lenve/p/5865876.html