1. 程式人生 > >Android中LRecyclerView的簡單使用

Android中LRecyclerView的簡單使用

想了解更多的請看GitHub

第一步:填加依賴

Step 1. 在你的根build.gradle檔案中增加JitPack倉庫依賴。

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

Step 2. 在你的module的build.gradle檔案中增加LRecyclerView依賴。

implementation 'com.github.jdsjlzx:LRecyclerView:1.4.3'

第二步:佈局

            <com.github.jdsjlzx.recyclerview.LRecyclerView
                android:id="@+id/lrv"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:layout_behavior="@string/appbar_scrolling_view_behavior">

            </com.github.jdsjlzx.recyclerview.LRecyclerView>

第三步:介面卡Adapter

public class SuperViewHolder extends RecyclerView.ViewHolder {

    private SparseArray<View> views;

    public SuperViewHolder(View itemView) {
        super(itemView);
        this.views = new SparseArray<>();
    }

    @SuppressWarnings("unchecked")
    public <T extends View> T getView(int viewId) {
        View view = views.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            views.put(viewId, view);
        }
        return (T) view;
    }
}
public abstract class ListBaseAdapter<T> extends RecyclerView.Adapter<SuperViewHolder> {

    protected Context mContext;
    private LayoutInflater mInflater;
    protected ArrayList<T> mDataList = new ArrayList<>();


    public ListBaseAdapter(Context mContext) {
        this.mContext = mContext;
        mInflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public SuperViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View itemView = mInflater.inflate(getLayoutId(), parent, false);
        return new SuperViewHolder(itemView);
    }

    @Override
    public void onBindViewHolder(SuperViewHolder holder, int position) {
        onBindItemHolder(holder, position);
    }

    //區域性重新整理關鍵:帶payload的這個onBindViewHolder方法必須實現
    @Override
    public void onBindViewHolder(SuperViewHolder holder, int position, List<Object> payloads) {
        if (payloads.isEmpty()) {
            onBindViewHolder(holder, position);
        } else {
            onBindItemHolder(holder, position, payloads);
        }
    }

    public abstract int getLayoutId();

    public abstract void onBindItemHolder(SuperViewHolder holder, int position);

    public void onBindItemHolder(SuperViewHolder holder, int position, List<Object> payloads){}

    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    /**
     * 獲得資料集合物件
     * @return
     */
    public List<T> getDataList() {
        return mDataList;
    }

    /**
     * 重新輸入集合資料
     * @param list
     */
    public void setDataList(Collection<T> list) {
        this.mDataList.clear();
        this.mDataList.addAll(list);
        notifyDataSetChanged();
    }

    /**
     * 新增一個集合的資料
     * @param list
     */
    public void addAll(Collection<T> list) {
        int lastIndex = this.mDataList.size();
        if (this.mDataList.addAll(list)) {
            notifyItemRangeInserted(lastIndex, list.size());
        }
    }

    /**
     * 新增一條資料
     * @param item
     */
    public void add(T item) {
        int lastIndex = this.mDataList.size();
        if (this.mDataList.add(item)) {
            notifyItemRangeInserted(lastIndex, 1);
        }
    }

    /**
     * 刪除一條資料
     * @param position
     */
    public void remove(int position) {
        this.mDataList.remove(position);
        notifyItemRemoved(position);
        if(position != (getDataList().size())){ // 如果移除的是最後一個,忽略
            notifyItemRangeChanged(position,this.mDataList.size()-position);
        }
    }

    /**
     * 清除資料
     */
    public void clear() {
        mDataList.clear();
        notifyDataSetChanged();
    }
}
public class MyDefaultAdapter extends ListBaseAdapter<String> {//此泛型就是你的資料格式Bean

    public MyDefaultAdapter(Context mContext) {
        super(mContext);
    }

    @Override
    public int getLayoutId() {
        return R.layout.adapter_item;
    }

    @Override
    public void onBindItemHolder(SuperViewHolder holder, int position) {
        TextView textView=holder.getView(R.id.tv);
        textView.setText(mDataList.get(position)+"");
    }

}

第四步:在Activity中實現

        adapter = new MyDefaultAdapter(this);
        lRecyclerViewAdapter = new LRecyclerViewAdapter(adapter);
        adapter.setDataList(list);//重新新增一個集合資料
//      adapter.addAll(allList);//在之前資料的基礎上增加一個集合資料
//      adapter.add("資料");//在之前資料的基礎上增加一條資料
//      adapter.remove(2);//刪除指定下標的一條資料
//      adapter.clear();//清除所有資料
        LinearLayoutManager manager = new LinearLayoutManager(this);
        mLrv.setLayoutManager(manager);
        mLrv.setAdapter(lRecyclerViewAdapter);
  1. MyDefaultAdapter是使用者自己真正的adapter,使用者自己定義;
  2. LRecyclerViewAdapter提供了一些實用的功能,使用者不用關心它的實現,只需構造的時候把自己的adapter以引數形式傳進去即可。

 第五步:程式碼混淆

#LRecyclerview
-dontwarn com.github.jdsjlzx.**
-keep class com.github.jdsjlzx.progressindicator.indicators.** { *; }

 第六步:注意事項

1.如果添加了footerview,不要再使用setLScrollListener方法,如有需要,自定義實現即可。如下面程式碼不要同時使用:

mRecyclerView.setLScrollListener(LScrollListener); 
mLRecyclerViewAdapter.addFooterView(new SampleFooter(this));

2.不要SwipeRefreshLayout與LRecyclerView一起使用,會有衝突,為了更好的滿足廣大使用者,新增了LuRecyclerView類,可以與SwipeRefreshLayout搭配使用,詳細請參考SwipeRefreshLayoutActivity類的實現。

3.關於RecyclerView自動滑動的問題

這個自動滑動歸根結底是焦點問題,子item有焦點,導致RecyclerView自動滑動到了子item,在根佈局上加了android:descendantFocusability="blocksDescendants",根view來處理焦點,不傳給子view就能解決問題。

4.關於LRecyclerView巢狀RecyclerView滑動卡頓的問題

可以參考:https://github.com/jdsjlzx/LRecyclerView/issues/165

 第七步:其他功能

1. 新增HeaderView、FooterView

                View header = LayoutInflater.from(this).inflate(R.layout.sample_header, (ViewGroup) findViewById(android.R.id.content), false);
                lRecyclerViewAdapter.addHeaderView(header);
                View footer = LayoutInflater.from(this).inflate(R.layout.sample_footer, (ViewGroup) findViewById(android.R.id.content), false);
                lRecyclerViewAdapter.addFooterView(footer);

2. 移除HeaderView、FooterView

lRecyclerViewAdapter.removeHeaderView();
lRecyclerViewAdapter.removeFooterView();

注意:如果有兩個以上的HeaderView,連續呼叫mLRecyclerViewAdapter.removeHeaderView()即可。

3. LScrollListener-滑動監聽事件介面

  • onScrollUp()——RecyclerView向上滑動的監聽事件;
  • onScrollDown()——RecyclerView向下滑動的監聽事件;
  • onScrolled()——RecyclerView正在滾動的監聽事件;
  • onScrollStateChanged(int state)——RecyclerView正在滾動的監聽事件;

使用方式

mRecyclerView.setLScrollListener(new LRecyclerView.LScrollListener() {
            @Override
            public void onScrollUp() {
            }

            @Override
            public void onScrollDown() {
            }

            @Override
            public void onScrolled(int distanceX, int distanceY) {
            }
            @Override
            public void onScrollStateChanged(int state) {

            }

        });

4. 下拉重新整理、載入更多

        mLrv.setOnRefreshListener(new OnRefreshListener() {
            @Override
            public void onRefresh() {
                mLrv.refreshComplete(REQUEST_COUNT);//REQUEST_COUNT為每頁重新整理數量
                lRecyclerViewAdapter.notifyDataSetChanged();
            }
        });

        mLrv.setOnLoadMoreListener(new OnLoadMoreListener() {
            @Override
            public void onLoadMore() {
                mLrv.refreshComplete(REQUEST_COUNT);//REQUEST_COUNT為每頁載入數量
                lRecyclerViewAdapter.notifyDataSetChanged();
                //如果沒有更多資料(也就是全部載入完成),加上如下程式碼:
                mRecyclerView.setNoMore(true);
            }
        });

設定下拉重新整理樣式

mRecyclerView.setRefreshProgressStyle(ProgressStyle.BallSpinFadeLoader); //設定下拉重新整理Progress的樣式
mRecyclerView.setArrowImageView(R.drawable.iconfont_downgrey);  //設定下拉重新整理箭頭

5. 設定下拉重新整理Header和Footer文字內容和顏色

//設定頭部載入顏色
mRecyclerView.setHeaderViewColor(R.color.colorAccent, R.color.dark ,android.R.color.white);
//設定底部載入顏色
mRecyclerView.setFooterViewColor(R.color.colorAccent, R.color.dark ,android.R.color.white);
//設定底部載入文字提示
mRecyclerView.setFooterViewHint("拼命載入中","已經全部為你呈現了","網路不給力啊,點選再試一次吧");

6. 開啟和禁止下拉重新整理、載入更多功能

mRecyclerView.setPullRefreshEnabled(true);
mRecyclerView.setLoadMoreEnabled(true);

7. 強制重新整理

mRecyclerView.forceToRefresh();

8. 當載入資料失敗時、網路異常出錯代時碼處理如下:

mRecyclerView.setOnNetWorkErrorListener(new OnNetWorkErrorListener() {
                @Override
                public void reload() {
                    requestData();
                }
            });

9. 點選事件和長按事件處理

mLRecyclerViewAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                
            }

        });

mLRecyclerViewAdapter.setOnItemLongClickListener(new OnItemLongClickListener() {
            @Override
            public void onItemLongClick(View view, int position) {
                
            }
        });

10. 設定空白View(setEmptyView)

mRecyclerView.setEmptyView(view);

11. 關於新增分割線

LinearLayoutManager佈局設定如下:

DividerDecoration divider = new DividerDecoration.Builder(this,mLRecyclerViewAdapter)
                .setHeight(R.dimen.default_divider_height)
                .setPadding(R.dimen.default_divider_padding)
                .setColorResource(R.color.split)
                .build();
mRecyclerView.addItemDecoration(divider);

GridLayoutManager佈局設定如下:

//第一種
int spacing = getResources().getDimensionPixelSize(R.dimen.dp_4);
mRecyclerView.addItemDecoration(SpacesItemDecoration.newInstance(spacing, spacing, manager.getSpanCount(), Color.GRAY));

//第二種
//根據需要選擇使用GridItemDecoration還是SpacesItemDecoration
GridItemDecoration divider = new GridItemDecoration.Builder(this)
        .setHorizontal(R.dimen.default_divider_padding)
        .setVertical(R.dimen.default_divider_padding)
        .setColorResource(R.color.split)
        .build();
//mRecyclerView.addItemDecoration(divider);