Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 推薦幾款好用的開源作品(二)之萬能RecyclerView適配器

Android 推薦幾款好用的開源作品(二)之萬能RecyclerView適配器

編輯:關於Android編程

前言:RecyclerView出現已經有一段時間了,我們肯定不陌生了,可以通過導入support-v7對其進行使用。

根據官方的文檔,該控件用於在有限的窗口中展示大量數據集,其實有了它就可以替代ListView、GridView了。

了解RecyclerView架構,可以高度的解耦,異常的靈活,通過設置它提供的不同LayoutManager,ItemDecoration , ItemAnimator可以實現的想要的效果。

1、首先介紹幾種LayoutManager

LinearLayoutManager mManager = new LinearLayoutManager(mContent);
LinearLayoutManager mManager = new LinearLayoutManager(mContent, LinearLayoutManager.VERTICAL, false);//垂直布局,true表示左右翻轉,false不翻轉
GridLayoutManager mManager = new GridLayoutManager(mContent,3);
GridLayoutManager mManager = new GridLayoutManager(mContent,3,LinearLayoutManager.HORIZONTAL,false);//每行3列,水平,true表示左右翻轉,false不翻轉
mRecyclerView.setLayoutManager(mManager);

2、RecycleView簡單使用
//初始化控件
mRecyclerView = findView(R.id.id_recyclerview);
//設置布局管理器
mManager = new LinearLayoutManager(mContent);
mRecyclerView.setLayoutManager(mManager);
//設置adapter
mRecyclerView.setAdapter(mAdapter)
//設置Item增加、移除動畫
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
//添加分割線
mRecyclerView.addItemDecoration(new DividerItemDecoration(
                getActivity(), DividerItemDecoration.HORIZONTAL_LIST));

3、接下來介紹的就是RecyclerView的適配器了,同樣,RecyclerView和ListView,GridView一樣需要adapter來填充數據,同樣,自定義一個adapter需要繼承RecyclerView.Adapter,代碼需要實現幾個父類方法onCreateViewHolder,onBindViewHolder,getItemCount(),根據名字就能知道:
(1)onCreateViewHolder:主要返回的是拿到布局,進而返回ViewHolder

 

return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null));
(2)onBindViewHolder:拿到ViewHolder中的控件對其賦值操作
(3)getItemCount():返回數組的size()

 

public class MyAdapter extends RecyclerView.Adapter {

    class ViewHolder extends RecyclerView.ViewHolder {

        TextView tvTitle,tvContent;

        public ViewHolder(View itemView) {
            super(itemView);
            tvTitle = (TextView) itemView.findViewById(R.id.tv_title);
            tvContent = (TextView) itemView.findViewById(R.id.tv_content);
        }

    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_cell,null));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ViewHolder vh = (ViewHolder) holder;
        CellData cd = data[position];
        vh.tvTitle.setText(cd.title);
        vh.tvContent.setText(cd.content);
    }

    @Override
    public int getItemCount() {
        return data.length;
    }

    private CellData[] data = new CellData[]{new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯"),new CellData("recycleview","學習recycleview"),new CellData("天氣","今天天氣不錯")};
}
4、效果圖,雖然很難看,但是是基本的實現方式。

 

\
可見,RecyclerView和傳統的ListView,GridView使用的流程是一樣的,但是由於RecyclerView的高定制性,使用者越來越多,已經有大部分的開發者放棄使用ListView和GridView了。想要用好RecyclerView也不難,關鍵就在於Adapter的書寫上,接下來介紹一個非常好用的RecyclerView萬能適配器(BaseRecyclerViewAdapterHelper),前幾天接觸到的,感覺十分好用,所包含的功能有以下幾個(官網介紹):

 

  • 優化Adapter代碼(減少百分之70%代碼)
  • 添加點擊item點擊、長按事件、以及item子控件的點擊事件
  • 添加加載動畫(一行代碼輕松切換5種默認動畫)
  • 添加頭部、尾部、下拉刷新、上拉加載(感覺又回到ListView時代)
  • 設置自定義的加載更多布局
  • 添加分組(隨心定義分組頭部)
  • 自定義不同的item類型(簡單配置、無需重寫額外方法)
  • 設置空布局(比Listview的setEmptyView還要好用!)
  • 添加拖拽item

 

1、添加item點擊、長按事件

 

mQuickAdapter.setOnRecyclerViewItemClickListener();
mQuickAdapter.setOnRecyclerViewItemLongClickListener();
2、新增添加子布局多個控件的點擊事件
Adapter

 

 

protected void convert(BaseViewHolder helper, Status item) {
    helper.setOnClickListener(R.id.tweetAvatar, new OnItemChildClickListener())
      .setOnClickListener(R.id.tweetName, new OnItemChildClickListener());
      }
Activity

 

 

mQuickAdapter.setOnRecyclerViewItemChildClickListener(new BaseQuickAdapter.OnRecyclerViewItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                String content = null;
                Status status = (Status) adapter.getItem(position);
                switch (view.getId()) {
                    case R.id.tweetAvatar:
                        content = "img:" + status.getUserAvatar();
                        break;
                    case R.id.tweetName:
                        content = "name:" + status.getUserName();
                        break;
                }
                Toast.makeText(AnimationUseActivity.this, content, Toast.LENGTH_LONG).show();
            }
        });
3、添加動畫

 

 

// 一行代碼搞定(默認為漸顯效果)
quickAdapter.openLoadAnimation();
// 默認提供5種方法(漸顯、縮放、從下到上,從左到右、從右到左)
quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);
// 自定義動畫如此輕松
quickAdapter.openLoadAnimation(new BaseAnimation() {
                            @Override
                            public Animator[] getAnimators(View view) {
                                return new Animator[]{
                                        ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
                                        ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
                                };
                            }
                        });
4、添加頭部和尾部

 

 

mQuickAdapter.addHeaderView(getView());
mQuickAdapter.addFooterView(getView());
5、上拉加載更多
mQuickAdapter.openLoadMore(PAGE_SIZE, true);//必須設置pageSize,否則上拉不會加載,pageSize一般為每次請求需要加載的數據條數
mQuickAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
            @Override
            public void onLoadMoreRequested() {
                mRecyclerView.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mCurrentCounter >= TOTAL_COUNTER) {
                            mQuickAdapter.notifyDataChangedAfterLoadMore(false);
                        } else {
                            mQuickAdapter.notifyDataChangedAfterLoadMore(DataServer.getSampleData(PAGE_SIZE), true);
                            mCurrentCounter = mQuickAdapter.getItemCount();
                        }
                    }

                });
            }
        });
可以通過mQuickAdapter.setLoadingView(customView);自定義加載更多的布局

 

6、使用分組

public class SectionAdapter extends BaseSectionQuickAdapter {
     public SectionAdapter(int layoutResId, int sectionHeadResId, List data) {
        super(layoutResId, sectionHeadResId, data);
    }
    @Override
    protected void convert(BaseViewHolder helper, MySection item) {
        helper.setImageUrl(R.id.iv, (String) item.t);
    }
    @Override
    protected void convertHead(BaseViewHolder helper,final MySection item) {
        helper.setText(R.id.header, item.header);
        else
        helper.setOnClickListener(R.id.more, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show();
            }
        });
    }
7、添加多種類型Item

 

 

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter {

    public MultipleItemQuickAdapter(List data) {
        super(data);
        addItemType(MultipleItem.TEXT, R.layout.text_view);
        addItemType(MultipleItem.IMG, R.layout.image_view);
    }

    @Override
    protected void convert(BaseViewHolder helper, MultipleItem item) {
        switch (helper.getItemViewType()) {
            case MultipleItem.TEXT:
                helper.setImageUrl(R.id.tv, item.getContent());
                break;
            case MultipleItem.IMG:
                helper.setImageUrl(R.id.iv, item.getContent());
                break;
        }
    }

}
8、使用setEmptyView

 

 

mQuickAdapter.setEmptyView(getView());
9、使用拖拽與滑動刪除

 

 

OnItemDragListener onItemDragListener = new OnItemDragListener() {
    @Override
    public void onItemDragStart(RecyclerView.ViewHolder viewHolder, int pos){}
    @Override
    public void onItemDragMoving(RecyclerView.ViewHolder source, int from, RecyclerView.ViewHolder target, int to) {}
    @Override
    public void onItemDragEnd(RecyclerView.ViewHolder viewHolder, int pos) {}
}

OnItemSwipeListener onItemSwipeListener = new OnItemSwipeListener() {
    @Override
    public void onItemSwipeStart(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public void clearView(RecyclerView.ViewHolder viewHolder, int pos) {}
    @Override
    public void onItemSwiped(RecyclerView.ViewHolder viewHolder, int pos) {}
};

ItemDragAndSwipeCallback itemDragAndSwipeCallback = new ItemDragAndSwipeCallback(mAdapter);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(itemDragAndSwipeCallback);
itemTouchHelper.attachToRecyclerView(mRecyclerView);

// 開啟拖拽
mAdapter.enableDragItem(itemTouchHelper, R.id.textView, true);
mAdapter.setOnItemDragListener(onItemDragListener);

// 開啟滑動刪除
mAdapter.enableSwipeItem();
mAdapter.setOnItemSwipeListener(onItemSwipeListener);

 

 

感覺每一個功能都很實用,目前也在努力在項目中進行測試使用。

最常用的莫過於下拉刷新,上拉加載的,基本每個頁面都會用到刷新,需要分頁的頁面還會用到加載。曾經搜了下網上的相關於這方面的資源,感覺基本沒有將RecyclerView配合SwipeRefreshLayout做到很好能刷新和加載的。其他的都是自定義的ListView 和GridView實現的刷新和加載,由於不太想用ListView了,所以就換成了RecyclerView,閒淡少扯,實戰繼續。

先上圖:

\
 

需求分析:通過接口返回的數據需要進行分頁

{ "code": 1, "pageCount": 33, "list": [ { "province": "XX省", "city": "XX市", "address": "XX區XX路", "scan_time": "2016/7/9 10:30:44", "product_id": "1", "product_name": "MOOKA4K電視U55H3", "product_small_image": "http://cdn02.ehaier.com/product/561f4f031671c47b688b4851_80_80.jpg", "eancode": "6925876304318", "sn": "DH1TV0A0701HUF530144" } ] }


Adapter

 

 

public class QuickAdapter extends BaseQuickAdapter {


    private ImageLoader imageLoader = ImageLoader.getInstance();

    public QuickAdapter(List data) {
        super(data);
    }

    public QuickAdapter(int layoutResId, List data) {
        super(layoutResId, data);
    }

    @Override
    protected void convert(BaseViewHolder helper, ScanRecordRowEntity item) {
        helper.setText(R.id.tv_product_name, item.getProduct_name())
                .setText(R.id.tv_time, item.getScan_time())
                .setText(R.id.tv_place, item.getProvince() + item.getCity());

//        imageLoader.displayImage(item.getProduct_small_image(), (ImageView) helper.getView(R.id.img_product_logo), ImageLoaderUtils.getDefaultOptions());

        Glide.with(mContext)
                .load(item.getProduct_small_image())
                .fitCenter()
                .placeholder(R.drawable.ic_product_default)
                .crossFade()
                .into((ImageView) helper.getView(R.id.img_product_logo));
    }

}

Activity

 

 

public class ScanRecordTestActivity extends BaseActivity implements SwipeRefreshLayout.OnRefreshListener, BaseQuickAdapter.RequestLoadMoreListener {


    private List list = new ArrayList<>();
    private String encode;
    private SwipeRefreshLayout mSwipeRefreshLayout;
    private RecyclerView mRecyclerView;
    private QuickAdapter mQuickAdapter;
    private int pageCount = 1;//分頁返回總頁數
    private int page = 1;//當前請求頁為第一頁
    private int pageSize = 10;//每次請求10條記錄


    @Override
    protected void initView() {
        setContentView(R.layout.activity_scan_record_test);
        setBack();
        setTitle("掃描記錄");
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.id_swiperefresh);
        RefreshUtil.setSwipeRefreshColor(mSwipeRefreshLayout);//設置刷新框顏色
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recycleview);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        initAdapter();
        mRecyclerView.setAdapter(mQuickAdapter);

    }

    private void initAdapter() {
        mQuickAdapter = new QuickAdapter(R.layout.item_scan_record, list);
        mQuickAdapter.openLoadAnimation();
        mRecyclerView.setAdapter(mQuickAdapter);
        mQuickAdapter.setOnLoadMoreListener(this);
        mQuickAdapter.setOnRecyclerViewItemClickListener(new BaseQuickAdapter.OnRecyclerViewItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                Toasters(Integer.toString(position));
            }
        });
    }

    @Override
    protected void initData() {
        encode = getIntent().getStringExtra("encode");
        if (NetUtil.isNetConnected(mContext)) {
            RefreshUtil.setSwipeRefreshLoadingState(mSwipeRefreshLayout);//設置首次加載數據時顯示加載框
            getRecord();
        } else {
            Toasters("無網絡連接!");
        }
    }

    @Override
    protected void setOnClickEvent() {
    }


    private void getRecord() {
        String url = Constant.GET_SCAN_RECORD + encode + "?rows=" + pageSize + "&page=" + page + "&type";
        webHttpconnection.getValue(url, 1);
    }

    private void LoadMore(final int page) {
        String url = Constant.GET_SCAN_RECORD + encode + "?rows=" + pageSize + "&page=" + page + "&type";
        webHttpconnection.getValue(url, 2);
    }

    @Override
    public void onRefresh() {
        page = 1;
        getRecord();
    }

    @Override
    public void onLoadMoreRequested() {
        if (page < pageCount) {
            page = page + 1;
            LoadMore(page);
        }
    }

    @Override
    public void requestJsonOnSucceed(String json, int msgFlag) {
        super.requestJsonOnSucceed(json, msgFlag);
        ScanRecordEntity entity;
        switch (msgFlag) {
            case 1:
                RefreshUtil.setSwipeRefreshLoadedState(mSwipeRefreshLayout);
                entity = JSON.parseObject(json, ScanRecordEntity.class);
                if (1 == entity.getCode() && null != entity.getList()) {
                    pageCount = entity.getPageCount();
                    mQuickAdapter.setNewData(entity.getList());
                    if (pageCount > 1) {
                        mQuickAdapter.openLoadMore(pageSize, true);
                        mQuickAdapter.notifyDataChangedAfterLoadMore(true);
                    }
                } else {
                    Toasters("無掃描記錄!");
                }
                break;
            case 2:
                entity = JSON.parseObject(json, ScanRecordEntity.class);
                if (1 == entity.getCode() && null != entity.getList()) {
                    mQuickAdapter.addData(entity.getList());
                }
                if (pageCount == page) {
                    mQuickAdapter.notifyDataChangedAfterLoadMore(false);
                    View view = getLayoutInflater().inflate(R.layout.not_loading, (ViewGroup) mRecyclerView.getParent(), false);
                    mQuickAdapter.addFooterView(view);
                } else {
                    mQuickAdapter.notifyDataChangedAfterLoadMore(true);
                }
                break;
        }
    }

    @Override
    public void requestJsonOnError(int msgFlag) {
        super.requestJsonOnError(msgFlag);
        Toasters("網絡不可用");
    }

BaseRecyclerViewAdapterHelper開源地址:https://github.com/CymChad/BaseRecyclerViewAdapterHelper,後續還會進行研究。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved