使用ViewPager实现幻灯片播放功能
来源:互联网 发布:阿里云esc远程连接 编辑:程序博客网 时间:2024/05/20 21:46
使用Viewpager实现幻灯片播放功能
最近要由于项目需要,要实现一个支持幻灯片播放功能的
图片轮播功能,自己在实现过程中也做了些总结,现在记录下来,以便之后复看,也希望可以帮到一些需要帮助的人吧。
基本的思路
总的来说实现幻灯片播放的思路如下:
- 1 完成动画效果
- 2 完成定时切换
1.动画切换效果
原理解析
完成动画切换效果的方法是通过ViewPager的这个函数实现:ViewPager.setPageTransformer(boolean reverseDrawingOrder,ViewPager.PageTransformer transformer);
我们先来看看这个方法的一些介绍:
Sets a {@link PageTransformer} that will be called for each attached page whenever
* the scroll position is changed. This allows the application to apply custom property
* transformations to each page, overriding the default sliding behavior.
大体意思就是说当ViewPager滑动时,设置的PageTransformer中的对应方法会被调用,使得应用可以使用自己的方式来实现不同的页面切换效果
那么这个动画切换效果的具体实现该怎么写呢,我们来看看ViewPager
.PageTransformer接口定义的方法:
public interface PageTransformer { /** * Apply a property transformation to the given page. * * @param page Apply the transformation to this page * @param position Position of page relative to the current front-and-center * position of the pager. 0 is front and center. 1 is one full * page position to the right, and -1 is one page position to the left. */ void transformPage(View page, float position); }
简单来说,就是当一个页面完全处于中间时,position的大小为0,当页面从中间向左滑动直到刚好消失时,position的变化为0 ->-1,当页面从中间向右滑动到刚好消失时,position的变化为0 -> 1。这样子我们就可以通过position的变化,在不同的position时将当前的page设置不同的属性(例如setTranslation,setRotation,setAlpha等),达到各种各样的页面切换效果.
一些实现的效果:
- 立方体旋转效果:
@Override public void transformPage(View page, float position) { //终极无敌史诗级例外的操作 position < -1 || position > 1 if ((position < -1) || (position > 1)){ return; } //刚好不可见 复原 if ((position == -1) ||(position == 1)){ resetPage(page); return; } //从左边出去 if (position <= 0) { page.setPivotX(page.getWidth()); page.setPivotY(page.getHeight() * 0.5f); page.setRotationY(90f * position); return; } //从右边出去 if (position < 1){ page.setPivotX(0); page.setPivotY(page.getWidth() * 0.5f); page.setRotationY(90f * position); return; } } /** * 恢复page的属性 * @param page 指定的view */ void resetPage(View page){ //设置旋转中心点; page.setPivotX(page.getWidth()); page.setPivotY(page.getHeight() * 0.5f); //只在Y轴做旋转操作 page.setRotationY(0); }
- 中心旋转效果
@Override public void transformPage(View page, float position) { int pageWidth = page.getWidth(); //终极无敌史诗级例外的操作 position < -1 || position > 1 if ((position < -1) || (position > 1)){ return; } //刚好不可见 复原 if ((position == -1) || (position == 1)){ resetPage(page); return; } //从左边出去 if (position <= 0){ //阻止消失界面的移动 page.setTranslationX(-pageWidth * position); final float rotation = -180f * position; page.setPivotX(page.getWidth() * 0.5f); page.setPivotY(page.getHeight() * 0.5f); page.setRotation(rotation); float alphaFactor = Math.max(0.0f, 1 - Math.abs(position)); //透明度改变 page.setAlpha(alphaFactor); return; } //从右边出去 if (position < 1){ //阻止出现的界面的移动 page.setTranslationX(-pageWidth * position); final float rotation = -180f * position; page.setPivotX(page.getWidth() * 0.5f); page.setPivotY(page.getHeight() * 0.5f); page.setRotation(rotation); float alphaFactor = Math.max(0.0f, 1 - Math.abs(position)); //透明度改变 page.setAlpha(alphaFactor); return; } } /** * 恢复page的属性 * @param page 当前page */ void resetPage(View page){ page.setAlpha(1.0f); page.setTranslationX(0); page.setPivotX(0); page.setPivotY(0); page.setRotation(0.0f); }
- 缩小平移效果
private static final float MIN_SCALE = 0.85f; private static final float MIN_ALPHA = 0.5f; @Override public void transformPage(View page, float position) { int pageWidth = page.getWidth(); int pageHeight = page.getHeight(); //终极无敌史诗级例外的操作 position < -1 || position > 1 if ((position < -1) || (position > 1)){ return; } //刚好不可见 复原 if ((position == -1) || (position == 1)){ resetPage(page); return; } //从左边出去 if (position <= 0){ float scaleFactor = Math.max(MIN_SCALE,1-Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horMargin = pageWidth * (1 - scaleFactor) / 2; //左移 page.setTranslationX(horMargin - vertMargin / 2); // Scale the page down (between MIN_SCALE and 1) page.setScaleX(scaleFactor); page.setScaleY(scaleFactor); // Fade the page relative to its size. page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); return; } //从右边出去 if (position < 1){ float scaleFactor = Math.max(MIN_SCALE,1-Math.abs(position)); float vertMargin = pageHeight * (1 - scaleFactor) / 2; float horMargin = pageWidth * (1 - scaleFactor) / 2; page.setTranslationX(-horMargin + vertMargin / 2); // Scale the page down (between MIN_SCALE and 1) page.setScaleX(scaleFactor); page.setScaleY(scaleFactor); // Fade the page relative to its size. page.setAlpha(MIN_ALPHA + (scaleFactor - MIN_SCALE) / (1 - MIN_SCALE) * (1 - MIN_ALPHA)); return; } } /** * 恢复page的属性 * @param page 当前page */ void resetPage(View page){ page.setAlpha(1.0f); page.setTranslationX(0.0f); page.setScaleX(1.0f); page.setScaleY(1.0f); }
- 旋转向下
@Override public void transformPage(View page, float position) { final float MAX_ROTATE_ANGLE = 20.0f; //终极无敌史诗级例外的操作 position < -1 || position > 1 if ((position < -1) || (position > 1)){ return; } //刚好不可见 复原 if ((position == -1) || (position == 1)){ resetPage(page); return; } //从左边出去 if (position <= 0){ float angle = MAX_ROTATE_ANGLE * position; page.setPivotX(page.getWidth() * 0.5f); page.setPivotY(page.getHeight()); page.setRotation(angle); return; } //从右边出去 if (position < 1){ float angle = MAX_ROTATE_ANGLE * position; page.setPivotX(page.getWidth() * 0.5f); page.setPivotY(page.getHeight()); page.setRotation(angle); return; } } /** * 恢复page的属性 * @param page 当前page */ void resetPage(View page){ page.setPivotX(page.getWidth() * 0.5f); page.setPivotY(page.getHeight()); page.setRotation(0); }
- 放大进入
@Override public void transformPage(View page, float position) { //终极无敌史诗级例外的操作 position < -1 || position > 1 if ((position < -1) || (position > 1)){ return; } //刚好不可见 复原 if ((position == -1)){ page.setPivotX(0); page.setPivotY(page.getHeight() * 0.5f); page.setScaleX(1.0f); page.setScaleY(1.0f); return; } //刚好不可见 复原 if (position == 1){ page.setPivotX(page.getWidth()); page.setPivotY(page.getHeight() * 0.5f); page.setScaleX(1.0f); page.setScaleY(1.0f); return; } //从左边出去 if (position <= 0){ page.setPivotX(0); page.setPivotY(page.getHeight() * 0.5f); float scale = 1.0f + position; page.setScaleX(scale); page.setScaleY(scale); return; } //从右边出去 if (position < 1){ page.setPivotX(page.getWidth()); page.setPivotY(page.getHeight() * 0.5f); float scale = 1.0f - position; page.setScaleX(scale); page.setScaleY(scale); return; } }
2.定时切换
这个实际上还蛮好实现的,我当时选择的实现方式是使用Timer + Handler的实现方式,主要是通过使用
Timer.scheduleAtFixedRate(TimerTask task, long delay, long period),通过设定period长短控制播放速度,在Timerask中发送message,通知Handler执行切换,完成幻灯片播放效果.
3.一些坑的地方
1.幻灯片播放功能中有切换动画的设置功能,之前在实现的时候,在切换了动画之后,当前page前后的两个page都没有复原,导致切换效果很奇怪,后来就在page变为不可见之后,将其所有属性复原,即可。
2.当进入到幻灯片播放模式之后,当前页面的切换动画总是一闪而过,导致切换效果很难受,所以查阅资料之后,发现可以通过修改ViewPager的mScroller的实现,来指定每一次scroll的时延。以下是解决方法:
/** * 使用反射设置viewpager的页面切换时间 * @param scrollDuration 切换时长 * @param isReset 是否恢复原来的效果 true:恢复 false:不恢复 一般为true */ private void setScrollDuration(final int scrollDuration, final boolean isReset){ LogUtils.d(TAG, "setScrollDuration: duration: " + scrollDuration); try { Field field = ViewPager.class.getDeclaredField("mScroller"); field.setAccessible(true); Scroller mScroller = new Scroller(this,new LinearInterpolator()){ @Override public void startScroll(int startX, int startY, int dx, int dy) { if (isReset){ super.startScroll(startX, startY, dx, dy); }else{ super.startScroll(startX, startY, dx, dy,scrollDuration); } } @Override public void startScroll(int startX, int startY, int dx, int dy, int duration) { if (isReset){//由系统控制 super.startScroll(startX, startY, dx, dy, duration); }else{//幻灯片播放 super.startScroll(startX, startY, dx, dy, scrollDuration); } } }; field.set(mPictureViewPager,mScroller); } catch (NoSuchFieldException e) { e.printStackTrace(); } catch (IllegalAccessException e){ e.printStackTrace(); } }
上面的实现都很清晰了,就不做介绍了。
好了,这篇文章就这么愉快地结束了
参考资料:
鸿洋大神的博文
suyan_why的博文
- 使用ViewPager实现幻灯片播放功能
- 使用ViewPager屏幕幻灯片
- ViewFlipper 实现幻灯片功能
- js实现幻灯片播放图片
- 幻灯片自动播放的实现
- viewpager实现无限循环滚动幻灯片
- 自定义ViewPager.PageTransformer实现幻灯片效果
- Using ViewPager for Screen Slides 使用屏幕幻灯片ViewPager
- vbscript实现的幻灯片播放效果
- 常用的幻灯片播放简单实现
- viewflipper实现幻灯片的简单播放
- 使用ViewPager实现循环滚动播放图片广告
- 使用vcastr3.swf实现视频播放功能
- 使用GStreamer实现播放器功能
- 使用AudioSession实现音乐后台播放功能
- android之ViewPager的使用实现应用的导航功能
- android使用viewpager+photoview实现新闻组图功能
- 使用ViewPager和RecyclerView实现水平分页功能
- Spring-web源码解析之Filter-OncePerRequestFilter:
- Java 8:不要再用循环了
- Euler theorem(水)
- Django引入原有的mysql数据库
- [Err] 1064
- 使用ViewPager实现幻灯片播放功能
- Flask 初印象
- Inno Setup 5 安装包制作工具
- 指针版lca之小机房的树
- Spring之AOP由浅入深
- 基础数论算法(八) 矩阵乘法与线性齐次递推公式的快速求值
- RE:JAVA学习-初访 对象与类
- SpringMVC报错:java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
- 关于python的整形(int)自动转长整形(long)的问题