【转】android 自定义ViewPager,修改原动画

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503

记 得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开 始让ViewPager来做。时间长了,ViewPager的切换效果觉得枯燥,形成了审美疲劳~~我们需要改变,今天教大家如何改变ViewPager 切换时的效果,实现个性化的图片切换~~

看一下这样效果的图片切换:

是不是比传统的效果个性很多,嘿嘿~~其实很简单,学习完这篇博客,保证你可以自定义切换效果,做出各种丧心病狂的切换~~

1、制作前的分析

观察下效果图,实际上改变的就是切换时的动画,那么简单了,只需要用户在切换时,拿到当前的View和下一个View,然后添加动画是不是就可以了。好,第一步,获取用户切换时的当前View和切换至的目的View。

我们在来看一下,如果或者了当前View和目的View,对于动画我们需要缓慢的变化,最好是根据用户的手势滑动。比如上述效果,用户滑动时,目的图片根据用户滑动距离缓缓出现和慢慢变大。好,第二步,设计动画的梯度变化。

经过分析,我们总结出两个步骤,下面我们开始一步一步来打造~~~

2、获取用户切换时当前View和切换至的目的View。

ViewPager 也需要监听用户的手势,所以肯定提供了某个方法。于是纵观ViewPager的方法,发现了一个叫做 onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法~~

没错就是这个方法:在页面滚动时调用~

下面仔细研究下这几个参数:

直接说测试结果:

在非第一页与最后一页时,滑动到下一页,position为当前页位置;滑动到上一页:position为当前页-1

positionOffset 滑动到下一页,[0,1)区间上变化;滑动到上一页:(1,0]区间上变化

positionOffsetPixels这个和positionOffset很像:滑动到下一页,[0,宽度)区间上变化;滑动到上一页:(宽度,0]区间上变化

第一页时:滑动到上一页position=0 ,其他基本为0 ;最后一页滑动到下一页 position为当前页位置,其他两个参数为0

豁然发现,我们需要的步骤的第二步解决了,positionOffset很适合作为,渐变,缩放的控制参数;positionOffsetPixels则可以作为平移等的控制参数。

那么如何获得当前View和目的View呢:

分享几个我的歧途:

1、【错误】我 通过getChildAt(position),getChildAt(position+1),getChildAt(position-1)获得滑动 时,左右的两个View;乍一看,还真觉得不错~~~在代码写出来,再乍效果也出不来~~错误原因:我们忽略一个特别大的东西,ViewPager的机 制,滑动时动态加载和删除View,ViewPager其实只会维持2到3个View,而position的范围基本属于无限~~

2、【错误】我 通过getCurrentItem获得当前的位置,然后+1,-1获得后一个或者前一个~~正在窃喜,赶快代码改过来,效果怎么也不对,乱七八糟的~~仔 细观察日志,这个getCurrentItem当用户手指离开的屏幕,Page还在动画执行时,就改变了~~难怪~整个滑动过程并不是固定的~~唉,心都 碎了~

3、【错误】position在整个滑动的过程中是不变 化的,而且ViewPager会保存2个或3个View;那么我考虑,如果是第一页、或者最后一页那么我取getChildAt(0)和 getChildAt(1),如果在其他页面则为getChildAt(0),getChildAt(2),然后经过一系列的变化~我想这会总该对了吧, 于是我遇到第一问题,第一页的时候,不管左右position都为0,尼玛,这哪个为左View,哪个为右View~~

说了这么多错误,大家可以绕过这些弯路,也能从这些弯路里面看出点什么~

下 面说正确的,其实ViewPager在添加一个View或者销毁一个View时,是我们自己的PageAdapter中控制的,于是我们可以在 ViewPager里面维系一个HashMap<Position,View>,然后滑动的时候,通过get(position)取出,比如 上述效果,始终是右边的View变化,要么从小到大,要么从大到小

那么滑倒下一页:左边的View:map.get(position) ,右边的View : map.get(position+1) . 

那么滑倒上一页:左边的View : map.get(position) , 右边的View : map.get(position+1) , 一样的,因为滑到上一页,position为当前页-1

好了,至此,我们分析了且解决了所有步骤。

 1 package com.example.zhy_jazzyviewpager;
 2
 3 import android.app.Activity;
 4 import android.os.Bundle;
 5 import android.support.v4.view.PagerAdapter;
 6 import android.view.Menu;
 7 import android.view.View;
 8 import android.view.ViewGroup;
 9 import android.widget.ImageView;
10 import android.widget.ImageView.ScaleType;
11
12 public class MainActivity extends Activity
13 {
14 protected static final String TAG = "MainActivity";
15 private int[] mImgIds;
16 private MyJazzyViewPager mViewPager;
17
18 @Override
19 protected void onCreate(Bundle savedInstanceState)
20 {
21 super.onCreate(savedInstanceState);
22 setContentView(R.layout.activity_main);
23 mImgIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c,
24 R.drawable.d };
25 mViewPager = (MyJazzyViewPager) findViewById(R.id.id_viewPager);
26 mViewPager.setAdapter(new PagerAdapter()
27 {
28
29 @Override
30 public boolean isViewFromObject(View arg0, Object arg1)
31 {
32 return arg0 == arg1;
33 }
34
35 @Override
36 public void destroyItem(ViewGroup container, int position,
37 Object object)
38 {
39 container.removeView((View) object);
40 }
41
42 @Override
43 public Object instantiateItem(ViewGroup container, int position)
44 {
45 ImageView imageView = new ImageView(MainActivity.this);
46 imageView.setImageResource(mImgIds[position]);
47 imageView.setScaleType(ScaleType.CENTER_CROP);
48 container.addView(imageView);
49 mViewPager.setObjectForPosition(imageView, position);
50 return imageView;
51 }
52
53 @Override
54 public int getCount()
55 {
56 return mImgIds.length;
57 }
58 });
59
60 }
61
62 }

这个很常见的代码,就是初始化ViewPager~~就没啥可说的了~~有一点需要注意:在instantiateItem方法,我们多调用了一个 mViewPager.setObjectForPosition(imageView, position);其实就是为了给我们的Map存值

主要看自定义的ViewPager

  1 package com.example.zhy_jazzyviewpager;
  2
  3 import java.util.HashMap;
  4 import java.util.LinkedHashMap;
  5
  6 import android.content.Context;
  7 import android.support.v4.view.ViewPager;
  8 import android.util.AttributeSet;
  9 import android.util.Log;
 10 import android.view.View;
 11
 12 import com.nineoldandroids.view.ViewHelper;
 13
 14 public class MyJazzyViewPager extends ViewPager
 15 {
 16 private float mTrans;
 17 private float mScale;
 18 /**
 19 * 最大的缩小比例
 20 */
 21 private static final float SCALE_MAX = 0.5f;
 22 private static final String TAG = "MyJazzyViewPager";
 23 /**
 24 * 保存position与对于的View
 25 */
 26 private HashMap<Integer, View> mChildrenViews = new LinkedHashMap<Integer, View>();
 27 /**
 28 * 滑动时左边的元素
 29 */
 30 private View mLeft;
 31 /**
 32 * 滑动时右边的元素
 33 */
 34 private View mRight;
 35
 36 public MyJazzyViewPager(Context context, AttributeSet attrs)
 37 {
 38 super(context, attrs);
 39 }
 40
 41 @Override
 42 public void onPageScrolled(int position, float positionOffset,
 43 int positionOffsetPixels)
 44 {
 45
 46 // Log.e(TAG, "position=" + position+", positionOffset = "+positionOffset+" ,positionOffsetPixels = " + positionOffsetPixels+" , currentPos = " + getCurrentItem());
 47 //滑动特别小的距离时,我们认为没有动,可有可无的判断
 48 float effectOffset = isSmall(positionOffset) ? 0 : positionOffset;
 49 //获取左边的View
 50 mLeft = findViewFromObject(position);
 51 //获取右边的View
 52 mRight = findViewFromObject(position + 1);
 53 // 添加切换动画效果
 54 animateStack(mLeft, mRight, effectOffset, positionOffsetPixels);
 55 super.onPageScrolled(position, positionOffset, positionOffsetPixels);
 56 }
 57
 58 public void setObjectForPosition(View view, int position)
 59 {
 60 mChildrenViews.put(position, view);
 61 }
 62
 63 /**
 64 * 通过过位置获得对应的View
 65 *
 66 * @param position
 67 * @return
 68 */
 69 public View findViewFromObject(int position)
 70 {
 71 return mChildrenViews.get(position);
 72 }
 73
 74 private boolean isSmall(float positionOffset)
 75 {
 76 return Math.abs(positionOffset) < 0.0001;
 77 }
 78
 79 protected void animateStack(View left, View right, float effectOffset,
 80 int positionOffsetPixels)
 81 {
 82 if (right != null)
 83 {
 84 /**
 85 * 缩小比例 如果手指从右到左的滑动(切换到后一个):0.0~1.0,即从一半到最大
 86 * 如果手指从左到右的滑动(切换到前一个):1.0~0,即从最大到一半
 87 */
 88 mScale = (1 - SCALE_MAX) * effectOffset + SCALE_MAX;
 89 /**
 90 * x偏移量: 如果手指从右到左的滑动(切换到后一个):0-720 如果手指从左到右的滑动(切换到前一个):720-0
 91 */
 92 mTrans = -getWidth() - getPageMargin() + positionOffsetPixels;
 93 ViewHelper.setScaleX(right, mScale);
 94 ViewHelper.setScaleY(right, mScale);
 95 ViewHelper.setTranslationX(right, mTrans);
 96 }
 97 if (left != null)
 98 {
 99 left.bringToFront();
100 }
101 }
102 }

可以看到,核心代码都是onPageScrolled,我们通过 findViewFromObject(position); findViewFromObject(position + 1);分别获取了左右两边的View,然后添加动画效果;当前这个例子添加了两个动画,一个是从0.5放大到1.0或者1.0缩小到0.5,没错由我们的 positionOffset提供梯度的变化~~还有个平移的动画:下一页直接移动到当前屏幕(默认是在右边,可以注释这个效果,怎么运行看看),然后不 断的通过positionOffsetPixels抵消原来默认移动时的位移,让用户感觉它就在原地放大缩小~~

好了,这样就实现了~~你可以随便写自己喜欢的动画效果,比如在默认上面加个淡入淡出或者神马,随便~~是不是很随意~~

我们的布局文件:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2 xmlns:tools="http://schemas.android.com/tools"
 3 android:layout_width="match_parent"
 4 android:layout_height="match_parent"
 5 >
 6
 7 <com.example.zhy_jazzyviewpager.MyJazzyViewPager
 8 android:layout_width="wrap_content"
 9 android:layout_height="wrap_content"
10 android:id="@+id/id_viewPager" />
11
12 </RelativeLayout>
4、JazzyViewPager的使用

其实上面的实现就是github上JazzyViewPager的源码,用法不用说了,就是我们的MainActivity,它内置了大概10来种效果,我们可以通过代码或者布局上面设置动画效果~~我们上面的例子效果,它叫做Stack;

使用JazzViewPager的代码:其实基本一样~~最后也会贴上JazzyViewPager的源码的下载

MainActivity

 1 package com.jfeinstein.jazzyviewpager;
 2
 3 import com.jfeinstein.jazzyviewpager.JazzyViewPager.TransitionEffect;
 4
 5 import android.app.Activity;
 6 import android.os.Bundle;
 7 import android.support.v4.view.PagerAdapter;
 8 import android.view.View;
 9 import android.view.ViewGroup;
10 import android.widget.ImageView;
11 import android.widget.ImageView.ScaleType;
12
13 public class MainActivity extends Activity
14 {
15 protected static final String TAG = "MainActivity";
16 private int[] mImgIds;
17 private JazzyViewPager mViewPager;
18
19 @Override
20 protected void onCreate(Bundle savedInstanceState)
21 {
22 super.onCreate(savedInstanceState);
23 setContentView(R.layout.activity_main);
24 mImgIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c,
25 R.drawable.d };
26 mViewPager = (JazzyViewPager) findViewById(R.id.id_viewPager);
27 //设置切换效果
28 mViewPager.setTransitionEffect(TransitionEffect.Stack);
29 mViewPager.setAdapter(new PagerAdapter()
30 {
31
32 @Override
33 public boolean isViewFromObject(View arg0, Object arg1)
34 {
35 return arg0 == arg1;
36 }
37
38 @Override
39 public void destroyItem(ViewGroup container, int position,
40 Object object)
41 {
42 container.removeView((View) object);
43 }
44
45 @Override
46 public Object instantiateItem(ViewGroup container, int position)
47 {
48 ImageView imageView = new ImageView(MainActivity.this);
49 imageView.setImageResource(mImgIds[position]);
50 imageView.setScaleType(ScaleType.CENTER_CROP);
51 container.addView(imageView);
52 mViewPager.setObjectForPosition(imageView, position);
53 return imageView;
54 }
55
56 @Override
57 public int getCount()
58 {
59 return mImgIds.length;
60 }
61 });
62
63 }
64
65 }

与我们的代码唯一区别就是:

//设置切换效果
mViewPager.setTransitionEffect(TransitionEffect.Stack);

它有12中可选的切换效果,其实就是写了12个切换的动画~~~

源码下载地址

自己网盘下载地址:地址

【转】android 自定义ViewPager,修改原动画,布布扣,bubuko.com

时间: 2024-10-11 03:24:22

【转】android 自定义ViewPager,修改原动画的相关文章

Android 自定义 ViewPager 打造千变万化的图片切换效果

Android 自定义 ViewPager 打造千变万化的图片切换效果 标签: Android自定义ViewPagerJazzyViewPager 目录(?)[+] 转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记 得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主界面通通ViewPager,以及图片切换也抛弃了ImageSwitch之类的,开 始让ViewPager来做.时间长了,ViewPa

Android重写ViewPager修改滑动灵敏度

使用ViewPager作为一个页面进行切换,里面可以存放很多View,但有时在操作View时不小心滑动一下就有可能跳到下一页,这并不是我们想要的,这里就需要重写ViewPager修改它的滑动条件 效果图 程序目录结构 BTViewPager.java package com.example.viewpagerdemo; import android.content.Context; import android.support.v4.view.ViewPager; import android.

Android为ViewPager增加切换动画——自定义ViewPager

转载请注明出处:http://blog.csdn.net/allen315410/article/details/44224517 在上篇博客中,我写了一个使用属性动画为ViewPager添加切换动画的方法,并且可以兼容到Android3.0以下版本的设备上,那么关于为ViewPager添加动画的方式还会有另外一种实现方案,就是自定义一个自己带动画效果的ViewPager,关于上篇博客,还没来得及查看的朋友可以点击这里进行查看.下面,我们将新建一个工程,来说说怎样自定义一个自带切换动画效果的Vi

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

转载请注明出处:http://blog.csdn.net/allen315410/article/details/44200623 ViewPager作为Android最常用的的组件之一,相信大家在项目中会频繁的使用到的,例如利用ViewPager制作引导页.轮播图,甚至做整个app的表现层的框架等等. Android3.0以下不支持切换动画 但是在Android 3.0(API 11)以下的ViewPager是比较死板的,不支持动画特效的,这也就让ViewPager在切换的时候达不到很好的用户

Android自定义下拉刷新动画--仿百度外卖下拉刷新

好久没写博客了,小编之前一段时间一直在找工作,从天津来到了我们的大帝都,感觉还不错.好了废话不多说了,开始我们今天的主题吧.现如今的APP各式各样,同样也带来了各种需求,一个下拉刷新都能玩出花样了,前两天订饭的时候不经意间看到了"百度外卖"的下拉刷新,今天的主题就是它–自定义下拉刷新动画. 看一下实现效果吧: 动画 我们先来看看Android中的动画吧: Android中的动画分为三种: Tween动画,这一类的动画提供了旋转.平移.缩放等效果. Alpha – 淡入淡出 Scale

Android自定义ViewPager(一)——自定义Scroller模拟动画过程

转载请注明出处:http://blog.csdn.net/allen315410/article/details/41575831 相信Android SDK提供的ViewPager组件,大家实在是熟悉不过了,但是ViewPager存在于support.v4包下的,说明ViewPager并不存在于早期的android版本中,那么如何在早期的android版本中也同样使用类似于ViewPager一样的滑动效果呢?这里,我们还是继续探讨一下andrid的自定义组件好了,并且这篇博文只探讨androi

android自定义GifView显示gif动画

gif动画在web开发中使用的非常的多,利用gif,许多动画不必再用程序编写,现在有非常多的App已经使用到了gif动画,可是android sdk并没有为我们提供gif这种View,所以我们只能自定义一个View,去实现gif效果. android虽然没有为我们提供现成的GifView,但是为我们提供了Movie类,这个类就是用来实现GifView的关键类.它主要有两个最重要的方法,一个是根据动画播放时间设置当前要现显示的帧,二是将当前要显示的帧绘制到画布中.下面看一下效果图: 点击暂停按钮还

android自定义ViewPager之——3D效果应用

今天在github里看到一个3D效果的ViewPager,感觉做出来的ViewPager滑动的时候效果十分的炫,就check out下来研究了一下如何实现的,以及如何使用,将整个ViewPager稍加修改后(主要是处理了一下与项目中其它控滑动控件的事件冲突)后,应用到了自己现在项目中.感觉这个效果真的非常的不错,现在把自己写的一个Demo分享出来. 下面是这个ViewPager嵌入到项目中的效果图: 修改以后,在切换ViewPager时会有立体感,会为自己的应用增色不少.下面把使用的Demo发出

Android 自定义录音、播放动画View,让你的录音浪起来

最近公司项目有一个录音的录制和播放动画需求,然后时间是那么紧,那么赶紧开撸. 先看效果图 嗯,然后大致就是这样,按住录音,然后有一个倒计时,最外层一个进度条,还有一个类似模拟声波的动画效果(其实中间的波浪会根据声音的大小浪起来的~) 2 实现思路 然后,我们适当的来分析一下这个录音动画的实现方式.这个肯定是通过自定义控件,咱们来把这个效果完完全全画出来. 大致包括以下几个点: 1. 最外层的进度条,最坑的就是一开始的一个渐变的效果 2. 然后进度条最前方是有一个点的(我肯定选择用图片来实现) 3