Android組件化——SXRecyclerView

簡介

前段時間封裝了一個RecyclerView相關的庫,叫做SXRecyclerView。該庫包含了很多常用的功能,包括觸摸反饋效果、點擊事件、長按事件、多選功能、HeaderAndFooter、PinnedHeader等等。在做應用開發(fā)的時候直接使用這樣一個組件能很快的實現相關功能,提高開發(fā)的效率。

SXRecyclerView的實現并不是直接引入原生的RecyclerView,而是抽取整個RecyclerView庫相關的源碼,在原生源碼基礎上進行封裝的。這樣做的好處一是打破權限的限制,便于功能的封裝與定制化;二是能對整個庫進行完全的掌控,避免由于導入不同版本導致兼容性問題。

SXRecyclerView需要依賴support-v4包,如果導入SXRecyclerView的工程中也引入v4包,最好保證引入的v4包是25.3.1及以上版本,不然有可能導致編譯出錯。

現在我將該組件庫開源分享給大家,地址如下:

SXRecyclerView

下面說下該庫的功能點及使用方式。

觸摸反饋效果

SXRecyclerView已經實現了觸摸反饋效果,默認進行點擊、長按操作都會有水波紋動畫。如果想自定義觸摸反饋效果,可以通過以下方法來設置:

public void setSelector(Drawable sel)
public void setSelector(int resID)

如果想去掉觸摸反饋效果,可以通過mRecyclerView.setSelector(null);這樣來設置。

點擊事件和長按事件

原生的RecyclerView沒有提供ItemView點擊和長按功能,通常的做法是在Adapter中進行數據綁定時對每個ViewHolder對應的view設置OnClickListenerOnLongClickListener來實現相應的功能?,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。

示意圖:


click.gif

多選功能

要使用多選功能,有兩個必要的步驟:

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():全不選

示意圖:


multichoice.gif

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);

示意圖:


pinnedheader.gif

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);

HeaderAndFooter.gif
HeaderAndFooterGrid.gif
HeaderAndFooterStag.gif

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

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

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,323評論 25 708
  • 寫在前面:參考YoKey,感謝。附上他的鏈接:http://www.itdecent.cn/p/d30fd8da4...
    喜歡丶下雨天閱讀 3,648評論 0 9
  • 一個人很難做到開放自己的心,那顆心在遙遠的幼兒園或孩提時期亦或在媽媽肚子就關閉了。心啊在一個人的物質身體里,別人無...
    朵朵頤閱讀 489評論 2 0
  • 001平凡女性也可以擁有美好人生 沒有人注定就會成功,同樣,也沒有人注定就要失敗。如果你一開始的技能不如別人強,請...
    2018蛻變閱讀 232評論 0 0
  • 畢業(yè)三年了,工作還算穩(wěn)定,但工資實在太少,正好是單身狗,費用勉強自給。盡管每天依然擠公車,偶爾因為懶床和公車擦身而...
    樂樂樂t閱讀 301評論 0 0

友情鏈接更多精彩內容