RecyclerView實(shí)現(xiàn)單選多選功能

又來(lái)更新小功能了详囤,項(xiàng)目中經(jīng)常會(huì)遇到單選多選功能,總是草草的寫下沒(méi)有系統(tǒng)總結(jié)镐作,今天來(lái)記錄一下藏姐。這篇是用RecyclerView實(shí)現(xiàn)單選多選功能,下一篇再來(lái)講用RecyclerView實(shí)現(xiàn)折疊效果的樹形結(jié)構(gòu)该贾。

1. 效果圖

單選.gif

單選取消.gif

多選.gif

2. RecyclerView實(shí)現(xiàn)單選功能

2.1 實(shí)現(xiàn)思路

  • itemView布局內(nèi)的字體顏色和背景使用selector來(lái)控制羔杨,所以當(dāng)RecyclerView的itemView的isSelect屬性為true時(shí),該布局內(nèi)的顏色和字體會(huì)變?yōu)檫x中狀態(tài)下的顏色靶庙。
  • 當(dāng)點(diǎn)擊新的itemView時(shí)问畅,將舊的itemView設(shè)置為false娃属,新的點(diǎn)擊位置設(shè)置為true六荒,即可實(shí)現(xiàn)單選的效果。

2.2 具體實(shí)現(xiàn)

2.2.1創(chuàng)建布局

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="72dp"
    android:layout_height="92dp"
    android:background="@drawable/bg_selector"
    xmlns:app="http://schemas.android.com/apk/res-auto">
    <TextView
        android:id="@+id/tvDate"
        android:text="10/28"
        android:textSize="15sp"
        android:textColor="@color/text_sel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="20dp"/>
  ......
</androidx.constraintlayout.widget.ConstraintLayout>

bg_selector

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/colorBlue" android:state_selected="true"></item>
    <item android:drawable="@color/colorWhite" android:state_selected="false"></item>
</selector>

text_sel 同理

這里的selector主要用到了state_selected屬性矾端,當(dāng)為true時(shí)代表選中掏击,設(shè)置背景為藍(lán)色,否則設(shè)置為灰色

2.2.2 創(chuàng)建適配器邏輯

class SingleSelectAdapter(var mDataList: MutableList<String>) :
RecyclerView.Adapter<SingleSelectAdapter.MyViewHolder>() {

    //選擇的位置
    var selPosition = 0
    //臨時(shí)記錄上次選擇的位置
    var temp =-1

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.date.text = mDataList[position]

        holder.itemView.isSelected = holder.layoutPosition==selPosition

        holder.itemView.setOnClickListener {
            holder.itemView.isSelected =true
            //將舊的位置保存下來(lái)秩铆,用于后面把舊的位置顏色變回來(lái)
            temp = selPosition
            //設(shè)置新的位置
            selPosition = holder.layoutPosition
            //更新舊位置
            notifyItemChanged(temp)
        }
    }
}

在該適配器中砚亭,我們使用到兩個(gè)變量,一個(gè)變量用來(lái)記錄當(dāng)前點(diǎn)擊的位置殴玛,即選中的位置捅膘;一個(gè)變量用來(lái)臨時(shí)記錄當(dāng)點(diǎn)擊新的位置時(shí),舊的位置滚粟,防止selPosition賦新值后舊的位置找不到了寻仗。

具體的邏輯在onBindViewHolder()方法內(nèi)

  • holder.itemView.isSelected = holder.layoutPosition==selPosition當(dāng) 當(dāng)前的itemView位置是selPosition時(shí),將其設(shè)置為true凡壤,否則設(shè)置為false署尤。

  • 當(dāng)點(diǎn)擊新位置時(shí),先將點(diǎn)擊位置itemView的isSelected設(shè)置為true代表選中亚侠,然后用temp記錄下原先選中的位置曹体,將新的位置保存在selPosition中,然后再將舊位置進(jìn)行更新硝烂。

2.2.4 出現(xiàn)的問(wèn)題

單選閃爍.gif

看動(dòng)畫箕别,你會(huì)發(fā)現(xiàn)當(dāng)點(diǎn)擊新的位置時(shí),舊位置會(huì)發(fā)生閃爍,這是因?yàn)镽ecyclerView默認(rèn)設(shè)置了DefaultItemAnimator動(dòng)畫串稀,所以在調(diào)用notifyItemChanged()方法時(shí)啥酱,會(huì)產(chǎn)生動(dòng)畫,發(fā)生閃爍現(xiàn)象厨诸。

解決方案:

(mRecyclerView.itemAnimator as DefaultItemAnimator).supportsChangeAnimations = false

將其設(shè)置為不支持?jǐn)?shù)據(jù)更改時(shí)的動(dòng)畫即可镶殷。

2.3 可取消的單選

2.3.1 實(shí)現(xiàn)思路

要實(shí)現(xiàn)可取消的單選,只需要將上面的Adapter更改兩個(gè)地方

  • 將selPosition設(shè)置為-1微酬,代表默認(rèn)不選中任何選項(xiàng)
  • 更改onBindViewHolder()內(nèi)ItemView的點(diǎn)擊事件邏輯

2.3.2 具體實(shí)現(xiàn)

class SingleSelectAdapter(var mDataList: MutableList<String>) :
RecyclerView.Adapter<SingleSelectAdapter2.MyViewHolder>() {
 
    private var mItemClickListener: MyItemClickListener?=null

    //選擇的位置(-1則代表默認(rèn)沒(méi)有選中)
    private var selPosition = -1
    //臨時(shí)記錄上次選擇的位置
    private var temp = -1

    .....
    override fun onBindViewHolder(holder: SingleSelectAdapter2.MyViewHolder, position: Int) {
        holder.date.text = mDataList[position]

        holder.itemView.isSelected = holder.layoutPosition == selPosition

        holder.itemView.setOnClickListener {
            //已選中則取消選中绘趋,更新原位置
            if (it.isSelected) {
                it.isSelected = false
                notifyItemChanged(selPosition)
                selPosition = -1
                //更新舊位置
                mItemClickListener?.onClick(holder.layoutPosition,false)
            }else{
                holder.itemView.isSelected = true
                //將舊的位置保存下來(lái),用于后面把舊的位置顏色變回來(lái)
                temp = selPosition
                //設(shè)置新的位置
                selPosition = holder.layoutPosition
                //更新舊位置
                notifyItemChanged(temp)
                mItemClickListener?.onClick(holder.layoutPosition,true)
            }
        }
    }

    interface MyItemClickListener{
        fun onClick(position:Int,isSelect:Boolean)
    }
    fun setOnMyItemClickListener(listener:MyItemClickListener){
        this.mItemClickListener = listener
    }
}

3. RecyclerView實(shí)現(xiàn)多選功能

3.1 實(shí)現(xiàn)思路

  • 相比及單選颗管,多選就容易多了陷遮,布局和單選的一樣,也是使用selector來(lái)控制選中和未選中狀態(tài)的顏色垦江。
  • 用集合來(lái)保存選中的位置下標(biāo)帽馋。
  • 當(dāng)點(diǎn)擊itemView時(shí),若該itemView的下標(biāo)不存在于集合中比吭,則將該位置放入集合绽族,且該位置的isSelect屬性設(shè)置為true;若存在于集合中衩藤,則將其從集合中remove掉吧慢,然后將該位置的isSelect屬性設(shè)置為false即可。

3.2 具體實(shí)現(xiàn)

class MutilSelectAdapter(val dataList:MutableList<String>):RecyclerView.Adapter<MutilSelectAdapter.MyViewHolder>() {

    //用來(lái)記錄已經(jīng)勾選的位置(set集合是為了防止放入重復(fù)數(shù)據(jù))
    var mutilSelectedList = mutableSetOf<Int>()

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        holder.tvContent.text = dataList[position]
        holder.ivSelect.isSelected = mutilSelectedList.contains(position)
        holder.itemView.setOnClickListener {
            if (mutilSelectedList.contains(position)) {
                mutilSelectedList.remove(position)
                holder.ivSelect.isSelected = false
                Log.i(TAG, "onBindViewHolder: 取消選中")
            } else {
                mutilSelectedList.add(position)
                holder.ivSelect.isSelected = true
                Log.i(TAG, "onBindViewHolder: 選中")
            }
        }
    }
}

總結(jié)

總體上還是很簡(jiǎn)單的赏表,無(wú)非就是用isSelect屬性配合Selector來(lái)實(shí)現(xiàn)選中和未選中的效果检诗,然后就是Adapter內(nèi)點(diǎn)擊事件里選中和未選中的邏輯設(shè)定,沒(méi)有太多難點(diǎn)瓢剿。以后遇到的無(wú)論是橫向還是縱向逢慌,什么樣的布局,無(wú)非就是item布局更改一下方向改變一下间狂,具體的操作沒(méi)什么難點(diǎn)攻泼。項(xiàng)目Github地址

如果本文對(duì)你有幫助,請(qǐng)別忘記三連前标,如果有不恰當(dāng)?shù)牡胤揭舱?qǐng)?zhí)岢鰜?lái)坠韩,下篇文章見(jiàn)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末炼列,一起剝皮案震驚了整個(gè)濱河市只搁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌俭尖,老刑警劉巖氢惋,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件洞翩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡焰望,警方通過(guò)查閱死者的電腦和手機(jī)骚亿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)熊赖,“玉大人来屠,你說(shuō)我怎么就攤上這事≌痧模” “怎么了俱笛?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)传趾。 經(jīng)常有香客問(wèn)我迎膜,道長(zhǎng)浆兰,這世上最難降的妖魔是什么榕订? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任玩裙,我火速辦了婚禮凌箕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赖歌。我一直安慰自己,他們只是感情好展父,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般弃榨。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼鹅经。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蹦误,可吹牛的內(nèi)容都是我干的妹沙。 我是一名探鬼主播涡真,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了奋渔?” 一聲冷哼從身側(cè)響起歹啼,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拓萌,失蹤者是張志新(化名)和其女友劉穎屡限,沒(méi)想到半個(gè)月后激才,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體册养,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年球拦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了靠闭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片帐我。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愧膀,靈堂內(nèi)的尸體忽然破棺而出拦键,到底是詐尸還是另有隱情,我是刑警寧澤檩淋,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布芬为,位于F島的核電站,受9級(jí)特大地震影響蟀悦,放射性物質(zhì)發(fā)生泄漏媚朦。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一日戈、第九天 我趴在偏房一處隱蔽的房頂上張望询张。 院中可真熱鬧,春花似錦浙炼、人聲如沸份氧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)半火。三九已至,卻和暖如春季俩,著一層夾襖步出監(jiān)牢的瞬間钮糖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工酌住, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留店归,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓酪我,卻偏偏與公主長(zhǎng)得像消痛,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子都哭,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容