卡片式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如下:
代码:
<?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=""
android:src="@mipmap/ic_launcher"/> <ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=""
android:src="@mipmap/ic_launcher"/> <ImageView
android:layout_width="0dp"
android:layout_height="72dp"
android:layout_gravity="bottom"
android:layout_weight=""
android:src="@mipmap/ic_launcher"/> <ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=""
android:src="@mipmap/ic_launcher"/> <ImageView
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=""
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();
viewPager.setOffscreenPageLimit();
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 < - || position > ) {
page.setAlpha(MINALPHA);
} else {
//不透明->半透明
if (position < ) {//[0,-1]
page.setAlpha(MINALPHA + ( + position) * ( - MINALPHA));
} else {//[1,0]
//半透明->不透明
page.setAlpha(MINALPHA + ( - position) * ( - 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 < - || position > ) {
page.setAlpha(MIN_ALPHA);
page.setScaleX(MIN_SCALE);
page.setScaleY(MIN_SCALE);
} else if (position <= ) { // [-1,1]
float scaleFactor = Math.max(MIN_SCALE, - Math.abs(position));
if (position < ) {
float scaleX = + 0.3f * position;
Log.d("google_lenve_fb", "transformPage: scaleX:" + scaleX);
page.setScaleX(scaleX);
page.setScaleY(scaleX);
} else {
float scaleX = - 0.3f * position;
page.setScaleX(scaleX);
page.setScaleY(scaleX);
}
page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / ( - MIN_SCALE) * ( - 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();
显示效果如下:
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,
, 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,
, context.getResources().getDisplayMetrics());
} @Override
public void transformPage(View page, float position) {
if (position < - || position > ) { } else {
if (position < ) {
((CardView) page).setCardElevation(( + position) * elevation);
} else {
((CardView) page).setCardElevation(( - position) * elevation);
}
}
}
}
很简单,我只是对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
卡片式ViewPager,一屏展示多个pager item,设置高度不一致的tabBar的更多相关文章
- Android ViewPager系列之ViewPager一屏显示多个子页面
ViewPager一屏显示多个子页面,常见的有两种形式: 1.当前展示的页面右侧显示一部分下个页面的内容 2.当前页面居中,左右两边分别显示上一个页面.下一个页面 第 1 种表现形式的实现代码 其实这 ...
- echarts图表自适应盒子的大小(盒子的大小是动态改变的),大到需要全屏展示
项目中用到了echarts,并且页面是自适应的,且页面中有一个[放大.缩小]功能,因此图表还需要根据盒子的大小来变化. 即:两个需求,如下: ① 图表根据窗口的大小自适应 ② 图表根据所在盒子的大小自 ...
- Unity3D_(游戏)卡牌01_启动屏界面
卡牌2D游戏展示 (游戏代码放到 卡牌04_游戏界面 文章最后面~) 游戏项目已托管到github上(里面有个32bit可执行文件) 传送门 规则 开始游戏每张卡牌初始翻开展示 展示几秒后卡牌 ...
- 树莓派Odroid等卡片式电脑上搭建NAS教程系列6-miniDLNA
目录: 1. 树莓派Odroid等卡片式电脑上搭建NAS教程系列1-Ubuntu系统安装 2. 树莓派Odroid等卡片式电脑上搭建NAS教程系列2-SSH连接访问 3. 树莓派Odroid等卡片式电 ...
- js控制页面的全屏展示和退出全屏显示
<!DOCTYPE html> <html> <meta http-equiv="Content-Type" content="text/h ...
- CollapsingToolbarLayoutDemo【可折叠式标题栏,顺便带有CardView卡片式布局】
版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 CollapsingToolBarLayout是一个作用于ToolBar基础之上的布局,它也是由Design Support库提供的 ...
- CardView卡片式布局
CardView适用于实现卡片式布局效果的重要控件,由appcompat-v7库提供,实际上CardView也是一个FrameLayout,只是额外提供了圆角和阴影效果,看上去有立体的感觉.一般Car ...
- [Android] Android 卡片式控件CardView的优雅使用
[Android] Android 卡片式控件CardView的优雅使用 CardView是在安卓5.0提出的卡片式控件 其具体用法如下: 1.在app/build.gradle 文件中添加 comp ...
- JavaScript 全屏展示
浏览器都有页面全屏的功能 F11 ,那么如何用JavaScript控制页面全屏呢?MDN上提供的的API , 一个小demo验证一下! <!DOCTYPE html> <html l ...
随机推荐
- MySQL5.7.11免安装版的安装和配置:解决MYSQL 服务无法启动问题
在http://dev.mysql.com/downloads/mysql 这个官网下载MySQL5.7.11 ZIP Archive版本号: watermark/2/text/aHR0cDovL2J ...
- C++的iterator与const_iterator
所有的标准库容器都定义了相应的迭代器类型.迭代器对所有的容器都适用,现代 C++ 程序更倾向于使用迭代器而不是下标操作访问容器元素. 1.iterator,const_iterator作用:遍历容器内 ...
- hive的UDF读取配置文件
hive的UDF读取配置文件 实现步骤 在读取配置文件的写为./file_name,然后在添加UDF的时候把配置文件也加入资源就好了: add jar xxx.jar; add file file_n ...
- VMWare ESX/ESXi 虚拟机硬盘的厚置备(Thick Provision)与精简置备(Thin Provision)的转换
VMWare ESX/ESXi 有两种硬盘置备方式,厚制备(thick)和精简置备(Thin) 有时可能会由于性能问题或磁盘空间需要将虚拟机磁盘在两种模式间进行互转,虽然在虚拟机配置页面是没有办法修改 ...
- 分类算法----k近邻算法
K最近邻(k-Nearest Neighbor,KNN)分类算法,是一个理论上比较成熟的方法,也是最简单的机器学习算法之一.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的 ...
- 进入Linux救援(rescue)模式的四大法门
原文:http://blog.51cto.com/xxrenzhe/1272838 适用场景: 当误操作修改系统启动文件/etc/fstab, /etc/rc.d/rc.sysinit时,就会造成系统 ...
- HTML 转义字符对照表
http://tool.oschina.net/commons 字符 十进制 转义字符 " " " & & & < < < &g ...
- 5. 支持向量机(SVM)软间隔
1. 感知机原理(Perceptron) 2. 感知机(Perceptron)基本形式和对偶形式实现 3. 支持向量机(SVM)拉格朗日对偶性(KKT) 4. 支持向量机(SVM)原理 5. 支持向量 ...
- SVD分解及线性最小二乘问题
这部分矩阵运算的知识是三维重建的数据基础. 矩阵分解 求解线性方程组:,其解可以表示为. 为了提高运算速度,节约存储空间,通常会采用矩阵分解的方案,常见的矩阵分解有LU分解.QR分解.Cholesky ...
- win7+python3.6+word_cloud 安装出现Microsoft Visual C++ 14.0 is required
说明 环境: 已安装Anaconda3 (64-bit) 4.4.0(Python 3.6.1).其中,代码调试在Spyder 3.1.4中进行,安装包则直接打开Anaconda Prompt调用cm ...