RecyclerView 之通用適配

本篇來自:https://blog.csdn.net/u012551350/article/details/52026740


RecyclerView 是Android L版本中新添加的一個用來取代ListView的SDK壁晒,它的靈活性與可替代性比listview更好鲤屡。RecyclerView 同樣也用到適配岗钩,枯燥重復(fù)的適配肯定會讓你不勝其煩,下面讓我們一起來打造一款通用的適配(BaseQuickAdapter)填具。受益群體幾乎是所有Android開發(fā)者,希望更你們能夠一起來維護這個項目,把這個項目做得更好劳景,幫助更多人誉简。

看到這里你肯定會有疑問,通用適配(BaseQuickAdapter)盟广,它具體能夠做些什么呢闷串,或者說它都有哪些功能?

這里非常感謝?陳宇明

本文結(jié)合他文章和我的一些修改筋量,希望大家能夠喜歡烹吵。

一、BaseQuickAdapter 簡介

1桨武、減少重復(fù) Adapter 代碼
2肋拔、添加 Item 的點擊事件,長按事件以及子控件的點擊事件
3呀酸、添加頭部凉蜂、尾部,下拉刷新性誉、上拉加載(上拉加載的5種加載更多動畫任你選擇窿吩,后期會添加更多的加載動畫)、沒有更多數(shù)據(jù)
4错览、可以自定義頭部纫雁、尾部、加載更多布局
5蝗砾、添加 Item滑動動畫 (9種動畫切換先较,輕松一行代碼)
6、添加新增悼粮、刪除 Item動畫 (目前支持默認的動畫方式)
7闲勺、網(wǎng)格,列表扣猫,流式隨意切換
8菜循、添加空布局(列表無數(shù)據(jù)時,顯示更加人性化)
9申尤、拖拽和側(cè)滑刪除
10癌幕、支持多類型布局
11、類似淘寶列表切換
12昧穿、字母導(dǎo)航
13勺远、類似探探翻牌

看了 BaseQuickAdapter 的特性,接著來看看外面如何在項目中導(dǎo)入(依賴)它时鸵。

BaseQuickAdapter 導(dǎo)入(依賴)

方式一:build.gradle 的 dependencies 添加如下代碼:

//最新代碼還沒更新到 jcenter 倉庫胶逢,推薦使用方法二依賴項目
compile 'com.github.baserecycleradapter:library:1.1.0'

方式二:下載源碼厅瞎,添加?library?庫到你項目當中。

這里推薦使用方法二依賴進項目初坠。

BaseQuickAdapter 使用

mRecyclerView.setAdapter(mAdapter = new BaseQuickAdapter(R.layout.rv_item, getItemDatas()) {
@Override
protected void convert(final BaseViewHolder helper, String item) {
?helper.setText(R.id.tv_item_text, item);
?}
?});

Item點擊和簸,長按事件

//Item 點擊事件
setOnItemClickListener(int viewId, AdapterView.OnItemClickListener listener)
//長按事件
setOnItemLongClickListener(int viewId, AdapterView.OnItemLongClickListener listener)

子控件的點擊事件

helper.setOnClickListener(R.id.tv_item_text, new View.OnClickListener() {

? ? ? @Override? ? ? public void onClick(View v) {

? ? ? ? ? //事件處理? ? ? }

? });

添加頭部,尾部

//頭部 mAdapter.addHeaderView();

?//尾部? ? mAdapter.addFooterView();

以下是添加頭部的代碼:

View headerView=getLayoutInflater().inflate(R.layout.rv_header, null);
headerView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT));
mAdapter.addHeaderView(headerView);

部的添加與頭部的添加類似碟刺。

添加 Item動畫

//一行代碼開啟動畫 默認CUSTOM動畫?
mAdapter.openLoadAnimation(BaseQuickAdapter.CUSTOMIN);

當然你可以更換其他動畫:

//ALPHAIN, SCALEIN, SLIDEIN_BOTTOM, SLIDEIN_LEFT, SLIDEIN_RIGHT, //SLIDEIN_LEFT_RIGHT, SLIDEIN_BOTTOM_TOP, CUSTOMIN

mAdapter.openLoadAnimation(BaseQuickAdapter.CUSTOMIN);

最后你可以自定義 Item動畫:

mAdapter.openLoadAnimation(new BaseAnimation[]{
? ? ? ? new BaseAnimation() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public Animator[] getAnimators(View view) {
? ? ? ? ? ? ? ? return new Animator[]{
? ? ? ? ? ? ? ? ? ? ? ?ObjectAnimator.ofFloat(view, "alpha", 0.5f, 1.0f),
? ? ? ? ? ? ? ? ? ? ? ?ObjectAnimator.ofFloat(view, "scaleX", 0.5f, 1.0f)};
? ? ? ? ? ? }
? ? ? ? }
});

設(shè)置加載更多

只需要設(shè)置加載更多接口锁保,就可以實現(xiàn)加載更多功能。

mAdapter.setOnLoadMoreListener(new BaseQuickAdapter.RequestLoadMoreListener() {

? ? ? ? @Override
? ? ? ? public void onLoadMoreRequested() {

? ? ? ? }

? ? });

以下演示正在加載中半沽,加載失敗點擊重試爽柒,加載完成等狀態(tài):

mShowType++;
? ? if (mShowType == 2) {
? ? ? ? mHandler.postDelayed(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ?//加載失敗,點擊重試
? ? ? ? ? ? ? ? mAdapter.loadMoreFail();
? ? ? ? ? ? }
? ? ? ? }, DELAY_MILLIS);
? ? } else if (mShowType >= 4) {
? ? ? ? mHandler.post(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? //加載完成
? ? ? ? ? ? ? ? mAdapter.loadMoreEnd();
? ? ? ? ? ? }
? ? ? ? });
? ? } else {
? ? ? ? mHandler.postDelayed(new Runnable() {
? ? ? ? ? ? @Override
? ? ? ? ? ? public void run() {
? ? ? ? ? ? ? ? mAdapter.addData(addDatas());
? ? ? ? ? ? ? ? //加載更多完成
? ? ? ? ? ? ? ? mAdapter.loadMoreComplete();
? ? ? ? ? ? }
? ? ? ? }, DELAY_MILLIS);
? ? }

你可以設(shè)置加載更多類型抄囚,只需要添加一行代碼霉赡,實現(xiàn)不同的加載更多動畫:

//設(shè)置加載更多 loadingview
setLoadMoreType(@LoadMoreTypeintloadMoreType)

這里有四種模式供你選擇,APAY, BALL_BEAT, BALL_CLIP_ROTATE, BALL_SCALE幔托,如果都不滿足你的需求穴亏,你可以繼承?BaseIndicator類從新加載視圖,或給我留言重挑。

添加空布局

View emptyView=getLayoutInflater().inflate(R.layout.rv_empty, null);
?emptyView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
? ? ? ? ? ? ViewGroup.LayoutParams.MATCH_PARENT));? ? //添加空視圖

? ? mAdapter.setEmptyView(emptyView);? ? emptyView.setOnClickListener(new View.OnClickListener() {
? ? ? ? @Override
? ? ? ? public void onClick(View view) {
? ? ? ? ? ? Snackbar.make(view, "your click empty", Snackbar.LENGTH_SHORT).show();? ? ? ? }

? ? });

拖拽和側(cè)滑

添加以下代碼:

ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mAdapter);
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback);
mAdapter.setItemTouchHelper(mItemTouchHelper);
mAdapter.setDragViewId(R.id.iv_drag);
mItemTouchHelper.attachToRecyclerView(mRecyclerView);

支持不同類型

mRecyclerView.setAdapter(mAdapter = new BaseMultiItemAdapter(this, getMultiItemDatas()) {

? ? @Override
? ? protected void convert(BaseViewHolder helper, MultiItem item) {
? ? ? ? switch (helper.getItemViewType()) {
? ? ? ? ? ? case MultiItem.SEND:
? ? ? ? ? ? ? ? helper.setText(R.id.chat_from_content, item.content); ?

? ? ? ? ? ? ? ? //helper.setImageBitmap(R.id.chat_from_icon,getRoundCornerBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.chat_head), 16));
? ? ? ? ? ? ? ? break;

? ? ? ? ? ? case MultiItem.FROM:
? ? ? ? ? ? ? ? helper.setText(R.id.chat_send_content, item.content);? ? ? ? ? ? ?

? ? ? ? ? ? ? ?//helper.setImageBitmap(R.id.chat_send_icon,getRoundCornerBitmap(BitmapFactory.decodeResource(getResources(), R.mipmap.from_head), 16));
? ? ? ? ? ? ? ? break;?
? ? ? ?}
? ? }

? ? @Override
? ? protected void addItemLayout() {
? ? ? ? addItemType(MultiItem.SEND, R.layout.chat_send_msg);? ? ? ? addItemType(MultiItem.FROM, R.layout.chat_from_msg);? ? }
});

mAdapter.openLoadAnimation(true);btnSend.setOnClickListener(new View.OnClickListener() {

? ? @Override
? ? public void onClick(View view) {

? ? ? ? MultiItem multiItem = new MultiItem();
? ? ? ? multiItem.itemType = MultiItem.SEND;
? ? ? ? multiItem.content = etChat.getText().toString();
? ? ? ? mAdapter.add(multiItem);
? ? ? ? mRecyclerView.smoothScrollToPosition(mAdapter.getItemCount());
? ? ? ? //mRecyclerView.scrollToPosition(mAdapter.getItemCount() - 1);
? ? }

});

數(shù)據(jù)源:

public static List getMultiItemDatas() {

? ? List list = new ArrayList<>();

? ? for (int i = 0; i < 100; i++) {

? ? ? ? MultiItem multiItem = new MultiItem();

? ? ? ? if (i % 2 == 0) {

? ? ? ? ? ? multiItem.itemType = MultiItem.SEND;

? ? ? ? ? ? multiItem.content = "海嗓化,妹子約嗎";

? ? ? ? } else {

? ? ? ? ? ? multiItem.itemType = MultiItem.FROM;

? ? ? ? ? ? multiItem.content = "大哥,你別怕";

? ? ? ? }

? ? ? ? list.add(multiItem);

? ? }

? ? return list;

}

這樣就輕松實現(xiàn)了聊天界面谬哀。

這樣簡單的配置就可以實現(xiàn)多類型布局刺覆,不需要你寫格外的代碼。

流式布局

先來看看效果圖:

一行代碼實現(xiàn)流式布局效果:

mRecyclerView.setLayoutManager(newFlowLayoutManager());


探探翻牌

類似流式效果史煎,重寫 LayoutManager 實現(xiàn)翻牌效果:

mRecyclerView.setLayoutManager(newOverLayCardLayoutManager());


//添加 itemTouchHelper

final TanTanCallback callback = new TanTanCallback(mRecyclerView, mAdapter, mAdapter.getData());

? ? //測試豎直滑動是否已經(jīng)不會被移除屏幕
? ?//callback.setHorizontalDeviation(Integer.MAX_VALUE);
? ? final ItemTouchHelper itemTouchHelper = new ItemTouchHelper(callback);

? ? itemTouchHelper.attachToRecyclerView(mRecyclerView);

效果圖一覽:

具體實現(xiàn)請參考 Demo

淘寶商品列表切換

先來看看效果圖:

看看代碼的實現(xiàn):

//線性 if (mIsLinearManager) {
? ? ? ? ? ? mAdapter.setLayoutType(BaseQuickAdapter.TRANS_0_VIEW);
? ? ? ? ? ? mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
? ? ? ? } else {
? ? ? ? ? ? //網(wǎng)格
? ? ? ? ? ? mAdapter.setLayoutType(BaseQuickAdapter.TRANS_1_VIEW);
? ? ? ? ? ? mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
? ? ? ? ? ? //需要顯示加載更多則加上下面這句? 從新關(guān)聯(lián)recycler
? ? ? ? ? ? mAdapter.onAttachedToRecyclerView(mRecyclerView);
? ? ? ? }
? ? ? ? mIsLinearManager = !mIsLinearManager;

注意:最多支持3種不同類型的轉(zhuǎn)換谦屑。

單選

實現(xiàn)單選,有好幾位同仁都在問我篇梭,其實實現(xiàn)單選是比較簡單的氢橙,方案也比較多,我這里就不在細講了恬偷。下面我給出一種實現(xiàn)方案:

public void setItemChecked(int position) {
? ? ? ? if (mLastCheckedPosition == position)
? ? ? ? ? ? return;
? ? ? ? mBooleanArray.put(position, true);
? ? ? ? if (mLastCheckedPosition > -1) {
? ? ? ? ? ? mBooleanArray.put(mLastCheckedPosition, false);
? ? ? ? ? ? mAdapter.notifyItemChanged(mLastCheckedPosition);
? ? ? ? } ? ? ? ?mAdapter.notifyDataSetChanged();

? ? ? ? mLastCheckedPosition = position;

? ? }

mBooleanArray 存儲是否被點擊悍手,把點擊前的索引值置為 false , 點擊索引置為 true 。

敬請大家的關(guān)注袍患,后期會一直維護本庫坦康,有什么好的想法,可以提出來诡延。我們互相學(xué)習(xí)進度滞欠。 下一個版本會自定義下拉刷新,全新多項的刷新貢大家喜歡肆良。再次感謝大家一直對我的關(guān)注仑撞,新年將近赤兴,祝愿大家新年新氣象,新年大吉隧哮!

源碼傳送門

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市座舍,隨后出現(xiàn)的幾起案子沮翔,更是在濱河造成了極大的恐慌,老刑警劉巖曲秉,帶你破解...
    沈念sama閱讀 221,635評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件采蚀,死亡現(xiàn)場離奇詭異,居然都是意外死亡承二,警方通過查閱死者的電腦和手機榆鼠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,543評論 3 399
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來亥鸠,“玉大人妆够,你說我怎么就攤上這事「何茫” “怎么了神妹?”我有些...
    開封第一講書人閱讀 168,083評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長家妆。 經(jīng)常有香客問我鸵荠,道長,這世上最難降的妖魔是什么伤极? 我笑而不...
    開封第一講書人閱讀 59,640評論 1 296
  • 正文 為了忘掉前任蛹找,我火速辦了婚禮,結(jié)果婚禮上哨坪,老公的妹妹穿的比我還像新娘庸疾。我一直安慰自己,他們只是感情好齿税,可當我...
    茶點故事閱讀 68,640評論 6 397
  • 文/花漫 我一把揭開白布彼硫。 她就那樣靜靜地躺著,像睡著了一般凌箕。 火紅的嫁衣襯著肌膚如雪拧篮。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,262評論 1 308
  • 那天牵舱,我揣著相機與錄音串绩,去河邊找鬼。 笑死芜壁,一個胖子當著我的面吹牛礁凡,可吹牛的內(nèi)容都是我干的高氮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,833評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼顷牌,長吁一口氣:“原來是場噩夢啊……” “哼剪芍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起窟蓝,我...
    開封第一講書人閱讀 39,736評論 0 276
  • 序言:老撾萬榮一對情侶失蹤蟀苛,失蹤者是張志新(化名)和其女友劉穎雁歌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,280評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡冻河,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,369評論 3 340
  • 正文 我和宋清朗相戀三年丰刊,在試婚紗的時候發(fā)現(xiàn)自己被綠了上渴。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吼虎。...
    茶點故事閱讀 40,503評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖匈挖,靈堂內(nèi)的尸體忽然破棺而出碾牌,到底是詐尸還是另有隱情,我是刑警寧澤关划,帶...
    沈念sama閱讀 36,185評論 5 350
  • 正文 年R本政府宣布小染,位于F島的核電站,受9級特大地震影響贮折,放射性物質(zhì)發(fā)生泄漏裤翩。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,870評論 3 333
  • 文/蒙蒙 一调榄、第九天 我趴在偏房一處隱蔽的房頂上張望踊赠。 院中可真熱鬧,春花似錦每庆、人聲如沸筐带。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,340評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伦籍。三九已至,卻和暖如春腮出,著一層夾襖步出監(jiān)牢的瞬間帖鸦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,460評論 1 272
  • 我被黑心中介騙來泰國打工胚嘲, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留作儿,地道東北人。 一個月前我還...
    沈念sama閱讀 48,909評論 3 376
  • 正文 我出身青樓馋劈,卻偏偏與公主長得像攻锰,于是被迫代替她去往敵國和親晾嘶。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,512評論 2 359

推薦閱讀更多精彩內(nèi)容