Android实现ViewPager视差动画效果及背景渐变过渡
Posted 胖子爱你520
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android实现ViewPager视差动画效果及背景渐变过渡相关的知识,希望对你有一定的参考价值。
在上一篇文章(TabLayout与ViewPager配合使用踩坑总结)中我记录了TabLayout搭配ViewPager使用过程中的踩坑过程,那么这一篇文章我来写一下ViewPager切换的视差动画效果及背景渐变过渡是如何实现的!
一、视差动画实现
惯例首先来看看ViewPager的切换效果:
注意下方的三行文字,在切换的时候是有一个视觉差的,也就是它们仨不是以同一个偏移量移动,可以看到名称那一行在滑动时偏移量比其他的大,第二行比第三行偏移量大,这就是我们说的视差效果,那么如何实现呢?
在上一篇的工程源码中可以看到,在PagerAdapter的实现中,instantiateItem方法最后我用一个数组mLayoutViewIdsMap将当前item布局中所有的id数组记录下来了:
@NonNull
@Override
public Object instantiateItem(@NonNull ViewGroup container, int position)
View view = LayoutInflater.from(MainActivity.this)
.inflate(R.layout.viewpager_item, null, false);
GirlBean bean = girlList.get(position);
if (null == bean)
return null;
TextView tvName = view.findViewById(R.id.tv_name);
tvName.setText(bean.name);
TextView tvDesc = view.findViewById(R.id.tv_desc);
tvDesc.setText(bean.desc);
TextView tvLike = view.findViewById(R.id.tv_like);
tvLike.setText(bean.like);
//存储布局ID
int[] ids = new int[]
R.id.tv_name, R.id.tv_desc, R.id.tv_like
;
mLayoutViewIdsMap.put(position, ids);
container.addView(view);
return view;
接下来就是使用ViewPager的setPageTransformer方法,这个方法可以给ViewPager设置切换场景的动画效果,我们这里只列出这个项目中用到的,就是每个Item中各个控件的偏移视差效果动画。
新建一个类实现PageTransformer:
private class ParallaxTransformer implements ViewPager.PageTransformer
float parallaxCoefficient;
float distanceCoefficient;
public ParallaxTransformer(float parallaxCoefficient, float distanceCoefficient)
this.parallaxCoefficient = parallaxCoefficient;
this.distanceCoefficient = distanceCoefficient;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void transformPage(View page, float position)
float scrollXOffset = page.getWidth() * parallaxCoefficient;
ViewGroup pageViewWrapper = (ViewGroup) page;
@SuppressWarnings("SuspiciousMethodCalls")
int[] layer = mLayoutViewIdsMap.get(viewPager.getCurrentItem());
for (int id : layer)
View view = page.findViewById(id);
if (view != null)
view.setTranslationX(scrollXOffset * position);
scrollXOffset *= distanceCoefficient;
transformPage方法中两个参数,page表示当前滑动的ViewPager中的Item,position表示滑动的位置,比如0->-1,1->0,具体的可以打log观察。
这里我们主要是取出每个position对应的Item的各个控件,然后对它设置一个setTranslationX偏移量,因为它们自身在布局中的位置不一样,所以这里通过view.setTranslationX(scrollXOffset * position)运行的效果也不一样,所以这样就实现了我们说的视差效果,如果有需要我们还可以对控件设置透明度等等。
最后调用
viewPager.setPageTransformer(true,
new ParallaxTransformer(PARALLAX_COEFFICIENT, DISTANCE_COEFFICIENT));
设置给ViewPager即可。
二、背景图片切换过渡
可以看出在切换过程中,背景图片是有一个渐变的效果的,这个背景位置因为是静态的,所以不能跟随ViewPager一起左右切换,所以图片就不适合放到PagerAdapter的Item布局中,应该放到ViewPager平级的布局文件中,作为一个底图背景:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="match_parent">
<ImageView
android:id="@+id/bg1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:background="@drawable/girl1" />
<ImageView
android:id="@+id/bg2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:background="@drawable/girl2" />
<ImageView
android:id="@+id/bg3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:background="@drawable/girl3" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.zhangyan.mytablayout.tablayout.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Hello World!"
app:tabGravity="fill"
app:tabIndicatorColor="#CBA788"
app:tabIndicatorHeight="3dp"
app:tabLineOffset="10dp"
app:tabMode="fixed"
app:tabSelectedTextColor="#CBA788"
app:tabTextColor="#CCFFFFFF" />
</RelativeLayout>
这里我放了三个ImageView作为背景。
bgImg1 = findViewById(R.id.bg1);
bgImg2 = findViewById(R.id.bg2);
bgImg3 = findViewById(R.id.bg3);
//刚进来只显示第一张背景
bgImg2.getBackground().setAlpha(0);
bgImg3.getBackground().setAlpha(0);
初始化的时候先将后两张透明度设为0,这样只显示出第一张。
剩下的处理逻辑就需要依赖OnPageChangeListener中实现了,实现OnPageChangeListener这个类:
private ViewPager.OnPageChangeListener mOnPageChangeListener =
new ViewPager.OnPageChangeListener()
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels)
float fraction = positionOffset;
if (position == 0)
bgImg1.getBackground().setAlpha(255);
bgImg2.getBackground().setAlpha((int) (fraction * 255));
bgImg3.getBackground().setAlpha(0);
if (position == 1)
bgImg2.getBackground().setAlpha(255);
bgImg3.getBackground().setAlpha((int) (fraction * 255));
bgImg1.getBackground().setAlpha(0);
if (position == 2)
bgImg3.getBackground().setAlpha(255);
@Override
public void onPageSelected(int position)
@Override
public void onPageScrollStateChanged(int state)
;
在onPageScrolled这个方法中有三个参数:
- position:当前滑动pager的position,第一张到第二张position从0开始,完全滑动到第二张时,position=1;第二张到第三张position从1开始,完全滑动到第三张时,position=2;以此类推。
- positionOffset:滑动的比例,往下一张滑动时,positionOffset从0慢慢过渡到1,往上一张滑动时,positionOffset从1慢慢过渡到0;
- positionOffsetPixels:滑动的像素,从0开始,最大值为屏幕的宽度(分辨率)
我们这里主要是在onPageScrolled中对三张图的背景alpha进行变化,实现我们所需要的效果即可,其他的逻辑大家可以尝试着改改。
三、最后
我们可以依托ViewPager的属性实现更多复杂和好看的动画效果,网上也有很多开源的项目已经做到了,大家可以根据自己的需要进行设置,么么哒~
以上是关于Android实现ViewPager视差动画效果及背景渐变过渡的主要内容,如果未能解决你的问题,请参考以下文章
android 卡片画廊效果及RecycleView、ViewPager、ScrollView之前的冲突解决
使用NestedScrollView+ViewPager+RecyclerView+SmartRefreshLayout打造酷炫下拉视差效果并解决各种滑动冲突
android ViewPager+fragment切换动画实现