簡介
前段時間封裝了一個RecyclerView相關的庫,叫做SXRecyclerView。該庫包含了很多常用的功能,包括觸摸反饋效果、點擊事件、長按事件、多選功能、HeaderAndFooter、PinnedHeader等等。在做應用開發(fā)的時候直接使用這樣一個組件能很快的實現相關功能,提高開發(fā)的效率。
SXRecyclerView的實現并不是直接引入原生的RecyclerView,而是抽取整個RecyclerView庫相關的源碼,在原生源碼基礎上進行封裝的。這樣做的好處一是打破權限的限制,便于功能的封裝與定制化;二是能對整個庫進行完全的掌控,避免由于導入不同版本導致兼容性問題。
SXRecyclerView需要依賴support-v4包,如果導入SXRecyclerView的工程中也引入v4包,最好保證引入的v4包是25.3.1及以上版本,不然有可能導致編譯出錯。
現在我將該組件庫開源分享給大家,地址如下:
下面說下該庫的功能點及使用方式。
觸摸反饋效果
SXRecyclerView已經實現了觸摸反饋效果,默認進行點擊、長按操作都會有水波紋動畫。如果想自定義觸摸反饋效果,可以通過以下方法來設置:
public void setSelector(Drawable sel)
public void setSelector(int resID)
如果想去掉觸摸反饋效果,可以通過mRecyclerView.setSelector(null);這樣來設置。
點擊事件和長按事件
原生的RecyclerView沒有提供ItemView點擊和長按功能,通常的做法是在Adapter中進行數據綁定時對每個ViewHolder對應的view設置OnClickListener、OnLongClickListener來實現相應的功能?,F在不需要這樣麻煩了。SXRecyclerView這個類在RecyclerView的基礎上中實現了該功能,并提供了事件回調,調用代碼如下:
//點擊事件
mRecyclerView.setOnItemClickListener(new SXRecyclerView.OnItemClickListener() {
@Override
public void onItemClick(RecyclerView parent, View view, int position, long id) {
//do something
}
});
//長按事件
mRecyclerView.setOnItemLongClickListener(new SXRecyclerView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(RecyclerView parent, View view, int position, long id){
//do something
return true;
}
});
默認情況下,設置了這兩個監(jiān)聽器之后,SXRecyclerView會對每個ItemView都響應操作。如果想讓某個ItemView不響應點擊、長按事件,可以通過重寫Adapter的isEnable(int position)方法來實現:
/**
* TYPE_TITLE 類型的Item不需要響應點擊、長按事件,故返回false
* @param position
* @return
*/
@Override
public boolean isEnable(int position) {
if (getItemViewType(position) == TYPE_TITLE){
return false;
}
return true;
}
原生RecyclerView沒有該方法,此方法是SXRecyclerView添加的。此方法返回false就代表對應位置的ItemView不啟用SXRecyclerView相關功能,也就是說不響應點擊事件、長按事件、觸摸反饋、多選功能等。該方法默認返回true。
示意圖:

多選功能
要使用多選功能,有兩個必要的步驟:
1、設置多選模式,多選模式如下:
- CHOICE_MODE_NONE : 不啟動多選功能。默認值為這種。
-
CHOICE_MODE_MULTIPLE :主動觸發(fā)啟動多選功能。觸發(fā)方式有長按和主動調用
startMultiChoice()方法兩種觸發(fā)方式。
2、設置選擇模式監(jiān)聽器,并根據需求實現相關的方法與ActionMode進行交互。代碼如下:
//設置選擇模式為多選模式
mRecyclerView.setChoiceMode(SXRecyclerView.CHOICE_MODE_MULTIPLE);
//設置多選模式監(jiān)聽器
mRecyclerView.setMultiChoiceModeListener(new SXRecyclerView.MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return true;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return true;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
}
});
這里的多選模式是與ActionMode進行綁定交互的,具體的實現可以參考下demo。
默認情況下,所有的ItemView都是可以被選中的。如果要讓某些項不可選中,除了前文提到的重寫Adaper中的isEnable(int position)方法讓對應位置的ItemView失效。還可以通過Adapter的另外一個方法來設置:
//返回false的數據項不可被選中
@Override
public boolean isSelectable(int position) {
if (position % 5 == 0) {
return false;
}
return true;
}
不同于isEnable(int position)方法,isSelectable(int position)方法只作用于多選功能,返回false的ItemView只是不能被選中,包括點擊、長按事件在內的其他功能都能響應。
一般使用多選功能都會在選中ItemView的時候對相應的ItemView進行標記,比如打個勾之類的操作。為了更簡單直接地實現選中標記操作,SXRecyclerView提供了一種實現方式,就是對ViewHolder實現Checkable接口,這樣在選中狀態(tài)發(fā)生改變時,setChecked(boolean checked)方法都會被調用,我們就可以在該方法中對ItemView為所欲為了。
// 實現Checkable接口,可以簡單直接地實現多選標記功能
class MyViewHolder extends RecyclerView.ViewHolder implements Checkable {
TextView mTextView;
ImageView mImageView;
public MyViewHolder(View itemView) {
super(itemView);
mTextView = (TextView) itemView.findViewById(R.id.item_tv);
mImageView = (ImageView) itemView.findViewById(R.id.img_check);
}
//此ItemView選中狀態(tài)發(fā)生改變時該方法會回調
@Override
public void setChecked(boolean checked) {
if (checked) {
mImageView.setVisibility(View.VISIBLE);
} else {
mImageView.setVisibility(View.GONE);
}
}
@Override
public boolean isChecked() {
return false;
}
@Override
public void toggle() {
}
}
tip :多選功能的相關方法如下:
-
public boolean startMultiChoice():進入多選狀態(tài) -
public void finishMultiChoice():退出多選狀態(tài) -
public Boolean isInMutiChoiceState():判斷SXRecyclerview是否處于多選狀態(tài) -
public void setItemChecked(int position, boolean value):設置某項的選中狀態(tài) -
public void clearChoices():清除所有的選中狀態(tài) -
public long[] getCheckedItemIds():獲取當前選中的項的id集合 -
public List<Integer> getCheckedItemPositions():獲取當前選中的項的position集合 -
public boolean isItemChecked(int position):判斷某項是否選中 -
public int getCheckedItemCount():獲取選中項總數 -
public void checkedAll():全選 -
public void unCheckedAll():全不選
示意圖:

PinnedHeader
PinnedHeader是指對ViewHolder進行分組,每個組都有一個Header,在滑動過程中,處于頂部的組的Header都會懸浮在SXRecyclerView頂部不會滑出屏幕,直到下一個Header滑到SXRecyclerView頂部位置時才會將上一個Header頂出屏幕。
實現PinnedHeader效果,有2個必要的步驟:
1、需要在其Adapter中實現以下接口
public interface RecyclerPinnedHeaderAdapter<VH extends MzRecyclerView.ViewHolder> {
// 返回PinnedHeader 的編號id
// 通過id來對ViewHolder進行分組,相同id的viewHolder會分到通一組,對應相同的PinnedHeader
// 返回 負數 的時候,表示該 PinnedHeader 不顯示
long getHeaderId(int position);
// 創(chuàng)建 PinnedHeader的樣式
VH onCreateHeaderViewHolder(ViewGroup parent);
// 綁定 PinnedHeader的數據
void onBindHeaderViewHolder(VH holder, int position);
int getItemCount();
}
2、以實現了RecyclerPinnedHeaderAdapter的Adapter對象為參數,創(chuàng)建RecyclerPinnedHeaderDecoration對象,并通過addItemDecoration添加到SXRecyclerView中,這時已經可以顯示PinnedHeader了。
//創(chuàng)建RecyclerPinnedHeaderDecoration
RecyclerPinnedHeaderDecoration headersDecor = new RecyclerPinnedHeaderDecoration(adapter);
//將創(chuàng)建RecyclerPinnedHeaderDecoration作為一個ItemDecoration添加到Recyclerview中,從而實現將PinnedHeader繪制到SXRecyclerview中
mRecyclerView.addItemDecoration(headersDecor);
RecyclerPinnedHeaderDecoration提供了PinnedHeader監(jiān)聽器,懸浮在頂部的PinnedHeader發(fā)生改變(被頂出屏幕或者屏幕外有新的PinnedHeader進來)時觸發(fā)監(jiān)聽器回調,通過此監(jiān)聽器可以對懸浮頭添加一些標識或者做一些動畫效果。示例代碼如下:
//可以通過對RecyclerPinnedHeaderDecoration設置監(jiān)聽器,來實現對切換PinnedHeader的監(jiān)聽
headersDecor.setPinnedHeaderListener(new RecyclerPinnedHeaderDecoration.OnPinnedHeaderChangeListener() {
@Override
public void OnPinnedHeaderChange(RecyclerView recyclerView, View currentHeader, int currentPosition, long currentHeaderId, View lastHeader, int lastPosition, long lastHeaderId) {
//do something
}
});
此外,SXRecyclerview還支持對PinnedHeader設置點擊事件。示例代碼如下:
//可以通過RecyclerPinnedHeaderTouchListener設置點擊PinnedHeader時的回調
RecyclerPinnedHeaderTouchListener touchListener = new RecyclerPinnedHeaderTouchListener(mRecyclerView, headersDecor);
touchListener.setOnHeaderClickListener(new RecyclerPinnedHeaderTouchListener.OnHeaderClickListener() {
@Override
public void onHeaderClick(View header, int position, long headerId, MotionEvent e) {
// do something
}
});
//記得將RecyclerPinnedHeaderTouchListener添加到SXRecyclerview中才會生效
mRecyclerView.addOnItemTouchListener(touchListener);
示意圖:

Header和Footer
SXRecyclerView提供了添加頭尾部的功能。示例代碼如下:
//創(chuàng)建view對象
View headerView = LayoutInflater.from(this).inflate(R.layout.recyclerview_header_view, mRecyclerView,null);
// 將view包裝成Viewholder
final HeaderViewHolder header = new HeaderViewHolder(headerView);
header.mTextView.setText("This is Header View");
header.mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// do something
}
});
//添加此被包裝過的headerview到SXRecyclerview中
mRecyclerView.addHeaderView(header);
View footerView = LayoutInflater.from(this).inflate(R.layout.recyclerview_footer_view, null);
final FooterViewHolder footer = new FooterViewHolder(footerView);
footer.mTextView.setText("This is Footer View");
footer.mTextView.setBackgroundColor(0xFF6495ED);
footer.mTextView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// do something
}
});
//添加此被包裝過的footerview到SXRecyclerview中
mRecyclerView.addFooterView(footer);



該庫我會一直更新維護,以后會逐漸添加更多通用的功能,更新后會同步文檔到本文和GitHub上。使用過程中有什么問題可以隨時交流~