-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
591: Add groups to user info, with sections and using RecyclerView for future expandability #16769
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 6 commits
98ab726
da3f262
6d88aa1
4917913
66ce69e
16486bf
b808845
8a5ded9
7f44e91
1de358f
25911dc
4301bf7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| /* | ||
| * Nextcloud - Android Client | ||
| * | ||
| * SPDX-FileCopyrightText: 2026 Daniele Verducci <daniele.verducci@ichibi.eu> | ||
| * SPDX-License-Identifier: AGPL-3.0-or-later | ||
| */ | ||
|
|
||
| package com.owncloud.android.ui.adapter | ||
|
|
||
| import android.content.Context | ||
| import android.view.LayoutInflater | ||
| import android.view.ViewGroup | ||
| import androidx.annotation.DrawableRes | ||
| import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter | ||
| import com.afollestad.sectionedrecyclerview.SectionedViewHolder | ||
| import com.nextcloud.android.common.ui.theme.utils.ColorRole | ||
| import com.owncloud.android.R | ||
| import com.owncloud.android.databinding.UserInfoDetailsTableItemBinding | ||
| import com.owncloud.android.databinding.UserInfoDetailsTableItemTitleBinding | ||
| import com.owncloud.android.utils.theme.ViewThemeUtils | ||
|
|
||
| class UserInfoAdapter(val context: Context, val mDisplayList: Map<Int, MutableList<UserInfoDetailsItem>>, val viewThemeUtils: ViewThemeUtils) : | ||
| SectionedRecyclerViewAdapter<SectionedViewHolder>() { | ||
| companion object { | ||
| const val SECTION_USERINFO = 0 | ||
| const val SECTION_GROUPS = 1 | ||
| } | ||
|
|
||
| class UserInfoDetailsItem( | ||
|
||
| @field:DrawableRes @param:DrawableRes var icon: Int, | ||
| var text: String?, | ||
| var iconContentDescription: String? | ||
| ) | ||
|
|
||
| class HeaderSectionedViewHolder(var binding: UserInfoDetailsTableItemTitleBinding) : | ||
| SectionedViewHolder(binding.getRoot()) | ||
|
|
||
| class UserInfoSectionedViewHolder(var binding: UserInfoDetailsTableItemBinding) : | ||
| SectionedViewHolder(binding.getRoot()) | ||
|
|
||
| override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SectionedViewHolder = when (viewType) { | ||
| VIEW_TYPE_HEADER -> HeaderSectionedViewHolder( | ||
| UserInfoDetailsTableItemTitleBinding.inflate( | ||
| LayoutInflater.from(parent.context), | ||
| parent, | ||
| false | ||
| ) | ||
| ) | ||
| else -> UserInfoSectionedViewHolder( | ||
| UserInfoDetailsTableItemBinding.inflate( | ||
| LayoutInflater.from(parent.context), | ||
| parent, | ||
| false | ||
| ), | ||
| ) | ||
| } | ||
|
|
||
| override fun onBindViewHolder( | ||
| holder: SectionedViewHolder?, | ||
|
||
| section: Int, | ||
| relativePosition: Int, | ||
| absolutePosition: Int | ||
| ) { | ||
| val item = mDisplayList[section]?.get(relativePosition) | ||
|
||
| val isFirst = relativePosition == 0 | ||
| val isLast = relativePosition == getItemCount(section) - 1 | ||
| val isSingle = isFirst && isLast | ||
| val uiHolder = holder as UserInfoSectionedViewHolder | ||
|
|
||
| // Set background | ||
| if (isSingle) { | ||
| uiHolder.binding.root.setBackgroundResource(R.drawable.rounded_corners_listitem_single_background) | ||
| } else if (isFirst) { | ||
| uiHolder.binding.root.setBackgroundResource(R.drawable.rounded_corners_listitem_first_background) | ||
| } else if (isLast) { | ||
| uiHolder.binding.root.setBackgroundResource(R.drawable.rounded_corners_listitem_last_background) | ||
| } else { | ||
| uiHolder.binding.root.setBackgroundResource(R.drawable.rounded_corners_listitem_center_background) | ||
| } | ||
|
|
||
| // Populate views | ||
| uiHolder.binding.icon.setImageResource(item?.icon ?: R.drawable.ic_user_outline) | ||
| uiHolder.binding.text.text = item?.text | ||
| uiHolder.binding.icon.contentDescription = item?.iconContentDescription | ||
| viewThemeUtils.platform.colorImageView(holder.binding.icon, ColorRole.PRIMARY) | ||
| } | ||
|
|
||
| override fun getSectionCount(): Int = 2 | ||
|
|
||
| override fun getItemCount(section: Int): Int = when (section) { | ||
| SECTION_GROUPS -> mDisplayList[SECTION_GROUPS]?.size ?: 0 | ||
| SECTION_USERINFO -> mDisplayList[SECTION_USERINFO]?.size ?: 0 | ||
| else -> 0 | ||
| } | ||
|
|
||
| override fun onBindHeaderViewHolder( | ||
| holder: SectionedViewHolder?, | ||
| section: Int, | ||
| expanded: Boolean | ||
| ) { | ||
| val title = when (section) { | ||
| SECTION_GROUPS -> context.getString(R.string.user_info_groups) | ||
| SECTION_USERINFO -> context.getString(R.string.user_info_profile) | ||
| else -> "" | ||
| } | ||
| val titleHolder = holder as HeaderSectionedViewHolder | ||
| titleHolder.binding.root.text = title | ||
| viewThemeUtils.platform.colorTextView(titleHolder.binding.root, ColorRole.PRIMARY) | ||
| } | ||
|
|
||
| override fun onBindFooterViewHolder(p0: SectionedViewHolder?, p1: Int) {} | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| <?xml version="1.0" encoding="utf-8"?><!-- | ||
| ~ Nextcloud - Android Client | ||
| ~ | ||
| ~ SPDX-FileCopyrightText: 2026 Daniele Verducci <daniele.verducci@ichibi.eu> | ||
| ~ SPDX-License-Identifier: AGPL-3.0-or-later | ||
| --> | ||
|
|
||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <item android:top="-2dp" android:left="0dp" android:right="0dp" android:bottom="0dp"> | ||
| <shape android:shape="rectangle"> | ||
| <stroke android:width="1dp" android:color="@color/grey_200"/> | ||
| </shape> | ||
| </item> | ||
| </layer-list> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| <?xml version="1.0" encoding="utf-8"?><!-- | ||
| ~ Nextcloud - Android Client | ||
| ~ | ||
| ~ SPDX-FileCopyrightText: 2026 Daniele Verducci <daniele.verducci@ichibi.eu> | ||
| ~ SPDX-License-Identifier: AGPL-3.0-or-later | ||
| --> | ||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <item> | ||
| <shape> | ||
| <solid android:color="@color/bg_default"/> | ||
| <stroke android:width="1dp" android:color="@color/grey_200" /> | ||
| <corners android:topLeftRadius="4dp" android:topRightRadius="4dp"/> | ||
| </shape> | ||
| </item> | ||
| </layer-list> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| <?xml version="1.0" encoding="utf-8"?><!-- | ||
| ~ Nextcloud - Android Client | ||
| ~ | ||
| ~ SPDX-FileCopyrightText: 2026 Daniele Verducci <daniele.verducci@ichibi.eu> | ||
| ~ SPDX-License-Identifier: AGPL-3.0-or-later | ||
| --> | ||
|
|
||
| <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <item android:top="-2dp" android:left="0dp" android:right="0dp" android:bottom="0dp"> | ||
| <shape> | ||
| <solid android:color="@color/bg_default"/> | ||
| <stroke android:width="1dp" android:color="@color/grey_200" /> | ||
| <corners android:bottomLeftRadius="4dp" android:bottomRightRadius="4dp"/> | ||
| </shape> | ||
| </item> | ||
| </layer-list> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| <?xml version="1.0" encoding="utf-8"?><!-- | ||
| ~ Nextcloud - Android Client | ||
| ~ | ||
| ~ SPDX-FileCopyrightText: 2026 Daniele Verducci <daniele.verducci@ichibi.eu> | ||
| ~ SPDX-License-Identifier: AGPL-3.0-or-later | ||
| --> | ||
|
|
||
| <shape xmlns:android="http://schemas.android.com/apk/res/android"> | ||
| <solid android:color="@color/bg_default"/> | ||
| <stroke android:width="1dp" android:color="@color/grey_200" /> | ||
| <corners android:radius="4dp"/> | ||
| </shape> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why
mDisplayListneeds to have mutable list? Adapter should just display the list.Also since this is a new class;
mDisplayListcan we rename it to thedisplayList?