600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > android滑动切换卡片 一步步实现Viewpager卡片翻页效果

android滑动切换卡片 一步步实现Viewpager卡片翻页效果

时间:2019-02-17 02:20:58

相关推荐

android滑动切换卡片 一步步实现Viewpager卡片翻页效果

这个CardStackViewpager的灵感来自Github上面的 FlippableStackView开源项目,而我想实现的效果方向上刚好与FlippableStackView相反,而且细节上也有些区别,详见下面的效果对比图:java

FlippableStackView运行效果图:

CardStackViewpager运行效果图:

这里讲一个小插曲,本身尝试实现CardStackViewpager的过程当中,因为一开始对PageTransformer的onTransform(View page, float position)实在很困惑,因而我用本身小学般的英语写了一封邮件给FlippableStackView的开发者,尴尬的是,至今他没回我邮件。android

回归正题,下面我就来具体讲一下CardStackViewpager的实现思路,其实整个核心就在下面这一段代码,把下面这段代码搞懂了,就能够经过自定义本身的PageTransformer实现各类各样想要的Viewpager效果了。git

核心的VerticalStackTransformer的onTransform方法最终版

@Override

protected void onTransform(View page, float position) {

if (position <= 0.0f) {

page.setAlpha(1.0f);

Log.e("onTransform", "position <= 0.0f ==>" + position);

page.setTranslationY(0f);

//控制中止滑动切换的时候,只有最上面的一张卡片能够点击

page.setClickable(true);

} else if (position <= 3.0f) {

Log.e("onTransform", "position <= 3.0f ==>" + position);

float scale = (float) (page.getWidth() - ScreenUtils.dp2px(context, spaceBetweenFirAndSecWith * position)) / (float) (page.getWidth());

//控制下面卡片的可见度

page.setAlpha(1.0f);

//控制中止滑动切换的时候,只有最上面的一张卡片能够点击

page.setClickable(false);

page.setPivotX(page.getWidth() / 2f);

page.setPivotY(page.getHeight() / 2f);

page.setScaleX(scale);

page.setScaleY(scale);

page.setTranslationY(-page.getHeight() * position + (page.getHeight() * 0.5f) * (1 - scale) + ScreenUtils.dp2px(context, spaceBetweenFirAndSecHeight) * position);

}

}

在分析上面的代码以前,咱们须要有如下几个知识准备:

Viewpager的setPageTransformer(boolean reverseDrawingOrder, ViewPager.PageTransformer transformer)方法的第一个参数,用来控制加入到Viewpager的Views对象是正序的仍是倒序的,这里为了实现咱们想要的效果,须要让第一个添加到布局的View来到第一个展现,因此传入true;

Viewpager的setOffscreenPageLimit(int limit)方法,设置有多少的缓存Views,这个将决定咱们的卡片重叠展现的效果显示几层卡片效果。

如今咱们继续看上面的onTransform(View page, float position)方法,这个方法设计的很巧妙,当初我在探索的时候,经过打印日志来判断这个方法是如何执行的时候,发现这这个position的值看似毫无规律,后来我想到之前数学里推理定理时的方法,从特殊状况入手,再一点点分析其余状况,而后一步步的实现上面的代码。github

第一步,分析应用初始化进来的时候的position

此时的onTransform(View page, float position)方法以下:web

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform","position ==>"+position);

//设置每一个卡片y方向偏移量,这样可使卡片都彻底叠加起来

page.setTranslationY(-page.getHeight() * position);

}

对应日志以下:缓存

根据这个日志很明显的能够判断获得:因为我如今设置的setOffscreenPageLimit(int limit)值为4,因此能够看到position有上面几种状况,显而易见,每一个position对应了一张卡片,这个时候界面的效果如图:ide

如今猜测2,3,4,5号卡片就在1号卡片下面,如今要想个法子证明咱们的猜测,将onTransform(View page, float position)方法改为下面这样:svg

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform","position ==>"+position);

//设置卡片透明度

page.setAlpha(0.5f);

//设置缩放中点

page.setPivotX(page.getWidth() / 2f);

page.setPivotY(page.getHeight() / 2f);

//设置缩放的比例 此处设置两个相邻的卡片的缩放比率为0.9f

page.setScaleX((float) Math.pow(0.9f,position));

page.setScaleY((float) Math.pow(0.9f,position));

//设置每一个卡片y方向偏移量,这样可使卡片都彻底叠加起来

page.setTranslationY(-page.getHeight() * position);

}

运行起来以后,证明了咱们的想法:布局

第二步,实现卡片叠加的最终效果

分析上面的图片效果,能够发现,把第二张卡片往下移动一段距离以后,就能够造成一个卡片叠加的初步效果了,变成下面这样:

其余的卡片,道理同样,那么如何实现这个向下偏移的值呢,这个值如何以一个表达式表现出来呢,先看下面的A,B,C步骤的分析图:

显而易见,相隔两张卡片的偏移量为:(H2-H1)+d1,咱们稍微改变一下onTransform(View page, float position)方法以下:

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform", "position ==>" + position);

page.setAlpha(0.5f);

page.setPivotX(page.getWidth() / 2f);

page.setPivotY(page.getHeight() / 2f);

page.setScaleX((float) Math.pow(0.9f, position));

page.setScaleY((float) Math.pow(0.9f, position));

//修改过的代码

page.setTranslationY(-page.getHeight() * position + (page.getHeight() * 0.5f) * (1 - (float) Math.pow(0.9f, position)) + ScreenUtils.dp2px(context, 10));

}

此时的效果图以下:

卡片半透明的时候,效果还不是特别的明显,把page.setAlpha(0.5f)改成page.setAlpha(1.0f)再试一次:

惊喜的发现这不就是卡片叠加效果嘛,虽然如今的效果细节还有点问题,咱们不急,这个细节问题简单分析一下就会想到,是咱们的缩放比例问题致使的,继续下一步的优化,咱们将会解决这个问题。

第三步,根据相邻卡片的间距值动态设置缩放值

上面的onTransform(View page, float position)方法中,咱们的x,y缩放比例都是写的一个固定值0.9f,这个显然不能知足平常需求,我这里是设置上下两张卡片的宽度比来做为最终想要的缩放比例,修改onTransform(View page, float position)方法以下:

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform", "position ==>" + position);

float scale = (float) (page.getWidth() - ScreenUtils.dp2px(context, 20 * position)) / (float) (page.getWidth());

page.setAlpha(1.0f);

page.setPivotX(page.getWidth() / 2f);

page.setPivotY(page.getHeight() / 2f);

page.setScaleX(scale);

page.setScaleY(scale);

//修改过的代码

page.setTranslationY(-page.getHeight() * position + (page.getHeight() * 0.5f) * (1 - scale) + ScreenUtils.dp2px(context, 10) * position);

}

再跑一下程序,完美的卡片效果就出现了:

第四步,特殊到通常,实现最终的卡片滑动效果

此时,咱们尝试一下滑动Viewpager,发现卡片的切换效果并无如期的出现,经过屡次尝试和分析,我发现,因为咱们这里没有对当前滑动过去的那张卡片作特殊处理,这里的特殊处理指的是:为了实现卡片抽动的切换效果,当前滑动的卡片应该不用执行任何缩放和偏移的操做,修改成page.setTranslationY(0f);,具体代码以下:

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform", "position ==>" + position);

if (position <= 0.0f) {

page.setAlpha(1.0f);

//出现卡片抽动效果的关键代码

page.setTranslationY(0f);

} else {

float scale = (float) (page.getWidth() - ScreenUtils.dp2px(context, 20 * position)) / (float) (page.getWidth());

page.setAlpha(1.0f);

page.setPivotX(page.getWidth() / 2f);

page.setPivotY(page.getHeight() / 2f);

page.setScaleX(scale);

page.setScaleY(scale);

//修改过的代码

page.setTranslationY(-page.getHeight() * position + (page.getHeight() * 0.5f) * (1 - scale) + ScreenUtils.dp2px(context, 10) * position);

}

}

至此,已经能够实现文章开头的动画效果了。回头想一下,咱们一直在基于特殊的状况写代码,最后发现其实他就是全部通常状况中的一种,只不过特殊状况因为他的特殊性最容易进行分析总结,更有利于咱们编写出易懂的代码。

最后补充下,在实际项目中,在每张卡片上可能还有有点击区域,更可能整张卡片都是一个点击区域,这个时候就会发现一个问题,当处于这种状况的时候:

我不但能够点到卡片1,也会点到卡片2,卡片3。。。这样确定不行的,因此咱们再次回到onTransform(View page, float position)方法,在里面加一个控制:

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform", "position ==>" + position);

if (position <= 0.0f) {

//最上面的卡片能够点击

page.setClickable(true);

.......

} else {

//下面的卡片不可点击

page.setClickable(false);

........

}

}

另外咱们可能只须要4张卡片重叠的效果就行,这个时候改变一下判断条件便可:

@Override

protected void onTransform(View page, float position) {

Log.e("onTransform", "position ==>" + position);

if (position <= 0.0f) {

......

//控制显示几张卡片

} else if(position <= 3.0f) {

......

}

}

至此这边文章就要结束了,这是个人总结,但愿能帮助你们对onTransform(View page, float position)方法有一个更深的理解。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。