Android Banner轮播图 recyclerView添加headVie

来源:互联网 发布:中国人工智能四巨头 编辑:程序博客网 时间:2024/05/22 02:24

Banner能实现循环播放多个广告图片和手动滑动循环等功能。因为原生ViewPager并不支持循环翻页, 要实现循环还得需要自己去动手。Banner框架可以进行不同样式、不同动画设置, 以及完善的api方法能满足大部分软件首页轮播图效果的需求。

有一篇博客讲了一些,可以参考banner框架,一个比较齐全的框架;

此项目的Github地址:链接。

本篇教程依然涉及一些其他方面的东西,如果有问题,可以参考我之前的系列文章。

二、添加依赖

  1. build.gradle中添加依赖:

    dependencies{    compile 'com.youth.banner:banner:1.4.9'  //最新版本}
  2. 添加权限:

    <!-- if you want to load images from the internet --><uses-permission android:name="android.permission.INTERNET" /> <!-- if you want to load images from a file OR from the internet --><uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

三、解锁技能

1. 加载数据和刷新数据:

  • 首先,添加我们MainActivity的布局文件,里面含有一个SwipeRefreshLayout,包裹RecyclerView,SwipeRefreshLayout用来实现下拉刷新。

    <?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="wrap_content"    tools:context="com.ping.bannerdemo.activity.MainActivity">    <android.support.v4.widget.SwipeRefreshLayout        android:id="@+id/swipeRefreshLayout"        android:layout_width="match_parent"        android:layout_height="wrap_content">        <android.support.v7.widget.RecyclerView            android:id="@+id/recyclerView"            android:layout_width="match_parent"            android:layout_height="wrap_content">        </android.support.v7.widget.RecyclerView>    </android.support.v4.widget.SwipeRefreshLayout></LinearLayout>
  • 然后,我们要在RecyclerView中添加俩种布局,一个Header存放Banner,另一个则是正常的item布局。先放上俩个布局的内容。

    //header.xml<?xml version="1.0" encoding="utf-8"?><com.youth.banner.Banner    xmlns:android="http://schemas.android.com/apk/res/android"    android:id="@+id/banner"    android:layout_width="match_parent"    android:layout_height="match_parent"/>//item_recycler.xml<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"              android:orientation="vertical"              android:layout_width="match_parent"              android:layout_height="wrap_content">    <TextView        android:padding="5dp"        android:gravity="center"        android:id="@+id/tv_item"        android:textSize="20dp"        android:textColor="#000"        android:layout_width="match_parent"        android:layout_height="wrap_content"/></LinearLayout>

    要添加俩种布局,得在Adapter中实现,这里可以全面的看一下各种LayoutManager中怎么添加header布局,戳这。这里,我就用了文中的第一个,主要方法就是根据不同的ViewType返回不同的ViewHolder。通过setter方法将header的view注入进adapter。先来看一下adapter吧。

    public class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyViewHolder> {    public static final int TYPE_HEADER = 0;    public static final int TYPE_NORMAL = 1;    private View mHeaderView;    private String[] mData;    private Context mContext;    public void setHeaderView(View headerView) {        mHeaderView = headerView;    }    public MyAdapter(Context context, String[] data) {        mContext = context;        mData = data;    }    //根据pos返回不同的ItemViewType    @Override    public int getItemViewType(int position) {        if (mHeaderView == null) return TYPE_NORMAL;        if (position == 0) return TYPE_HEADER;        return TYPE_NORMAL;    }    //在此根据ItemViewType来决定返回何种ViewHolder    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        if (mHeaderView != null && viewType == TYPE_HEADER)            return new MyViewHolder(mHeaderView);        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_recycler, parent, false);        return new MyViewHolder(view);    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        if(getItemViewType(position) == TYPE_HEADER) return;        final int pos = getRealPosition(holder);        final String data = mData[pos];        if(holder instanceof MyViewHolder) {            ((MyViewHolder) holder).mTvItem.setText(data);        }    }    private int getRealPosition(RecyclerView.ViewHolder holder) {        int position = holder.getLayoutPosition();        return mHeaderView == null ? position : position - 1;    }    //返回正确的item个数    @Override    public int getItemCount() {        return mHeaderView == null ? mData.length : mData.length + 1;    }    public class MyViewHolder extends RecyclerView.ViewHolder {        @BindView(R.id.tv_item)        TextView mTvItem;        public MyViewHolder(View itemView) {            super(itemView);            if(itemView == mHeaderView)                return;            ButterKnife.bind(this, itemView);        }    }}
  • 看完Adapter,我们要看看在哪里对headerview进行set了。MainActivity中我们渲染出header的布局,然后通过setHeaderView将view传递进去即可。

    //渲染header布局View header = LayoutInflater.from(this).inflate(R.layout.header, null);mBanner = (Banner) header.findViewById(R.id.banner);//设置banner的高度为手机屏幕的四分之一mBanner.setLayoutParams(new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, App.H/4));//arrays资源文件存放banner图片的url地址String[] data = getResources().getStringArray(R.array.demo_list);mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));myAdapter = new MyAdapter(this, data);//设置headerviewmyAdapter.setHeaderView(mBanner);mRecyclerView.setAdapter(myAdapter);
  • 然而启动banner:

    mBanner.setImages(App.images)       .setImageLoader(new GlideImageLoader())       .start();

    这里new了一个GlideImageLoader的实例,官方给出的各种图片加载库加载的方式如下:

    public class GlideImageLoader extends ImageLoader {    @Override    public void displayImage(Context context, Object path, ImageView imageView) {        /**          注意:          1.图片加载器由自己选择,这里不限制,只是提供几种使用方法          2.返回的图片路径为Object类型,由于不能确定你到底使用的那种图片加载器,          传输的到的是什么格式,那么这种就使用Object接收和返回,你只需要强转成你传输的类型就行,          切记不要胡乱强转!         */        eg:        //Glide 加载图片简单用法        Glide.with(context).load(path).into(imageView);        //Picasso 加载图片简单用法        Picasso.with(context).load(path).into(imageView);        //用fresco加载图片简单用法,记得要写下面的createImageView方法        Uri uri = Uri.parse((String) path);        imageView.setImageURI(uri);    }    //提供createImageView 方法,如果不用可以不重写这个方法,主要是方便自定义ImageView的创建    @Override    public ImageView createImageView(Context context) {        //使用fresco,需要创建它提供的ImageView,当然你也可以用自己自定义的具有图片加载功能的ImageView        SimpleDraweeView simpleDraweeView=new SimpleDraweeView(context);        return simpleDraweeView;    }}
  • 下拉时,我们需要在轮播图中更新数据,我们需要为SwipeRefreshLayout添加onRefresh()事件:

    private Handler mHandler = new Handler() {    public void handleMessage(android.os.Message msg) {        switch (msg.what) {            case REFRESH_COMPLETE:                String[] urls = getResources().getStringArray(R.array.url);                List list = Arrays.asList(urls);                List arrayList = new ArrayList(list);                //把新的图片地址加载到Banner                mBanner.update(arrayList);                //下拉刷新控件隐藏                mSwipeRefreshLayout.setRefreshing(false);                break;        }    }};.......mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {    @Override    public void onRefresh() {        mHandler.sendEmptyMessageDelayed(REFRESH_COMPLETE, 2000);    }});
  • 在Banner中,我们设置了高度为四分之一屏幕,屏幕的高度是在app一初始化就获取到的,同时,在这里我们用了一个Android Crash的框架Recovery,也没必要用,就是可以把错误反馈到手机上。可以参考这个博客。

    public class App extends Application{    public static int H;    public static List<?> images=new ArrayList<>();    public static List<String> titles=new ArrayList<>();    @Override    public void onCreate() {        super.onCreate();        initBanner();    }    private void initBanner() {        H = getScreenH(this);        Recovery.getInstance()                .debug(true)                .recoverInBackground(false)                .recoverStack(true)                .mainPage(MainActivity.class)                .init(this);        String[] urls = getResources().getStringArray(R.array.url4);        String[] tips = getResources().getStringArray(R.array.title);        List list = Arrays.asList(urls);        images = new ArrayList<>(list);        titles= Arrays.asList(tips);    }    /**     * 获取屏幕高度     * @param aty     * @return     */    public int getScreenH(Context aty){        DisplayMetrics dm = aty.getResources().getDisplayMetrics();        return dm.heightPixels;    }}
  • 最后,看一下我们的运行效果: 

2. Banner的各种动画:

  • Banner的动画都在com.youth.banner.transformer包下,包含下面的这些,相信看名字就知道大概什么效果。

    com.youth.banner.transformer.AccordionTransformer;com.youth.banner.transformer.BackgroundToForegroundTransformer;com.youth.banner.transformer.CubeInTransformer;com.youth.banner.transformer.CubeOutTransformer;com.youth.banner.transformer.DefaultTransformer;com.youth.banner.transformer.DepthPageTransformer;com.youth.banner.transformer.FlipHorizontalTransformer;com.youth.banner.transformer.FlipVerticalTransformer;com.youth.banner.transformer.ForegroundToBackgroundTransformer;com.youth.banner.transformer.RotateDownTransformer;com.youth.banner.transformer.RotateUpTransformer;com.youth.banner.transformer.ScaleInOutTransformer;com.youth.banner.transformer.StackTransformer;com.youth.banner.transformer.TabletTransformer;com.youth.banner.transformer.ZoomInTransformer;com.youth.banner.transformer.ZoomOutSlideTransformer;com.youth.banner.transformer.ZoomOutTranformer;
  • 通过setBannerAnimation()来设置动画。例如,设置为方块滚动;

     ...... mBanner.setImages(App.images)        .setBannerAnimation(CubeOutTransformer.class)        .setImageLoader(new GlideImageLoader())        .start(); ......
  • 效果如下: 

3. Banner的各种内置样式 :

  • Banner内置的样式有以下几种,

    BannerConfig.NOT_INDICATOR       //没有指示器BannerConfig.CIRCLE_INDICATOR    //圆圈指示器(默认)BannerConfig.NUM_INDICATOR       //数字圆盘指示器BannerConfig.NUM_INDICATOR_TITLE //数字圆盘带标题的BannerConfig.CIRCLE_INDICATOR_TITLE  //圆圈指示器附带标题BannerConfig.CIRCLE_INDICATOR_TITLE_INSIDE  //区别于上一个,圆圈指示器在标题栏里
  • 这里我们实现一下圆圈指示器附带标题的样式:

    ArrayList<String> titles = new ArrayList<>(Arrays.asList(new String[]{"first title", "second title", "third title", "fourth title"}));mBanner.setImages(App.images)        .setBannerAnimation(CubeOutTransformer.class)        .setBannerStyle(BannerConfig.CIRCLE_INDICATOR_TITLE)        .setBannerTitles(titles)        .setImageLoader(new GlideImageLoader())        .start();
  • 效果如下: 

4. Banner自定义样式:

  • 自定义banner的属性:

    Attributesformadescribedelay_timeinteger轮播间隔时间,默认2000scroll_timeinteger轮播滑动执行时间,默认800is_auto_playboolean是否自动轮播,默认truetitle_backgroundcolorreferencetitle_textcolorcolor标题字体颜色title_textsizedimension标题字体大小title_heightdimension标题栏高度indicator_widthdimension指示器圆形按钮的宽度indicator_heightdimension指示器圆形按钮的高度indicator_margindimension指示器之间的间距indicator_drawable_selectedreference指示器选中效果indicator_drawable_unselectedreference指示器未选中效果image_scale_typeenum和imageview的ScaleType作用一样

    参照上述属性,现在对指示器设置高宽和选中颜色:

    <com.youth.banner.Banner    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    android:id="@+id/banner"    android:layout_width="match_parent"    android:layout_height="match_parent"    app:indicator_drawable_selected="@color/colorAccent"    app:indicator_drawable_unselected="@android:color/white"    app:indicator_height="4dp"    app:indicator_margin="4dp"    app:indicator_width="20dp"/>
  • 实现效果: 

四、Demo下载:

      源码下载 
原文地址:http://blog.csdn.net/bskfnvjtlyzmv867/article/details/71156080

原创粉丝点击