Sei sulla pagina 1di 25

enoent

RSS

Search

Navigate

Blog
Archives

RecyclerViewbasics
Jan18th,20157:37pm

IntroductiontoRecyclerView
RecyclerViewhasbeenintroducedwithAndroid5,inthesupportv7package.Itallowstodisplayacollectionofitemsinanarbitrary
disposition(thinkofaListView,butmuchmoreflexible).Asthenameofthesupportpackageindicates,itsavailablefromtheAPIlevel7
(Android2.1).

Itsnamecomesfromthewayitworks:whenanitemishidden,insteadofbeingdestroyedandanewonebeingcreatedforeachnewly
displayeditem,hiddenonesarerecycled:theyarereused,withnewdataboundonthem.

ARecyclerViewissplitinto6maincomponents:

anAdapter,providingdata(similartoListViews)
anItemAnimator,responsibleonanimationstoplaywhenitemsaremodified,added,removedormoved
anItemDecoration,whichcanadddrawingsorchangethelayoutofanitem(e.g.addingdividers)
aLayoutManager,whichspecifieshowitemsarelaidout(grid,list)
aViewHolder,thebaseclassforeachitemsview
theRecyclerViewitself,bindingeverythingtogether

Defaultimplementationsarebundledinthesupportv7packageforsomeofthesecomponents.YouhaveanItemAnimatorandthree
LayoutManagers(alinearone,similartoaListView,astaticgrid,andastaggeredgrid).TheRecyclerViewdoesntneedtobemodified,
andtheItemDecorationisoptional.ThisleavesustheAdapterandtheViewHolder.

DisplayaRecyclerView
1.Prepareyourproject
TouseaRecyclerView,youneedaspecificmoduleofthesupprtv7package.IfyouuseGradle,addtoyourdependencies:

compile'com.android.support:recyclerviewv7:21.0.3'

ThispostwillalsouseCardViews,sowereferencethemtoo:

compile'com.android.support:cardviewv7:21.0.3'

Thatsit!

2.Thebaseitem
Wellwriteaverysimplelist,containingitemswithatitleandasubtitle.

Item.java

1 publicclassItem{
2 privateStringtitle;
3 privateStringsubtitle;
4
5 Item(Stringtitle,Stringsubtitle){
6 this.title=title;
7 this.subtitle=subtitle;
8 }
9
10 publicStringgetTitle(){
11 returntitle;
12 }
13
14 publicStringgetSubtitle(){
15 returnsubtitle;
16 }
17 }

3.Itemlayout
Asmentionnedearlier,ouritemswillbedisplayedonaCardView.ACardViewisjustaFrameLayoutwithsomedecorations,hencehaving
twoTextViewstodisplayisprettysimple:

layout/item.xml

1 <?xmlversion="1.0"encoding="utf8"?>
2 <android.support.v7.widget.CardView
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/resauto"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 app:contentPadding="8dp"
8 app:cardUseCompatPadding="true">
9
10 <LinearLayout
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 android:orientation="vertical">
14
15 <TextView
16 android:id="@+id/title"
17 android:layout_width="match_parent"
18 android:layout_height="wrap_content"
19 android:singleLine="true"
20 style="@style/Base.TextAppearance.AppCompat.Headline"/>
21
22 <TextView
23 android:id="@+id/subtitle"
24 android:layout_width="match_parent"
25 android:layout_height="0dp"
26 android:layout_weight="1"
27 style="@style/Base.TextAppearance.AppCompat.Subhead"/>
28
29 </LinearLayout>
30
31 </android.support.v7.widget.CardView>

4.Theadapter
ThefirststepistodefineourViewHolderclass.ItmustextendRecyclerView.ViewHolder,andshouldstorereferencestotheviewsyoull
needwhenbindingyourdataontheholder.Here,wehaveourtwoTextViews:

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 @SuppressWarnings("unused")
3 privatestaticfinalStringTAG=Adapter.class.getSimpleName();
4
5 publicstaticclassViewHolderextendsRecyclerView.ViewHolder{
6 TextViewtitle;
7 TextViewsubtitle;
8
9 publicViewHolder(ViewitemView){
10 super(itemView);
11
12 title=(TextView)itemView.findViewById(R.id.title);
13 subtitle=(TextView)itemView.findViewById(R.id.subtitle);
14 }
15 }
16 }

Now,whatsthesimplestwaytostoreacollectionofobjects?Well,aCollection.Sometimes,evenJavagetsitright.Forthesimplicityof
thisexample,wellstoreouritemsinanArrayListinourAdapter:

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 @SuppressWarnings("unused")
3 privatestaticfinalStringTAG=Adapter.class.getSimpleName();
4
5 privatestaticfinalintITEM_COUNT=50;
6 privateList<Item>items;
7
8 publicAdapter(){
9 super();
10
11 //Createsomeitems
12 items=newArrayList<>();
13 for(inti=0;i<ITEM_COUNT;++i){
14 items.add(newItem("Item"+i,"Thisistheitemnumber"+i));
15 }
16 }
17
18 //ViewHolderdefinitionomitted
19 }

ThenweshouldimplementtheactualRecyclerView.Adaptermethods:

onCreateViewHolder(ViewGroupparent,intviewType)shouldcreatetheview,andreturnamatchingViewHolder,
onBindViewHolder(ViewHolderholder,intposition)shouldfilltheViewHolderwithdatafromitematpositionposition,
getItemCount()shouldgivethenumberofelementsintheAdapterunderlyingdatacollection.

Theimplementationofthesemethodsisprettystraightforwardinourcase:

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //Attributesandconstructoromitted
3
4 @Override
5 publicViewHolderonCreateViewHolder(ViewGroupparent,intviewType){
6 Viewv=LayoutInflater.from(parent.getContext()).inflate(R.layout.item,parent,false);
7 returnnewViewHolder(v);
8 }
9
10 @Override
11 publicvoidonBindViewHolder(ViewHolderholder,intposition){
12 finalItemitem=items.get(position);
13
14 holder.title.setText(item.getTitle());
15 holder.subtitle.setText(item.getSubtitle());
16 }
17
18 @Override
19 publicintgetItemCount(){
20 returnitems.size();
21 }
22
23 //ViewHolderdefinitionomitted
24 }

5.Bindeverythingtogether
Wedefinedeverythingweneeded.Now,itstimetogiveeverythingtoaRecyclerView,andwatchthemagichappen!Firststep,adda
RecyclerViewtoanActivity:

layout/activity_main.xml

1 <RelativeLayout
2 xmlns:android="http://schemas.android.com/apk/res/android"
3 xmlns:tools="http://schemas.android.com/tools"
4 android:layout_width="match_parent"
5 android:layout_height="match_parent"
6 tools:context=".MainActivity">
7
8 <android.support.v7.widget.RecyclerView
9 android:id="@+id/recycler_view"
10 android:layout_width="match_parent"
11 android:layout_height="match_parent"/>
12
13 </RelativeLayout>

Wewillusethesimplestlayoutmanagerfornow:LinearLayoutManager.WewillalsousetheDefaultItemAnimator.

MainActivity.java

1 publicclassMainActivityextendsActionBarActivity{
2 @SuppressWarnings("unused")
3 privatestaticfinalStringTAG=MainActivity.class.getSimpleName();
4
5 @Override
6 protectedvoidonCreate(BundlesavedInstanceState){
7 super.onCreate(savedInstanceState);
8 setContentView(R.layout.activity_main);
9
10 RecyclerViewrecyclerView=(RecyclerView)findViewById(R.id.recycler_view);
11 recyclerView.setAdapter(newAdapter());
12 recyclerView.setItemAnimator(newDefaultItemAnimator());
13 recyclerView.setLayoutManager(newLinearLayoutManager(this));
14 }
15 }

Compile,run,and

NowthatwehaveabasicRecyclerViewdisplayed,letsseewhatwecandowithit.
DifferentkindofviewsonthesameRecyclerView
Letssayyouhavetwotypesofitemsyouwanttodisplay.Forexample,youdisplayaremotemusiccollection,andonlysomealbumsare
availableoffline.Youcandospecificactionsonthem,anddisplaysomespecificinformationstoo.

Forourexample,wewilladdanactivepropertytoouritems.

Item.java

1 publicclassItem{
2 privateStringtitle;
3 privateStringsubtitle;
4 privatebooleanactive;
5
6 Item(Stringtitle,Stringsubtitle,booleanactive){
7 this.title=title;
8 this.subtitle=subtitle;
9 this.active=active;
10 }
11
12 publicStringgetTitle(){
13 returntitle;
14 }
15
16 publicStringgetSubtitle(){
17 returnsubtitle;
18 }
19
20 publicbooleanisActive(){
21 returnactive;
22 }
23 }

Wechangeouritemscreationtohavesomeactiveones,andchangethesubtitletoaddanactive/inactiveindication:

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //Attributesomitted
3
4 publicAdapter(){
5 super();
6
7 //Createsomeitems
8 Randomrandom=newRandom();
9 items=newArrayList<>();
10 for(inti=0;i<ITEM_COUNT;++i){
11 items.add(newItem("Item"+i,"Thisistheitemnumber"+i,random.nextBoolean()));
12 }
13 }
14
15 //onCreateViewHolderomitted
16
17 @Override
18 publicvoidonBindViewHolder(ViewHolderholder,intposition){
19 finalItemitem=items.get(position);
20
21 holder.title.setText(item.getTitle());
22 holder.subtitle.setText(item.getSubtitle()+",whichis"+
23 (item.isActive()?"active":"inactive"));
24 }
25
26 //
27 }

Displayingadifferentstringisagoodstart,butweneedmore.Whenwewerewritingtheadapter,youmayhavenoticedanargumentthat
wedidntuseinonCreateViewHolder(ViewGroupparent,intviewType).ThisviewTypeisheretoachieveexactlywhatweneed:alterthe
ViewHoldercreation.WemusttelltheAdapterhowtodeterminethetypeofanitem.Wedothisbyoverridinganewmethod,
getItemViewType(intposition):

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //
3
4 privatestaticfinalintTYPE_INACTIVE=0;
4 privatestaticfinalintTYPE_INACTIVE=0;
5 privatestaticfinalintTYPE_ACTIVE=1;
6
7 //
8
9 @Override
10 publicintgetItemViewType(intposition){
11 finalItemitem=items.get(position);
12
13 returnitem.isActive()?TYPE_ACTIVE:TYPE_INACTIVE;
14 }
15
16 //
17 }

Now,youhavemultiplepossibilitiesdependingonyourneeds:createadifferentViewHolderforeachviewtype,inflateadifferentlayoutbut
usethesameViewHolderTokeepthingssimplehere,wewillusethesameViewHolder,butadifferentlayout.Wewillkeepusingthe
presentlayoutforinactiveitems,andcreateanewforactiveones:

layout/item_active.xml

1 <?xmlversion="1.0"encoding="utf8"?>
2 <android.support.v7.widget.CardView
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/resauto"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 app:contentPadding="8dp"
8 app:cardUseCompatPadding="true">
9
10 <LinearLayout
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 android:orientation="vertical">
14
15 <TextView
16 android:id="@+id/title"
17 android:layout_width="match_parent"
18 android:layout_height="wrap_content"
19 android:singleLine="true"
20 android:textColor="@color/material_deep_teal_500"
21 style="@style/Base.TextAppearance.AppCompat.Headline"/>
22
23 <TextView
24 android:id="@+id/subtitle"
25 android:layout_width="match_parent"
26 android:layout_height="0dp"
27 android:layout_weight="1"
28 android:textColor="@color/material_blue_grey_900"
29 style="@style/Base.TextAppearance.AppCompat.Subhead"/>
30
31 </LinearLayout>
32
33 </android.support.v7.widget.CardView>

Lastbutnotleast:wehavetoinflateadifferentlayoutdependingonviewTypeinonCreateViewHolder:

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //
3
4 @Override
5 publicViewHolderonCreateViewHolder(ViewGroupparent,intviewType){
6 finalintlayout=viewType==TYPE_INACTIVE?R.layout.item:R.layout.item_active;
7
8 Viewv=LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
9 returnnewViewHolder(v);
10 }
11
12 //
13 }

Now,wecandistinguishactiveitemsfrominactiveones:
Layoutmanagers
LinearLayoutManager

Thisistheoneweused.ThismanagerreplicatestheListViewbehaviour.Ittakesuptothreeparameters:aContext(mandatory),an
orientation(vertical,whichisthedefault,orhorizontal),andabooleanallowingtoreversethelayout.

Thisiswhathappenswithareversed,horizontallinearlayoutmanager:
NotethatwhenreverseLayoutissettotrue,theviewisautomaticalydisplayedattheendwithouttheneedforscrolling.

GridLayoutManager

ThisoneissimilartotheGridView.Ittakesuptofourparameters:aContext(mandatory),aspancount(mandatory),anorientation
(vertical,whichisthedefaulttoo,orhorizontal),andareverseLayoutoption.

HeresaGridLayoutManagerwithaspancountsetto3,verticalorientation,notreversed:
NotethatthereverseLayoutcanbesurprisingwhenworkingwithagrid.Itreversesthelayoutinthedirectionyougaveit,butnotonthe
otherone.Withaverticalorientation,theitemsarereversedinverticalorder,butnotinhorizontal:
StaggeredGridLayoutManager

TheStaggeredGridLayoutManagerisaGridLayoutManageronsteroids.Andassteroidsmayhavebadeffectsonyourbody,theyhavebad
effectsontheStaggeredGridLayoutManager,whichatthetimeofwritingofthispost(supportv721.0.0.3),hassomeprettyannoyingbugs.
Itseemsthatthislayoutmanagerwasfinishedinahurry,andisntinparwiththeotherones.Wecannotethisinitsparameters:itdoesnt
needaContext,buttheorientationismandatory.Italsoneedsaspancount,liketheGridLayoutManager.Thecodeallowstoreverseit,but
theresnoparameterintheconstructortodothis.

Thislayoutisagrid,withafixedspan.However,wecanhaveitemsspanningonthewholelineorcolumn.Letsseehowitworks.Using
ouractive/inactiveitemsfromearlier,wellmakeactiveitemsfullyspanning.ThisisdoneintheAdapter,whenbindinganitem.

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //
3
4 @Override
5 publicvoidonBindViewHolder(ViewHolderholder,intposition){
6 finalItemitem=items.get(position);
7
8 holder.title.setText(item.getTitle());
9 holder.subtitle.setText(item.getSubtitle()+",whichis"+(item.isActive()?"active":"inactive"));
10
11 //Spantheitemifactive
12 finalViewGroup.LayoutParamslp=holder.itemView.getLayoutParams();
13 if(lpinstanceofStaggeredGridLayoutManager.LayoutParams){
14 StaggeredGridLayoutManager.LayoutParamssglp=(StaggeredGridLayoutManager.LayoutParams)lp;
15 sglp.setFullSpan(item.isActive());
16 holder.itemView.setLayoutParams(sglp);
17 }
18 }
19
20 //
21 }
Here,wemustcheckifthelayoutmanagerisaStaggeredGridLayoutManager(line13).Ifitsthecase,wecanmodifythelayoutparams
accordingly.

Themandatoryscreenshot:

Respondtoclicksonitems
TheRecyclerViewdoesntprovideanyhighlevelAPItohandleitemclicksastheListViewdoes.However,itsstillprettysimpleto
achieve.

Letsthinkaboutit:wewanttolistentoclickandlongclickeventsoneachitem.EachitemisrepresentedbyaViewHolder.Each
ViewHolderisinitializedfromitsrootView.Well,thatsperfect:Viewascallbacksforclickandlongclickevents.Thelastthingweneedis
mappingeachViewHoldertoitsposition.RecyclerView.ViewHolderdoesalltheworkforus:themethodgetPosition()returnsthe
positionofthecurrentlybounditem.

Adapter.java

1 publicclassAdapterextendsRecyclerView.Adapter<Adapter.ViewHolder>{
2 //
3
4 publicstaticclassViewHolderextendsRecyclerView.ViewHolderimplementsView.OnClickListener,
5 View.OnLongClickListener{
6 @SuppressWarnings("unused")
7 privatestaticfinalStringTAG=ViewHolder.class.getSimpleName();
8
9 TextViewtitle;
10 TextViewsubtitle;
11
12 publicViewHolder(ViewitemView){
13 super(itemView);
14
15 title=(TextView)itemView.findViewById(R.id.title);
16 subtitle=(TextView)itemView.findViewById(R.id.subtitle);
17
18 itemView.setOnClickListener(this);
19 itemView.setOnLongClickListener(this);
20 }
21
22 @Override
23 publicvoidonClick(Viewv){
24 Log.d(TAG,"Itemclickedatposition"+getPosition());
25 }
26
27 @Override
28 publicbooleanonLongClick(Viewv){
29 Log.d(TAG,"Itemlongclickedatposition"+getPosition());
30 returntrue;
31 }
32 }
33 }

Selectionhandling
Afrequentpatternwhenlongclickingonalistitemistotriggeraselectionmode.Onceagain,theRecyclerViewdoesnthelpuswiththis,
butitsprettysimpletodo.Itcanbesplitinthreesteps:

maintainaselectionstate,
updatetheviewoftheselecteditems,
starttheselectionmode.

Toillustratethispart,wewilladdawaytoselectitems,thenremovethisselection.

1.Selectionstate
WeneedtomodifyourAdaptertokeepalistofselectedelements.HeresalistofwhattheAdapterhastoprovide:

listofselectedelements,
changeselectionstateofagivenelement.

Wecanaddbonusmethods:

checkifaspecificelementisselected,
clearthewholeselection,
givethenumberofselectedelements.

Ididntchosethesemethodsrandomly,wewillneedthemforthenextparts.

Wecannoticeonethingwiththesefivemethods:noneofthemisItemspecific.Wecanwritetheminagenericway,andreuseourAdapter
behaviour.

Oncewegotallofthisprepared,thecodeisprettysimple:

SelectableAdapter.java

1 publicabstractclassSelectableAdapter<VHextendsRecyclerView.ViewHolder>extendsRecyclerView.Adapter<VH>{
2 @SuppressWarnings("unused")
3 privatestaticfinalStringTAG=SelectableAdapter.class.getSimpleName();
4
5 privateSparseBooleanArrayselectedItems;
6
7 publicSelectableAdapter(){
8 selectedItems=newSparseBooleanArray();
9 }
10
11 /**
12 *Indicatesiftheitematpositionpositionisselected
13 *@parampositionPositionoftheitemtocheck
14 *@returntrueiftheitemisselected,falseotherwise
15 */
16 publicbooleanisSelected(intposition){
17 returngetSelectedItems().contains(position);
18 }
19
20 /**
21 *Toggletheselectionstatusoftheitematagivenposition
22 *@parampositionPositionoftheitemtotoggletheselectionstatusfor
23 */
24 publicvoidtoggleSelection(intposition){
25 if(selectedItems.get(position,false)){
26 selectedItems.delete(position);
27 }else{
28 selectedItems.put(position,true);
29 }
30 notifyItemChanged(position);
31 }
32
33 /**
34 *Cleartheselectionstatusforallitems
35 */
36 publicvoidclearSelection(){
37 List<Integer>selection=getSelectedItems();
38 selectedItems.clear();
39 for(Integeri:selection){
40 notifyItemChanged(i);
41 }
42 }
43
44 /**
45 *Counttheselecteditems
46 *@returnSelecteditemscount
47 */
48 publicintgetSelectedItemCount(){
49 returnselectedItems.size();
50 }
51
52 /**
53 *Indicatesthelistofselecteditems
54 *@returnListofselecteditemsids
55 */
56 publicList<Integer>getSelectedItems(){
57 List<Integer>items=newArrayList<>(selectedItems.size());
58 for(inti=0;i<selectedItems.size();++i){
59 items.add(selectedItems.keyAt(i));
60 }
61 returnitems;
62 }
63 }

Lastchangeneeded:ourAdaptermustextendSelectableAdapter.Itscodedoesntchange:

Adapter.java

1 publicclassAdapterextendsSelectableAdapter<Adapter.ViewHolder>{
2 //
3}

2.Updatetheitemviews
Tonotifytheuserthatanitemisselected,weoftenseeacoloredoverlayontheselectedviews.Thatswhatwelldo.Onbothitem.xml
anditem_active.xml,weaddaninvisible,coloredView.AsthisViewshouldfillthewholeCardViewspace,weneedtomakesomechange
inthelayout(movethepaddingtotheinnerLinearLayoutinsteadoftheCardView).Thecolorshouldbetransparent.

WecanalsoaddanicetouchfeedbackusingtheframeworksselectableItemBackgroundasaforegroundontheCardView.OnAndroid
5,thisbackgrounddisplaysaripple,andasimplegreyoverlayonpreviousAndroidversions.

item.xml(samechangesgoesforitem_active.xml)

1 <?xmlversion="1.0"encoding="utf8"?>
2 <android.support.v7.widget.CardView
3 xmlns:android="http://schemas.android.com/apk/res/android"
4 xmlns:app="http://schemas.android.com/apk/resauto"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:foreground="?android:attr/selectableItemBackground"
8 app:cardUseCompatPadding="true">
9
10 <LinearLayout
11 android:layout_width="match_parent"
12 android:layout_height="match_parent"
13 android:orientation="vertical"
14 android:padding="8dp">
15
16 <TextView
17 android:id="@+id/title"
18 android:layout_width="match_parent"
19 android:layout_height="wrap_content"
20 android:singleLine="true"
21 style="@style/Base.TextAppearance.AppCompat.Headline"/>
22
23 <TextView
24 android:id="@+id/subtitle"
25 android:layout_width="match_parent"
26 android:layout_height="0dp"
27 android:layout_weight="1"
28 style="@style/Base.TextAppearance.AppCompat.Subhead"/>
29
30 </LinearLayout>
31
32 <View
33 android:id="@+id/selected_overlay"
34 android:layout_width="match_parent"
35 android:layout_height="match_parent"
36 android:background="@color/selected_overlay"
37 android:visibility="invisible"/>
38
39 </android.support.v7.widget.CardView>

Thenextstepistodecidewhentodisplaythisoverlay.Therightplacetodoitseemsprettyobvious:AdaptersonBindViewHolder().We
alsoneedtoaddareferencetotheoverlayintheViewHolder.

Adapter.java

1 publicclassAdapterextendsSelectableAdapter<Adapter.ViewHolder>{
2 //
3
4 @Override
5 publicvoidonBindViewHolder(ViewHolderholder,intposition){
6 finalItemitem=items.get(position);
7
8 holder.title.setText(item.getTitle());
9 holder.subtitle.setText(item.getSubtitle()+",whichis"+(item.isActive()?"active":"inactive"));
10
11 //Spantheitemifactive
12 finalViewGroup.LayoutParamslp=holder.itemView.getLayoutParams();
13 if(lpinstanceofStaggeredGridLayoutManager.LayoutParams){
14 StaggeredGridLayoutManager.LayoutParamssglp=(StaggeredGridLayoutManager.LayoutParams)lp;
15 sglp.setFullSpan(item.isActive());
16 holder.itemView.setLayoutParams(sglp);
17 }
18
19 //Highlighttheitemifit'sselected
20 holder.selectedOverlay.setVisibility(isSelected(position)?View.VISIBLE:View.INVISIBLE);
21 }
22
23 //
24
25 publicstaticclassViewHolderextendsRecyclerView.ViewHolderimplementsView.OnClickListener,
26 View.OnLongClickListener{
27 @SuppressWarnings("unused")
28 privatestaticfinalStringTAG=ViewHolder.class.getSimpleName();
29
30 TextViewtitle;
31 TextViewsubtitle;
32 ViewselectedOverlay;
33
34 publicViewHolder(ViewitemView){
35 super(itemView);
36
37 title=(TextView)itemView.findViewById(R.id.title);
38 subtitle=(TextView)itemView.findViewById(R.id.subtitle);
39 selectedOverlay=itemView.findViewById(R.id.selected_overlay);
40
41 itemView.setOnClickListener(this);
42 itemView.setOnLongClickListener(this);
43 }
44
45 //
46 }
47 }
3.Starttheselectionmode
Thislaststepwillbealittlemorecomplex,butnothingreallyhard.First,weneedtorouteclickandlongclickeventsbacktoourActivity.
Toachievethis,ourViewHolderswillexposealistener.WewillpassitthroughtheAdapter:

Adapter.java

1 publicclassAdapterextendsSelectableAdapter<Adapter.ViewHolder>{
2 //
3
4 privateViewHolder.ClickListenerclickListener;
5
6 publicAdapter(ViewHolder.ClickListenerclickListener){
7 super();
8
9 this.clickListener=clickListener;
10
11 //Createsomeitems
12 Randomrandom=newRandom();
13 items=newArrayList<>();
14 for(inti=0;i<ITEM_COUNT;++i){
15 items.add(newItem("Item"+i,"Thisistheitemnumber"+i,random.nextBoolean()));
16 }
17 }
18
19 @Override
20 publicViewHolderonCreateViewHolder(ViewGroupparent,intviewType){
21 finalintlayout=viewType==TYPE_INACTIVE?R.layout.item:R.layout.item_active;
22
23 Viewv=LayoutInflater.from(parent.getContext()).inflate(layout,parent,false);
24 returnnewViewHolder(v,clickListener);
25 }
26
27 //
28
29 publicstaticclassViewHolderextendsRecyclerView.ViewHolderimplementsView.OnClickListener,
30 View.OnLongClickListener{
31 @SuppressWarnings("unused")
32 privatestaticfinalStringTAG=ViewHolder.class.getSimpleName();
33
34 TextViewtitle;
35 TextViewsubtitle;
36 ViewselectedOverlay;
37
38 privateClickListenerlistener;
39
40 publicViewHolder(ViewitemView,ClickListenerlistener){
41 super(itemView);
42
43 title=(TextView)itemView.findViewById(R.id.title);
44 subtitle=(TextView)itemView.findViewById(R.id.subtitle);
45 selectedOverlay=itemView.findViewById(R.id.selected_overlay);
46
47 this.listener=listener;
48
49 itemView.setOnClickListener(this);
50 itemView.setOnLongClickListener(this);
51 }
52
53 @Override
54 publicvoidonClick(Viewv){
55 if(listener!=null){
56 listener.onItemClicked(getPosition());
57 }
58 }
59
60 @Override
61 publicbooleanonLongClick(Viewv){
62 if(listener!=null){
63 returnlistener.onItemLongClicked(getPosition());
64 }
65
66 returnfalse;
67 }
68
69 publicinterfaceClickListener{
70 publicvoidonItemClicked(intposition);
71 publicbooleanonItemLongClicked(intposition);
72 }
73 }

74 }
74 }

Todistinguishtheselectionmodefromthenormalmode,wewilluseanActionMode,allowingustodisplayadifferentActionBarwhilethe
selectionisactive.Toachievethis,wehavetoimplementabasicActionMode.Callback.Forsimplicity,ourActivitywillimplementthis
interfaceinaninnerclass.Itwillalsoimplementournewclicklistenerinterface,Adapter.ViewHolder.ClickListener.Wewillneedaccess
toourAdapterfromthecallbackclass,sowemoveitasanattributeintheActivity.

Letssummarizetheclickhandlerslogic.Onaclick,iftheresnocurrentselection,wedonothing.Ifthereissomethingselected,wetoggle
theselectionstateoftheclickeditem.Onalongclick,ifthereisnocurrentselection,westarttheselectionandtoggletheselectionstateof
theclickeditem.Ifthereisalreadysomethingselected,wetoggletheselectionstatetoo.

OurMainActivitybecomesalittlemorecomplex:

MainActivity.java

1 publicclassMainActivityextendsActionBarActivityimplementsAdapter.ViewHolder.ClickListener{
2 @SuppressWarnings("unused")
3 privatestaticfinalStringTAG=MainActivity.class.getSimpleName();
4
5 privateAdapteradapter;
6 privateActionModeCallbackactionModeCallback=newActionModeCallback();
7 privateActionModeactionMode;
8
9 @Override
10 protectedvoidonCreate(BundlesavedInstanceState){
11 super.onCreate(savedInstanceState);
12 setContentView(R.layout.activity_main);
13
14 adapter=newAdapter(this);
15
16 RecyclerViewrecyclerView=(RecyclerView)findViewById(R.id.recycler_view);
17 recyclerView.setAdapter(adapter);
18 recyclerView.setItemAnimator(newDefaultItemAnimator());
19 recyclerView.setLayoutManager(newStaggeredGridLayoutManager(3,StaggeredGridLayoutManager.VERTICAL));
20 }
21
22 @Override
23 publicvoidonItemClicked(intposition){
24 if(actionMode!=null){
25 toggleSelection(position);
26 }
27 }
28
29 @Override
30 publicbooleanonItemLongClicked(intposition){
31 if(actionMode==null){
32 actionMode=startSupportActionMode(actionModeCallback);
33 }
34
35 toggleSelection(position);
36
37 returntrue;
38 }
39
40 /**
41 *Toggletheselectionstateofanitem.
42 *
43 *Iftheitemwasthelastoneintheselectionandisunselected,theselectionisstopped.
44 *Notethattheselectionmustalreadybestarted(actionModemustnotbenull).
45 *
46 *@parampositionPositionoftheitemtotoggletheselectionstate
47 */
48 privatevoidtoggleSelection(intposition){
49 adapter.toggleSelection(position);
50 intcount=adapter.getSelectedItemCount();
51
52 if(count==0){
53 actionMode.finish();
54 }else{
55 actionMode.setTitle(String.valueOf(count));
56 actionMode.invalidate();
57 }
58 }
59
60 privateclassActionModeCallbackimplementsActionMode.Callback{
61 @SuppressWarnings("unused")
62 privatefinalStringTAG=ActionModeCallback.class.getSimpleName();
63
64 @Override
64 @Override
65 publicbooleanonCreateActionMode(ActionModemode,Menumenu){
66 mode.getMenuInflater().inflate(R.menu.selected_menu,menu);
67 returntrue;
68 }
69
70 @Override
71 publicbooleanonPrepareActionMode(ActionModemode,Menumenu){
72 returnfalse;
73 }
74
75 @Override
76 publicbooleanonActionItemClicked(ActionModemode,MenuItemitem){
77 switch(item.getItemId()){
78 caseR.id.menu_remove:
79 //TODO:actuallyremoveitems
80 Log.d(TAG,"menu_remove");
81 mode.finish();
82 returntrue;
83
84 default:
85 returnfalse;
86 }
87 }
88
89 @Override
90 publicvoidonDestroyActionMode(ActionModemode){
91 adapter.clearSelection();
92 actionMode=null;
93 }
94 }
95 }

Andhereistheresult.ThescreenshotwastakenwhileselectingtheitemItem5:

Weneedtohandleourremoveevent,whichdoesnothingfornow.Letsseehowtomodifyourdatasetinthelastpart.
Changingthedataset
Inordertoupdatetheview,theAdaptermustnotifywhenachangeoccursonitsdata.OnbasicListViews,adaptershadasinglemethod
toachievethat:notifyDataSetChanged().However,thismethodisfarfromoptimal:everyviewmustberefreshed,becausewedontknow
exactlywhatchanged.WiththeRecyclerView.Adapter,wevegotmultiplemethods:

notifyItemChanged(intposition)
notifyItemInserted(intposition)
notifyItemRemoved(intposition)
notifyItemMoved(intfromPosition,inttoPosition)
notifyItemRangeChanged(intpositionStart,intitemCount)
notifyItemRangeInserted(intpositionStart,intitemCount)
notifyItemRangeRemoved(intpositionStart,intitemCount)
notifyDataSetChanged()

Wecannotifyaniteminsertion,removalandchange,sameforarangeofitems,anitemmove,orafulldatasetchange.Letstakethe
removalasanexample.

WewillwritetwopublicmethodsinourAdaptertoallowexternalclassestoremoveeitherasingleitem,oralistofitems.Whiletheremoval
ofasingleitemisstraightforward,weneedtothinkalittlemoreforthelist.

Iftheuserprovidesuswithalistof[5,8,9]toremove,ifwestartbyremovingtheitem5,ourlistisanitemshorter,before8and9.We
shouldremove[5,7,7]oneaftertheother.Wecanhandlethat.Butwhathappensiftheuserprovides[8,9,5]?

Theresaprettysimplesolutiontothis:sortourinputlistinthereverseorder.Thisallowseasyrangesdetectiontoo,whichissomethingwe
willneedtomakeourcallstonotifyItemRangeRemoved().

Adapter.java

1 publicclassAdapterextendsSelectableAdapter<Adapter.ViewHolder>{
2 //
3
4 publicvoidremoveItem(intposition){
5 items.remove(position);
6 notifyItemRemoved(position);
7 }
8
9 publicvoidremoveItems(List<Integer>positions){
10 //Reversesortthelist
11 Collections.sort(positions,newComparator<Integer>(){
12 @Override
13 publicintcompare(Integerlhs,Integerrhs){
14 returnrhslhs;
15 }
16 });
17
18 //Splitthelistinranges
19 while(!positions.isEmpty()){
20 if(positions.size()==1){
21 removeItem(positions.get(0));
22 positions.remove(0);
23 }else{
24 intcount=1;
25 while(positions.size()>count&&positions.get(count).equals(positions.get(count1)1)){
26 ++count;
27 }
28
29 if(count==1){
30 removeItem(positions.get(0));
31 }else{
32 removeRange(positions.get(count1),count);
33 }
34
35 for(inti=0;i<count;++i){
36 positions.remove(0);
37 }
38 }
39 }
40 }
41
42 privatevoidremoveRange(intpositionStart,intitemCount){
43 for(inti=0;i<itemCount;++i){
44 items.remove(positionStart);
45 }
46 notifyItemRangeRemoved(positionStart,itemCount);
47 }
48
49 //
50 }

Andthefinalcodechunkofthisarticle:actuallycallthesetwomethods.WealreadysetupaRemoveactioninourcontextualmenu,we
justneedtocallremoveItems()fromit.Totesttheotherone,letssaythataclickonaviewwillremoveit:

MainActivity.java

1 publicclassMainActivityextendsActionBarActivityimplementsAdapter.ViewHolder.ClickListener{
2 //
3
4 @Override
5 publicvoidonItemClicked(intposition){
6 if(actionMode!=null){
7 toggleSelection(position);
8 }else{
9 adapter.removeItem(position);
10 }
11 }
12
13 //
14
15 privateclassActionModeCallbackimplementsActionMode.Callback{
16 //
17
18 @Override
19 publicbooleanonActionItemClicked(ActionModemode,MenuItemitem){
20 switch(item.getItemId()){
21 caseR.id.menu_remove:
22 adapter.removeItems(adapter.getSelectedItems());
23 mode.finish();
24 returntrue;
25
26 default:
27 returnfalse;
28 }
29 }
30
31 //
32 }
33 }

Andthatsit.Wecanremoveitems.AsabonusfromusingtherightnotificationmethodinsteadofthegenericnotifyDataSetChanged(),we
haveaniceanimation!
Conclusion
WhiletheRecyclerViewisalittlemoredifficulttosetupthanaListVieworaGridView,itallowsforaneasierresponsabilityseparation
betweentheviewholders,thedatasource,thelistitselfandamorepolisheduserexperience,thankstotheanimations.

Regardingtheperformance,IthinkthatincomparisontoawellusedListView,implementingtheViewHolderpatterncorrectly,itshouldbe
prettysimilar.However,withtheRecyclerView,youhavetousetheViewHolderpattern.Itsnotanoption.Andthatsagoodthingfor
boththeuser,whowillhavebetterperformancethanwithouttheViewHolder,andforthedeveloper,whowillhavetowritebettercode.

WhiletheRecyclerViewobviouslystilllackssomepolish(yes,Imlookingatyou,StaggeredGridLayoutManager),itsperfectlyuseable
rightnow,andisawelcomeadditionintheSDK.

ThefullexamplecodeisavailableonGitHub.

PostedbyMarcPlanoLesayJan18th,20157:37pmandroid

HostingdifferentkindsofappsonnginxSharecodeacrossmultipleplatforms

Comments

47Comments enoent
1 Login

Recommend 10 Share SortbyBest

Jointhediscussion

rockfight ayearago
IhavebeensearchingallaroundthenetforcleansolutionformultipleselectiononRecyclerView,Imustsaythisis
IhavebeensearchingallaroundthenetforcleansolutionformultipleselectiononRecyclerView,Imustsaythisis
thebestone.EverywherearoundtheinternetpeopleareimplementingGestureDetectorandIhadafeelingthatit
wasanoverkill.Ihighlyrecommendthisway.Thankyouforthistutorial.
2 Reply Share

Kernald Mod >rockfight ayearago


I'mgladithelpedyou!
2 Reply Share

OscarEscobar 9daysago
Hey,greattutorial!Iwashavinganissuewithyourcode(Testedasitisongithub).Sometimesitcrasheswitha
ArrayIndexOutOfBoundsException:length=60index=1andsometimesitdidn't.Recyclerviewandcardview
versionsv7:23.4.0.SoinsteadofusingthegetAdapterPosition(),(orgetPosition)Iused
listener.onItemClicked(getLayoutPosition())Whichseemstosolvethecrashing.I'mtryingtomakeaGalleryGrid,
yourcodejustsavedmealotoftime.Thanks!
Reply Share

Kernald Mod >OscarEscobar 8daysago


Great!Assomeonementionedinthecomments,thepositionrelatedmethodshavechangedsincethispost
waswrittenwiththefirstRecyclerViewrelease.Sorryforthetrouble)
Reply Share

richestmanalive 2monthsago
Hi,thanksforthetutorial.pleasecanyoudirectmeonupdatinganitembesidesremoval?
Reply Share

ShabeerJamaludeen 2monthsago
Haithanksforthetutorial
.Ifilledmyrecycleviewbyusingdatafromwebserviceresponseandimplementedyourselectableadapter..multi
selectionworksfine..butselecteditemnothighlighted...
Ihaveanotherdoubt.
Howtoimplementsearchin.Amultiselectrecycler??
Reply Share

Dmitry 2monthsago
Greatarticle!Ifollowedthelinkfromstackoverflowalsotryingtoimplementmultipleselectionmodewith
RecyclerView.AfterreadingIfeellikebeengraduating.HereIfoundstraightandclearanswers.Thanks!!!
Reply Share

AnkeshJaisansaria 3monthsago
Thankyouverymuchforthisarticle..........
Veryhelpfulandwellexplained

MyonlyquestioniswhattodoifIwanttochangecontextualActionbar(Actionmode)backgroundcolor.

Thankyou
Reply Share

Kernald Mod >AnkeshJaisansaria 3monthsago


Thiswillprobablyhelpyou:http://stackoverflow.com/a/237...
Reply Share

DaviBandeira 5monthsago
Whatagreattutorial.Absolutelywellexplained.
Reply Share

EkundayoBlessingFunminiyi 5monthsago
Well,Idon'tknowwhattosay.morethan...Thankyou.
Reply Share
developer 5monthsago
Himan,Thanksforthispost.HowwouldyouimplementanautofitusingGridLayoutManager?
Reply Share

Kernald Mod >developer 5monthsago


Whatdoyoumeanbyautofit?
Reply Share

developer>Kernald 5monthsago
Thankyousomuchforyourreply.Ifoundananswerherehttp://stackoverflow.com/quest....

Ijustcan'tseemtodoitwithStaggeredGridLayoutManager.
Reply Share

Aymer 6monthsago
Thanksalotman!youarealifesaver!
Reply Share

YanChengCheok 7monthsago
Hi,Isawyouareusing

holder.selectedOverlay.setVisibility(isSelected(position)?View.VISIBLE:View.INVISIBLE)

ashighlighttechnique.However,Iwouldprefertochangethebackgroundcolorashavingoverlaytechniqueseems
tohave"bluring"effect.

Isthereanywaytouseselector?AsI'mfacingflickeringproblemwhenusingselector
http://stackoverflow.com/quest...
Reply Share

Kernald Mod >YanChengCheok 7monthsago


Y oumaytryusing`View.setSelected`andcorrespondingselectorsinsteadofactivationstate.Animationsmay
bedifferents
Reply Share

pico 7monthsago
Ireallyappreciateyourguy'sarticle
Reply Share

Hoshomoh 8monthsago
Ihavebeensearchingforthisallmylife...Thanksman.Wasreallyhelpful.EventhoughIrespondedtoclicksand
longclicksfrommyadapter
Reply Share

Kernald Mod >Hoshomoh 8monthsago


Y ou'reverywelcome:)
Reply Share

BalaVamsiKrishnaVenigalla 9monthsago
HowtoImplementonItemClickandshowinaFullScreen.
Reply Share

Kernald Mod >BalaVamsiKrishnaVenigalla 9monthsago


TheonItemClickequivalentisexplainedinthearticle:https://enoent.fr/blog/2015/01...

Whatdoyoumeanby"showinaFullScreen"?
Reply Share

BalaVamsiKrishnaVenigalla>Kernald 9monthsago
Iwantaddsomeitemsintorecyclerviewlikeihaveanapi(likeopenweather)inthatihavetosearch
Iwantaddsomeitemsintorecyclerviewlikeihaveanapi(likeopenweather)inthatihavetosearch
andadd10locationsinarecyclerviewisitpossible
Reply Share

Kernald Mod >BalaVamsiKrishnaVenigalla 9monthsago


IfIunderstandyoucorrectly,yes,that'sthestandardusecaseforaRecyclerView,simplyfill
youradapterwiththeresultofyourAPIrequest.
Reply Share

TilemachosSheva ayearago
Hello.IwasintoandroiddevelopingsometimeagoandImustadmin.Googleismakingitmorecomplexinevery
sdkversion.Ididn'tfinishyourguideyet,butIwassearchingthewholeinternetforaselectableRecyclerViewandI
couldn'tfindanythingthatworks.Thisseemstoworkandisnice.

ButIamwondering:
Exceptforthevisualeffects,ifIkeepaList/Map(something)totrackclicksinonClick(usenotifyItemChanged())
andthendoacheckinonBindifthatitemisonlistusebackgroundAelseusebackdroundB.Shouldn'tthatworkor
not?

Anywaysawesomeguide
Reply Share

Kernald Mod >TilemachosSheva ayearago


It'sprettymuchthesamethingwhichisdonehere,ifIunderstandyoucorrectly.Idon'tseewhyitwouldn't
work)
Reply Share

TilemachosSheva>Kernald ayearago
Okthanks.
Anotherquestion.Isthisapproachefficient?ImeanchangingbackgroundseverytimeonBindiscalled
shouldn'tbeaproblemright?
Reply Share

Kernald Mod >TilemachosSheva ayearago


Indeedchangingbackgroundwillnotbeamajorbottleneck.Justchoosecarefullythedata
structureyouusetostoreselecteditems,itneedstobelookedupquickly.
Reply Share

TilemachosSheva>Kernald ayearago
Thankyouverymuch.
AHashMaporaSparseBooleanArrayshouldbeenough.
Reply Share

Davidoff ayearago
I'vesomeimprovementsuggestionsandnotes:

Manyotherpeopleimplementsthev4GestureDetectorCompat,yes,withthatwecanhandlemoregestureslike
doubletap,butfor99%oftheappsingleClickandlongClickarethemostusedandIMHOit'soktoimplementsthem
insideVH.

TheAPIchangedabitafterthisarticle,nowthewaythepositionisretrieved,isobtainedbygetAdapterPosition().

IntheclearSelection()isn'titbettertocalldirectlynotifyDataSetChanged()insteadofnotifyItemChanged(i)cycling
thearraythatiseverytimecreatedinthegetSelectedItems()?

Moreingeneral,sinceweneedtoknowonlyifapositionisselected,couldwemakeuseofaList<integer>withonly
theselecteditemsnotcaringoftheothers.Itwillimprovealotthememoryandtheperformance,gettingridofthe
SparseBooleanArray,thatwithmanyitemsinside,it'snotefficient(theysayintheAPI)andgettingridotthe
creationofthenewListingetSelectedItems().

Pleaseletmeknowwhatyouthinkandthanksforyourtime.
Reply Share
Reply Share

Kernald Mod >Davidoff ayearago


RegardingtheGestureDetectorCompat,itdependsonyourneeds,asalways.Ifyoucandowithoutit,go
ahead,yourapplicationwillbelighter,that'salwasgoodtotake.

ItakenoticeofthenewgetAdapterPosition()methodandmakeaneditthisweekendtomentionit.

Clearingtheselection:theproblemwithnotifyDataSetChanged()isthatitscrewstheanimations.Itwould
forcetheRecyclverViewtocycleaccrossyourwholeadaptertoknowwhatchanged.ItwouldcostmoreCPU
cycles,andlookworse.Unlessyouhavereallybigdatachanges,avoidnotifyDataSetChanged().

AndfortheList<integer>,avoidingthegetSelectedItems()creationwouldmaybebeabonus,butIdon'tthink
youwouldgainanymemory.SparseBooleanArrayisareallylightweightstructure
Reply Share

Davidoff>Kernald ayearago
Okthenthanksforyouranswers!
Reply Share

Kernald Mod >Davidoff ayearago


Thanksforyourgoodquestions)
Reply Share

Davidoff>Davidoff ayearago
I'vejustseenthattheBundlecanhandleanArrayList<integer>withouttheneedofmakinganobject
(containingit)Serializable.
Reply Share

Davidoff ayearago
Howisthebehaviorwhenchangingorientation?
Isthestatemaintained?
Reply Share

Kernald Mod >Davidoff ayearago


Idon'thavethecodeinmindrightnow,butifIremembercorrectly,Ididn'thandlethisintheexample,I
triedtokeepthisassimpleasIcould.Thereisaprettysimplesolutiontohandleorientationchanges:putyour
adapterinaretainedfragment.Asit'stheonekeepingtheselectedstateoftheitems,theRecyclerViewitself
doesn'tholdanythingusefulexceptedthescrollposition.Letitberecreated.

Iwon'tcoverinthiscommenthowtousearetainedfragmentasitshouldhaveanarticlebyitself,andyou
shouldfindmanyonthenet,beinggenericAndroidstuff.Thekeyhereissimplytosavetheadapter(andthe
scrollpositionifneeded).
Reply Share

Davidoff>Kernald ayearago
Thanks,forthesuggestions.
ActuallyI'veexecutedyourcode,itlooksgoodifyoudon'tconsidertheRandomItemspopulation...
Thepositionseemskeptinsomehowonthescreen(maybethescrollisalreadyretained).

Ithink,whatisimportanttoretainistheinformationoftheselections(SparseBooleanArray),maybe
justthis?wecouldmakeitSerializableorParcelable.AndsetitintotheAdapterafterithasbeen
recreatedduetotherotationforinstance.
Reply Share

Kernald Mod >Davidoff ayearago


Goodtoknowforthescrollposition.Regardingtheselection,Iguessitdependsonyouradapter
complexity.Ifyourdataiseasilyavailable,justsavetheSparseBooleanArrayhandlingthe
selection.Ifyoudependonanetworkrequesttogetyourdataback,youprobablyshouldsave
thewholeadapter,toavoidanewnetworkrequestonconfigurationchange.Butyougotthe
idearight)
idearight)
Reply Share

Davidoff>Kernald ayearago
Indeed,datafromnetworkrequestshouldbehandledwithafragmentretained.
Reply Share

Davidoff ayearago
FinallyasuperbtutorialasI'veneverseenonRecyclerView!I'mgoingtoimplementitsoon)
ItalsoincludessomepartsI'veseeninsomeothersblogsbutthisoneiscompletedineveryaspect.

Whatisthepurposeoftheactiveitemsfromthenotactive?justtodisplaysomethingdifferenttomakethisarticle?

HowtheOverlayViewisdisplayedonpreL?
Reply Share

Kernald Mod >Davidoff ayearago


Thanksforyourcomment.Asyouhaveguessed,theactive/inactivestateisonlytomakeavisualdistinction.
Ishouldhaveuseda"green/blue"stateorsomethinglikethat,toavoidtheconfusion,that'sagoodpoint.I'll
bemorecarefulinthefuturewhileworkingonmyexamples:)

AsfarasIremember,theoverlaylooksnearlythesameonpreLdevices.Thecornersmaybesquaredinstead
ofthesubtlecircleshape,butthat'stheonlydifference.It'slargelyusableanyway.
1 Reply Share

Davidoff>Kernald ayearago
AhOK,Iguessedrightthen.Indeedwecanhandlemorerealcustomtypesviewinthatway)

I'veseenthatmaybeisnotnecessarytoaddtheselectedOverlayView.Astateselectorxmlcanbe
maybeappliedtotheitemView(bythewayyoucandirectlyaccesstothe
"RecyclerView.ViewHolder.itemView"itseemsaprotectedmember)andcallsetActivated()onit.
1 Reply Share

Kernald Mod >Davidoff ayearago


IhadissueswiththefirstreleaseofCardView,usingaselectorforitsforeground,onpreL
devices.That'swhyIchosetodothisinthesimplestwayIcouldimagine.Butit'sworthtaking
alooktoday,ithasprobablybeenfixedsince.
Reply Share

sadegh ayearago
howcanhighlightselecteditem?

inyourexampleicantfindhowcansetactivetheitemintoggleSelection?
Reply Share

Kernald Mod >sadegh ayearago


ThehighlightingisdonewithasimpleViewontopoftheitem.It'stheviewnamed"selectedoverlay"inthe
article.Justsetitasinvisiblebydefault,withabackgroundof"@color/selected_overlay".Then,inyour
onBindViewHolder()method,yousetitvisibleornotdependingontheselectionstateoftheitemyou're
currentlybounding:

holder.selectedOverlay.setVisibility(isSelected(position)?View.VISIBLE:View.INVISIBLE)
Reply Share

Copyright2016MarcPlanoLesayPoweredbyOctopress

Potrebbero piacerti anche