卡片式Viewpager

ViewPager的基本用法不必多說,這都很簡單,我們可以在ViewPager中加載一個ImageView,也可以加載一個Fragment,這都是目前非常常見的用法。那么我今天說的是ViewPager中的PageTransformer屬性,用好這個屬性可以讓我們的應(yīng)用更加出彩,OK,那我們就開始吧!

本文將從如下幾方面來介紹:

1.clipChildren屬性
2.一個頁面顯示多個ViewPager的Item
3.初識PagerTransformer
4.進一步了解PagerTransformer
5.ViewPager結(jié)合CardView

1.clipChildren屬性

clipChildren屬性表示是否限制子控件在該容器所在的范圍內(nèi),clipChildren屬性配合layout_gravity屬性,可以用來設(shè)置多余部分的顯示位置,我這里舉一個簡單的例子,比如喜馬拉雅FM這個應(yīng)用的首頁:


image.png

大家注意看這個應(yīng)用底部導(dǎo)航欄中中間一個是要比另外四個高的,這種效果很多人就會想到使用一個RelativeLayout布局來實現(xiàn),其實不用那么麻煩,這種效果一個clipChildren屬性就能實現(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é)點添加clipChildren屬性,然后在第三個ImageView上添加layout_gravity屬性即可,layout_gravity屬性值為bottom表示控件大小超出后控件底部對齊。效果如下:


image.png

OK,上面是對clipChildren屬性一個簡單介紹,算是一個鋪墊,接下來我們來看看ViewPager。

2.一個頁面顯示多個ViewPager的Item

我們要來解決的第一個問題是如何在一個頁面上顯示ViewPager的多個item,一共有兩種解決方案,第一種就是我們上文所說的clipChildren屬性,第二種是clipToPadding屬性,我們先來看看使用第一種屬性設(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è)置左右兩個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,這個是設(shè)置預(yù)加載的頁數(shù),我們知道默認情況下這個參數(shù)為1,也就是左右各預(yù)加載一頁,但是我們這里要讓左右各預(yù)加載兩頁,原因一會再說,另外一個PageMargin就好說了,就是設(shè)置ViewPager中兩頁之間的距離。OK,那我們來看看顯示效果:


image.png

OK,就是這么簡單,這樣,我們現(xiàn)在已經(jīng)可以在一個頁面上來顯示多個ViewPager中的item,接下來我們先來看看PageTransformer的簡單使用。

3.初識PagerTransformer

我們知道可以給ViewPager設(shè)置一個setPagerTransformer屬性,設(shè)置時候需要我們自己來實現(xiàn)PagerTransformer接口,實現(xiàn)這個接口的時候要實現(xiàn)該接口中的方法,transformPage,該方法接收兩個參數(shù),其中一個是position,如果你直接打印position出來可能會看得你云里霧里,實際上position表示的是第一個參數(shù)View的position,把這兩個參數(shù)一起打印出來就可以找到規(guī)律了:

比如從第1頁滑動到第2頁:

第一頁position的變化為 [0,-1]

第二頁position的變化為 [1,0]

知道了這個我們就可以寫一個簡單的切換動畫了,我希望頁面上正中間的item是正常的,兩邊的item都有一點透明度。那我們可以使用如下方式來定義:

public class AlphaTransformer implements ViewPager.PageTransformer {  
    private float MINALPHA = 0.5f;  
  
    /** 
     * position取值特點: 
     * 假設(shè)頁面從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));  
            }  
        }  
    }  
}  

定義好了之后再設(shè)置給ViewPager即可:

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

我們再來看看運行效果:


image.png

4.進一步了解PagerTransformer

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

image.png

這是一個非常常見的效果,實現(xiàn)思路和前文一致,就是讓ImageView動態(tà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());  

就是這么簡單。其它復(fù)雜的旋轉(zhuǎn)平移等都是按照這個思路來實現(xiàn),這里不再贅述。

5.ViewPager結(jié)合CardView

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

那么在這之前,我想先介紹一個屬性,那就是clipToPadding,這個屬性是什么意思呢?它表示是否允許ViewGroup在ViewGroup的padding中進行繪制,默認情況下該屬性的值為true,即不允許在ViewGroup的padding中進行繪制。那如果我設(shè)置了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);  

顯示效果如下:


image.png

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


image.png

整體思路和上文其實是一致的,我們來看看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);  
            }  
        }  
    }  
}

原文鏈接
http://blog.csdn.net/u012702547/article/details/52334161

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容