天天看點

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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這個應用的首頁:

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

大家注意看這個應用底部導航欄中中間一個是要比另外四個高的,這種效果很多人就會想到使用一個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表示控件大小超出後控件底部對齊。效果如下:

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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,那我們來看看顯示效果:

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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());
           

我們再來看看運作效果:

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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

4.進一步了解PagerTransformer

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

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

這是一個非常常見的效果,實作思路和前文一緻,就是讓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);
           

顯示效果如下:

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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

一個卡片式的ViewPager,帶你玩轉ViewPager的PageTransformer屬性!1.clipChildren屬性2.一個頁面顯示多個ViewPager的Item3.初識PagerTransformer4.進一步了解PagerTransformer5.ViewPager結合CardView

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