一个卡片式的ViewPager,带你玩转ViewPager的PageTransformer属性!

时间:2022-09-27 00:05:32

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属性!

大家注意看这个应用底部导航栏中中间一个是要比另外四个高的,这种效果很多人就会想到使用一个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属性!

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属性!

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属性!

OK,透明度的效果已经有了。很简单吧!

4.进一步了解PagerTransformer

上面是一个简答的效果,遵循这个思路,我们可以做出更多的效果,比如下面这个效果:

一个卡片式的ViewPager,带你玩转ViewPager的PageTransformer属性!

这是一个非常常见的效果,实现思路和前文一致,就是让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属性!

OK,那这个clipToPadding属性是我们在一个页面中显示多个ViewPager  item的第二种方式。这个CardView式的ViewPager我们就使用这种方式来实现。先来看看效果图:

一个卡片式的ViewPager,带你玩转ViewPager的PageTransformer属性!

整体思路和上文其实是一致的,我们来看看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

以上。

一个卡片式的ViewPager,带你玩转ViewPager的PageTransformer属性!的更多相关文章

  1. 卡片式ViewPager,一屏展示多个pager item,设置高度不一致的tabBar

    ViewPager的基本用法不必多说,这都很简单,我们可以在ViewPager中加载一个ImageView,也可以加载一个Fragment,这都是目前非常常见的用法.那么我今天说的是ViewPager ...

  2. 一个winform带你玩转rabbitMQ

    源码已放出 https://github.com/dubing/MaoyaRabbit 本章分3部分 一.安装部署初探 二.进阶 三.api相关 安装 部署 初探 先上图 一. 安装部署 下载 rab ...

  3. Android SurfaceView实战 带你玩转flabby bird (下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43063331,本文出自:[张鸿洋的博客] 1.概述 在Android Surfa ...

  4. Google发布机器学习平台Tensorflow游乐场~带你玩神经网络(转载)

    Google发布机器学习平台Tensorflow游乐场-带你玩神经网络 原文地址:http://f.dataguru.cn/article-9324-1.html> 摘要: 昨天,Google发 ...

  5. 带你玩转Visual Studio

    带你玩转Visual Studio 带你新建一个工程 工程目录下各文件的含义 解决方案与工程 在这之前先了解一个概念:解决方案与工程. 解决方案(Solution):一个大型项目的整体的工作环境: 工 ...

  6. 来吧!带你玩转 Excel VBA

    来吧!带你玩转 Excel VBA 从错失良机到艰辛的DOS征程,从坎坷购机自学路到转机起程,从爱好到事业,他从一个完全不懂电脑的人到VBA高级应用者,一切全是自学…… 我是罗刚君,来自四川的一个小县 ...

  7. 转: 带你玩转Visual Studio——带你理解多字节编码与Unicode码

    上一篇文章带你玩转Visual Studio——带你跳出坑爹的Runtime Library坑帮我们理解了Windows中的各种类型C/C++运行时库及它的来龙去脉,这是C++开发中特别容易误入歧途的 ...

  8. iOS开发——高级UI&amp&semi;带你玩转UITableView

    带你玩装UITableView 在实际iOS开发中UITableView是使用最多,也是最重要的一个控件,如果你不会用它,那别说什么大神了,菜鸟都不如. 其实关于UItableView事非常简单的,实 ...

  9. acdream 瑶瑶带你玩激光坦克 &lpar;模拟&rpar;

    瑶瑶带你玩激光坦克 Time Limit: 2000/1000MS (Java/Others)    Memory Limit: 256000/128000KB (Java/Others) Submi ...

随机推荐

  1. Jquery 自定义弹窗等待

    (function ($) { $.extend({ //弹窗蒙层 ShowLoadDialog : function () { ) { var cusrtxt = $("<div i ...

  2. VMware系统运维(四)SQL Server 2008 R2 新建数据库与ODBC数据

    1.新建数据库,右击"新建数据库-." 2.设置数据库名,初始数据库大小,如果要配置数据库优化,可以考虑初始大小与日志大小,点击添加安装完成,即完成数据库新建. 3.ODBC数据源 ...

  3. Java&lowbar;eclipse软件与git配合使用创建git仓库

    一.在eclipse上安装git,和安装其他插件一样 help->Install new software->add... 在弹出框中输入name,location;点击-->ok ...

  4. 设置listview的header不能点击

    View headView = inflater.inflate(R.layout.search_top, null); mListView.addHeaderView(headView ,null, ...

  5. 内存测试工具memtester

    Memtester是用户态工具,用于测试内存子系统的故障.非常方便,支持32位 或64位Unix-like系统.对于硬件开发开发者来说,memtester可以定位到物理地址. 1. 安装 下载地址ht ...

  6. tokyocabinet安装日志&lpar;持续更新&rpar;

    http://sourceforge.jp/projects/sfnet_tokyocabinet/releases/这个网站的最新tt和tc都在此1.下载tokyocabinethttp://sou ...

  7. 製程能力介紹&lpar;SPC introduction&rpar; &HorizontalLine; Ck之製程能力解釋

    Ck之製程能力解釋 a=M-X: 代表規格中心(也就是製程之期望中心)與實際製造出來之群體中心的距離. b=T/2: 代表規格的一半. 所以,當Ck=a/b=M-X/(T/2)以文字來說明就是:實際作 ...

  8. linux下tomcat shutdown后 java进程依然存在

    今天遇到一个非常奇怪的问题,如标题所看到的: linux下(之所以强调linux下,是由于在windows下正常),运行tomcat ./shutdown.sh 后,尽管tomcat服务不能正常訪问了 ...

  9. ABP&plus;AdminLTE&plus;Bootstrap Table权限管理系统第二节--在ABP的基础做数据库脚本处理

    返回总目录:ABP+AdminLTE+Bootstrap Table权限管理系统一期 第一点,上一篇文章中我们讲到codefirst中一些问题包括如图,codefirst在每次执行命令的时候会生成新的 ...

  10. iOS 图片本地存储、本地获取、本地删除

    在iOS开发中.经常用到图片的本地化. iOS 图片本地存储.本地获取.本地删除,可以通过以下类方法实现. p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: ...