RecyclerView-Adapter系列簡述(第1篇)

從這篇文章文章開始將會連載幾篇文章簡單描述下最近抽空針對RecyclerViewAdapter做的一個擴展庫。系列文章是對擴展庫逐步進行擴展的,有一定的先后關(guān)系,所以閱讀的話還是按照這個順序比較好。

這篇先不開始描述怎么去擴展,先說一下這個擴展庫將擁有什么樣的功能以及如何使用,也就是告訴讀者這些功能是不是符合口味,能不能吸引再往下讀。
該庫github地址:
https://github.com/yangxiaoweihn/RecyclerViewAdapter

該系列內(nèi)容已經(jīng)完結(jié),其他部分可以點擊下列閱讀:
RecyclerView-為Adapter添加頭部、尾部及事件響應(yīng)(第2篇)
RecyclerView-數(shù)據(jù)域的操作方法(第3篇)
RecyclerView-為Adapter增加滑動菜單支持(第4篇)
RecyclerView-為Adapter增加粘性頭部支持(第5篇)

本篇主要描述以下幾方面內(nèi)容:

  1. 擴展庫如何在項目中使用
  2. 擴展庫具有的功能
  3. 貼圖看看效果
  4. 擴展庫的api使用說明

擴展庫的使用

該庫已經(jīng)打包上傳到了maven、jcenter倉庫,使用Android Studio開發(fā)的同學(xué)肯定都知道怎么從倉庫引入庫的。
特殊注意:另外,這系列文章是針對源碼版本2.0描述的

    compile 'ws.dyt.view:recyclerview-adapter-hf:2.0'

具有的功能

  1. 可以添加、刪除任意數(shù)量的頭部、尾部(就像ListView那樣)
  2. 可以添加系統(tǒng)頭部、尾部(數(shù)量和使用上做了限制,在使用上盡量不要去使用這部分),具體說明將會在之后的文章中進行闡述。
  3. 可以針對不同的item添加滑動菜單(目前只支持左滑、右滑),并且菜單定制性高
  4. 支持粘性視圖,同時支持滑動菜單

效果圖

在能讓讀者有足夠的好奇心讀以下的文章前,先貼幾張效果圖,拿效果圖最能說明該庫擁有的功能。

1.png
2.png
3.png
4.png
5.png
6.png
7.png

好了,效果圖已經(jīng)貼完,如果覺得這些功能不夠吸引的話,同學(xué)就可以止步了,因為只有得系列文章主要是為了闡述以上功能的開發(fā)過程及思路。

api使用說明

首先要說明一點:該api的使用與系統(tǒng)原生提供的有區(qū)別,不要思維定式。簡單說起來就是使用更簡單,大概姿勢如下:
1. 構(gòu)造(構(gòu)造方法)
2. 數(shù)據(jù)綁定
3. 多類型支持(設(shè)置布局,如果需要的話)
4. 事件
5. 添加頭部尾部控件
6. 橫跨列處理
7. 添加菜單
8. 添加粘性頭部

該庫主要實現(xiàn)了兩個具有一定功能的Adapter,命名為SuperAdapterSuperPinnedAdapter。從實現(xiàn)上來講,SuperPinnedAdapter間接繼承自SuperAdapter,所以功能上就不言而喻了。
SuperAdapter具有添加頭部尾部、以及滑動菜單功能,而SuperPinnedAdapter在此基礎(chǔ)上增加了粘性視圖的支持。

通過構(gòu)造方法進行初始化(具體的參數(shù)說明請看注釋)

/** 
    * 調(diào)用該構(gòu)造方法時需要調(diào)用 {@link #getItemViewLayout(int)} 設(shè)置item布局 
    * @param context 
    * @param datas 
    */
  public SuperAdapter(Context context, List<T> datas) {
      super(context, datas);
  }
  /** 
    * 調(diào)用該構(gòu)造方法時默認(rèn)數(shù)據(jù)項都采用 itemLayoutResId 布局,同樣可以調(diào)用 {@link #getItemViewLayout(int)} 重新設(shè)置item布局 
    * @param context 
    * @param datas 
    * @param itemLayoutResId 
    */
public SuperAdapter(Context context, List<T> datas, @LayoutRes int itemLayoutResId) {    
      this(context, datas);
}

以上兩個構(gòu)造方法最大的區(qū)別是:用第一種方法構(gòu)造后需要調(diào)用getItemViewLayout()設(shè)置item的布局。用后一種的話已經(jīng)設(shè)置了item布局,不過這種方式是所有的item布局都是一樣的。

數(shù)據(jù)綁定

數(shù)據(jù)的綁定在原生里是onBindViewHolder(),而在這里,將該方法進行了屏蔽,而是用convert()方法(使用上與onBindViewHolder()一致,但是也更簡單),可以簡單的將他倆看成是對等的關(guān)系,但是事實上不是這樣的,具體的我將會在后續(xù)的文章中進行具體描述。

  /** 
    * 綁定數(shù)據(jù) 
    * @param holder 
    * @param position  數(shù)據(jù)域從0開始,已經(jīng)除去頭部       
    */
  abstract
  public void convert(BaseViewHolder holder, int position);

該方法的第一個參數(shù)該庫做了進一步封裝,具體來說就是整個庫里BaseViewHolder類無法被擴展,所有常用的操作方法已經(jīng)在該類中進行了封裝(后續(xù)版本在決定是否可以允許該類擴展),BaseViewHolder的功能將會在后面的文章進行描述。BaseViewHolder的鏈條操作:

  //只是一個例子而已,旨在說明鏈條操作,不必注意實體類是什么
  CourseResult.Course e = getItem(position).data;
  holder.
      setText(R.id.tv_name, e.name).
      setText(R.id.tv_length, e.length);

多item支持

通過構(gòu)造方法已經(jīng)知道,用構(gòu)造方法是沒有辦法設(shè)置Adapter的多item樣式支持的。那么在該庫中,通過以下方法進行設(shè)置:

  /**  
    * 提供item對應(yīng)的布局 
    */
public int getItemViewLayout(int position) {}

事件

網(wǎng)上一大片文章都在講RecyclerView怎么設(shè)置item的點擊事件云云,事實上確實很簡單,RecyclerView暴露的方法就那么幾個,所以在這里事件是怎么加上去的也將在后續(xù)的文章中闡述,這里只需要知道該庫一定也提供了設(shè)置事件監(jiān)聽的方法。
對item的點擊事件支持以下兩種:

  /** 
    * 點擊事件 
    */
  public interface OnItemClickListener {    
      void onItemClick(View itemView, int position);
  }
  /** 
    * 長按事件 
    */
  public interface OnItemLongClickListener {    
      void onItemLongClick(View itemView, int position);
  }

設(shè)置監(jiān)聽器:

  //設(shè)置點擊事件
  adapter.setOnItemClickListener(new SuperAdapter.OnItemClickListener() {    
      @Override    
      public void onItemClick(View itemView, int position) {     
      }
});
  //設(shè)置長按事件
  adapter.setOnItemLongClickListener(new SuperAdapter.OnItemLongClickListener() {    
      @Override    
      public void onItemLongClick(View itemView, int position) {     
      }
});

添加頭部、尾部控件

原生RecyclerView并沒有提供像ListView中那樣可以隨意添加header和footer的api,但是在實際的場景中我們確實需要這樣的功能,那么該庫也一定提供了這樣的方法。
首先需要簡單說一下SuperAdapter數(shù)據(jù)域的構(gòu)成:

  {
      item_sys_header - item_header - 
      item_data - 
      item_footer - item_sys_footer
  }
從上面的結(jié)構(gòu)中可以看到,大體分為3中(header部分、數(shù)據(jù)部分、footer部分),細(xì)分的話,頭部又分為系統(tǒng)header部分(item_sys_header)和用戶header部分(item_header),footer部分分為系統(tǒng)footer部分(item_footer)和用戶footer部分(item_sys_footer)。
我為什么要這么劃分呢,在實現(xiàn)上是有一些考慮的,頭部和尾部不要去污染數(shù)據(jù)部分(分離),這樣在擴展上更好一些。一般在使用時系統(tǒng)header和系統(tǒng)footer可以忽略,加這兩個的用途也是為了擴展用,比如在我的另外一個上拉加載庫中就用了系統(tǒng)footer。

主要提供了一下幾個api:

final
public void addHeaderView(View view);
final
public void addHeaderView(View view, boolean changeAllVisibleItems);
final
public void removeHeaderView(View view);
final
public void removeHeaderView(View view, boolean changeAllVisibleItems);
final
public void addFooterView(View view);
final
public void addFooterView(View view, boolean changeAllVisibleItems);
final
public void removeFooterView(View view);
final
public void removeFooterView(View view, boolean changeAllVisibleItems);

其中changeAllVisibleItems表示是否只刷新可見區(qū)域(為true時),否則只刷新當(dāng)前發(fā)生變化的item,默認(rèn)為false

橫跨列的api

RecyclerView的布局管理器是GridLayoutManager或者StaggeredGridLayoutManager時,有些item需要橫跨所有列,這種情況下我們也提供了以下api去設(shè)置,默認(rèn)為false,表示保持管理器設(shè)置,為true時表示橫跨。

/**
 * 設(shè)置是否橫跨
 * @param position
 * @return
 */
protected boolean isFullSpanWithItemView(int position) {
    return false;
}

添加菜單及菜單事件

public List<MenuItem> onCreateMultiMenuItem(int viewType) {
    List<MenuItem> mm = new ArrayList<>();
    mm.add(new MenuItem(R.layout.menu_item_test_delete, MenuItem.EdgeTrack.RIGHT, 01));
    mm.add(new MenuItem(R.layout.menu_item_test_mark, MenuItem.EdgeTrack.RIGHT, 02));
    return mm;
}
@Override
public boolean isCloseOtherItemsWhenThisWillOpen() {
    return true;}adapter.setOnItemMenuClickListener(new OnItemMenuClickListener() {
    @Override
    public void onMenuClick(SwipeLayout swipeItemView, View itemView, View menuView, int position, int menuId) {
        if (menuId == 01) {
            swipeItemView.closeMenuItem();
            Log.d("DEBUG", "--menu: 刪除 -> position: " + position + " , menuId: " + menuId);
            Toast.makeText(getContext(), "刪除", Toast.LENGTH_SHORT).show();
        } else if (menuId == 02) {
            Log.d("DEBUG", "--menu: 關(guān)注 -> position: " + position + " , menuId: " + menuId);
            Toast.makeText(getContext(), "加關(guān)注", Toast.LENGTH_SHORT).show();
        }
    }
});

添加粘性頭部及數(shù)據(jù)綁定

注意粘性頭部的AdapterPinnedAdapter.

@Override
public int getPinnedItemViewLayout() {
    return R.layout.item_pinned;
}
@Override
public void convertPinnedHolder(BaseViewHolder holder, int position, int type) {
    holder.setText(R.id.tv_text_pinned, getItem(position).data.title);
}

概括的介紹就到這里。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • 內(nèi)容抽屜菜單ListViewWebViewSwitchButton按鈕點贊按鈕進度條TabLayout圖標(biāo)下拉刷新...
    皇小弟閱讀 47,183評論 22 665
  • 我終于等到這年夏天,陽光將萬物都涂抹上燦燦的光,碧藍(lán)的天空卻把人卷進無盡的虛無。游樂場中人們尖叫、打鬧。笑聲像...
    絢爛的小哈閱讀 578評論 0 2
  • 大清早上的,腦子懵懵的。做了2012年12月真題的聽力,嚴(yán)重懷疑自己是不是把腦子丟進太平洋了! 第一大題錯2個,第...
    諾凡閱讀 423評論 4 1
  • 首先,嚴(yán)把產(chǎn)品的質(zhì)量 商家在運營社群時,首先要清楚了解產(chǎn)品或者服務(wù)的亮點,同時多與社群成員交流互動,從交流中尋找提...
    qzuser_6e42閱讀 594評論 0 0

友情鏈接更多精彩內(nèi)容