recycleview

Brvah在RecyclerView中的使用

2017-08-26  本文已影响500人  Chenyangqi

BRVAH在RecyclerView中的使用


前言

RecyclerView虽然好用但是确实比起ListView使用难度上略大,写过五遍以上的原始的RecyclerView.Adapter后我迫切的打开了全球最大单生交友平台GitHub,寻找BaseAdapter for RecyclerView。然后我找到了BAVAH。哈哈赶快学习一下。
BRVAH github地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper

学习目标

  • 加载普通列表布局
  • item点击事件,item子元素点击事件
  • item设置加载动画
  • 下拉刷新上拉加载
  • RecyclerView添加头部和尾部
  • 多类型item列表
  • 恩 暂时就先这么多吧,后续有新需求再持续更新......

具体实现

先看看效果,实现凤凰新闻客户端新闻列表,包含banner头部和三张item类型的新闻列表,实现底部自动加载更多,下拉刷新。点击item能够进入新闻详情页面

image.png M2YRF_4R__5%AY3RUJ5)YOI.png
image.png

先来看看实现这么一个复杂的列表所使用的adapter代码量有多少:

public class DocNewsAdapter extends BaseMultiItemQuickAdapter<BRVAHActivity.NewsBean, BaseViewHolder> {
    private Context context;
    private List<BRVAHActivity.NewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<BRVAHActivity.NewsBean> list) {
        super(list);
        this.context = context;
        this.list = list;
        addItemType(BRVAHActivity.NewsBean.doc, R.layout.item_doc_news);
        addItemType(BRVAHActivity.NewsBean.slide, R.layout.item_slide_news);
        addItemType(BRVAHActivity.NewsBean.text_live, R.layout.item_textlive_news);
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, BRVAHActivity.NewsBean item) {

        switch (baseViewHolder.getItemViewType()) {

            case BRVAHActivity.NewsBean.doc:
                baseViewHolder.setText(R.id.txt_doc_title, item.docNewsBean.getTitle())
                        .setText(R.id.txt_doc_commentsall, item.docNewsBean.getCommentsall())
                        .setText(R.id.txt_doc_source, item.docNewsBean.getSource())
                        .setText(R.id.txt_doc_updateTime, item.docNewsBean.getUpdateTime());
                Glide.with(context).load(item.docNewsBean.getThumbnail()).placeholder(R.drawable.ic_fh_defals)
                        .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_doc_thumbnail));
                baseViewHolder.addOnClickListener(R.id.img_doc_thumbnail);
                break;
            case BRVAHActivity.NewsBean.slide:
                baseViewHolder.setText(R.id.txt_slide_title, item.slideNewsBean.getTitle())
                        .setText(R.id.txt_slide_commensall, item.slideNewsBean.getCommentsall())
                        .setText(R.id.txt_slide_resource, item.slideNewsBean.getSource());
                for (int i = 0; i < item.slideNewsBean.getStyle().getImages().size(); i++) {
                    if (i == 0)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img1));
                    else if (i == 1)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img2));
                    else if (i == 2)
                        Glide.with(context).load(item.slideNewsBean.getStyle().getImages().get(i)).placeholder(R.drawable.ic_fh_defals)
                                .crossFade().into((ImageView) baseViewHolder.getView(R.id.img_slie_img3));
                }
                break;
            case BRVAHActivity.NewsBean.text_live:
                baseViewHolder.setText(R.id.txt_textlive_title, item.textLiveNewsBean.getTitle());
                Glide.with(context).load(item.textLiveNewsBean.getThumbnail()).placeholder(R.drawable.ic_fh_defals)
                        .centerCrop().into((ImageView) baseViewHolder.getView(R.id.img_textlive_thumbnail));
                break;
        }
    }
}

完成全部功能的activity代码


public class BRVAHActivity extends AppCompatActivity implements BaseQuickAdapter.OnItemClickListener,
        BaseQuickAdapter.OnItemChildClickListener, BaseQuickAdapter.RequestLoadMoreListener, SwipeRefreshLayout.OnRefreshListener {
    Toolbar toolbar;
    LinearLayout container;
    int currentPage = 0, totalPage = 0;
    boolean isRefresh = true;//当前操作是否是下拉刷新
    List<NewsBean> list = new ArrayList<>();
    @BindView(R.id.recyc_news)
    RecyclerView recyclerView;
    DocNewsAdapter adapter;
    @BindView(R.id.swipeRefreshLayout)
    SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_brvah);
        ButterKnife.bind(this);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes();
            localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags);
        }
        toolbar = (Toolbar) findViewById(R.id.tb_toolbar);
        setSupportActionBar(toolbar);
        requestData(currentPage);
        adapter = new DocNewsAdapter(BRVAHActivity.this, list);
        recyclerView.setLayoutManager(new LinearLayoutManager(BRVAHActivity.this));
        recyclerView.setAdapter(adapter);
        //item点击事件
        adapter.setOnItemClickListener(this);
        //item子元素点击事件
        adapter.setOnItemChildClickListener(this);
//        adapter.openLoadAnimation();
        adapter.isFirstOnly(false);
        //adapter设置头部banner
        adapter.addHeaderView(initBanner());
        //自动加载
        adapter.setOnLoadMoreListener(this);
        //上拉刷新
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.rgb(47, 223, 189));
    }

    /**
     * 初始化banner
     */
    private View initBanner() {
        container = (LinearLayout) findViewById(R.id.container);
        View customBanner = LayoutInflater.from(this).inflate(R.layout.custom_banner, container, false);
        ViewGroup viewGroup = (ViewGroup) customBanner;
        Banner banner = (Banner) viewGroup.getChildAt(0);
        banner.setOnBannerListener(new OnBannerListener() {
            @Override
            public void OnBannerClick(int position) {
                Toast.makeText(BRVAHActivity.this, "点击了focus news" + position, Toast.LENGTH_SHORT).show();
            }
        });
        return customBanner;
    }

    /**
     * 请求新闻数据
     *
     * @param page 第几页新闻
     */
    private void requestData(final int page) {
        OkHttpUtils
                .get()
                .url(API.getFh_toutiao() + page)
                .build()
                .execute(new StringCallback() {
                    @Override
                    public void onError(Call call, Exception e, int id) {
                        Toast.makeText(BRVAHActivity.this, "网络请求失败,请检查网络设置", Toast.LENGTH_SHORT).show();
                    }

                    @Override
                    public void onResponse(String response, int id) {
                        JSONObject data = (JSONObject) JSON.parseArray(response).get(0);
                        totalPage = data.getInteger("totalPage");
                        currentPage = data.getInteger("currentPage");
                        JSONArray item = data.getJSONArray("item");
                        for (int i = 0; i < item.size(); i++) {
                            JSONObject newsData = (JSONObject) item.get(i);
                            String newsType = newsData.getString("type");
                            if (newsType.equals("doc")) {
                                DocNewsBean docNewsBean = JSON.parseObject(item.get(i).toString(), DocNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.doc, docNewsBean, null, null);
                                list.add(newsBean);
                            } else if (newsType.equals("slide")) {
                                SlideNewsBean slideNewsBean = JSON.parseObject(item.get(i).toString(), SlideNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.slide, null, slideNewsBean, null);
                                list.add(newsBean);
                            } else if (newsType.equals("text_live")) {
                                TextLiveNewsBean textLiveNewsBean = JSON.parseObject(item.get(i).toString(), TextLiveNewsBean.class);
                                NewsBean newsBean = new NewsBean(NewsBean.text_live, null, null, textLiveNewsBean);
                                list.add(newsBean);
                            }
                        }
                        adapter.notifyDataSetChanged();
                        if (isRefresh) {
                            //结束下拉刷新动画
                            mSwipeRefreshLayout.setRefreshing(false);
                        } else {
                            //结束加载更多动画
                            adapter.loadMoreComplete();
                        }

                    }
                });
    }

    /**
     * item的点击事件
     *
     * @param adapter  设置点击事件的Adapter
     * @param view     item的view
     * @param position item位置
     */
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        Intent intent = new Intent(BRVAHActivity.this, NewsDitailsActivity.class);
        String url = null;
        if (list.get(position).docNewsBean != null)
            url = list.get(position).docNewsBean.getLink().getWeburl();
        else if (list.get(position).slideNewsBean != null)
            url = list.get(position).slideNewsBean.getLink().getWeburl();
        else if (list.get(position).textLiveNewsBean != null)
            url = list.get(position).textLiveNewsBean.getLink().getWeburl();
        intent.putExtra("url", url);
        startActivity(intent);
    }

    /**
     * item子元素点击事件
     *
     * @param adapter
     * @param view
     * @param position
     * @return
     */
    @Override
    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击子元素中的图片" + position, Toast.LENGTH_SHORT).show();
    }


    @Override
    public void onLoadMoreRequested() {
        isRefresh = false;
        if (currentPage < totalPage) {
            requestData(currentPage + 1);
        } else {
            adapter.loadMoreEnd();
        }

    }

    /**
     * 下拉刷新
     */
    @Override
    public void onRefresh() {
        isRefresh = true;
        currentPage = 0;
        list.clear();
        requestData(currentPage);
    }

    /**
     * 包含三种类型的新闻实体
     */
    public class NewsBean implements MultiItemEntity {
        public DocNewsBean docNewsBean;
        public SlideNewsBean slideNewsBean;
        public TextLiveNewsBean textLiveNewsBean;
        private int itemType;
        public static final int doc = 1;
        public static final int slide = 2;
        public static final int text_live = 3;

        public NewsBean(int itemType, DocNewsBean docNewsBean, SlideNewsBean slideNewsBean, TextLiveNewsBean
                textLiveNewsBean) {
            this.docNewsBean = docNewsBean;
            this.slideNewsBean = slideNewsBean;
            this.textLiveNewsBean = textLiveNewsBean;
            this.itemType = itemType;
        }

        @Override
        public int getItemType() {
            return this.itemType;
        }
    }
}

减少了绝大部分adapter代码量,效率还是非常高的。

仿照凤凰新闻客户端头条新闻列表部分,使用RecyclerView+BRVAH实现具有banner头部的新闻列表,具有上拉刷新下拉加载,点击查看新闻详情的功能。凤凰新闻-头条新闻列表如下:
项目使用到的库如下:



dependencies {
    ...
    compile 'com.android.support:recyclerview-v7:26.+'
    compile 'cn.yipianfengye.android:zxing-library:1.1'
    compile 'com.jakewharton:butterknife:8.8.1'
     annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
    compile 'com.zhy:okhttputils:2.6.2'
    compile 'net.qiujuer.genius:ui:2.0.0'
    compile 'net.qiujuer.genius:res:2.0.0'
    compile 'de.hdodenhof:circleimageview:2.1.0'
    compile 'com.github.bumptech.glide:glide:3.7.0'
    testCompile 'junit:junit:4.12'
    compile files('libs/fastjson-1.2.36.jar')
    compile files('libs/glide-3.7.0.jar')
    compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.22'
}


1: 加载普通列表布局

现加载凤凰新闻type为doc的普通新闻数据列表


初始化Adapter,三部曲没啥好说的

adapter = new DocNewsAdapter(BRVAHActivity.this, list);
recyclerView.setLayoutManager(new LinearLayoutManager(BRVAHActivity.this));
recyclerView.setAdapter(adapter);

Adapter实现如下,传入数据绑定即可(R.layout.item_doc_news是item布局,list是新闻数据实体类)

 public class DocNewsAdapter extends BaseQuickAdapter<DocNewsBean, BaseViewHolder> {
    private Context context;
    private List<DocNewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<DocNewsBean> list) {
        super(R.layout.item_doc_news,list);
        this.context = context;
        this.list = list;
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, DocNewsBean item) {
        baseViewHolder.setText(R.id.txt_doc_title, item.getTitle())
                .setText(R.id.txt_doc_commentsall, item.getCommentsall())
                .setText(R.id.txt_doc_source, item.getSource())
                .setText(R.id.txt_doc_updateTime, item.getUpdateTime());
        Glide.with(context).load(item.getThumbnail()).placeholder(R.drawable.ic_fh_defals).crossFade().into((ImageView) baseViewHolder.getView(R.id.img_doc_thumbnail));
    }
}   

效果如如下:

123.png

2:item,item子元素点击事件

activity中调用

        //item点击事件
        adapter.setOnItemClickListener(this);
        //item子元素点击事件
        adapter.setOnItemChildClickListener(this);

/**
     * item的点击事件
     *
     * @param adapter  设置点击事件的Adapter
     * @param view     item的view
     * @param position item位置
     */
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击了第" + position + "个item", Toast.LENGTH_SHORT)
                .show();
    }

    /**
     * item子元素点击事件
     *
     * @param adapter
     * @param view
     * @param position
     * @return
     */
    @Override
    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(BRVAHActivity.this, "点击子元素中的图片" + position, Toast.LENGTH_SHORT).show();
    }

子元素的点击需要再Adapter中进行绑定

/**
 * 新闻列表adapter
 * Created by CYQ on 2017/8/26.
 */
public class DocNewsAdapter extends BaseQuickAdapter<DocNewsBean, BaseViewHolder> {
    private Context context;
    private List<DocNewsBean> list = new ArrayList<>();

    public DocNewsAdapter(Context context, List<DocNewsBean> list) {
        super(R.layout.item_doc_news, list);
        this.context = context;
        this.list = list;
    }

    @Override
    protected void convert(BaseViewHolder baseViewHolder, DocNewsBean item) {
        baseViewHolder.setText(R.id.txt_doc_title, item.getTitle())
                .setText(R.id.txt_doc_commentsall, item.getCommentsall())
                .setText(R.id.txt_doc_source, item.getSource())
                .setText(R.id.txt_doc_updateTime, item.getUpdateTime());
        //为子元素中的图片设置点击事件
        Glide.with(context).load(item.getThumbnail()).placeholder(R.drawable.ic_fh_defals).crossFade().into((ImageView)
                baseViewHolder.getView(R.id.img_doc_thumbnail));
        baseViewHolder.addOnClickListener(R.id.img_doc_thumbnail);
    }
}

这么简单就实现了item和他的子元素的点击事件,比起原生的Adapter少了太多的代码了。


item设置加载动画

个人感觉为item设置动画没太大的实际用途,哈哈BRVAH为item设置动画一行代码搞定

 adapter.openLoadAnimation();

BRVAH为开发者提供了五中默认的动画效果:渐显、缩放、从下到上,从左到右、从右到左通过quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);设置即可


下拉刷新上拉加载

下拉刷新使用Android SDK自带的SwipeRefreshLayout

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyc_news"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
 //上拉刷新
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.rgb(47, 223, 189));
        //............
         /**
     * 下拉刷新
     */
    @Override
    public void onRefresh() {
        //刷新操作
    }

上拉加载

BRVAH提供了自动加载更多的属性,也可以自定义加载更多的view

//上拉自动加载
adapter.setOnLoadMoreListener(this);
...
@Override
    public void onLoadMoreRequested() {
        //加载更多操作
    }

恩就是这么方便就实现了列表上拉加载下拉刷新的功能


添加头部banner
这里我自定义了一个banner轮播View,BRVAH为RecyclerView提供了和listview一样方便的增加头部的功能addHeadView(youHeadView).

adapter.addHeaderView(initBanner());

initBanner();是我自定义的广告banner,返回一个view类型,把他替换成你要add的view就OK。

   /**
     * 初始化banner
     */
    private View initBanner() {
        container = (LinearLayout) findViewById(R.id.container);
        View customBanner = LayoutInflater.from(this).inflate(R.layout.custom_banner, container, false);
        ViewGroup viewGroup = (ViewGroup) customBanner;
        Banner banner = (Banner) viewGroup.getChildAt(0);
        banner.setOnBannerListener(new OnBannerListener() {
            @Override
            public void OnBannerClick(int position) {
                Toast.makeText(BRVAHActivity.this, "点击了focus news" + position, Toast.LENGTH_SHORT).show();
            }
        });
        return customBanner;
    }

多类型item列表

持续更新中。。。。。

上一篇下一篇

猜你喜欢

热点阅读