banner框架,一个比较齐全的框架

首先奉献上作者的github地址 https://github.com/youth5201314/banner  这是一个star数过千,fork数过百的轮子,用起来也是good的,不过使用的时候不注意也是能遇到坑的,这里的话效果图就不贴了,需要看的话可以直接去GitHub 上直接看

怎么去读这个框架呢,它不是一个项目,所以不能从启动的activity开始读起,但它是一个自定义的view,所以我们可以从自定义的view开始读起来 也就是我们的布局引用的com.youth.banner下的Banner类 

 Banner类的拆包

     构造方法

  首先我们看到的是banner继承自FrameLayout类,所以我们当然想到的是三大构造方法了,想到了,那当然去看了



直接看三个参数的构造方法了,前面都是一些常规的初始化操作,直接看initView(context,attrs)方法了,

        a.initView(context,attrs)方法


加载banner的布局文件(下一个小节会看下),然后初始化控件,这个都是没得说的, 接下来handleTypedArray(context,attrs)初始化自定义的属性,最后的initViewPagerScroll()初始化viewpager的滚动时间的这里面应用了两个自定义的控件BannerScroller 和BannerViewpager
             1.这里来简单看下布局文件 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/bannerContainer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clipChildren="false">


    <com.youth.banner.view.BannerViewPager
        android:id="@+id/bannerViewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipChildren="false" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true">

        <LinearLayout
            android:id="@+id/circleIndicator"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:gravity="center"
            android:orientation="horizontal"
            android:padding="10dp"
            android:visibility="visible" />

        <TextView
            android:id="@+id/numIndicator"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:layout_alignParentRight="true"
            android:layout_margin="8dp"
            android:background="@drawable/black_background"
            android:gravity="center"
            android:text="1/1"
            android:textColor="#ffffff"
            android:visibility="visible" />

        <LinearLayout
            android:id="@+id/titleView"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:layout_below="@+id/circleIndicator"
            android:background="#44000000"
            android:orientation="horizontal"
            android:visibility="visible">

            <TextView
                android:id="@+id/bannerTitle"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1000"
                android:ellipsize="marquee"
                android:focusable="true"
                android:focusableInTouchMode="true"
                android:gravity="center_vertical"
                android:paddingLeft="10dp"
                android:singleLine="true"
                android:textColor="#ffffff"
                android:visibility="gone" />

            <FrameLayout
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:paddingLeft="10dp"
                android:paddingRight="10dp">

                <TextView
                    android:id="@+id/numIndicatorInside"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:gravity="center_vertical"
                    android:text="1/1"
                    android:textColor="#ffffff"
                    android:visibility="gone" />

                <LinearLayout
                    android:id="@+id/indicatorInside"
                    android:layout_width="wrap_content"
                    android:layout_height="match_parent"
                    android:gravity="center_vertical"
                    android:orientation="horizontal"
                    android:visibility="gone" />
            </FrameLayout>
        </LinearLayout>
    </RelativeLayout>
</RelativeLayout>

            这里用的是一个相对布局包裹了一个自定义的viewpager和一系列的指示器,还是很简单的了。
              2. BannerScroller类
            bannerScroller继承自scroller,重写了其中的startScroll这个方法,增加一个setDuration(int time)  从而使得两个banner之间切换的持续时间可控
               3.BannerViewpager类
            bannerViewpager类继承自viewPager,增加了一个属性scrollable,重写了事件监听ontouchEvent()和事件拦截onInterceptTouchEvent  从而控制了是否让用户手滑动banner ,默认的话是true

这个时候感觉不知道从哪看了,我们可以看下banner的初始化,省去一些set的基本操作,我们会看到调用了start(),ok,那我们从这边开始看

start()方法

    里面很简单就下面的三个方法
setBannerStyleUI();
setImageList(imageUrls);
setData();
    我们一个个来看

   a.setBannerStyleUI() 文字指示器的初始化

    
这个主要是对banner的文字描述进行初始化,   首先做的是一些异常情况,比如你的文字描述的条数和banner图片的url不一样那么不开玩笑了么,作者为了防止这种情况抛了个异常,后面的话就是一些初始化的操作了

b.setImageList(imageUrls)  小圆点指示器的初始化

    
    根据imagesUrl的size()通过initImages()--  createIndicator()方法去 动态创建类似小圆点指示器 
        这里我们还要⚠️的是一个方法 imageLoader.displayImage(context,url,imageView);看名字我们知道这是一个通过url加载图片的方法,这个imageLoader来自
public interface ImageLoaderInterface<T extends View> extends Serializable {

    void displayImage(Context context, Object path, T imageView);

    T createImageView(Context context);
}

   是需要你写个类去实现这个ImageLoaderInterface接口并且在start()方法之前实例话setImageLoader()进去的    

c:setData()

    
        这个方法就是对viewpager的一些初始化操作了,比如adapte,滑动点击事件 (addOnpageChangeListtener(this),这里重要重写onPageChangeListener事件的三个方法),以及只有一个轮播图片的时候,设置不能滑动,如果想一张能滑动的话就要修改这边了,最后的是自动轮播的
    

监听事件的操作方法

   a onPageChangeListener事件  

@Override
public void onPageScrollStateChanged(int state) {
    if (mOnPageChangeListener != null) {
        mOnPageChangeListener.onPageScrollStateChanged(state);
    }
    currentItem = viewPager.getCurrentItem();
    switch (state) {
        case 0://No operation
            if (currentItem == 0) {
                viewPager.setCurrentItem(count, false);
            } else if (currentItem == count + 1) {
                viewPager.setCurrentItem(1, false);
            }
            break;
        case 1://start Sliding
            if (currentItem == count + 1) {
                viewPager.setCurrentItem(1, false);
            } else if (currentItem == 0) {
                viewPager.setCurrentItem(count, false);
            }
            break;
        case 2://end Sliding
            break;
    }
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    if (mOnPageChangeListener != null) {
        mOnPageChangeListener.onPageScrolled(position, positionOffset, positionOffsetPixels);
    }
}

@Override
public void onPageSelected(int position) {
    if (mOnPageChangeListener != null) {
        mOnPageChangeListener.onPageSelected(position);
    }
    if (bannerStyle == BannerConfig.CIRCLE_INDICATOR ||
            bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE ||
            bannerStyle == BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE) {
        indicatorImages.get((lastPosition - 1 + count) % count).setImageResource(mIndicatorUnselectedResId);
        indicatorImages.get((position - 1 + count) % count).setImageResource(mIndicatorSelectedResId);
        lastPosition = position;
    }
    if (position == 0) position = count;
    if (position > count) position = 1;
    switch (bannerStyle) {
        case BannerConfig.CIRCLE_INDICATOR:
            break;
        case BannerConfig.NUM_INDICATOR:
            numIndicator.setText(position + "/" + count);
            break;
        case BannerConfig.NUM_INDICATOR_TITLE:
            numIndicatorInside.setText(position + "/" + count);
            bannerTitle.setText(titles.get(position - 1));
            break;
        case BannerConfig.CIRCLE_INDICATOR_TITLE:
            bannerTitle.setText(titles.get(position - 1));
            break;
        case BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE:
            bannerTitle.setText(titles.get(position - 1));
            break;
    }

}

    这个里面设置了图片的轮播形势,指示器的改变

  b 点击的dispatchTouchEvent()事件

@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
//        Log.i(tag, ev.getAction() + "--" + isAutoPlay);
        if (isAutoPlay) {
            int action = ev.getAction();
            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL
                    || action == MotionEvent.ACTION_OUTSIDE) {
                startAutoPlay();
            } else if (action == MotionEvent.ACTION_DOWN) {
                stopAutoPlay();
            }
        }
        return super.dispatchTouchEvent(ev);
    }


    手指放到banner上的时候停止自动轮播,抬起或者取消,或者移到控件外面的时候重新开始自动轮播

c.设置banner图片的点击事件

    通过 BannerPagerAdapter这个

来进行回掉设置的。

ok,剩下的就是一些方法都是增加对外的接口,设置默认的一些属性的,基本也就是这样了,是不是很简单的呢,其实真正的实现没有说的这么简单。
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值