Toolbar UI (2/2)
Test: Manually tested.
Bug: 337941334
Flag: com.android.wallpaper.new_picker_ui_flag
Change-Id: Ieff3724458d695103ce30629dff0d9ebd821d95a
diff --git a/res/layout/bottom_sheet_shortcut.xml b/res/layout/bottom_sheet_shortcut.xml
index e285604..29222d3 100644
--- a/res/layout/bottom_sheet_shortcut.xml
+++ b/res/layout/bottom_sheet_shortcut.xml
@@ -24,7 +24,7 @@
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:background="@drawable/picker_fragment_background">
+ android:background="@drawable/floating_sheet_background2">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/quick_affordance_horizontal_list"
@@ -34,16 +34,10 @@
android:clipToPadding="false"/>
</FrameLayout>
- <FrameLayout
- android:layout_width="match_parent"
+ <com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+ android:id="@+id/floating_bar_tabs"
+ android:layout_width="wrap_content"
android:layout_height="wrap_content"
- android:paddingVertical="8dp">
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@id/slot_tabs"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:clipToPadding="false" />
- </FrameLayout>
+ android:layout_gravity="center_horizontal"
+ android:paddingVertical="8dp" />
</LinearLayout>
\ No newline at end of file
diff --git a/src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt b/src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt
index de95fc3..f9cb688 100644
--- a/src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt
+++ b/src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt
@@ -19,28 +19,26 @@
import android.app.Dialog
import android.content.Context
import android.view.View
-import android.view.ViewGroup
-import android.view.accessibility.AccessibilityEvent
import android.widget.ImageView
-import androidx.core.view.AccessibilityDelegateCompat
-import androidx.core.view.ViewCompat
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle
import androidx.recyclerview.widget.GridLayoutManager
-import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
-import com.android.customization.picker.common.ui.view.ItemSpacing
import com.android.customization.picker.common.ui.view.KeyguardQuickAffordanceItemSpacing
-import com.android.customization.picker.quickaffordance.ui.adapter.SlotTabAdapter
import com.android.themepicker.R
import com.android.wallpaper.customization.ui.viewmodel.KeyguardQuickAffordancePickerViewModel2
import com.android.wallpaper.picker.common.dialog.ui.viewbinder.DialogViewBinder
import com.android.wallpaper.picker.common.dialog.ui.viewmodel.DialogViewModel
import com.android.wallpaper.picker.common.icon.ui.viewbinder.IconViewBinder
import com.android.wallpaper.picker.common.icon.ui.viewmodel.Icon
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.PRIMARY
+import com.android.wallpaper.picker.customization.ui.view.FloatingTabToolbar.Tab.SECONDARY
import com.android.wallpaper.picker.option.ui.adapter.OptionItemAdapter
+import com.android.wallpaper.picker.option.ui.viewmodel.OptionItemViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.collectIndexed
import kotlinx.coroutines.flow.combine
@@ -57,52 +55,13 @@
viewModel: KeyguardQuickAffordancePickerViewModel2,
lifecycleOwner: LifecycleOwner,
) {
- val quickAffordanceAdapter =
- OptionItemAdapter(
- layoutResourceId = R.layout.quick_affordance_list_item,
- lifecycleOwner = lifecycleOwner,
- bindIcon = { foregroundView: View, gridIcon: Icon ->
- val imageView = foregroundView as? ImageView
- imageView?.let { IconViewBinder.bind(imageView, gridIcon) }
- },
- )
+ val quickAffordanceAdapter = createOptionItemAdapter(lifecycleOwner)
val quickAffordanceList =
- view.requireViewById<RecyclerView>(R.id.quick_affordance_horizontal_list).apply {
- adapter = quickAffordanceAdapter
- layoutManager =
- GridLayoutManager(
- view.context.applicationContext,
- 2,
- GridLayoutManager.HORIZONTAL,
- false
- )
- addItemDecoration(KeyguardQuickAffordanceItemSpacing())
+ view.requireViewById<RecyclerView>(R.id.quick_affordance_horizontal_list).also {
+ it.initQuickAffordanceList(view.context.applicationContext, quickAffordanceAdapter)
}
- val slotTabAdapter = SlotTabAdapter()
- val slotTabView: RecyclerView =
- view.requireViewById<RecyclerView>(R.id.slot_tabs).apply {
- adapter = slotTabAdapter
- layoutManager = LinearLayoutManager(view.context, RecyclerView.HORIZONTAL, false)
- addItemDecoration(ItemSpacing(ItemSpacing.TAB_ITEM_SPACING_DP))
- }
- // Setting a custom accessibility delegate so that the default content descriptions
- // for items in a list aren't announced (for left & right shortcuts). We populate
- // the content description for these shortcuts later on with the right (expected)
- // values.
- val slotTabViewDelegate: AccessibilityDelegateCompat =
- object : AccessibilityDelegateCompat() {
- override fun onRequestSendAccessibilityEvent(
- host: ViewGroup,
- child: View,
- event: AccessibilityEvent
- ): Boolean {
- if (event.eventType != AccessibilityEvent.TYPE_VIEW_FOCUSED) {
- child.contentDescription = null
- }
- return super.onRequestSendAccessibilityEvent(host, child, event)
- }
- }
- ViewCompat.setAccessibilityDelegate(slotTabView, slotTabViewDelegate)
+
+ val tabs = view.requireViewById<FloatingTabToolbar>(R.id.floating_bar_tabs)
var dialog: Dialog? = null
@@ -111,7 +70,24 @@
launch {
viewModel.slots
.map { slotById -> slotById.values }
- .collect { slots -> slotTabAdapter.setItems(slots.toList()) }
+ .collect { slots ->
+ val list = slots.toList()
+ list.mapIndexed { index, slot ->
+ val tab = if (index == 0) PRIMARY else SECONDARY
+ tabs.setSelectedAffordances(tab, slot.selectedQuickAffordances)
+ tabs.setTabText(tab, slot.name)
+ tabs.setOnTabClick(tab, slot.onClicked)
+ }
+ list
+ .indexOfFirst { it.isSelected }
+ .let {
+ if (it == 0) {
+ tabs.setTabSelected(PRIMARY)
+ } else if (it == 1) {
+ tabs.setTabSelected(SECONDARY)
+ }
+ }
+ }
}
launch {
@@ -184,4 +160,48 @@
onDismissed = onDismissed,
)
}
+
+ private fun createOptionItemAdapter(lifecycleOwner: LifecycleOwner): OptionItemAdapter<Icon> =
+ OptionItemAdapter(
+ layoutResourceId = R.layout.quick_affordance_list_item,
+ lifecycleOwner = lifecycleOwner,
+ bindIcon = { foregroundView: View, gridIcon: Icon ->
+ val imageView = foregroundView as? ImageView
+ imageView?.let { IconViewBinder.bind(imageView, gridIcon) }
+ },
+ )
+
+ private fun RecyclerView.initQuickAffordanceList(
+ context: Context,
+ adapter: OptionItemAdapter<Icon>
+ ) {
+ apply {
+ this.adapter = adapter
+ layoutManager =
+ GridLayoutManager(
+ context,
+ 2,
+ GridLayoutManager.HORIZONTAL,
+ false,
+ )
+ addItemDecoration(KeyguardQuickAffordanceItemSpacing())
+ }
+ }
+
+ private fun FloatingTabToolbar.setSelectedAffordances(
+ tab: Tab,
+ selectedQuickAffordances: List<OptionItemViewModel<Icon>>,
+ ) {
+ val icon =
+ selectedQuickAffordances.firstOrNull()?.payload
+ ?: Icon.Resource(res = R.drawable.link_off, contentDescription = null)
+ IconViewBinder.bind(
+ if (tab == PRIMARY) {
+ this.primaryIcon
+ } else {
+ this.secondaryIcon
+ },
+ icon,
+ )
+ }
}