转载请注明出处:http://blog.csdn.net/allen315410/article/details/44224517

在上篇博客中,我写了一个使用属性动画为ViewPager加入切换动画的方法。而且能够兼容到Android3.0以下版本号的设备上。那么关于为ViewPager加入动画的方式还会有第二种实现方案。就是自己定义一个自己带动画效果的ViewPager,关于上篇博客,还没来得及查看的朋友能够点击这里进行查看。以下。我们将新建一个project。来说说如何自己定义一个自带切换动画效果的ViewPager。

分析

首先我们分析一下实现自己定义ViewPager自带切换动画效果时,我们须要拿到一些什么?第一,我们知道ViewPager来回切换的时候。事实上就是不同的View在屏幕上切换。所以我们在自己定义ViewPager的时候须要拿到当前正在切换的2个View。第二,既然我们要为ViewPager加入动画。那么我们就须要自己定义动画。好,以上两个点都是在这个自己定义ViewPager中被须要的东西,我们一步步来创建和获取到吧。

接下来。我新建一个类ViewPagerWithTransformer继承自ViewPager。来实现自己定义的ViewPager。首先。我们重写一下ViewPager中的一个方法,代码例如以下。我们在方法中打印一下方法中的參数,在布局文件里使用这个自己定义的ViewPager。在Activity中为这个ViewPager添加数据适配器。加入3个ImageView到ViewPager中,实现ViewPager上的切换,代码能够见上一篇博客中MainActivity中。

@Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
super.onPageScrolled(position, offset, offsetPixels);
Log.i("TAG", "position = " + position + ",offset = " + offset + ",offsetPixels = " + offsetPixels);
}

上面方法中的參数已经被打印了,LOG输出日志在以下,首先看一下从第0页滑动到第1页的LOG:

然后,再看一下从第1页滑动到第0页的LOG:

分析一下上面的LOG日志:

当第0页-->第1页:position从0-->1;offset从0-->1;offsetPixels从0-->屏幕最大宽度

当第1页-->第0页:position从1-->0;offset从1-->0;offsetPixels从0-->屏幕最大宽度

明显能够感知,仅仅有position代表的是当前正在切换View的位置,offset表示View的偏移比重,offsetPixels表示View实际的偏移量(px)。

获取切换中的View对象

【错误】上面我们分析我们再自己定义一个带动画切换的ViewPager时,须要得到正在切换中的2个View对象。那么我们该怎么在代码中获取到这2个View的对象呢?大家知道,上篇博客中我们使用了ViewPager的源代码。ViewPager的父类是ViewGroup,我们知道在ViewGroup中想要获取View对象的话,有个getChildAt(int index)方法能够得到View对象。这种方法在ViewGroup中使用是没有问题的,然后在ViewPager中使用就会出错了。由于ViewPager中加入了缓存机制。一个ViewPager默认仅仅能缓存2-3个View的对象,当有很多其它的View对象被载入到ViewPager中时。ViewPager会舍弃掉前面一个View对象,这样就导致我们不能通过getChildAt(position)、getChildAt(position-1)、getChildAt(position+1)方法来获取上一个、当前、下一个View对象了,显然position代表的View对象不止两三个,而是无限的。

【错误】通过getChildAt(position)显然获取不到我们想要的对象了,既然不能使用position的话。ViewGroup中另一个getCurrentItem()获取当前View的角标和getChildCount()方法获取View数量的方法。是不是能够用呢?我们先在onPageScrolled()方法中打印一下LOG日志吧。

我们能够看到,getCurrentItem的值一直在不断的变化着,当我们打开第1页时。getCurrentItem=0,这是我们能够依据这个getCurrentItem的值带入getChildAt(getCurrentItem-1)、getChildAt(getCurrentItem)、getChildAt(getCurrentItem+1)中。确实能够获取到上一个View。当前View、下一个View。

然后不幸的是,当我们手指从屏幕中放开的时候。getCurrentItem变成了1。这时前面通过getChildAt(getCurrentItem)获取到的View就不正确了。

所以依据getCurrentItem()获取View也是不正确的。

【正确】通过上面2种方法均不能准确的获取到当前的View对象了。我们再来细看一下position这个參数。结合上面的LOG输入看一下。当我们在ViewPager中使得第0页滑向第1页的时候。position是没有变化的,此时pisition=0;当我们从第1页滑到第0页的时候,position还没没有变化,此时position=0;由此我们是不是还是能够依据position来确定View的对象。我们如果position代表第0页的View,那么position+1就是代表第1页的View了。以此类推就能够得到所有的View了。以下,我们就能够在代码中去实现我们这种想法了。也特别的简单,就是创建一个Map集合用来为View做一个缓存机制,我们使用position作为键,使用view的对象作为值,而且向外提供一个加入View缓存的方法和一个移除View缓存的方法。当我们为ViewPager提供适配器PagerAdapter时,能够在instantiateItem(ViewGroup
container, int position)方法中将View对象设置进View的缓存集合中。在destroyItem(ViewGroup container, int position, Object object)方法中将View从缓存集合中移除。详细部分代码例如以下:

// 保存ViewPager上View的对象
private Map<Integer, View> mViewCache = new HashMap<Integer, View>(); /**
* 设置View的缓存
*
* @param position
* @param viewCache
*/
public void setViewCache(Integer position, View viewCache) {
mViewCache.put(position, viewCache);
} /**
* 从View的缓存集合中移除指定position的View
*
* @param position
*/
public void removeViewCache(Integer position) {
mViewCache.remove(position);
}

切换动画的实现

上面攻克了一个头疼的问题。如果获取正在切换中的View对象,这个问题已经在上面解决掉了,那么以下就仅仅剩下动画了。

我们在这个案例模仿上篇博客中的DepthPageTransformer动画效果吧。我们自己定义两种动画。一个Scale动画和一个Translate动画,使两个动画交替一起运行就能够模仿出DepthPageTransformer这种平移缩放的动画效果出来,代码非常easy,不单独贴出了。以下有完整的代码的。

完整的代码

自己定义ViewPager的源代码。ViewPagerWithTransformer.java
public class ViewPagerWithTransformer extends ViewPager {

	// 左边的View
private View mLeftView;
// 右边的View
private View mRightView;
// 平移动画的梯度值
private float mTranslate;
// 缩放动画的梯度值
private float mScale;
// 最小缩放比例
private static final float MIN_SCALE = 0.6f;
// 保存ViewPager上View的对象
private Map<Integer, View> mViewCache = new HashMap<Integer, View>(); /**
* 设置View的缓存
*
* @param position
* @param viewCache
*/
public void setViewCache(Integer position, View viewCache) {
mViewCache.put(position, viewCache);
} /**
* 从View的缓存集合中移除指定position的View
*
* @param position
*/
public void removeViewCache(Integer position) {
mViewCache.remove(position);
} public ViewPagerWithTransformer(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
} @Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
super.onPageScrolled(position, offset, offsetPixels);
mLeftView = mViewCache.get(position);
mRightView = mViewCache.get(position + 1);
animStack(mLeftView, mRightView, offset, offsetPixels);
} private void animStack(View left, View right, float offset, int offsetPixels) {
// TODO Auto-generated method stub
if (right != null) {
// 从第0页——》到第1页,offset:0~1。缩放比例mScale:0.6~1
mScale = (1 - MIN_SCALE) * offset + MIN_SCALE;
//平移的距离
mTranslate = -getWidth() - getPageMargin() + offsetPixels; //使用NineOldAndroids编写属性动画
ViewHelper.setScaleX(right, mScale);
ViewHelper.setScaleY(right, mScale);
ViewHelper.setTranslationX(right, mTranslate);
}
if (left != null) {
// 左边的页永远在最上面
left.bringToFront();
}
}
}

在布局文件里申明,activity_main.xml

<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" > <com.example.viewpagerwithtransformeranim.ViewPagerWithTransformer
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</com.example.viewpagerwithtransformeranim.ViewPagerWithTransformer> </RelativeLayout>

在Activity中使用这个控件。MainActivity.java

public class MainActivity extends Activity {

	private int[] imgRes = new int[] { R.drawable.guide_image1, R.drawable.guide_image2, R.drawable.guide_image3 };
private List<ImageView> imgList = new ArrayList<ImageView>();
private ViewPagerWithTransformer mViewPager; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
mViewPager = (ViewPagerWithTransformer) findViewById(R.id.viewpager);
mViewPager.setAdapter(new PagerAdapter() { @Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
} @Override
public int getCount() {
return imgRes.length;
} @Override
public Object instantiateItem(ViewGroup container, int position) {
ImageView mImageView = new ImageView(MainActivity.this);
mImageView.setBackgroundResource(imgRes[position]);
mImageView.setScaleType(ScaleType.CENTER_CROP);
imgList.add(mImageView);
//给ViewPager设置View缓存
mViewPager.setViewCache(position, mImageView);
container.addView(mImageView);
return mImageView;
} @Override
public void destroyItem(ViewGroup container, int position, Object object) {
//移除ViewPager的View缓存
mViewPager.removeViewCache(position);
container.removeView(imgList.get(position));
}
});
}
}

好,所有源代码在上面了,注意一下,在给ViewPager设置的适配器PagerAdapter里面重写instantiateItem方法时。一定要记得调用mViewPager.setViewCache(position, mImageView)方法,给ViewPager设置View缓存。然后在重写destroyItem方法中调用mViewPager.removeViewCache(position)方法移除View缓存。

感谢CSDN博客专家鸿洋无私奉献的教程。教程视频地址:http://www.imooc.com/learn/226

Android为ViewPager添加切换动画——自己定义ViewPager的更多相关文章

  1. Android至ViewPager添加切换动画——使用属性动画

    转载请注明出处:http://blog.csdn.net/allen315410/article/details/44200623 ViewPager作为Android最经常使用的的组件之中的一个.相 ...

  2. Android为ViewPager增加切换动画——使用属性动画.

    ViewPager作为Android最常用的的组件之一,相信大家在项目中会频繁的使用到的,例如利用ViewPager制作引导页.轮播图,甚至做整个app的表现层的框架等等. Android3.0以下不 ...

  3. Android开发中activity切换动画的实现

    (1)我们在MainAcitvity中定义两个textview,用于点击触发切换Activity事件,下面是布局文件代码. <LinearLayout android:layout_width= ...

  4. Android的Activity屏幕切换动画(一)-左右滑动切换

    (国内知名Android开发论坛eoe开发者社区推荐:http://www.eoeandroid.com/) Android的Activity屏幕切换动画(一)-左右滑动切换 在Android开发过程 ...

  5. viewPager的切换动画

    今天在看苏州通的代码,里面有个引导的代码,涉及到viewPager的切换动画: DepthPageTransformer : package com.soyoungboy.guide; import ...

  6. Android的Activity屏幕切换动画-左右滑动切换

    . --> 在Android开发过程中,经常会碰到Activity之间的切换效果的问题,下面介绍一下如何实现左右滑动的切换效果,首先了解一下Activity切换的实现,从Android2.0开始 ...

  7. (转)Android中的页面切换动画

    这段时间一直在忙Android的项目,总算抽出点时间休息一下,准备把一些项目用到的Android经验分享一下. 在Android开发过程中,经常会碰到Activity之间的切换效果的问题,下面介绍一下 ...

  8. Android的Activity屏幕切换动画左右滑动切换

    在Android开发过程中,经常会碰到Activity之间的切换效果的问题,下面介绍一下如何实现左右滑动的切换效果,首先了解一下Activity切换的实现,从Android2.0开始在Activity ...

  9. Android Studio之Activity切换动画(三)

    1.上一篇文章"Android Studio之多个Activity的滑动切换(二)"中实现了多个activity之间的滑动切换,可是新切换出的activity大多是从右側进入 2. ...

随机推荐

  1. Asp.Net MVC3.0项目部署到Win7 64过程总结

    前言 之前一直是通过Visual Studio直接F5来运行自己编写的项目或者小程序,很少通过部署发布到IIS上面,于是自己便在自己的笔记本上进行测试,结果还真是发现了不少问题,于是自己重新通过虚机程 ...

  2. 国家code和区号计算

    因为项目中要用到这个功能.实现类似微信注冊时能够选择国家并得到对应的区号.还要推断号码正确与否的正则. 找到了 libPhoneNumber-iOS 标准化电话号码库 https://github.c ...

  3. window.opener()方法

    <!DOCTYPE html><html><head><meta charset="GBK"><title>菜鸟教程(r ...

  4. [Android Pro] 开发一流Android SDK

    cp from : https://blog.csdn.net/dd864140130/article/details/53558011 本篇文章已授权微信公众号 guolin_blog (郭霖)独家 ...

  5. .NET零基础入门之01:开篇及CSharp程序、解决方案的结构

    一:为什么选择C# 每个人都有梦想,有些人的梦想就是:成为程序员.最课程(www.zuikc.com)的<零基础c#入门>是试图帮助我们实现这个梦想. 也许你要问:我基础很差怎么办?最课程 ...

  6. HTML 5 <script> async 属性简单设置代码异步执行

    HTML5中 script标签支持脚本的异步执行async.脚本将会异步运行: <script type="text/javascript" src="demo_a ...

  7. 要恢复页面吗?Chrome未正确关闭

    谷歌chrome浏览器每次打开提示"要恢复页面吗"怎么办? 谷歌chrome浏览器每次打开提示"要恢复页面吗"怎么办? 如下图所示: 每次打开启动谷歌chrom ...

  8. 洛谷 P1164 小A点菜

    题目背景 uim神犇拿到了uoi的ra(镭牌)后,立刻拉着基友小A到了一家……餐馆,很低端的那种. uim指着墙上的价目表(太低级了没有菜单),说:“随便点”. 题目描述 不过uim由于买了一些辅(e ...

  9. C语言中将0到1000的浮点数用强制指针类型转换的方式生成一幅图像

    搞过计算机图像的人都知道,图像中的每一个像素通常为一个整型数,它可以分成4个无符号的char类型,以表示其RGBA四个分量.一幅图像可以看做是一个二维整型数组.这里我会生成一个float数组,其数组大 ...

  10. Max Points on a Line leetcode java

    题目: Given n points on a 2D plane, find the maximum number of points that lie on the same straight li ...