ViewPager切换动画及性能优化
2015-06-04 14:49
441 查看
首先我们先展示一个Viewpager的一个Demo
1. 布局文件的编写
2. Mainactivity的编写
3. 适配器编写。
好的,现在这个代码已经写完了。viewpager里面分别加入了3张图片,切换子view的时候是没有动画效果的。
那么问题来了,如果我们要加入动画,应该需要什么?
1. 因为动画效果是根据我们手势操作来动的,所以我们要监听用户的手势。那么viewpager提供这样的方法呢?有的,就是一个叫做发现了一个叫做
onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法
仔细研究下这几个参数
position 表示 当前viewpager处于第几页,positionOffset 就是表示这个pager的偏移的值,这个值是跟随我们的手势不断变化的
从第0页切换到第1页,就是向左边滑动的时候,我们打印一下这个参数看下变化
![](http://img.blog.csdn.net/20150604150925039)
说白了,
就是像右边滑动,positionOffset的变化区间是【0,1】
同样的,我们页打印一下像左边滑动的信息
![](http://img.blog.csdn.net/20150604151829324)
像左边滑动,positionOffset的变化区间是【1,0】
可是有个问题。在onPageScrolled中我们每次只能拿到一个view的偏移量啊,我们要对2个子view进行动画,必须拿到2个动态变化的偏移量才行
其实android已经提供给我们这个方法了,只需要ViewPager.PageTransformer 这个接口就可以了。里面会提供给我们一个
void transformPage(View view, float position) 方法,这个方法中可以同时获取左右2个变化的子view的偏移量的结果
但是这里偏移量有点不同,举个例子
当我们滑动时:会打印出当然ViewPager中存活的每个View以及它们的position的变化
* 比如从第0页滑动到第1页时候,
* 第0页的positon :
【0,-1】
* 第1页的positon : 【-1,0】
豁然发现,这个positon非常适合做渐变,缩放等动画效果的控制参数
接下来我们就在void transformPage(View arg0, float arg1) 里面,根据positon的变化区域,为我们的左右2个子view做动画
![](http://img.blog.csdn.net/20150604154926968)
因为要实现旋转的动画效果,
1. 所以必须给这个旋转动画设置一个梯度,就是一个变化区间,让他能从0度,根据我们的手势,变化到另一个角度
2.必须给这个旋转动画设置一个中定点
这个梯度,我们借助positon来实现就可以了,给他整个数学公司,让他也随着position的变化而变化
float mRot = (ROT_MAX * position);
左边那一页的posiotn是从【0,-1】,那么左边那一页的旋转角度应该是从【0,-20度】
右边那一页的positon是从【1,0】,那么右边那一页的旋转角度应该是从【20,0】
上源代码把
好的,这样我们的动画就写好了。
别忘了我们还是回到viewpager中,给他设置一下我们定义的这个切换动画
具体效果,请参考我们的平板
关于Viewpager的性能优化
如果我们的viewpager中加入了多个view,而且这多个view的布局都非常的深,加载非常多的高清图片,那么我们就会发现,viewpager在切换的时候非常的卡,加上动画就跟卡了,我们可以开启Viewpager的缓存功能来解决他,并且让他加载第0页的pager的同时,就去预加载其他页
这里viewpager就会去缓存我们的动画和图片,不再重复的加载(注意,adapter的ondestoryitem方法也要修改,不要再让他销毁之前加载的内容)
代码中我们去开启预加载
这样加载第0页,就回去预加载另外的2页
这些都是牺牲内存去换取时间的方法,并不好。
最根本的还是要回头解决子view布局过深和加载过多高清大图的问题
1. 布局文件的编写
<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" android:background="#000000" > <android.support.v4.view.ViewPager android:id="@+id/id_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
2. Mainactivity的编写
public class MainActivity extends Activity { private ViewPager viewPager; private MyAdapter pagerAdapter ; private int[] mImgIds = new int[]{R.drawable.one,R.drawable.two,R.drawable.three}; private Context mcontext; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); mcontext = MainActivity.this; initView(); } private void initView() { // TODO Auto-generated method stub viewPager = (ViewPager) findViewById(R.id.id_viewpager); pagerAdapter = new MyAdapter(mcontext, mImgIds); viewPager.setAdapter(pagerAdapter); } }
3. 适配器编写。
public class MyAdapter extends PagerAdapter{ private int[] mImgIds; private Context mcontext; public MyAdapter(Context mcontext, int[] mImgIds) { super(); this.mImgIds = mImgIds; this.mcontext = mcontext; } @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub container.removeView((View) object); } @Override public Object instantiateItem(ViewGroup container, int position) { // TODO Auto-generated method stub ImageView imageView = new ImageView(mcontext); imageView.setImageResource(mImgIds[position]); imageView.setScaleType(ScaleType.CENTER_INSIDE); container.addView(imageView); return imageView; } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0 == arg1; } @Override public int getCount() { // TODO Auto-generated method stub return mImgIds.length; } }
好的,现在这个代码已经写完了。viewpager里面分别加入了3张图片,切换子view的时候是没有动画效果的。
那么问题来了,如果我们要加入动画,应该需要什么?
1. 因为动画效果是根据我们手势操作来动的,所以我们要监听用户的手势。那么viewpager提供这样的方法呢?有的,就是一个叫做发现了一个叫做
onPageScrolled(int position, float positionOffset, int positionOffsetPixels)的方法
仔细研究下这几个参数
position 表示 当前viewpager处于第几页,positionOffset 就是表示这个pager的偏移的值,这个值是跟随我们的手势不断变化的
从第0页切换到第1页,就是向左边滑动的时候,我们打印一下这个参数看下变化
说白了,
就是像右边滑动,positionOffset的变化区间是【0,1】
同样的,我们页打印一下像左边滑动的信息
像左边滑动,positionOffset的变化区间是【1,0】
可是有个问题。在onPageScrolled中我们每次只能拿到一个view的偏移量啊,我们要对2个子view进行动画,必须拿到2个动态变化的偏移量才行
其实android已经提供给我们这个方法了,只需要ViewPager.PageTransformer 这个接口就可以了。里面会提供给我们一个
void transformPage(View view, float position) 方法,这个方法中可以同时获取左右2个变化的子view的偏移量的结果
但是这里偏移量有点不同,举个例子
当我们滑动时:会打印出当然ViewPager中存活的每个View以及它们的position的变化
* 比如从第0页滑动到第1页时候,
* 第0页的positon :
【0,-1】
* 第1页的positon : 【-1,0】
豁然发现,这个positon非常适合做渐变,缩放等动画效果的控制参数
接下来我们就在void transformPage(View arg0, float arg1) 里面,根据positon的变化区域,为我们的左右2个子view做动画
因为要实现旋转的动画效果,
1. 所以必须给这个旋转动画设置一个梯度,就是一个变化区间,让他能从0度,根据我们的手势,变化到另一个角度
2.必须给这个旋转动画设置一个中定点
这个梯度,我们借助positon来实现就可以了,给他整个数学公司,让他也随着position的变化而变化
float mRot = (ROT_MAX * position);
左边那一页的posiotn是从【0,-1】,那么左边那一页的旋转角度应该是从【0,-20度】
右边那一页的positon是从【1,0】,那么右边那一页的旋转角度应该是从【20,0】
上源代码把
public class pagerAnimation implements ViewPager.PageTransformer { <span style="white-space:pre"> </span>//动画梯度 <span style="white-space:pre"> </span>private float ROT_MAX = 50; <span style="white-space:pre"> </span>private float mRot ; <span style="white-space:pre"> </span>@Override <span style="white-space:pre"> </span>public void transformPage(View view, float position) { <span style="white-space:pre"> </span>// TODO Auto-generated method stub <span style="white-space:pre"> </span> //这个是左边页的动画 if (position < 0) { <span style="white-space:pre"> </span>//现在我们要根据这个position来定义我们的每个view的角度变化的梯度 mRot = (ROT_MAX * position); //posiotn是从【0,-1】,所以mRot是从【0,-20度】 //旋转的中心点是哪里?我们把他定义在正下方中间处 view.setPivotX(view.getMeasuredWidth() * 0.5f); view.setPivotY(view.getMeasuredHeight()); view.setRotation(mRot); } //这个是右边页的动画 else if (position > 0) { mRot = (ROT_MAX * position); //posiotn是从【1,0】,所以mRot是从【20度到0度】 view.setPivotX(view.getMeasuredWidth() * 0.5f); view.setPivotY(view.getMeasuredHeight()); view.setRotation(mRot); } <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span> }
好的,这样我们的动画就写好了。
别忘了我们还是回到viewpager中,给他设置一下我们定义的这个切换动画
private void initView() { // TODO Auto-generated method stub viewPager = (ViewPager) findViewById(R.id.id_viewpager); pagerAdapter = new MyAdapter(mcontext, mImgIds); viewPager.setAdapter(pagerAdapter); viewPager.setPageTransformer(true, new pagerAnimation()); }
具体效果,请参考我们的平板
关于Viewpager的性能优化
如果我们的viewpager中加入了多个view,而且这多个view的布局都非常的深,加载非常多的高清图片,那么我们就会发现,viewpager在切换的时候非常的卡,加上动画就跟卡了,我们可以开启Viewpager的缓存功能来解决他,并且让他加载第0页的pager的同时,就去预加载其他页
<android.support.v4.view.ViewPager android:id="@+id/id_viewpager" android:layout_width="match_parent" android:layout_height="match_parent" android:persistentDrawingCache="all" />
这里viewpager就会去缓存我们的动画和图片,不再重复的加载(注意,adapter的ondestoryitem方法也要修改,不要再让他销毁之前加载的内容)
代码中我们去开启预加载
private void initView() { // TODO Auto-generated method stub viewPager = (ViewPager) findViewById(R.id.id_viewpager); pagerAdapter = new MyAdapter(mcontext, mImgIds); viewPager.setOffscreenPageLimit(3); viewPager.setAdapter(pagerAdapter); viewPager.setPageTransformer(true, new pagerAnimation()); }
这样加载第0页,就回去预加载另外的2页
这些都是牺牲内存去换取时间的方法,并不好。
最根本的还是要回头解决子view布局过深和加载过多高清大图的问题
相关文章推荐
- MAC 开启root权限
- 【Decode Ways】cpp
- VHDL MOD和REM(转)
- AngularJS中的$apply方法
- cocos2dx中文乱码问题
- MySql如何分级查询上千万行记录的表,并将该大数据显示到界面中
- 软件测试职业之面试
- 查看某个端口是否被占用
- 15OJ——换座位
- linux驱动之定时器的介绍和内核时间的学习
- Centos 6.4 安装scp和lrzsz
- 1- 不能连网
- 阿里巴巴CTO王坚:只有跑在互联网和云计算上的才是大数据
- 两道SAT数学练习题
- LightOJ - 1038 Race to 1 Again 递推+期望
- JQuery的跨域方法
- Java Thread.join详解
- CentOS 6.2安装nagios
- Linux常用网络工具:fping主机扫描
- python定时器(Timer)用法简单实例