卡片式ViewPager,一屏展示多個pager item,設置高度不一致的tabBar


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如下:

代碼:

 

 1 <?xml version="1.0" encoding="utf-8"?>  
 2 <RelativeLayout  
 3     xmlns:android="http://schemas.android.com/apk/res/android"  
 4     xmlns:tools="http://schemas.android.com/tools"  
 5     android:layout_width="match_parent"  
 6     android:layout_height="match_parent"  
 7     android:clipChildren="false"  
 8     tools:context="org.lenve.clipchildren.MainActivity">  
 9   
10     <LinearLayout  
11         android:layout_width="match_parent"  
12         android:layout_height="48dp"  
13         android:layout_alignParentBottom="true"  
14         android:background="#03b9fc"  
15         android:orientation="horizontal">  
16   
17         <ImageView  
18             android:layout_width="0dp"  
19             android:layout_height="match_parent"  
20             android:layout_weight="1"  
21             android:src="@mipmap/ic_launcher"/>  
22   
23         <ImageView  
24             android:layout_width="0dp"  
25             android:layout_height="match_parent"  
26             android:layout_weight="1"  
27             android:src="@mipmap/ic_launcher"/>  
28   
29         <ImageView  
30             android:layout_width="0dp"  
31             android:layout_height="72dp"  
32             android:layout_gravity="bottom"  
33             android:layout_weight="1"  
34             android:src="@mipmap/ic_launcher"/>  
35   
36         <ImageView  
37             android:layout_width="0dp"  
38             android:layout_height="match_parent"  
39             android:layout_weight="1"  
40             android:src="@mipmap/ic_launcher"/>  
41   
42         <ImageView  
43             android:layout_width="0dp"  
44             android:layout_height="match_parent"  
45             android:layout_weight="1"  
46             android:src="@mipmap/ic_launcher"/>  
47     </LinearLayout>  
48 </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:

 

 1 public class MyVpAdater extends PagerAdapter {  
 2     private List<Integer> list;  
 3     private Context context;  
 4   
 5     public MyVpAdater(Context context, List<Integer> list) {  
 6         this.context = context;  
 7         this.list = list;  
 8     }  
 9   
10     @Override  
11     public int getCount() {  
12         return list.size();  
13     }  
14   
15     @Override  
16     public boolean isViewFromObject(View view, Object object) {  
17         return view == object;  
18     }  
19   
20     @Override  
21     public Object instantiateItem(ViewGroup container, int position) {  
22         ImageView iv = new ImageView(context);  
23         iv.setImageResource(list.get(position));  
24         container.addView(iv);  
25         return iv;  
26     }  
27   
28     @Override  
29     public void destroyItem(ViewGroup container, int position, Object object) {  
30         container.removeView((View) object);  
31     }  
32 }  

 

最后再來看看Activity中的代碼:

 

 1 ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);  
 2         viewPager.setPageMargin(80);  
 3         viewPager.setOffscreenPageLimit(3);  
 4         List<Integer> list = new ArrayList<>();  
 5         list.add(R.drawable.p001);  
 6         list.add(R.drawable.p002);  
 7         list.add(R.drawable.p003);  
 8         list.add(R.drawable.p004);  
 9         list.add(R.drawable.p005);  
10         MyVpAdater adater = new MyVpAdater(this, list);  
11         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都有一點透明度。那我們可以使用如下方式來定義:

 

 1 public class AlphaTransformer implements ViewPager.PageTransformer {  
 2     private float MINALPHA = 0.5f;  
 3   
 4     /** 
 5      * position取值特點: 
 6      * 假設頁面從0~1,則: 
 7      * 第一個頁面position變化為[0,-1] 
 8      * 第二個頁面position變化為[1,0] 
 9      * 
10      * @param page 
11      * @param position 
12      */  
13     @Override  
14     public void transformPage(View page, float position) {  
15         if (position < -1 || position > 1) {  
16             page.setAlpha(MINALPHA);  
17         } else {  
18             //不透明->半透明  
19             if (position < 0) {//[0,-1]  
20                 page.setAlpha(MINALPHA + (1 + position) * (1 - MINALPHA));  
21             } else {//[1,0]  
22                 //半透明->不透明  
23                 page.setAlpha(MINALPHA + (1 - position) * (1 - MINALPHA));  
24             }  
25         }  
26     }  
27 }  

 

定義好了之后再設置給ViewPager即可:

 

viewPager.setPageTransformer(false, new AlphaTransformer());  

 


我們再來看看運行效果:

 

OK,透明度的效果已經有了。很簡單吧!

4.進一步了解PagerTransformer

上面是一個簡答的效果,遵循這個思路,我們可以做出更多的效果,比如下面這個效果:

這是一個非常常見的效果,實現思路和前文一致,就是讓ImageView動態縮放。那我們來看看這里的PagerTransformer:

 

 1 public class ScaleTransformer implements ViewPager.PageTransformer {  
 2     private static final float MIN_SCALE = 0.70f;  
 3     private static final float MIN_ALPHA = 0.5f;  
 4   
 5     @Override  
 6     public void transformPage(View page, float position) {  
 7         if (position < -1 || position > 1) {  
 8             page.setAlpha(MIN_ALPHA);  
 9             page.setScaleX(MIN_SCALE);  
10             page.setScaleY(MIN_SCALE);  
11         } else if (position <= 1) { // [-1,1]  
12             float scaleFactor = Math.max(MIN_SCALE, 1 - Math.abs(position));  
13             if (position < 0) {  
14                 float scaleX = 1 + 0.3f * position;  
15                 Log.d("google_lenve_fb", "transformPage: scaleX:" + scaleX);  
16                 page.setScaleX(scaleX);  
17                 page.setScaleY(scaleX);  
18             } else {  
19                 float scaleX = 1 - 0.3f * position;  
20                 page.setScaleX(scaleX);  
21                 page.setScaleY(scaleX);  
22             }  
23             page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA));  
24         }  
25     }  
26 }  

 


然后給ViewPager設置相應的PagerTransformer:

 

viewPager.setPageTransformer(false, new ScaleTransformer());  

 


就是這么簡單。其它復雜的旋轉平移等都是按照這個思路來實現,這里不再贅述。

5.ViewPager結合CardView

如果你還不會使用CardView,可以參考我之前的文章Android5.0之CardView的使用,那今天我們來看看ViewPager結合CardView會產生怎樣的效果呢?

 

那么在這之前,我想先介紹一個屬性,那就是clipToPadding,這個屬性是什么意思呢?它表示是否允許ViewGroup在ViewGroup的padding中進行繪制,默認情況下該屬性的值為true,即不允許在ViewGroup的padding中進行繪制。那如果我設置了false呢?我們來看看:

 

 1 <?xml version="1.0" encoding="utf-8"?>  
 2 <RelativeLayout  
 3     xmlns:android="http://schemas.android.com/apk/res/android"  
 4     xmlns:tools="http://schemas.android.com/tools"  
 5     android:layout_width="match_parent"  
 6     android:layout_height="match_parent"  
 7     tools:context="org.lenve.myviewpagercards2.MainActivity">  
 8   
 9     <android.support.v4.view.ViewPager  
10         android:id="@+id/viewpager"  
11         android:layout_width="match_parent"  
12         android:layout_height="200dp"  
13         android:clipToPadding="false"  
14         android:paddingBottom="24dp"  
15         android:paddingLeft="48dp"  
16         android:paddingRight="48dp"  
17         android:paddingTop="24dp"></android.support.v4.view.ViewPager>  
18 </RelativeLayout>  

 


ViewPager的Adapter如下:

 

 1 public class MyAdapter extends PagerAdapter {  
 2     private List<Integer> list;  
 3     private Context context;  
 4   
 5     public MyAdapter(Context context, List<Integer> list) {  
 6         this.context = context;  
 7         this.list = list;  
 8     }  
 9   
10     @Override  
11     public int getCount() {  
12         return list.size();  
13     }  
14   
15     @Override  
16     public boolean isViewFromObject(View view, Object object) {  
17         return view == object;  
18     }  
19   
20     @Override  
21     public Object instantiateItem(ViewGroup container, int position) {  
22         ImageView iv = new ImageView(context);  
23         iv.setImageResource(list.get(position));  
24         container.addView(iv);  
25         return iv;  
26     }  
27   
28     @Override  
29     public void destroyItem(ViewGroup container, int position, Object object) {  
30         container.removeView((View) object);  
31     }  
32 }  

 

Activity中的代碼:

 

 1 ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);  
 2 List<Integer> list = new ArrayList<>();  
 3 list.add(R.drawable.p001);  
 4 list.add(R.drawable.p002);  
 5 list.add(R.drawable.p003);  
 6 list.add(R.drawable.p004);  
 7 list.add(R.drawable.p005);  
 8 MyAdapter adapter = new MyAdapter(this, list);  
 9 viewPager.setAdapter(adapter);  
10 viewPager.setPageMargin(20);  

 


顯示效果如下:

OK,那這個clipToPadding屬性是我們在一個頁面中顯示多個ViewPager  item的第二種方式。這個CardView式的ViewPager我們就使用這種方式來實現。先來看看效果圖:

整體思路和上文其實是一致的,我們來看看activity的布局:

 

 1 <?xml version="1.0" encoding="utf-8"?>  
 2 <RelativeLayout  
 3     xmlns:android="http://schemas.android.com/apk/res/android"  
 4     xmlns:tools="http://schemas.android.com/tools"  
 5     android:layout_width="match_parent"  
 6     android:layout_height="match_parent"  
 7     tools:context="org.lenve.myviewpagercards2.MainActivity">  
 8   
 9     <android.support.v4.view.ViewPager  
10         android:id="@+id/viewpager"  
11         android:layout_width="match_parent"  
12         android:layout_height="300dp"  
13         android:clipToPadding="false"  
14         android:paddingBottom="24dp"  
15         android:paddingLeft="80dp"  
16         android:paddingRight="80dp"  
17         android:paddingTop="24dp"></android.support.v4.view.ViewPager>  
18 </RelativeLayout>  

 


ViewPager中每一個item的布局:

 

 1 <?xml version="1.0" encoding="utf-8"?>  
 2 <android.support.v7.widget.CardView android:id="@+id/cardview"  
 3                                     xmlns:android="http://schemas.android.com/apk/res/android"  
 4                                     xmlns:app="http://schemas.android.com/apk/res-auto"  
 5                                     android:layout_width="match_parent"  
 6                                     android:layout_height="wrap_content"  
 7                                     android:orientation="vertical"  
 8                                     app:cardCornerRadius="10dp">  
 9   
10     <RelativeLayout  
11         android:layout_width="match_parent"  
12         android:layout_height="300dp">  
13   
14         <TextView  
15             android:id="@+id/tv"  
16             android:layout_width="match_parent"  
17             android:layout_height="wrap_content"  
18             android:layout_centerInParent="true"  
19             android:gravity="center"  
20             android:text="我是一個TextView"/>  
21   
22         <Button  
23             android:layout_width="96dp"  
24             android:layout_height="36dp"  
25             android:textColor="#ffffff"  
26             android:layout_below="@id/tv"  
27             android:layout_centerHorizontal="true"  
28             android:layout_marginTop="12dp"  
29             android:background="@color/colorAccent"  
30             android:text="我是一個按鈕"/>  
31     </RelativeLayout>  
32 </android.support.v7.widget.CardView>  

 


Adapter:

 

 1 public class MyAdapter extends PagerAdapter {  
 2     private List<Integer> list;  
 3     private Context context;  
 4     private LayoutInflater inflater;  
 5   
 6     public MyAdapter(Context context, List<Integer> list) {  
 7         this.context = context;  
 8         this.list = list;  
 9         inflater = LayoutInflater.from(context);  
10     }  
11     @Override  
12     public int getCount() {  
13         return list.size();  
14     }  
15   
16     @Override  
17     public boolean isViewFromObject(View view, Object object) {  
18         return view == object;  
19     }  
20   
21     @Override  
22     public Object instantiateItem(ViewGroup container, int position) {  
23         View view = inflater.inflate(R.layout.vp_item, container, false);  
24         container.addView(view);  
25         return view;  
26     }  
27   
28     @Override  
29     public void destroyItem(ViewGroup container, int position, Object object) {  
30         container.removeView((View) object);  
31     }  
32 }  

 


Activity中的代碼:

 

 1 ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);  
 2         List<Integer> list = new ArrayList<>();  
 3         list.add(R.drawable.p001);  
 4         list.add(R.drawable.p002);  
 5         list.add(R.drawable.p003);  
 6         list.add(R.drawable.p004);  
 7         list.add(R.drawable.p005);  
 8         MyAdapter adapter = new MyAdapter(this, list);  
 9         viewPager.setAdapter(adapter);  
10         viewPager.setPageMargin((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
11                 48, getResources().getDisplayMetrics()));  
12         viewPager.setPageTransformer(false, new ScaleTransformer(this));  

 


最后再來看看我們定義的PageTransformer:

 

 1 public class ScaleTransformer implements ViewPager.PageTransformer {  
 2     private Context context;  
 3     private float elevation;  
 4   
 5     public ScaleTransformer(Context context) {  
 6         this.context = context;  
 7         elevation = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,  
 8                 20, context.getResources().getDisplayMetrics());  
 9     }  
10   
11     @Override  
12     public void transformPage(View page, float position) {  
13         if (position < -1 || position > 1) {  
14   
15         } else {  
16             if (position < 0) {  
17                 ((CardView) page).setCardElevation((1 + position) * elevation);  
18             } else {  
19                 ((CardView) page).setCardElevation((1 - position) * elevation);  
20             }  
21         }  
22     }  
23 }  

 


很簡單,我只是對CardView的陰影做了處理 ,其他屬性都沒改,這樣就有了我們剛才看到的效果。

 


Demo下載:http://download.csdn.net/detail/u012702547/9615195

 

參考資料:

http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1030/1870.html

 

轉自:http://blog.csdn.net/u012702547/article/details/52334161


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM