package Ġsp ann able . grid . layout Ċ Ċ import Ġandroid . content . Context Ċ import Ġandroid . util . Attribute Set Ċ import Ġandroid . util . Log Ċ import Ġandroid . view . View Ċ import Ġandroid . view . ViewGroup Ċ import Ġandroid . view . View Tree Observer Ċ import Ġandroid . widget . GridLayout Ċ import Ġandroid . widget . ScrollView Ċ import Ġandroid . widget . Space Ċ import Ġandroidx . annotation . Dim en Res Ċ import Ġandroidx . recyclerview . widget . RecyclerView Ċ import Ġjava . lang . ref . Weak Reference Ċ import Ġkotlin . math . ceil Ċ import Ġkotlin . math . floor Ċ import Ġkotlin . math . max Ċ Ċ class ĠGrid Layout RecyclerView < T , ĠD > Ġ: ĠScroll View , ĠView Tree Observer . On Global Layout Listener , ĊĠĠĠ ĠView Tree Observer . On Scroll Changed Listener Ġ{ ĊĠĠĠ Ġconstructor ( context : ĠContext ) Ġ: Ġsuper ( context ) ĊĠĠĠ Ġconstructor ( context : ĠContext , Ġattributes : ĠAttributeSet ) Ġ: Ġsuper ( context , Ġattributes ) Ġ{ ĊĠĠĠĠĠĠĠ Ġset Attributes ( attributes ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġconstructor ( context : ĠContext , Ġattributes : ĠAttributeSet , Ġdef Style Attribute Set : ĠInt ) Ġ: Ġsuper ( ĊĠĠĠĠĠĠĠ Ġcontext , Ġattributes , Ġdef Style Attribute Set ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġset Attributes ( attributes ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ ĠView . inflate ( context , ĠR . layout . grid _ layout _ recycler _ view , Ġthis ) ĊĠĠĠĠĠĠĠ Ġview Tree Observer . add On Scroll Changed Listener ( this ) ĊĠĠĠĠĠĠĠ Ġgrid Layout Ġ= ĠfindViewById ( R . id . grid _ layout ) ĊĠĠĠĠĠĠĠ Ġview Tree Observer . add On Global Layout Listener ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Dim en Res ĊĠĠĠ Ġvar Ġmargin Ġ= ĠR . dim en . default _ gap ĊĠĠĠ Ġvar Ġadd Side Padding Ġ= Ġtrue ĊĠĠĠ Ġvar Ġadapter : ĠAdapter < T , ĠD >? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġset ( newValue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠnewValue ?. column Count Ġ= Ġgrid Layout . column Count ĊĠĠĠĠĠĠĠĠĠĠĠ ĠnewValue ?. weak Reference Ġ= ĠWeak Reference ( this ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠnewValue ?. let Ġ{ Ġmax RowCount Ġ= Ġit . definitions . fold ( 0 ) Ġ{ Ġm , Ġh Ġ-> Ġmax ( m , Ġh . max Row ) Ġ} Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfield Ġ= ĠnewValue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġvar Ġcolumn Count : ĠInt Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġset ( newValue ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgrid Layout . column Count Ġ= ĠnewValue ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfield Ġ= ĠnewValue ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġvar Ġright To Left Ġ= Ġfalse ĊĊĠĠĠ Ġprivate Ġvar Ġmax RowCount : ĠInt ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġvar Ġgrid Layout : ĠGrid Layout ĊĠĠĠ Ġprivate Ġvar Ġcolumn Width Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġvisible RowCount Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġcached Cell Ġ= Ġmutable Map Of < D , ĠT >() ĊĠĠĠ Ġprivate Ġvar Ġre usable Ids Ġ= Ġmutable ListOf < D >() ĊĠĠĠ Ġprivate Ġvar Ġvisible Row Range Ġ= Ġ 0 .. 0 ĊĊĠĠĠ Ġprivate Ġvar Ġcell Gap : ĠInt ? Ġ= Ġnull ĊĠĠĠ Ġprivate Ġval Ġgap : ĠInt ĊĠĠĠĠĠĠĠ Ġget () Ġ= Ġcell Gap Ġ?: Ġresources . get Dimension Pixel Size ( margin ) ĊĊĠĠĠ Ġprivate Ġfun Ġset Attributes ( attributes : ĠAttributeSet ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġarray Ġ= Ġcontext . obtain Styled Attributes ( attributes , ĠR . style able . GridLayout RecyclerView ) ĊĠĠĠĠĠĠĠ Ġcolumn Count Ġ= Ġarray . getInt ( R . style able . GridLayout RecyclerView _ column _ count , Ġ 1 ) ĊĠĠĠĠĠĠĠ Ġcell Gap Ġ= Ġarray . get Dimension Pixel Size ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠR . style able . GridLayout RecyclerView _ cell _ gap , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġresources . get Dimension Pixel Size ( R . dim en . zero ) ĊĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠ Ġright To Left Ġ= Ġarray . getBoolean ( R . style able . GridLayout RecyclerView _ right _ to _ left , Ġright To Left ) ĊĠĠĠĠĠĠĠ Ġadd Side Padding Ġ= Ġarray . getBoolean ( R . style able . GridLayout RecyclerView _ add _ side _ padding , Ġadd Side Padding ) ĊĠĠĠĠĠĠĠ Ġarray . recycle () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġregion ĠGrid ĠLayout ĠDefinition ĊĠĠĠ Ġopen Ġclass ĠDefinition < D >( ĊĠĠĠĠĠĠĠ Ġval Ġid : ĠD , Ġval Ġrow Span : ĠInt , Ġval Ġcol Span : ĠInt , ĊĠĠĠĠĠĠĠ Ġvar Ġrow Start : ĠInt ? Ġ= Ġnull , Ġvar Ġcol Start : ĠInt ? Ġ= Ġnull ĊĠĠĠ Ġ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġmax Row : ĠInt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġrow Span Ġ+ Ġ( row Start Ġ?: Ġ 0 ) ĊĊĠĠĠĠĠĠĠ Ġval Ġmax Col : ĠInt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġget () Ġ= Ġcol Span Ġ+ Ġ( col Start Ġ?: Ġ 0 ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġdefined () Ġ= Ġ(( row Start Ġ?: Ġ- 1 ) Ġ>= Ġ 0 ) Ġ&& Ġ(( col Start Ġ?: Ġ- 1 ) Ġ>= Ġ 0 ) ĊĊĠĠĠĠĠĠĠ Ġfun Ġbuild LayoutParams ( ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolumn Width : ĠInt , Ġright To Left : ĠBoolean , Ġcolumn Count : ĠInt , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġright Gap : ĠInt Ġ= Ġ 0 , Ġbottom Gap : ĠInt Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ) Ġ= ĠGrid Layout . LayoutParams ( ĊĠĠĠĠĠĠĠĠĠĠĠ ĠGrid Layout . spec ( row Start Ġ?: Ġ 0 , Ġrow Span ), ĊĠĠĠĠĠĠĠĠĠĠĠ ĠGrid Layout . spec ( if Ġ( right To Left ) Ġcolumn Count Ġ- Ġmax Col Ġelse Ġcol Start Ġ?: Ġ 0 , Ġcol Span ) ĊĠĠĠĠĠĠĠ Ġ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwidth Ġ= Ġ( column Width Ġ* Ġcol Span ) Ġ- Ġright Gap ĊĠĠĠĠĠĠĠĠĠĠĠ Ġheight Ġ= Ġ( column Width Ġ* Ġrow Span ) Ġ- Ġbottom Gap ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// Ġend region ĊĊĠĠĠ Ġ// Ġregion ĠGrid ĠLayout ĠAdapter ĊĠĠĠ Ġabstract Ġclass ĠAdapter < T , ĠD > Ġ{ ĊĠĠĠĠĠĠĠ Ġinternal Ġlateinit Ġvar Ġweak Reference : ĠWeak Reference < GridLayout RecyclerView < T , ĠD >> ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġcolumn Count : ĠInt Ġ= Ġ 1 ĊĠĠĠĠĠĠĠ Ġinternal Ġvar Ġdefinitions : ĠList < Definition < D >> Ġ= Ġempty List () ĊĊĠĠĠĠĠĠĠ Ġopen Ġfun ĠgetItem ViewType ( id : ĠD ) Ġ= Ġ 0 ĊĊĠĠĠĠĠĠĠ Ġabstract Ġfun Ġon Bind ViewHolder ( holder : ĠT , Ġid : ĠD ) ĊĊĠĠĠĠĠĠĠ Ġabstract Ġfun ĠonCreate ViewHolder ( parent : ĠViewGroup , Ġview Type : ĠInt ): ĠT ĊĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġreferences Ġ= Ġmutable ListOf < Mutable List < Boolean >>() Ġ// Ġtrue Ġ= Ġfilled , ĊĊĠĠĠĠĠĠĠ Ġfun Ġprepare Layout ( in Order : ĠList < Definition < D >>) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreferences . clear () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġundefined Ġ= Ġprepare Pre defined Layout ( in Order ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolumn Count Ġ= Ġmax ( column Count , Ġundefined . max By Ġ{ Ġit . col Span Ġ} ?. col Span Ġ?: Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġweak Reference . get ()?. column Count Ġ= Ġcolumn Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprocess Definition ( undefined ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġdefinitions Ġ= Ġin Order ĊĠĠĠĠĠĠĠĠĠĠĠ Ġweak Reference . get ()?. reload IfNeeded () ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġprepare Pre defined Layout ( in Order : ĠList < Definition < D >> ): ĠList < Definition < D >> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġdefined Ġ= Ġin Order . filter Ġ{ Ġit . defined () Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġundefined Ġ= Ġin Order . filter Ġ{ Ġ! it . defined () Ġ}. to Mutable List () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolumn Count Ġ= Ġmax ( column Count , Ġ( defined . max By Ġ{ Ġit . max Col Ġ} ?. max Col Ġ?: Ġ 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrow Count Ġ= Ġdefined . max By Ġ{ Ġit . max Row Ġ} ?. max Row Ġ?: Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġadd Empty Reference Row ( rowCount ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( item Ġin Ġdefined ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( can Fit ( item . row Start , Ġitem . col Start , Ġitem . row Span , Ġitem . col Span )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġregister ( item . row Start , Ġitem . col Start , Ġitem ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġindex Ġ= Ġin Order . indexOf ( item ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( index Ġ!= Ġ- 1 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġpointer Ġ= Ġindex ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhile Ġ( pointer Ġ< Ġin Order . count () Ġ&& Ġ! in Order [ pointer ]. defined ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġpointer Ġ+= Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( pointer Ġ< Ġin Order . count ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġanchor Definition Ġ= Ġin Order [ pointer ] ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġanchor Index Ġ= Ġundefined . indexOf ( anchor Definition ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( anchor Index Ġ!= Ġ- 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġundefined . add ( anchor Index , Ġitem ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġundefined ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġadd Empty Reference Row ( times : ĠInt Ġ= Ġ 1 ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrepeat ( times ) Ġ{ Ġreferences . add ( Mutable List ( column Count ) Ġ{ Ġfalse Ġ}) Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġcan Fit At Row ( row : ĠInt , ĠcolumnIndex : ĠInt , Ġcol Span : ĠInt ) Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( column Index Ġ+ Ġcol Span Ġ> Ġcolumn Count Ġ|| Ġrow Ġ>= Ġreferences . count ()) Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġreferences [ row ]. sub List ( column Index , ĠcolumnIndex Ġ+ Ġcol Span ). all Ġ{ Ġ! it Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġcan Fit ( from Row : ĠInt ?, ĠcolumnIndex : ĠInt ?, Ġrow Span : ĠInt , Ġcol Span : ĠInt , ĠrowIndex : ĠInt Ġ= Ġ 0 ): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfrom Row Ġ== Ġnull Ġ|| ĠcolumnIndex Ġ== Ġnull Ġ-> Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreferences . count () Ġ<= Ġfrom Row Ġ+ ĠrowIndex Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Empty Reference Row ( from Row Ġ+ Ġrow Span Ġ- Ġreferences . count () Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtrue ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrow Span Ġ== ĠrowIndex Ġ+ Ġ 1 Ġ-> Ġcan Fit At Row ( from Row Ġ+ ĠrowIndex , ĠcolumnIndex , Ġcol Span ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġcan Fit At Row ( from Row Ġ+ ĠrowIndex , ĠcolumnIndex , Ġcol Span ) Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcan Fit ( from Row , ĠcolumnIndex , Ġrow Span , Ġcol Span , ĠrowIndex Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġregister ( row : ĠInt ?, Ġcol : ĠInt ?, Ġitem : ĠDefinition < D >): ĠBoolean Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( row Ġ== Ġnull Ġ|| Ġcol Ġ== Ġnull ) Ġreturn Ġfalse ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġrow . until ( row Ġ+ Ġitem . row Span ). forEach Ġ{ Ġr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcol . until ( col Ġ+ Ġitem . col Span ). forEach Ġ{ Ġc Ġ-> Ġreferences [ r ][ c ] Ġ= Ġtrue Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitem . row Start Ġ= Ġrow ĊĠĠĠĠĠĠĠĠĠĠĠ Ġitem . col Start Ġ= Ġcol ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġtrue ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġprivate Ġfun Ġprocess Definition ( items : ĠList < Definition < D >>) Ġ= Ġitems . forEach Ġ{ Ġitem Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġfound Free Space Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠĠ 0 . until ( references . count ()). forEach Ġ{ Ġr Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġindex Ġ= Ġreferences [ r ]. indexOf First Ġ{ Ġ! it Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! found Free Space Ġ&& Ġindex Ġ!= Ġ- 1 Ġ&& Ġcan Fit ( r , Ġindex , Ġitem . row Span , Ġitem . col Span )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfound Free Space Ġ= Ġregister ( r , Ġindex , Ġitem ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ(! found Free Space ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġrow Ġ= Ġreferences . count () ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Empty Reference Row ( item . row Span ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġregister ( row , Ġ 0 , Ġitem ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// Ġend region ĊĊĠĠĠ Ġinternal Ġfun Ġreload IfNeeded () Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( grid Layout . child Count Ġ> Ġ 0 ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgrid Layout . removeAll Views () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcached Cell . clear () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġre usable Ids . clear () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvisible Row Range Ġ= Ġ 0 .. 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġside Gap Ġ= Ġif Ġ( add Side Padding ) Ġgap Ġelse Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcolumn Width Ġ= Ġ( grid Layout . width Ġ- Ġside Gap ) Ġ/ Ġgrid Layout . column Count ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprepare Views () ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġregion ĠView Tree Observer . On Global Layout Listener ĊĠĠĠ Ġoverride Ġfun Ġon Global Layout () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġside Gap Ġ= Ġif Ġ( add Side Padding ) Ġgap Ġelse Ġ 0 ĊĠĠĠĠĠĠĠ Ġcolumn Width Ġ= Ġ( grid Layout . width Ġ- Ġside Gap ) Ġ/ Ġgrid Layout . column Count ĊĠĠĠĠĠĠĠ Ġprepare Views () ĊĠĠĠĠĠĠĠ Ġview Tree Observer . remove On Global Layout Listener ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprepare Views () Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġzero Ġ= Ġresources . get Dimension Pixel Size ( R . dim en . zero ) ĊĠĠĠĠĠĠĠ Ġif Ġ( add Side Padding ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgrid Layout . set Padding ( gap , Ġgap , Ġzero , Ġzero ) ĊĠĠĠĠĠĠĠ Ġvisible RowCount Ġ= Ġceil ( height . toDouble () Ġ/ Ġcolumn Width . toDouble ()). toInt () ĊĊĠĠĠĠĠĠĠ Ġadapter ?. definitions ?. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġgrid Layout . addView ( Space ( context ), Ġit . build LayoutParams ( column Width , Ġright To Left , Ġcolumn Count )) ĊĠĠĠĠĠĠĠ Ġ} Ġ// Ġadd Ġplaceholders , Ġthis Ġis Ġto Ġensure Ġthat Ġwhen Ġgrid Ġlayout 's Ġview Ġis Ġremoved , Ġit Ġwon 't Ġmess Ġup Ġwith Ġcontent Ġposition ĊĊĠĠĠĠĠĠĠ Ġrender Visible Content () ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// Ġend region ĊĊĠĠĠ Ġ// Ġregion ĠView Tree Observer . On Scroll Changed Listener ĊĠĠĠ Ġoverride Ġfun Ġon Scroll Changed () Ġ{ ĊĠĠĠĠĠĠĠ Ġrender Visible Content () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrender Visible Content () Ġ= Ġadapter ?. apply Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġoffset Y Ġ= Ġscroll Y ĊĠĠĠĠĠĠĠ Ġval Ġtop Gap Ġ= Ġif Ġ( add Side Padding ) Ġgap Ġelse Ġ 0 ĊĠĠĠĠĠĠĠ Ġval Ġmin Visible Row Ġ= Ġmax ( 0 , Ġfloor (( offset Y Ġ- Ġtop Gap ). toDouble () Ġ/ Ġcolumn Width . toDouble ()). toInt ()) ĊĠĠĠĠĠĠĠ Ġval Ġmax Visible Row Ġ= Ġmin Visible Row Ġ+ Ġvisible RowCount ĊĊĠĠĠĠĠĠĠ Ġif Ġ(! visible Row Range . contains ( min Visible Row ) Ġ|| Ġ! visible Row Range . contains ( max Visible Row )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġvisible Ids Ġ= Ġdefinitions ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġit . max Row Ġ>= Ġmin Visible Row Ġ&& Ġ( it . row Start Ġ?: Ġ- 1 ) Ġ<= Ġmax Visible Row Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. map Ġ{ Ġit . id Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġre usable Ids Ġ= Ġdefinitions . map Ġ{ Ġit . id Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. minus ( visible Ids ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. filter Ġ{ Ġgrid Layout . find View With Tag < View >( it ) Ġ!= Ġnull Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. to Mutable List () ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġdefinitions . filter Ġ{ Ġvisible Ids . contains ( it . id ) Ġ&& Ġgrid Layout . find View With Tag < View >( it . id ) Ġ== Ġnull Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ. forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġprepare View ( it . id ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ// Ġadd Ġview Ġif Ġits Ġnot Ġvisible Ġin Ġgrid Ġlayout ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġvisible Row Range Ġ= Ġmin Visible Row .. max Visible Row ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprepare Layout ( holder : ĠT , Ġid : ĠD ): ĠGrid Layout . LayoutParams ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġview Ġ= Ġ( holder Ġas ? ĠRecyclerView . ViewHolder )?. item View Ġ?: Ġholder Ġas ? ĠView Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġdef Ġ= Ġadapter ?. definitions ?. first OrNull Ġ{ Ġit . id Ġ== Ġid Ġ} Ġ?: Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġview . tag Ġ= Ġdef . id ĊĠĠĠĠĠĠĠ Ġval Ġright Gap Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! add Side Padding Ġ&& Ġdef . max Col Ġ== Ġgrid Layout . column Count Ġ-> Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġgap ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġval Ġbottom Gap Ġ= Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ! add Side Padding Ġ&& Ġdef . max Row Ġ== Ġmax RowCount Ġ-> Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġgap ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġparams Ġ= Ġdef . build LayoutParams ( column Width , Ġright To Left , Ġcolumn Count , Ġright Gap , Ġbottom Gap ) ĊĊĠĠĠĠĠĠĠ Ġparams . right Margin Ġ= Ġright Gap ĊĠĠĠĠĠĠĠ Ġparams . bottom Margin Ġ= Ġbottom Gap ĊĠĠĠĠĠĠĠ Ġview . layout Params Ġ= Ġparams ĊĠĠĠĠĠĠĠ Ġreturn Ġparams ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġprepare View ( id : ĠD ) Ġ= Ġadapter ?. apply Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġview Type Ġ= ĠgetItem ViewType ( id ) ĊĠĠĠĠĠĠĠ Ġvar Ġreuse Id : ĠD ? Ġ= Ġnull ĊĠĠĠĠĠĠĠ Ġval Ġv h Ġ= Ġre usable Ids . first OrNull Ġ{ ĠgetItem ViewType ( id ) Ġ== Ġview Type Ġ} ?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreuse Id Ġ= Ġit ĊĠĠĠĠĠĠĠĠĠĠĠ Ġre usable Ids . remove ( it ) ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" deque ", Ġ" reuse : Ġ$ it Ġfor Ġ$ id , Ġreuse Size : Ġ${ reusable Ids . size }") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcached Cell [ it ]. apply Ġ{ Ġcached Cell . remove ( it ) Ġ} ĊĠĠĠĠĠĠĠ Ġ} Ġ?: ĠonCreate ViewHolder ( this @ GridLayout RecyclerView , Ġview Type ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ ĠLog . d (" deque ", Ġ" create : Ġ$ id , Ġreuse Size : Ġ${ reusable Ids . size }") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġon Bind ViewHolder ( vh , Ġid ) ĊĠĠĠĠĠĠĠ Ġcached Cell [ id ] Ġ= Ġv h ĊĠĠĠĠĠĠĠ Ġprepare Layout ( vh , Ġid )?. let Ġ{ Ġparams Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( reuse Id Ġ== Ġnull Ġ|| Ġgrid Layout . find View With Tag < View >( id ) Ġ== Ġnull ) Ġ(( vh Ġas ? ĠRecyclerView . ViewHolder )?. item View ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ?: Ġv h Ġas ? ĠView )?. let Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġgrid Layout . addView ( it , Ġparams ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġ// Ġadd Ġview Ġto Ġgrid Ġlayout Ġif Ġit 's Ġnewly Ġcreated ĊĠĠĠĠĠĠĠ Ġ} Ġ// Ġprepare Layout ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// Ġend region Ċ } Ċ