ViewPager系列之 仿魅族应用的广告BannerView

转自:http://www.jianshu.com/p/653680cfe877#
目的:添加自己的理解和注释。
主要改动:展示多页的更深解释、动画效果的优化。
1 . ViewPager展示多页
要让ViewPager页面展示多页的内容,就要用到ViewGroup的一个强大的属性。这个属性虽然强大,但是也不常用,可能有些小伙伴不知道(之前我也没用过…),那就是clipChildren属性。这个属性有什么作用呢,我们看一下它的文档介绍:

/**
     * By default, children are clipped to their bounds before drawing. This
     * allows view groups to override this behavior for animations, etc.
     *
     * @param clipChildren true to clip children to their bounds,
     *        false otherwise
     * @attr ref android.R.styleable#ViewGroup_clipChildren
     */

clipChildren: 默认值为true, 子View 的大小只能在父View规定的范围之内,比如父View的高为50,子View的高为60 ,那么多处的部分就会被裁剪。如果我们设置这个值为false的话,那么多处的部分就不会被裁剪了。

clipChildren的意思:是否限制子View在其范围内,我们将其值设置为false后那么当子控件的高度高于父控件时也会完全显示,而不会被压缩,ViewPager是一组连续的图片,我们设置了false,其实父控件也不能控制ViewPager的大小了。

这里我们就可以利用这个属性来实现了这个效果了,我们设置ViewPager的父布局的clipChildren为false。然后设置ViewPager 左右一定的边距,那么左右就空出了一定的区域,利用clipChildren 属性,就能让前后页面的部分显示在当前页了。布局如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:clipChildren="false"
    android:orientation="vertical"
    >


   <android.support.v4.view.ViewPager
       android:id="@+id/view_pager"
       android:layout_width="match_parent"
       android:layout_height="200dp"
       android:layout_marginLeft="30dp"
       android:layout_marginRight="30dp"
       />
</LinearLayout>

这样就能实现ViewPager 展示前后页面的部分内容。
2 . 自定义ViewPager.PageTransformer动画
上面实现了ViewPager当前页面显示前后页的部分内容,但是从最开始魅族的Banner效果我们可以看出,滑动的时候是有 一个放大缩小的动画的。左右显示的部分有一定比例的缩小。这就要用到ViewPager.PageTransformer了。

ViewPager.PageTransformer 干什么的呢?ViewPager.PageTransformer 是用来做ViewPager切换动画的,它是一个接口,里面只有一个方法transformPage。

 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);
    }

虽然只有一个方法,但是它很强大,它能反映出在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动画。代码如下:

public class CustomTransformer implements ViewPager.PageTransformer {
    private static final float MIN_SCALE = 0.9F;

    @Override
    public void transformPage(View page, float position) {

        Log.e("xsr", "position = " + position + ", page = " + page);
        if (position <= -1) {
            page.setScaleY(MIN_SCALE);
        } else if (position < 1 && position > -1) {
            // position会显示ViewPager里面的所有的位置。这些位置都是相对于中间(0)位置的。最中间是0,往右:1,2,3。。。往左:-1,-2,-3。。。相对位置越靠近中间(0),数值越小。相当于就是-1到0到1之间无穷的小数。所以我们直接取到这个位置的绝对值,然后乘以0.1f得到缩小的距离比例。然后再用1减去,得到最终的比例。
            float scale = 1 - Math.abs(position) * 0.1f;
            Log.e("xsr", "scale = " + scale);
            page.setScaleY(scale);
            /*page.setScaleX(scale);

            if(position<0){
                page.setTranslationX(width * (1 - scale) /2);
            }else{
                page.setTranslationX(-width * (1 - scale) /2);
            }*/

        } else {
            page.setScaleY(MIN_SCALE);
        }
    }
}

到此,我们仿魅族Banner的静态效果就实现了。接下来我们就要让Banner动起来,实现无限轮播效果。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
现在的APP Banner大多数千篇一律,前几天看到魅族手机上所有魅族自家APP上的Banner效果不错,于是就想着来仿着做一个类似的效果。因此就有了这个库。但是为了使用方便,这个库不仅仅只有仿魅族效果的BannerView使用,还可以当作普通的BannerView使用,还可以当作一个ViewPager 来使用使用很方便,具体使用方法和API 请看后面的示例。 ---  左图为魅族APP上的Banner效果,右图是高仿效果。MZBannerView 有以下功能:1 . 仿魅族BannerView 效果。2 . 当普通Banner 使用3 . 当普通ViewPager 使用。4 . 当普通ViewPager使用(有魅族Banner效果)5 . 仿某视频网站Banner效果。Demo APKgif图片有点模糊,可以扫描下方二维码下载APK体验相关博客ViewPager系列仿魅族应用广告BannerView更新日志v1.1.1 : 增加按住Banner 停止轮播,松开开始自动轮播的功能v1.1.0 : fix 在从网上获取数据后,banner 显示 造成 ANR 的bug(如果在onCreate()中设置资源显示则没问题)v1.1.2 : fix 更改数据之后,调用setPages重新刷新数据会crush的bugv2.0.0 :1,add: 添加仿魅族Banner效果,中间Page覆盖两边。 -- 2,fix 部分bug: 添加OnPageChangeListener 回调 pisition 不对的bug.DependencyAdd it in your root build.gradle at the end of repositories:allprojects {      repositories {           ...           maven { url 'https://jitpack.io' }      } }Step 2. Add the dependencydependencies {          compile 'com.github.pinguo-zhouwei:MZBannerView:v2.0.0' }自定义属性属性名属性意义取值open_mz_mode是否开启魅族模式true 为魅族Banner效果,false 则普通Banner效果canLoop是否轮播true 轮播,false 则为普通ViewPagerindicatorPaddingLeft设置指示器距离左侧的距离单位为 dp 的值indicatorPaddingRight设置指示器距离右侧的距离单位为 dp 的值indicatorAlign设置指示器的位置有三个取值:left 左边,center 剧中显示,right 右侧显示middle_page_cover设置中间Page是否覆盖(真正的魅族Banner效果)true 覆盖,false 无覆盖效果使用方法1 . xml 布局文件2 . activity中代码:mMZBanner = (MZBannerViewview.findViewById(R.id.banner);              // 设置数据         mMZBanner.setPages(list, new MZHolderCreator() {             @Override             public BannerViewHolder createViewHolder() {                 return new BannerViewHolder();             }         });  public static class BannerViewHolder implements MZViewHolder {         private ImageView mImageView;         @Override         public View createView(Context cont
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值