RV BaseRecyclerViewAdapterHelper 總結 MD


Markdown版本筆記 我的GitHub首頁 我的博客 我的微信 我的郵箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

RV BaseRecyclerViewAdapterHelper 總結 MD


目錄

介紹

項目地址
文檔
網站

添加依賴

allprojects {
    repositories {
        ...
        maven { url "https://jitpack.io" }
    }
}
compile 'com.github.CymChad:BaseRecyclerViewAdapterHelper:VERSION_CODE'

這里 的真實發行版本號, 替換 VERSION_CODE(2017-6最新版本號:2.9.18)。

功能一覽

優化Adapter代碼

使用代碼

public class QuickAdapter extends BaseQuickAdapter<Status, BaseViewHolder> {
    public QuickAdapter(List data) {
        super(R.layout.tweet, data);
    }

    @Override
  protected void convert(BaseViewHolder viewHolder, Status item) {
        viewHolder.setText(R.id.tweetName, item.getUserName())
                .setVisible(R.id.tweetRT, item.isRetweet())
                .linkify(R.id.tweetText);
                 Glide.with(mContext).load(item.getUserAvatar()).crossFade().into((ImageView) helper.getView(R.id.iv));
    }
}
  • 繼承BaseQuickAdapter基類, 泛型為List的數據類型
  • 重寫convert方法,通過viewHolder.點出各種常用方法,如果有自定義控件或者viewHolder沒有提供的方法,就可以通過getView方法來實現獲取控件,然后進行的操作。
  • 如果需要獲取當前position可以通過viewHolder.getLayoutPosition()來獲取

Item的點擊事件

adapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
    @Override
    public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(ItemClickActivity.this, "onItemClick" + position, Toast.LENGTH_SHORT).show();
    }
});
adapter.setOnItemLongClickListener(BaseQuickAdapter.OnItemLongClickListener);
adapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
    @Override
    public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
        Toast.makeText(ItemClickActivity.this, "onItemChildClick" + position, Toast.LENGTH_SHORT).show();
    }
});
mRecyclerView.addOnItemTouchListener(new OnItemClickListener() {
    @Override
    public void onSimpleItemClick(final BaseQuickAdapter adapter, final View view, final int position) {
        Toast.makeText(ItemClickActivity.this, "onSimpleItemClick" + position, Toast.LENGTH_LONG).show();
    }
});

添加列表加載動畫

默認漸顯效果:quickAdapter.openLoadAnimation();
漸顯、縮放、從下到上,從左到右、從右到左:quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);
默認動畫每個item只執行一次,如果想重復執行動畫可以調用一下方法:mQuickAdapter.isFirstOnly(false);

自定義動畫

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)
        };
    }
});

添加頭部、尾部

  • 使用代碼 添加頭部、尾部 mQuickAdapter.addHeaderView(getView());
  • 刪除指定頭部、尾部 mQuickAdapter.removeHeaderView(getView);
  • 刪除所有頭部、尾部 mQuickAdapter.removeAllHeaderView();
  • 擴展方法 setHeaderAndEmpty
  • 設置頭部、尾部不占一行(使用場景:gv的頭部添加一個"+"號) setHeaderViewAsFlow

加載更多

  • 加載更多:setOnLoadMoreListener() //滑動最后一個Item的時候回調
  • 加載完成:mQuickAdapter.loadMoreComplete();
  • 加載失敗:mQuickAdapter.loadMoreFail();
  • 沒有更多數據:mQuickAdapter.loadMoreEnd();
  • 打開或關閉加載:mQuickAdapter.setEnableLoadMore(boolean);
  • 預加載:mQuickAdapter.setAutoLoadMoreSize(int);// 當列表滑動到倒數第N個Item的時候(默認是1)回調onLoadMoreRequested方法
  • 檢查是否滿一屏,如果不滿足關閉loadMore:mQuickAdapter.disableLoadMoreIfNotFullPage();
  • 設置自定義加載布局:mQuickAdapter.setLoadMoreView(new LoadMoreView());
mQuickAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {
    @Override 
    public void onLoadMoreRequested() {
        mRecyclerView.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (mCurrentCounter >= TOTAL_COUNTER) {
                    //數據全部加載完畢
                    mQuickAdapter.loadMoreEnd();
                } else {
                    if (isErr) {
                        //成功獲取更多數據
                        mQuickAdapter.addData(DataServer.getSampleData(PAGE_SIZE));
                        mCurrentCounter = mQuickAdapter.getData().size();
                        mQuickAdapter.loadMoreComplete();
                    } else {
                        //獲取更多數據失敗
                        isErr = true;
                        mQuickAdapter.loadMoreFail();
                    }
                }
            }
        }, delayMillis);
    }
}, mReyclerView);

注意:如果上拉結束后,下拉刷新需要再次開啟上拉監聽,需要使用setNewData方法填充數據。

自定義加載布局

設置自定義加載布局:mQuickAdapter.setLoadMoreView(new LoadMoreView());

public final class CustomLoadMoreView extends LoadMoreView {

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

    /**
     * 如果返回true,數據全部加載完畢后會隱藏加載更多
     * 如果返回false,數據全部加載完畢后會顯示getLoadEndViewId()布局
     */
    @Override 
    public boolean isLoadEndGone() {
        return true;
    }

    @Override protected int getLoadingViewId() {
        return R.id.load_more_loading_view;
    }

    @Override 
    protected int getLoadFailViewId() {
        return R.id.load_more_load_fail_view;
    }

    /**
     * isLoadEndGone()為true,可以返回0,為false,不能返回0
     */
    @Override 
    protected int getLoadEndViewId() {
        return 0;
    }
}
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="@dimen/dp_40">
    <LinearLayout
        android:id="@+id/load_more_loading_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="horizontal">
        <ProgressBar
            android:id="@+id/loading_progress"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="?android:attr/progressBarStyleSmall"
            android:layout_marginRight="@dimen/dp_4"
            android:indeterminateDrawable="@drawable/sample_footer_loading_progress"/>
        <TextView
            android:id="@+id/loading_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/dp_4"
            android:text="@string/loading"
            android:textColor="#0dddb8"
            android:textSize="@dimen/sp_14"/>
    </LinearLayout>
    <FrameLayout
        android:id="@+id/load_more_load_fail_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone">
        <TextView
            android:id="@+id/tv_prompt"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:textColor="#0dddb8"
            android:text="@string/load_failed"/>
    </FrameLayout>
</FrameLayout>

添加分組

實體類必須繼承SectionEntity

public class MySection extends SectionEntity<Video> {
    private boolean isMore;
    public MySection(boolean isHeader, String header) {
        super(isHeader, header);
    }
    public MySection(Video t) {
        super(t);
    }
}

adapter構造需要傳入兩個布局id,第一個是item的,第二個是head的,在convert方法里面加載item數據,在convertHead方法里面加載head數據

public class SectionAdapter extends BaseSectionQuickAdapter<MySection> {
  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);
        helper.setOnClickListener(R.id.more, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(context,item.header+"more..",Toast.LENGTH_LONG).show();
            }
        });
    }
}

自定義不同的item類型

實體類必須實現MultiItemEntity,在設置數據的時候,需要給每一個數據設置itemType

public class MultipleItem implements MultiItemEntity {
    public static final int TEXT = 1;
    public static final int IMG = 2;
    private int itemType;

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

在構造里面addItemType綁定type和layout的關系

public class MultipleItemQuickAdapter extends BaseMultiItemQuickAdapter<MultipleItem, BaseViewHolder> {

    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;
        }
    }

}

如有多布局有兩行布局的item都是一樣的,這個時候item是可以被復用的,我們可以使用GridLayoutManager

multipleItemAdapter.setSpanSizeLookup(new BaseQuickAdapter.SpanSizeLookup() {
   @Override
    public int getSpanSize(GridLayoutManager gridLayoutManager, int position) {
        return data.get(position).getSpanSize();
    }
});

通過重寫他的SapnSize來重用ImageView。 假設GridLayoutManager的spanCount是3,那么第一個、第二個、item的spanSize就是3,因為要占據一行(和權重差不多的意思),然后第三個、第四個、第五個、item的spanSize就是1。

設置空布局

mQuickAdapter.setEmptyView(getView());

添加拖拽、滑動刪除

拖拽和滑動刪除的回調方法

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) {}
};

adapter需要繼承BaseItemDraggableAdapter

public class ItemDragAdapter extends BaseItemDraggableAdapter<String, BaseViewHolder> {
    public ItemDragAdapter(List data) {
        super(R.layout.item_draggable_view, data);
    }

    @Override
  protected void convert(BaseViewHolder helper, String item) {
        helper.setText(R.id.tv, item);
    }
}

Activity使用代碼

mAdapter = new ItemDragAdapter(mData);

ItemTouchHelper itemTouchHelper = new ItemTouchHelper(new ItemDragAndSwipeCallback(mAdapter));
itemTouchHelper.attachToRecyclerView(mRecyclerView);
// 開啟拖拽
mAdapter.enableDragItem(itemTouchHelper, R.id.textView, true);
mAdapter.setOnItemDragListener(onItemDragListener);
// 開啟滑動刪除
mAdapter.enableSwipeItem();
mAdapter.setOnItemSwipeListener(onItemSwipeListener);

默認不支持多個不同的 ViewType 之間進行拖拽,如果開發者有所需求,重寫ItemDragAndSwipeCallback里的onMove()方法,return true即可

分組的伸縮欄

代碼

// if you don't want to extent a class, you can also use the interface IExpandable. AbstractExpandableItem is just a helper class.
public class Level0Item extends AbstractExpandableItem<Level1Item> {...}
public class Level1Item extends AbstractExpandableItem<Person> {...}
public class Person {...}

adapter需要繼承BaseMultiItemQuickAdapter

public class ExpandableItemAdapter extends BaseMultiItemQuickAdapter<MultiItemEntity, BaseViewHolder> { 
    public ExpandableItemAdapter(List<MultiItemEntity> data) {    
        super(data);
        addItemType(TYPE_LEVEL_0, R.layout.item_expandable_lv0);   
        addItemType(TYPE_LEVEL_1, R.layout.item_expandable_lv1);    
        addItemType(TYPE_PERSON, R.layout.item_text_view);
    }
    @Override
  protected void convert(final BaseViewHolder holder, final MultiItemEntity item) {
        switch (holder.getItemViewType()) {
        case TYPE_LEVEL_0:
            ....
      //set view content
           holder.itemView.setOnClickListener(new View.OnClickListener() {
               @Override
        public void onClick(View v) {
                   int pos = holder.getAdapterPosition();
                   if (lv0.isExpanded())  collapse(pos);
                   else expand(pos);
           }});
           break;
        case TYPE_LEVEL_1: // similar with level 0
      break;
        case TYPE_PERSON: //just set the content
      break;
    }
}

Activity使用代碼

public class ExpandableUseActivity extends Activity {
    @Override
  protected  void onCreate(Bundle savedInstanceState) {
        ...
    ArrayList<MultiItemEntity> list = generateData();
        ExpandableItemAdapter adapter = new ExpandableItemAdapter(list);
        mRecyclerView.setAdapter(adapter);
    }

    private ArrayList<MultiItemEntity> generateData() {
        ArrayList<MultiItemEntity> res = new ArrayList<>();
        for (int i = 0; i < lv0Count; i++) {
            Level0Item lv0 = new Level0Item(...);
            for (int j = 0; j < lv1Count; j++) {
                Level1Item lv1 = new Level1Item(...);
                for (int k = 0; k < personCount; k++) {
                    lv1.addSubItem(new Person());
                }
                lv0.addSubItem(lv1);
            }
            res.add(lv0);
        }
        return res;
    }
}

自定義BaseViewHolder

之前的寫法:public class QuickAdapter extends BaseQuickAdapter
現在的寫法:public class QuickAdapter extends BaseQuickAdapter
注意:需要單獨建一個外部類繼承BaseViewHolder,否則部分機型會出現ClassCastException

案例

public class BRVAHActivity extends Activity implements BaseQuickAdapter.RequestLoadMoreListener, SwipeRefreshLayout.OnRefreshListener {
    private List<String> mDatas;
    private RecyclerView mRecyclerView;
    private PullToRefreshAdapter mAdapter;
    private SwipeRefreshLayout mSwipeRefreshLayout;
​
    private static final int TOTAL_COUNTER = 18;
    private static final int PAGE_SIZE = 6;
    private static final int DELAY_MILLIS = 1000;
    private int mCurrentCounter = 0;
​
    private boolean isErr;
    private boolean mLoadMoreEndGone = false;
​
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
​
        setContentView(R.layout.activity_main);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeLayout);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.setColorSchemeColors(Color.rgb(47, 223, 189));
​
        mRecyclerView = (RecyclerView) findViewById(R.id.rv);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
​
        initDate();
        initAdapter();
​
        ImageView headView = new ImageView(this);
        headView.setImageResource(R.mipmap.ic_launcher);
        mAdapter.addHeaderView(headView);
    }
​
    private void initDate() {
        mDatas = new ArrayList<String>();
        for (int i = 'A'; i < 'z'; i++) {
            mDatas.add("" + (char) i);
        }
    }
​
    private void initAdapter() {
        mAdapter = new PullToRefreshAdapter();
        mAdapter.setOnLoadMoreListener(this, mRecyclerView);
        mAdapter.openLoadAnimation(BaseQuickAdapter.SLIDEIN_RIGHT);//動畫
        mAdapter.setPreLoadNumber(3);//預加載
        mRecyclerView.setAdapter(mAdapter);
        mCurrentCounter = mAdapter.getData().size();
​
        //item點擊事件
        mAdapter.setOnItemClickListener(new BaseQuickAdapter.OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(BRVAHActivity.this, "onItemClick" + position, Toast.LENGTH_SHORT).show();
            }
        });
        //item中View的點擊事件
        mAdapter.setOnItemChildClickListener(new BaseQuickAdapter.OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                Toast.makeText(BRVAHActivity.this, "onItemChildClick" + position, Toast.LENGTH_SHORT).show();
            }
        });
    }
​
    @Override
    public void onLoadMoreRequested() {
        mSwipeRefreshLayout.setEnabled(false);
        if (mAdapter.getData().size() < PAGE_SIZE) {
            mAdapter.loadMoreEnd(true);
        } else {
            if (mCurrentCounter >= TOTAL_COUNTER) {
                //pullToRefreshAdapter.loadMoreEnd();//default visible
                mAdapter.loadMoreEnd(mLoadMoreEndGone);//true is gone,false is visible
            } else {
                if (isErr) {
                    mAdapter.addData("新數據");
                    mCurrentCounter = mAdapter.getData().size();
                    mAdapter.loadMoreComplete();
                } else {
                    isErr = true;
                    Toast.makeText(BRVAHActivity.this, "錯誤", Toast.LENGTH_LONG).show();
                    mAdapter.loadMoreFail();
                }
            }
            mSwipeRefreshLayout.setEnabled(true);
        }
    }
​
    @Override
    public void onRefresh() {
        mAdapter.setEnableLoadMore(false);//禁止加載
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                mAdapter.setNewData(mDatas);
                isErr = false;
                mCurrentCounter = PAGE_SIZE;
                mSwipeRefreshLayout.setRefreshing(false);
                mAdapter.setEnableLoadMore(true);//啟用加載
            }
        }, DELAY_MILLIS);
    }
​
    class PullToRefreshAdapter extends BaseQuickAdapter<String, BaseViewHolder> {
        public PullToRefreshAdapter() {
            super(R.layout.item2, mDatas);
        }
​
        @Override
        protected void convert(BaseViewHolder helper, String item) {
            helper.setText(R.id.id_num, item)
                    .setImageResource(R.id.iv, R.drawable.actionbar_add_icon)
                    .addOnClickListener(R.id.iv);
        }
    }
}

2017-5-31


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM