Android ViewPager实现动画切换效果

时间:2021-05-21

概述

ViewPager是Android开发中使用场景非常频繁的控件,单一的动画效果切换已经越来越不能满足追求个性化的应用中。而ViewPager自身也带有一个接口来处理页面间的动画切换,那就是setPageTransformer。下面我们通过代码来学习动画效果的切换。

实现简单动画切换

代码如下:

1.布局文件

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/view_pager_box" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_margin="10dp" android:layout_width="wrap_content" android:layout_height="120dp" /></LinearLayout>

MainActivity 中相关 java 代码

import android.app.Activity;import android.os.Bundle;import android.support.v4.view.PagerAdapter;import android.support.v4.view.ViewPager;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.ImageView.ScaleType;public class MainActivity extends Activity { private ViewPager viewPager; private int[] imageIds = new int[]{R.drawable.pic1,R.drawable.pic2,R.drawable.pic3,R.drawable.pic4,R.drawable.pic5,}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); viewPager = (ViewPager) findViewById(R.id.viewpager); viewPager.setOffscreenPageLimit(3); //设置内存中预加载页面数 viewPager.setPageTransformer(true, new DepthPageTransformer()); //设置页面切换过渡动画 viewPager.setAdapter(new PagerAdapter() { @Override public boolean isViewFromObject(View view, Object object) { return view == object; } @Override public int getCount() { return imageIds.length; } @Override public Object instantiateItem(ViewGroup container, int position) { ImageView imageView = new ImageView(MainActivity.this); imageView.setScaleType(ScaleType.CENTER_CROP); imageView.setImageResource(imageIds[position]); imageView.setTag(position); //设置标记 container.addView(imageView); return imageView; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView((View)object); } }); }}

3.控制切换动画的类DepthPageTransformer的代码

import android.support.v4.view.ViewPager;import android.view.View;public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; @Override public void transformPage(View view, float position) { android.util.Log.i("yuminfeng", "====view:" + view.getTag() + ",position:" + position); int pageWidth = view.getWidth(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out. view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } }}

上面的代码十分简单,仅仅只是ViewPager的初始化配置,然后通过setPageTransformer设置页面切换动画。有一个细节还需要注意,设置setOffscreenPageLimit(3),表示内存中预加载页面为3,这三个页面是不可见的。如果加上当前显示的页面,总共初始化了4个页面。不设置的话,系统使用默认的预加载的页数为1。
第一次启动应用后,我们通过在DepthPageTransformer类中记录的日志可以看到,如下:

总共初始化了4个view,其中当前对用户可见view的位置为0,其余都是不可见。所以当position=0时,表示当前的页面。

我们继续操作并向左滑动一页,日志如下:

由此可以看到,之前的view的位置变为-1,它的右边的view位置为0,变成可见。
继续滑动至最后一页后:

我们看到最后一页的view已经展现在用户面前,位置为0,而其他页面位置都是为负,表示所有页面都滑至左边。这时我们注意的话,可以发现view:0,不在日志信息中,难道它没有被初始化?其实它已经被系统回收了,通过Adapter中destroyItem方法。因为我们之前设置ViewPager中预加载的页数限制为3,系统中最多的存在4个view,所以view:0被回收。

从上面的分析我们可以知道,当view的position处于[-1,1]时,该view能够被用户所见,其他位置便不可见。而PageTransformer的接口中,真是利用了这个特点,根据view的position来对它进行缩放,旋转等动画操作。我们继续分析DepthPageTransformer类:
当 position < -1,即[-Infinity,-1) 时:
view处于左边不可见中,这里view.setAlpha(0); 表示完全透明。
当-1 <= position <= 0 时,该view处于可见区域,:
1.如果view向左滑动,表示当前view逐渐滑出可见区域
2.如果view向右滑动,表示左边的view逐渐划入当前可见区域。
view.setAlpha(1),设置透明度,表示完全不透明。
view.setTranslationX(0),表示设置view相对于左侧位置的水平位置,距离左边的距离。
view.setScaleX(1)和view.setScaleY(1),表示view的x,y轴不进行缩放。
当0 < position <= 1 时,该view处于可见区域:
1.如果view向右滑动,表示当前view逐渐滑出可见区域。
2.如果view向左滑动,表示右边的view逐渐滑入可见区域。
view.setAlpha(1 - position),根据view滑动的位置,设置view的透明度。position 越接近于0,表明view面对用户显示的越多,所以就越不透明。
view.setTranslationX(pageWidth * -position),根据view滑动的位置,设置view相对于左侧位置的水平位置,当position = 0 时,view完全显示,这时相对左边为0,当 position = 1 时,view完全不可见,这时相对左边为view的宽度。
float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position));
view.setScaleX(scaleFactor);
view.setScaleY(scaleFactor);
根据view的position,设置view的缩放大小。当 position,越大时,越远离用户界面,于是越不可见。
当1< position 时,即(1,+Infinity]时:
view.setAlpha(0),设置完全透明不可见。

上述代码执行效果如下:

我们还可以定制其他的动画效果,实现原理和上面一样,这里就不一一列出来了。

实现广告轮播效果图

如图:

实现上面的效果图,只需要对上面的代码进行一些修改即可:

想要在屏幕上出现多个页面,我们需要设置属性:android:clipChildren=”false”,该属性的意思是在View进行绘制的时候,不去裁切它们的显示范围,即不限制view的显示范围。
我们修改布局文件,如下:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/view_pager_box" android:layout_width="match_parent" android:layout_height="160dp" android:gravity="center" android:clipChildren="false" android:orientation="horizontal" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_margin="30dp" android:layout_height="120dp" /></LinearLayout>

在ViewPager的外面控件中设置了android:clipChildren=”false”,然后设置viewpager中android:layout_margin属性,留出间距,方便显示左右两边的图片。后面我们还要java代码设置viewpager的属性,如:
viewPager.setPageMargin(40); //设置页面间间距
这样可以让页面之间存在一定的间隔。最后,我们通过setPageTransformer方法设置自己定义的动画即可,与上面一致。
该效果的动画类代码:

import android.support.v4.view.ViewPager;import android.view.View;public class AlphaScaleTransformer implements ViewPager.PageTransformer { private static final float DEFAULT_MIN_ALPHA = 0.5f; private float mMinAlpha = DEFAULT_MIN_ALPHA; private static final float DEFAULT_MIN_SCALE = 0.85f; private float mMinScale = DEFAULT_MIN_SCALE; public static final float DEFAULT_CENTER = 0.5f; @Override public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); view.setScaleX(0.999f);// hack view.setPivotY(pageHeight / 2); view.setPivotX(pageWidth / 2); if (position < -1) { // [-Infinity,-1) view.setAlpha(mMinAlpha); view.setScaleX(mMinScale); view.setScaleY(mMinScale); view.setPivotX(pageWidth); } else if (position <= 1) { // [-1,1] if (position < 0) // [0,-1] { // [1,min] float factor = mMinAlpha + (1 - mMinAlpha) * (1 + position); float scaleFactor = (1 + position) * (1 - mMinScale) + mMinScale; view.setAlpha(factor); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); view.setPivotX(pageWidth * (DEFAULT_CENTER + (DEFAULT_CENTER * -position))); } else// [1,0] { // [min,1] float factor = mMinAlpha + (1 - mMinAlpha) * (1 - position); float scaleFactor = (1 - position) * (1 - mMinScale) + mMinScale; view.setAlpha(factor); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); view.setPivotX(pageWidth * ((1 - position) * DEFAULT_CENTER)); } } else { // (1,+Infinity] view.setAlpha(mMinAlpha); view.setPivotX(0); view.setScaleX(mMinScale); view.setScaleY(mMinScale); } }}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章