Hôm nay mình muốn chia sẻ với các bạn một ví dụ về Expandable List sử dụng ListAdapter
+ Data Binding và multi-type trong RecyclerView
.
Các bạn có thể tham khảo source code của mình tại đây!
Mình đang sử dụng Gradle 6.5 và Android Studio 4.1 nhé.
Ví dụ này sẽ hiển thị một danh sách các Section, khi chúng ta tap vào một Section nó sẽ mở rộng ra và hiển các Item của nó.
Dependencies
Đầu tiên chúng ta sẽ cần một vài dependencies trong build.gradle
của module như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | dependencies <span class="token punctuation">{</span> implementation <span class="token string">'org.jetbrains.kotlin:kotlin-stdlib:1.4.10'</span> implementation <span class="token string">'androidx.core:core-ktx:1.3.2'</span> implementation <span class="token string">'androidx.appcompat:appcompat:1.2.0'</span> implementation <span class="token string">'com.google.android.material:material:1.2.1'</span> implementation <span class="token string">'androidx.constraintlayout:constraintlayout:2.0.2'</span> implementation <span class="token string">'androidx.activity:activity-ktx:1.1.0'</span> implementation <span class="token string">'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'</span> implementation <span class="token string">'androidx.recyclerview:recyclerview:1.1.0'</span> implementation <span class="token string">'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'</span> <span class="token punctuation">}</span> |
Section Model
Chúng ta sẽ có một Section
model chứa các thông tin:
1 2 3 4 5 6 7 8 9 10 11 12 | <span class="token keyword">data</span> <span class="token keyword">class</span> <span class="token function">Section</span><span class="token punctuation">(</span> <span class="token keyword">val</span> id<span class="token operator">:</span> Int<span class="token punctuation">,</span> <span class="token keyword">val</span> name<span class="token operator">:</span> String<span class="token punctuation">,</span> <span class="token keyword">val</span> isExpandable<span class="token operator">:</span> Boolean<span class="token punctuation">,</span> <span class="token keyword">val</span> items<span class="token operator">:</span> List<span class="token operator"><</span>Item<span class="token operator">></span> <span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">data</span> <span class="token keyword">class</span> <span class="token function">Item</span><span class="token punctuation">(</span> <span class="token keyword">val</span> id<span class="token operator">:</span> Int<span class="token punctuation">,</span> <span class="token keyword">val</span> name<span class="token operator">:</span> String <span class="token punctuation">)</span> <span class="token punctuation">}</span> |
Các bạn chú ý 2 thuộc tính sau nhé:
isExpandable
: Xác định trạng thái có thể mở rộng.true
nếu đang thu gọn,false
nếu đang mở rộng.items
: Danh sách các item sẽ hiển thị khi list mở rộng.
Ở đây mình khuyến khích sử dụng data class
để tiện cho việc compare trong DiffUtil
sau này.
ViewHolder
Tiếp theo, chúng ta sẽ có 2 ViewHolder
để hiển thị cho Section
và các Item
của nó:
SectionViewHolder
Mình sẽ tạo một layout là item_section.xml
chứa một TextView
để hiển thị name của Section và một AppCompatImageView
để hiển thị expand icon, cái này thay đổi theo isExpandable
trong Section
model.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <span class="token prolog"><?xml version="1.0" encoding="utf-8"?></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>layout</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>android</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res/android<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>app</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res-auto<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>tools</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/tools<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>variable</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>section<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.example.expandable_list_adapter_example.Section<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>LinearLayout</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>background</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>?selectableItemBackground<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>gravity</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>center<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>orientation</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>horizontal<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>padding</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16dp<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TextView</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_weight</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>1<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{section.name}<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>textAppearance</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@style/TextAppearance.AppCompat.Medium<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>textStyle</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>bold<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">tools:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Section 0<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>androidx.appcompat.widget.AppCompatImageView</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>sectionExpandable</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{section.expandable}<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">tools:</span>srcCompat</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@drawable/ic_baseline_expand_more_24<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>LinearLayout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>layout</span><span class="token punctuation">></span></span> |
Mình có thêm một BindingAdapter
là sectionExpandable
để cập nhật expand icon khi isExpandable
thay đổi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token keyword">class</span> <span class="token function">SectionViewHolder</span><span class="token punctuation">(</span> <span class="token keyword">private</span> <span class="token keyword">val</span> binding<span class="token operator">:</span> ItemSectionBinding<span class="token punctuation">,</span> <span class="token keyword">private</span> <span class="token keyword">val</span> onSectionClickListener<span class="token operator">:</span> <span class="token punctuation">(</span>Section<span class="token punctuation">)</span> <span class="token operator">-></span> Unit <span class="token punctuation">)</span> <span class="token operator">:</span> RecyclerView<span class="token punctuation">.</span><span class="token function">ViewHolder</span><span class="token punctuation">(</span>binding<span class="token punctuation">.</span>root<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">init</span> <span class="token punctuation">{</span> binding<span class="token punctuation">.</span>root<span class="token punctuation">.</span><span class="token function">setOnSingleClickListener</span> <span class="token punctuation">{</span> binding<span class="token punctuation">.</span>section<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">let</span> <span class="token punctuation">{</span> <span class="token function">onSectionClickListener</span><span class="token punctuation">(</span>it<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">fun</span> <span class="token function">bind</span><span class="token punctuation">(</span>section<span class="token operator">:</span> Section<span class="token punctuation">)</span> <span class="token punctuation">{</span> binding<span class="token punctuation">.</span>section <span class="token operator">=</span> section <span class="token punctuation">}</span> <span class="token keyword">object</span> Binding <span class="token punctuation">{</span> <span class="token annotation builtin">@JvmStatic</span> <span class="token annotation builtin">@BindingAdapter</span><span class="token punctuation">(</span><span class="token string">"sectionExpandable"</span><span class="token punctuation">)</span> <span class="token keyword">fun</span> <span class="token function">setSectionExpandable</span><span class="token punctuation">(</span>imageView<span class="token operator">:</span> AppCompatImageView<span class="token punctuation">,</span> isExpandable<span class="token operator">:</span> Boolean<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>isExpandable<span class="token punctuation">)</span> <span class="token punctuation">{</span> imageView<span class="token punctuation">.</span><span class="token function">setImageResource</span><span class="token punctuation">(</span>R<span class="token punctuation">.</span>drawable<span class="token punctuation">.</span>ic_baseline_expand_more_24<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> imageView<span class="token punctuation">.</span><span class="token function">setImageResource</span><span class="token punctuation">(</span>R<span class="token punctuation">.</span>drawable<span class="token punctuation">.</span>ic_baseline_expand_less_24<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Để hiển thị các Item
của Section
, mình sẽ xây dựng thêm một ViewHodder
khác là:
SectionItemViewHolder
Đối với Section Item mình chỉ cần một TextView
để hiển thị name của Item đó.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token prolog"><?xml version="1.0" encoding="utf-8"?></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>layout</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>android</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res/android<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>tools</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/tools<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>variable</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>sectionItem<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.example.expandable_list_adapter_example.Section.Item<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>TextView</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>wrap_content<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>paddingStart</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>32dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>paddingTop</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>paddingEnd</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>paddingBottom</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>16dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{sectionItem.name}<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>textAppearance</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@style/TextAppearance.AppCompat.Small<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">tools:</span>text</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>Item 0<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>layout</span><span class="token punctuation">></span></span> |
1 2 3 4 5 6 7 8 9 | <span class="token keyword">class</span> <span class="token function">SectionItemViewHolder</span><span class="token punctuation">(</span> <span class="token keyword">private</span> <span class="token keyword">val</span> binding<span class="token operator">:</span> ItemSectionItemBinding <span class="token punctuation">)</span> <span class="token operator">:</span> RecyclerView<span class="token punctuation">.</span><span class="token function">ViewHolder</span><span class="token punctuation">(</span>binding<span class="token punctuation">.</span>root<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">fun</span> <span class="token function">bind</span><span class="token punctuation">(</span>sectionItem<span class="token operator">:</span> Section<span class="token punctuation">.</span>Item<span class="token punctuation">)</span> <span class="token punctuation">{</span> binding<span class="token punctuation">.</span>sectionItem <span class="token operator">=</span> sectionItem <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
ListAdapter
Bây giờ, chúng ta sẽ xử lý ListAdapter
để tích hợp với các ViewHolder
trên.
Lý do để mình sử dụng ListAdapter
đó là nó tích hợp DiffUtil để compare sự khác nhau của list được submit. Các bạn có thể tham khảo thêm ở đây.
Đầu tiên, chúng ta sẽ cần cung cấp cho nó một DiffUtil.ItemCallback
như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <span class="token keyword">class</span> <span class="token function">MainListAdapter</span><span class="token punctuation">(</span> <span class="token keyword">private</span> <span class="token keyword">val</span> onSectionClickListener<span class="token operator">:</span> <span class="token punctuation">(</span>Section<span class="token punctuation">)</span> <span class="token operator">-></span> Unit <span class="token punctuation">)</span> <span class="token operator">:</span> ListAdapter<span class="token operator"><</span>Any<span class="token punctuation">,</span> RecyclerView<span class="token punctuation">.</span>ViewHolder<span class="token operator">></span><span class="token punctuation">(</span>DIFF_CALLBACK<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">companion</span> <span class="token keyword">object</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">val</span> DIFF_CALLBACK <span class="token operator">=</span> <span class="token keyword">object</span> <span class="token operator">:</span> DiffUtil<span class="token punctuation">.</span>ItemCallback<span class="token operator"><</span>Any<span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">areItemsTheSame</span><span class="token punctuation">(</span>oldItem<span class="token operator">:</span> Any<span class="token punctuation">,</span> newItem<span class="token operator">:</span> Any<span class="token punctuation">)</span><span class="token operator">:</span> Boolean <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">when</span> <span class="token punctuation">{</span> oldItem <span class="token keyword">is</span> Section <span class="token operator">&&</span> newItem <span class="token keyword">is</span> Section <span class="token operator">-></span> <span class="token punctuation">{</span> oldItem<span class="token punctuation">.</span>id <span class="token operator">==</span> newItem<span class="token punctuation">.</span>id <span class="token punctuation">}</span> oldItem <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">&&</span> newItem <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">-></span> <span class="token punctuation">{</span> oldItem<span class="token punctuation">.</span>id <span class="token operator">==</span> newItem<span class="token punctuation">.</span>id <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token operator">-></span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token annotation builtin">@SuppressLint</span><span class="token punctuation">(</span><span class="token string">"DiffUtilEquals"</span><span class="token punctuation">)</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">areContentsTheSame</span><span class="token punctuation">(</span>oldItem<span class="token operator">:</span> Any<span class="token punctuation">,</span> newItem<span class="token operator">:</span> Any<span class="token punctuation">)</span><span class="token operator">:</span> Boolean <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">when</span> <span class="token punctuation">{</span> oldItem <span class="token keyword">is</span> Section <span class="token operator">&&</span> newItem <span class="token keyword">is</span> Section <span class="token operator">-></span> <span class="token punctuation">{</span> oldItem <span class="token operator">==</span> newItem <span class="token punctuation">}</span> oldItem <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">&&</span> newItem <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">-></span> <span class="token punctuation">{</span> oldItem <span class="token operator">==</span> newItem <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token operator">-></span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Trong Adapter sẽ có 2 types, một cho Section và một cho Section Item.
Để có thể display 2 types này trong RecyclerView
thì Adapter cần xác định chúng thông qua việc override getItemViewType(_: Int) : Int
method.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <span class="token keyword">class</span> <span class="token function">MainListAdapter</span><span class="token punctuation">(</span> <span class="token keyword">private</span> <span class="token keyword">val</span> onSectionClickListener<span class="token operator">:</span> <span class="token punctuation">(</span>Section<span class="token punctuation">)</span> <span class="token operator">-></span> Unit <span class="token punctuation">)</span> <span class="token operator">:</span> ListAdapter<span class="token operator"><</span>Any<span class="token punctuation">,</span> RecyclerView<span class="token punctuation">.</span>ViewHolder<span class="token operator">></span><span class="token punctuation">(</span>DIFF_CALLBACK<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">getItemViewType</span><span class="token punctuation">(</span>position<span class="token operator">:</span> Int<span class="token punctuation">)</span><span class="token operator">:</span> Int <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token keyword">when</span> <span class="token punctuation">(</span><span class="token function">getItem</span><span class="token punctuation">(</span>position<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">is</span> Section <span class="token operator">-></span> <span class="token punctuation">{</span> ViewType<span class="token punctuation">.</span>SECTION <span class="token punctuation">}</span> <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">-></span> <span class="token punctuation">{</span> ViewType<span class="token punctuation">.</span>SECTION_ITEM <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token operator">-></span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">getItemViewType</span><span class="token punctuation">(</span>position<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">object</span> ViewType <span class="token punctuation">{</span> <span class="token keyword">const</span> <span class="token keyword">val</span> SECTION <span class="token operator">=</span> <span class="token number">101</span> <span class="token keyword">const</span> <span class="token keyword">val</span> SECTION_ITEM <span class="token operator">=</span> <span class="token number">102</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Tiếp theo, chúng ta sẽ tạo ViewHolder
tướng ứng với các ViewType đã định nghĩa và bind data cho chúng.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | <span class="token keyword">class</span> <span class="token function">MainListAdapter</span><span class="token punctuation">(</span> <span class="token keyword">private</span> <span class="token keyword">val</span> onSectionClickListener<span class="token operator">:</span> <span class="token punctuation">(</span>Section<span class="token punctuation">)</span> <span class="token operator">-></span> Unit <span class="token punctuation">)</span> <span class="token operator">:</span> ListAdapter<span class="token operator"><</span>Any<span class="token punctuation">,</span> RecyclerView<span class="token punctuation">.</span>ViewHolder<span class="token operator">></span><span class="token punctuation">(</span>DIFF_CALLBACK<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onCreateViewHolder</span><span class="token punctuation">(</span>parent<span class="token operator">:</span> ViewGroup<span class="token punctuation">,</span> viewType<span class="token operator">:</span> Int<span class="token punctuation">)</span><span class="token operator">:</span> RecyclerView<span class="token punctuation">.</span><span class="token function">ViewHolder</span> <span class="token punctuation">{</span> <span class="token keyword">val</span> inflater <span class="token operator">=</span> LayoutInflater<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>parent<span class="token punctuation">.</span>context<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">when</span> <span class="token punctuation">(</span>viewType<span class="token punctuation">)</span> <span class="token punctuation">{</span> ViewType<span class="token punctuation">.</span>SECTION <span class="token operator">-></span> <span class="token punctuation">{</span> <span class="token keyword">val</span> itemSectionBinding <span class="token operator">=</span> ItemSectionBinding<span class="token punctuation">.</span><span class="token function">inflate</span><span class="token punctuation">(</span>inflater<span class="token punctuation">,</span> parent<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token function">SectionViewHolder</span><span class="token punctuation">(</span>itemSectionBinding<span class="token punctuation">,</span> onSectionClickListener<span class="token punctuation">)</span> <span class="token punctuation">}</span> ViewType<span class="token punctuation">.</span>SECTION_ITEM <span class="token operator">-></span> <span class="token punctuation">{</span> <span class="token keyword">val</span> itemSectionItemBinding <span class="token operator">=</span> ItemSectionItemBinding<span class="token punctuation">.</span><span class="token function">inflate</span><span class="token punctuation">(</span>inflater<span class="token punctuation">,</span> parent<span class="token punctuation">,</span> <span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token function">SectionItemViewHolder</span><span class="token punctuation">(</span>itemSectionItemBinding<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token operator">-></span> <span class="token keyword">throw</span><span class="token punctuation">(</span><span class="token function">Throwable</span><span class="token punctuation">(</span><span class="token string">"View type not matching"</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onBindViewHolder</span><span class="token punctuation">(</span>holder<span class="token operator">:</span> RecyclerView<span class="token punctuation">.</span>ViewHolder<span class="token punctuation">,</span> position<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">when</span> <span class="token punctuation">(</span><span class="token keyword">val</span> item <span class="token operator">=</span> <span class="token function">getItem</span><span class="token punctuation">(</span>position<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">is</span> Section <span class="token operator">-></span> <span class="token punctuation">(</span>holder <span class="token keyword">as</span><span class="token operator">?</span> SectionViewHolder<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span> <span class="token keyword">is</span> Section<span class="token punctuation">.</span>Item <span class="token operator">-></span> <span class="token punctuation">(</span>holder <span class="token keyword">as</span><span class="token operator">?</span> SectionItemViewHolder<span class="token punctuation">)</span><span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
MainViewModel
Bây giờ, mình sẽ sử dụng ViewModel để xử lý dữ liệu cho Section cũng như cập nhật lại Section list khi có action expanding.
class
MainViewModel
sẽ như sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | <span class="token keyword">class</span> MainViewModel <span class="token operator">:</span> <span class="token function">ViewModel</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">var</span> sectionList<span class="token operator">:</span> List<span class="token operator"><</span>Section<span class="token operator">></span> <span class="token operator">=</span> <span class="token function">listOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">val</span> sectionListLiveData <span class="token operator">=</span> MutableLiveData<span class="token operator"><</span>List<span class="token operator"><</span>Section<span class="token operator">></span><span class="token operator">></span><span class="token punctuation">(</span>sectionList<span class="token punctuation">)</span> <span class="token keyword">val</span> isRefreshing <span class="token operator">=</span> MutableLiveData<span class="token operator"><</span>Boolean<span class="token operator">></span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span> <span class="token keyword">fun</span> <span class="token function">refresh</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> isRefreshing<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token function">getSectionList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">fun</span> <span class="token function">getSectionList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> sectionList <span class="token operator">=</span> <span class="token function">fakeSectionList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> sectionListLiveData<span class="token punctuation">.</span>value <span class="token operator">=</span> sectionList isRefreshing<span class="token punctuation">.</span>value <span class="token operator">=</span> <span class="token boolean">false</span> <span class="token punctuation">}</span> <span class="token keyword">fun</span> <span class="token function">expand</span><span class="token punctuation">(</span>sectionId<span class="token operator">:</span> Int<span class="token punctuation">)</span> <span class="token punctuation">{</span> sectionList <span class="token operator">=</span> sectionList<span class="token punctuation">.</span><span class="token function">map</span> <span class="token punctuation">{</span> section <span class="token operator">-></span> <span class="token keyword">if</span> <span class="token punctuation">(</span>section<span class="token punctuation">.</span>id <span class="token operator">==</span> sectionId<span class="token punctuation">)</span> <span class="token punctuation">{</span> section<span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span> isExpandable <span class="token operator">=</span> <span class="token operator">!</span>section<span class="token punctuation">.</span>isExpandable <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> section<span class="token punctuation">.</span><span class="token function">copy</span><span class="token punctuation">(</span> isExpandable <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> sectionListLiveData<span class="token punctuation">.</span>value <span class="token operator">=</span> sectionList <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">fun</span> <span class="token function">fakeSectionList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> List<span class="token operator"><</span>Section<span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">val</span> sectionList<span class="token operator">:</span> MutableList<span class="token operator"><</span>Section<span class="token operator">></span> <span class="token operator">=</span> <span class="token function">mutableListOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token function">repeat</span><span class="token punctuation">(</span>Random<span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">100</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> index <span class="token operator">-></span> <span class="token keyword">val</span> section <span class="token operator">=</span> <span class="token function">Section</span><span class="token punctuation">(</span> id <span class="token operator">=</span> index<span class="token punctuation">,</span> name <span class="token operator">=</span> <span class="token string">"Section <span class="token interpolation variable">$index</span>"</span><span class="token punctuation">,</span> items <span class="token operator">=</span> <span class="token function">fakeSectionItemList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> isExpandable <span class="token operator">=</span> <span class="token boolean">true</span> <span class="token punctuation">)</span> sectionList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>section<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> sectionList <span class="token punctuation">}</span> <span class="token keyword">private</span> <span class="token keyword">fun</span> <span class="token function">fakeSectionItemList</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> List<span class="token operator"><</span>Section<span class="token punctuation">.</span>Item<span class="token operator">></span> <span class="token punctuation">{</span> <span class="token keyword">val</span> sectionItemList<span class="token operator">:</span> MutableList<span class="token operator"><</span>Section<span class="token punctuation">.</span>Item<span class="token operator">></span> <span class="token operator">=</span> <span class="token function">mutableListOf</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token function">repeat</span><span class="token punctuation">(</span>Random<span class="token punctuation">.</span><span class="token function">nextInt</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> index <span class="token operator">-></span> <span class="token keyword">val</span> sectionItem <span class="token operator">=</span> Section<span class="token punctuation">.</span><span class="token function">Item</span><span class="token punctuation">(</span> id <span class="token operator">=</span> index<span class="token punctuation">,</span> name <span class="token operator">=</span> <span class="token string">"Item <span class="token interpolation variable">$index</span>"</span> <span class="token punctuation">)</span> sectionItemList<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>sectionItem<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">return</span> sectionItemList <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
getSectionList()
: Random một Section listexpand(_: Int)
: Cập nhật trạng thái khi một section expading.refresh()
: Refresh lại Section list.
Cuối cùng chúng ta sẽ apply tất cả chúng vào RecyclerView
trong MainActivity
.
MainActivity
activity_main.xml
Trong activity_main.xml
layout, mình chỉ có một RecyclerView
và SwipeRefreshLayout
phục vụ cho việc refresh lại Section list.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <span class="token prolog"><?xml version="1.0" encoding="utf-8"?></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>layout</span> <span class="token attr-name"><span class="token namespace">xmlns:</span>android</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res/android<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>app</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/apk/res-auto<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">xmlns:</span>tools</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>http://schemas.android.com/tools<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>variable</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>viewModel<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>com.example.expandable_list_adapter_example.MainViewModel<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>data</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>androidx.constraintlayout.widget.ConstraintLayout</span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">tools:</span>context</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>.MainActivity<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>androidx.swiperefreshlayout.widget.SwipeRefreshLayout</span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/swipeRefreshLayout<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>0dp<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintBottom_toBottomOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintLeft_toLeftOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintRight_toRightOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>layout_constraintTop_toTopOf</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>onRefreshListener</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{() -> viewModel.refresh()}<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>refreshing</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{viewModel.isRefreshing()}<span class="token punctuation">"</span></span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>androidx.recyclerview.widget.RecyclerView</span> <span class="token attr-name"><span class="token namespace">android:</span>id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@+id/recyclerView<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_width</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">android:</span>layout_height</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>match_parent<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>layoutManager</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>LinearLayoutManager<span class="token punctuation">"</span></span> <span class="token attr-name"><span class="token namespace">app:</span>sectionList</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>@{viewModel.sectionListLiveData}<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>androidx.swiperefreshlayout.widget.SwipeRefreshLayout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>androidx.constraintlayout.widget.ConstraintLayout</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>layout</span><span class="token punctuation">></span></span> |
app:onRefreshListener="@{() -> viewModel.refresh()}"
nhận action refresh từ user và gọirefresh()
method.app:refreshing="@{viewModel.isRefreshing()}"
hiển thị icon loading theoisRefreshing()
.app:sectionList="@{viewModel.sectionListLiveData}"
là mộtBindingAdapter
mình định nghĩa trongMainActivity.Binding
, để submit một list mới khisectionListLiveData
changed.
MainActivity
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <span class="token keyword">class</span> MainActivity <span class="token operator">:</span> <span class="token function">AppCompatActivity</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">private</span> <span class="token keyword">lateinit</span> <span class="token keyword">var</span> binding<span class="token operator">:</span> ActivityMainBinding <span class="token keyword">private</span> <span class="token keyword">val</span> viewModel<span class="token operator">:</span> MainViewModel <span class="token keyword">by</span> <span class="token function">viewModels</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">override</span> <span class="token keyword">fun</span> <span class="token function">onCreate</span><span class="token punctuation">(</span>savedInstanceState<span class="token operator">:</span> Bundle<span class="token operator">?</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">super</span><span class="token punctuation">.</span><span class="token function">onCreate</span><span class="token punctuation">(</span>savedInstanceState<span class="token punctuation">)</span> binding <span class="token operator">=</span> DataBindingUtil<span class="token punctuation">.</span><span class="token function">setContentView</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> R<span class="token punctuation">.</span>layout<span class="token punctuation">.</span>activity_main<span class="token punctuation">)</span> binding<span class="token punctuation">.</span>viewModel <span class="token operator">=</span> viewModel binding<span class="token punctuation">.</span>lifecycleOwner <span class="token operator">=</span> <span class="token keyword">this</span> binding<span class="token punctuation">.</span><span class="token function">executePendingBindings</span><span class="token punctuation">(</span><span class="token punctuation">)</span> binding<span class="token punctuation">.</span>recyclerView<span class="token punctuation">.</span>adapter <span class="token operator">=</span> <span class="token function">MainListAdapter</span><span class="token punctuation">(</span> onSectionClickListener <span class="token operator">=</span> <span class="token punctuation">{</span> section <span class="token operator">-></span> viewModel<span class="token punctuation">.</span><span class="token function">expand</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>id<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">)</span> viewModel<span class="token punctuation">.</span><span class="token function">getSectionList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">object</span> Binding <span class="token punctuation">{</span> <span class="token annotation builtin">@JvmStatic</span> <span class="token annotation builtin">@BindingAdapter</span><span class="token punctuation">(</span><span class="token string">"sectionList"</span><span class="token punctuation">)</span> <span class="token keyword">fun</span> <span class="token function">setSectionList</span><span class="token punctuation">(</span>recyclerView<span class="token operator">:</span> RecyclerView<span class="token punctuation">,</span> sectionList<span class="token operator">:</span> List<span class="token operator"><</span>Section<span class="token operator">></span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">val</span> list <span class="token operator">=</span> mutableListOf<span class="token operator"><</span>Any<span class="token operator">></span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token keyword">val</span> mainListAdapter <span class="token operator">=</span> recyclerView<span class="token punctuation">.</span>adapter <span class="token keyword">as</span><span class="token operator">?</span> MainListAdapter sectionList<span class="token punctuation">.</span><span class="token function">forEach</span> <span class="token punctuation">{</span> section <span class="token operator">-></span> list<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span>section<span class="token punctuation">)</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>section<span class="token punctuation">.</span>isExpandable<span class="token punctuation">)</span> <span class="token punctuation">{</span> list<span class="token punctuation">.</span><span class="token function">addAll</span><span class="token punctuation">(</span>section<span class="token punctuation">.</span>items<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> mainListAdapter<span class="token operator">?</span><span class="token punctuation">.</span><span class="token function">submitList</span><span class="token punctuation">(</span>list<span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> |
Trong BindingAdapter
sectionList
, mình sẽ check isExpandable
để add hoặc không add section item.
Khi isExpandable
là false
, nghĩa là đang mở rộng thì chúng ta sẽ add các Section Item vào. Và ngược lại, chúng ta chỉ add Section thôi.
Túm lại
Mình đã giới thiệu xong một example về Expandable List. Có thể đây không phải cách tối ưu nhất khi xử lý vấn đề này. Nhưng hi vọng nó sẽ giúp một chút gì cho các bạn.
Nếu có bất kì vấn đề nào hoặc góp ý cho bài viết, hãy comment dưới nhé…
Cám ơn các bạn đã đọc đến đây.
Thank you and Happy coding!!!