本文由
依然范特稀西
投稿。
依然范特稀西
的博客地址:
http://www.jianshu.com/u/35167a70aa39
作者的其他文章:
Banner广告位是APP 中的一个非常重要的位置,为什么呢?
因为它能带来money。是一个公司很重要的一个营收点。像那种用户数基数特别大的产品,如facebook、twitter、QQ、微信等等。
Banner广告位日营收估计得上千万美刀(猜的,不知道具体数据)。一个漂亮的Banner往往能够吸引用户的眼球,引导用户点击,从而提高转化率。遗憾的是现在的大多数产品的Banner都是千篇一律的,没有什么亮点可言。
但是前几天在魅族手机上发现了一个效果不错的Banner,魅族所有自家的APP所用的Banner 引起了我的注意。
效果是这样子的:
看到这个Banner 第一眼就吸引了我,随后就反复的体验了几次了,感觉这种Banner的效果还不错。
最后想着高仿一个和这种效果差不多的BannerView 。那么本文就讲一下如何实现这样一个BannerView。最终实现的效果如下:
本文会讲实现仿魅族Banner效果所要用到的一些关键知识点,目录如下图所示。所有的效果已经封装成一个库。
详细代码请看
github: https://github.com/pinguo-zhouwei/MZBannerView
在开始实现魅族Banner效果之前,我们先来整理一下实现一个BannerView的思路,首先需要用ViewPager,其次让ViewPager无限轮播。
其实BannerView就是一个无限轮播的ViewPager,然后做一些封装处理,让使用更加简单就ok。
现在我们在来看一下魅族的这个Banner。他与普通的banner的区别是当前页显示了前一页和后一页的部分内容。
抛开切换时的动画先不说,要实现这个效果的第一步就是要让ViewPager在一个页面显示多页的内容(当前页+前后页部分)。
(1) ViewPager展示多页
要让ViewPager页面展示多页的内容,就要用到ViewGroup的一个强大的属性。这个属性虽然强大,但是也不常用,可能有些小伙伴不知道(之前我也没用过...),那就是clipChildren属性。
这个属性有什么作用呢,我们看一下它的文档介绍:
clipChildren: 默认值为true, 子View 的大小只能在父View规定的范围之内,比如父View的高为50,子View的高为60 ,那么多处的部分就会被裁剪。如果我们设置这个值为false的话,那么多处的部分就不会被裁剪了。
这里我们就可以利用这个属性来实现了这个效果了,我们设置ViewPager的父布局的clipChildren为false。然后设置ViewPager 左右一定的边距,那么左右就空出了一定的区域,利用clipChildren 属性,就能让前后页面的部分显示在当前页了。
布局如下:
这样就能实现ViewPager 展示前后页面的部分内容。
(2)自定义ViewPager.PageTransformer动画
上面实现了ViewPager当前页面显示前后页的部分内容,但是从最开始魅族的Banner效果我们可以看出,滑动的时候是有 一个放大缩小的动画的。左右显示的部分有一定比例的缩小。
这就要用到ViewPager.PageTransformer了。
ViewPager.PageTransformer 干什么的呢?
ViewPager.PageTransformer 是用来做ViewPager切换动画的,它是一个接口,里面只有一个方法transformPage。
虽然只有一个方法,但是它很强大,它能反映出在ViewPager滑动过程中,各个View的位置变化。我们拿到了这些位置变化,就能在这个过程中对View做各种各样的动画了。
要自定义动画,我们就来需要知道positon这个值的变化区间。从官方给的ViewPager的两个示例我们知道,position的变换有三个区间,[-Infinity,-1),[-1,1],(1.Infinity)。
-
[-Infinity,-1):已经在屏幕之外,看不到了
-
(1.Infinity): 已经在屏幕之外,看不到了。
-
[-1,1]: 这个区间是我门操作View动画的重点区间。
我们来看一下官方对于position的解释:
官方的解释:The position parameter indicates where a given page is located relative to the center of the screen. It is a dynamic property that changes as the user scrolls through the pages. When a page fills the screen, its position value is 0. When a page is drawn just off the right side of the screen, its position value is 1. If the user scrolls halfway between pages one and two, page one has a position of -0.5 and page two has a position of 0.5.
根据解释,也就是说当前停留的页面的位置为 0,右边屏幕之外绘制的这个页面位置为 1。
那么,A 页面滑到 B 页面有 2 种情况:
第一种:左边划出屏幕,那么 A:0 -> -1,B :1 -> 0。
第二种:右边划出屏幕,A:0->1, B :-1-> 0
了解了这个方法的变化后,我们就来自定义我们的切换动画,这里很简单,我们只需要一个scale动画。
代码如下:
效果图是这样的:
到此,我们仿魅族Banner的静态效果就实现了。接下来我们就要让Banner动起来,实现无限轮播效果。
上面我们已经实现了Bannerd的静态展示和切换动画,那么我们现在就需要让Banner动起来,实现无限轮播。
ViewPager实现Banner无效轮播效果有2种方案,第一种是:在列表的最前面插入最后一条数据,在列表末尾插入第一个数据,造成循环的假象。第二种方案是:采用getCount 返回 Integer.MAX_VALUE。
结下来分别看一下这两种方案。
方案1:
在列表的最前面插入最后一条数据,在列表末尾插入第一个数据,造成循环的假象。
这种方法是怎么做的呢?,是这样的:假如我们的列表有3条数据,用三个页面展示,分别编号为1,2,3。
我们再创建一个新的列表,长度为真实列表的长度+2,也就是5。在最前面插入最后一条数据,然后在末尾插入第一条数据。
新列表就变成了这样了,3-1-2-3-1。如果当前滑到的是0位置(页面3),那就通过ViewPager的setCurrentItem(int item, boolean smoothScroll)方法神不知鬼不觉的切换到3位置(页面3),当滑到4的位置时(页面1),也用这个方法滑到1位置(页面1)。这样给我们的感觉就是无限轮播了。
来一张图辅助理解一下。