近来闲得无聊,觉得有必要学习下viewpage的切换动画效果。
首先是先阅读官网对于viewpage动画的说明和demo:http://developer.android.com/training/animation/screen-slide.html
对于官网给出的demo我已无力吐槽了。。。
所以还是根据官网的Demo自己修改下吧!
省去布局文件,我们直接上Fragment的代码,主要用来显示,没有什么代码,很简单,不解释。
/** * Created by victor on 2016/5/12. */ public class ScreenSlidePageFragment extends Fragment { public static ScreenSlidePageFragment newInstance(int redId) { ScreenSlidePageFragment fragment = new ScreenSlidePageFragment(); Bundle bundle = new Bundle(); bundle.putInt("tag", redId); fragment.setArguments(bundle); return fragment; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { Bundle bundle = getArguments(); ImageView imageView = new ImageView(getContext()); if (bundle != null) { imageView.setImageResource(bundle.getInt("tag")); imageView.setScaleType(ImageView.ScaleType.CENTER_CROP); } return imageView; } }
接下来才是我们要看的重头戏。
先是简单的viewpage布局
android:id="@+id/pager"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="true"/>
然后是我们的主控制器ScreenSlidePagerActivity,用来控制Fragment的切换,也就是上面的图片的显示切换效果;
import android.support.v4.app.FragmentActivity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentStatePagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import com.example.viewpageanim.com.example.viewpageanim.transformer.ScaleInTransformer; public class ScreenSlidePagerActivity extends FragmentActivity { private static final int IMAGES[] = {R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e, R.drawable.f}; /** * The number of pages (wizard steps) to show in this demo. */ private static final int NUM_PAGES = 5; /** * The pager widget, which handles animation and allows swiping horizontally to access previous * and next wizard steps. */ private ViewPager mPager; /** * The pager adapter, which provides the pages to the view pager widget. */ private PagerAdapter mPagerAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_screen_slide); // Instantiate a ViewPager and a PagerAdapter. mPager = (ViewPager) findViewById(R.id.pager); mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); mPager.setAdapter(mPagerAdapter);
mPager.setCurrentItem(1); // 默认显示第二页,当然显示页数至少需要2页mPager.setPageTransformer( true, new ScaleInTransformer()) ; } /** * A simple pager adapter that represents 5 ScreenSlidePageFragment objects, in * sequence. */ private class ScreenSlidePagerAdapter extends FragmentStatePagerAdapter { public ScreenSlidePagerAdapter(FragmentManager fm) { super(fm) ; } @Override public Fragment getItem( int position) { return ScreenSlidePageFragment. newInstance( IMAGES[position]) ; } @Override public int getCount() { return NUM_PAGES ; } }}
代码量很少,但是却实现了我们常用的轮播图效果。
下面我们来具体分析下。
onCreate中对pageview实例化,然后设置对应的Adapter,最后设置我们需要自定义的动画接口类ZoomOutPageTransformer
。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_screen_slide); mPager = (ViewPager) findViewById(R.id.pager); mPagerAdapter = new ScreenSlidePagerAdapter(getSupportFragmentManager()); mPager.setAdapter(mPagerAdapter); mPager.setOffscreenPageLimit(3); mPager.setPageTransformer(true, new ZoomOutPageTransformer());
mPager.setCurrentItem(1); // 默认显示第二页,当然显示页数至少需要2页}
而ScreenSlidePagerAdapter中设置了固定的5页图片显示,很简单,没什么好说的。
另外我们最好再设置一下viewpage的缓存个数:
mPager.setOffscreenPageLimit(3);//设置缓存的页面数量
接下来就是来实现我们的PageTransformer接口了。
先看效果图:
不多说,上代码:
import android.annotation.TargetApi; import android.os.Build; import android.support.v4.view.ViewPager; import android.view.View; /** * Created by Victor on 2016/5/13. */ public class ZoomOutPageTransformer implements ViewPager.PageTransformer {
private static final float MIN_SCALE = 0.75f; private static final float DEFAULT_MAX_ROTATE = 12.0f; private static final float MIN_ALPH = 0.4f; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public void transformPage(View view, float position) { int pageWidth = view.getWidth(); int pageHeight = view.getHeight(); if (position < -1) { // [-Infinity,-1) // This page is way off-screen to the left. view.setAlpha(0); } else if (position <= 1) { if (position < 0) //[0,-1] ;[-1,0] { float scaleFactor = MIN_SCALE + (1 + position) * (1 - MIN_SCALE) ; view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); float alphFactor = MIN_ALPH + (1 + position) * (1 - MIN_ALPH) ; view.setAlpha(alphFactor); view.setRotation(DEFAULT_MAX_ROTATE * position); } else //[0,1] ;[1,0] { float scaleFactor = MIN_SCALE + (1 - position) * (1 - MIN_SCALE); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); float alphFactor = MIN_ALPH + (1 - position) * (1 - MIN_ALPH) ; view.setAlpha(alphFactor); view.setRotation(DEFAULT_MAX_ROTATE * position); } } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } } }
这就是根据谷歌官网给的滑动缩放动画类修改后的动画效果,其中包括alph变化效果、缩放效果和旋转效果。要实现pageview的动画效果,我们必须实现接口
ZoomOutPageTransformer implementsViewPager.PageTransformer;
然后设置mPager.setPageTransformer(new ZoomOutPageTransformer());
看完代码后,下面我们来解释下pageview的position区间是什么意思。
动画的整个区间范围是[-Infinity,+Infinity],这个范围又分为3个小范围。
--为了方便分析,我们假设有A、B、C三页,设置默认显示第二页B--
mPager.setCurrentItem(1); // 默认显示第二页,当然显示页数至少2页
区间[-Infinity, -1)对应的是第一页A不可见视图;
区间[1, + Infinity)对应的是第三页C不可见视图;
区间[-1,1]就是我们在滑动过程中出现的两页视图
注意:这里默认pageview的属性android:clipChildren="true",所以当动画停下来后,pageview只有当前页可见。
而对于android:clipChildren="false"的情况需要另外分析。我们先从简单的入手。
所以现在我们关心的就是[-1,1]区间的动画怎么实现。[-1,1]区间又可以分为两个部分:
手势:向右滑动
[-1,0)区间,即将出现的是A页,此时的动画是A页的动画。
那么(0,1]区间,则表示的是B页正在向右消失,此时是B页的动画。
手势:向左滑动
(0, -1]区间,表示的是B页正在向左消失,此时是B页的动画。
那么[1,0)区间,则表示的是C页正在向左,此时是C页的动画。
需要注意的是,不同的手势,[-1,1]区间的变化范围不同。网上有部分资料对于区间[-1,1]的解释有误,或混乱!
搞清楚了[-Infinity,+Infinity]区间的意义,那么写动画就方便多了。
看完之后,你的脑袋里是否有Ding的一一声呢?赶紧打开死丢丢,打造出一个属于你的ViewPage切换效果吧!
另外,我们注意到Viewpage是在3.0之后引入的,所以对于3.0之前的版本没有效果。但是已经有大神给出了解决方案,
那就是使用nineoldandroids来实现动画效果,自定义ViewPage。
源码都在上面了,就不上传了。
如分析有问题,欢迎回复讨论。
内容参考连接:http://blog.csdn.net/lmj623565791/article/details/51339751,感谢鸿洋大神
http://blog.csdn.net/lmj623565791/article/details/40411921/ 解决viewpage版本的向下兼容问题
https://github.com/luhaoaimama1/Zbanner