前段時間封裝了一個RecyclerView相關的庫,叫作SXRecyclerView。該庫包含了不少經常使用的功能,包括觸摸反饋效果、點擊事件、長按事件、多選功能、HeaderAndFooter、PinnedHeader等等。在作應用開發的時候直接使用這樣一個組件能很快的實現相關功能,提升開發的效率。SXRecyclerView的實現並非直接引入原生的RecyclerView,而是抽取整個RecyclerView庫相關的源碼,在原生源碼基礎上進行封裝的。這樣作的好處一是打破權限的限制,便於功能的封裝與定製化;二是能對整個庫進行徹底的掌控,避免因爲導入不一樣版本致使兼容性問題。SXRecyclerView須要依賴support-v4包,若是導入SXRecyclerView的工程中也引入v4包,最好保證引入的v4包是25.3.1及以上版本,否則有可能致使編譯出錯。如今我將該組件庫開源分享給你們,地址以下:github.com/zhimaochen/…java
SXRecyclerView已經實現了觸摸反饋效果,默認進行點擊、長按操做都會有水波紋動畫。若是想自定義觸摸反饋效果,能夠經過如下方法來設置:git
public void setSelector(Drawable sel)
public void setSelector(int resID)
複製代碼
若是想去掉觸摸反饋效果,能夠經過mRecyclerView.setSelector(null);
這樣來設置。github
原生的RecyclerView沒有提供ItemView點擊和長按功能,一般的作法是在Adapter中進行數據綁定時對每一個ViewHolder對應的view設置OnClickListener
、OnLongClickListener
來實現相應的功能。如今不須要這樣麻煩了。SXRecyclerView這個類在RecyclerView的基礎上中實現了該功能,並提供了事件回調,調用代碼以下:web
//點擊事件
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;
}
});
複製代碼
默認狀況下,設置了這兩個監聽器以後,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。示意圖:bash
click架構
要使用多選功能,有兩個必要的步驟:一、設置多選模式,多選模式以下:ide
startMultiChoice()
方法兩種觸發方式。二、設置選擇模式監聽器,並根據需求實現相關的方法與ActionMode進行交互。代碼以下:學習
//設置選擇模式爲多選模式
mRecyclerView.setChoiceMode(SXRecyclerView.CHOICE_MODE_MULTIPLE);
//設置多選模式監聽器
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
接口,這樣在選中狀態發生改變時,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選中狀態發生改變時該方法會回調
@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()
:進入多選狀態public void finishMultiChoice()
:退出多選狀態public Boolean isInMutiChoiceState()
:判斷SXRecyclerview是否處於多選狀態public void setItemChecked(int position, boolean value)
:設置某項的選中狀態public void clearChoices()
:清除全部的選中狀態public long[] getCheckedItemIds()
:獲取當前選中的項的id集合public List<integer style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; font-size: inherit; color: inherit; line-height: inherit;">getCheckedItemPositions()</integer>
:獲取當前選中的項的position集合public boolean isItemChecked(int position)
:判斷某項是否選中public int getCheckedItemCount()
:獲取選中項總數public void checkedAll()
:全選public void unCheckedAll()
:全不選示意圖:
multichoice
PinnedHeader是指對ViewHolder進行分組,每一個組都有一個Header,在滑動過程當中,處於頂部的組的Header都會懸浮在SXRecyclerView頂部不會滑出屏幕,直到下一個Header滑到SXRecyclerView頂部位置時纔會將上一個Header頂出屏幕。實現PinnedHeader效果,有2個必要的步驟:一、須要在其Adapter中實現如下接口
public interface RecyclerPinnedHeaderAdapter<VH extends MzRecyclerView.ViewHolder> {
// 返回PinnedHeader 的編號id
// 經過id來對ViewHolder進行分組,相同id的viewHolder會分到同一組,對應相同的PinnedHeader
// 返回 負數 的時候,表示該 PinnedHeader 不顯示
long getHeaderId(int position);
// 建立 PinnedHeader的樣式
VH onCreateHeaderViewHolder(ViewGroup parent);
// 綁定 PinnedHeader的數據
void onBindHeaderViewHolder(VH holder, int position);
int getItemCount();
}
複製代碼
二、以實現了RecyclerPinnedHeaderAdapter的Adapter對象爲參數,建立RecyclerPinnedHeaderDecoration對象,並經過addItemDecoration添加到SXRecyclerView中,這時已經能夠顯示PinnedHeader了。
//建立RecyclerPinnedHeaderDecoration
RecyclerPinnedHeaderDecoration headersDecor = new RecyclerPinnedHeaderDecoration(adapter);
//將建立RecyclerPinnedHeaderDecoration做爲一個ItemDecoration添加到Recyclerview中,從而實現將PinnedHeader繪製到SXRecyclerview中
mRecyclerView.addItemDecoration(headersDecor); </pre>
RecyclerPinnedHeaderDecoration提供了PinnedHeader監聽器,懸浮在頂部的PinnedHeader發生改變(被頂出屏幕或者屏幕外有新的PinnedHeader進來)時觸發監聽器回調,經過此監聽器能夠對懸浮頭添加一些標識或者作一些動畫效果。示例代碼以下:
<pre style="margin: 0px; padding: 0px; max-width: 100%; box-sizing: border-box !important; word-wrap: break-word !important; color: inherit; font-size: inherit; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: 2; text-align: justify; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; background-color: rgb(255, 255, 255); line-height: inherit;">//能夠經過對RecyclerPinnedHeaderDecoration設置監聽器,來實現對切換PinnedHeader的監聽
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);
複製代碼
示意圖:
pinnedheader
SXRecyclerView提供了添加頭尾部的功能。示例代碼以下:
//建立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);
複製代碼
HeaderAndFooter
HeaderAndFooterGrid
HeaderAndFooterStag該庫我會一直更新維護,之後會逐漸添加更多通用的功能,更新後會同步文檔到本文和GitHub上。使用過程當中有什麼問題能夠隨時交流~ Android學習PDF+架構視頻+面試文檔+源碼筆記