Android組件化——SXRecyclerView

簡介

前段時間封裝了一個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設置OnClickListenerOnLongClickListener來實現相應的功能。如今不須要這樣麻煩了。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

  • CHOICE_MODE_NONE :不啓動多選功能。默認值爲這種。
  • CHOICE_MODE_MULTIPLE :主動觸發啓動多選功能。觸發方式有長按和主動調用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

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

Header和Footer

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+架構視頻+面試文檔+源碼筆記

相關文章
相關標籤/搜索