Loading res/layout/bottom_sheet_shortcut.xml +31 −6 Original line number Diff line number Diff line Loading @@ -14,11 +14,36 @@ ~ limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingBottom="16dp" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/picker_fragment_background"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/quick_affordance_horizontal_list" android:layout_width="match_parent" android:layout_height="wrap_content" /> android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false"/> </FrameLayout> <FrameLayout android:layout_width="match_parent" 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> </LinearLayout> No newline at end of file res/layout/quick_affordance_list_item.xml 0 → 100644 +63 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2024 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="64dp" android:layout_height="wrap_content" android:divider="@drawable/vertical_divider_8dp" android:clipChildren="false" android:showDividers="middle"> <FrameLayout android:layout_width="64dp" android:layout_height="64dp" android:background="@drawable/option_item_background" android:clipChildren="false"> <ImageView android:id="@id/selection_border" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/option_item_border" android:alpha="0" android:importantForAccessibility="no" /> <ImageView android:id="@id/background" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/option_item_background" android:importantForAccessibility="no" /> <ImageView android:id="@id/foreground" android:layout_width="@dimen/keyguard_quick_affordance_icon_size" android:layout_height="@dimen/keyguard_quick_affordance_icon_size" android:layout_gravity="center" android:tint="@color/system_on_surface" /> </FrameLayout> <TextView android:id="@id/text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textColor="@color/system_on_surface" android:lines="2" android:hyphenationFrequency="normal" android:ellipsize="end" /> </LinearLayout> No newline at end of file src/com/android/customization/picker/common/ui/view/KeyguardQuickAffordanceItemSpacing.kt 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.customization.picker.common.ui.view import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView /** Item spacing used by the RecyclerView. */ class KeyguardQuickAffordanceItemSpacing() : RecyclerView.ItemDecoration() { override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { val itemIndex = parent.getChildAdapterPosition(view) val columnIndex = itemIndex / 2 val isRtl = parent.layoutManager?.layoutDirection == View.LAYOUT_DIRECTION_RTL val density = parent.context.resources.displayMetrics.density val itemCount = parent.adapter?.itemCount ?: 0 val columnCount = (itemCount + 1) / 2 when { columnCount == 1 -> { outRect.left = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex > 0 && columnIndex < columnCount - 1 -> { outRect.left = COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = COMMON_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex == 0 -> { outRect.left = if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex == columnCount - 1 -> { outRect.right = if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.left = if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) } } if (itemIndex % 2 == 0) { outRect.top = FIRST_ROW_TOP_SPACING_DP.toPx(density) outRect.bottom = FIRST_ROW_BOTTOM_SPACING_DP.toPx(density) } else { outRect.bottom = SECOND_ROW_BOTTOM_SPACING_DP.toPx(density) } } private fun Int.toPx(density: Float): Int { return (this * density).toInt() } companion object { const val EDGE_ITEM_HORIZONTAL_SPACING_DP = 20 const val COMMON_HORIZONTAL_SPACING_DP = 9 const val FIRST_ROW_TOP_SPACING_DP = 20 const val FIRST_ROW_BOTTOM_SPACING_DP = 8 const val SECOND_ROW_BOTTOM_SPACING_DP = 24 } } src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt 0 → 100644 +187 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wallpaper.customization.ui.binder 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.option.ui.adapter.OptionItemAdapter import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collectIndexed import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) object ShortcutBottomSheetBinder { fun bind( view: View, 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 quickAffordanceList = view.requireViewById<RecyclerView>(R.id.quick_affordance_horizontal_list).apply { adapter = quickAffordanceAdapter layoutManager = GridLayoutManager( view.context.applicationContext, 2, GridLayoutManager.HORIZONTAL, false ) addItemDecoration(KeyguardQuickAffordanceItemSpacing()) } 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) var dialog: Dialog? = null lifecycleOwner.lifecycleScope.launch { lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { launch { viewModel.slots .map { slotById -> slotById.values } .collect { slots -> slotTabAdapter.setItems(slots.toList()) } } launch { viewModel.quickAffordances.collect { affordances -> quickAffordanceAdapter.setItems(affordances) } } launch { viewModel.quickAffordances .flatMapLatest { affordances -> combine(affordances.map { affordance -> affordance.isSelected }) { selectedFlags -> selectedFlags.indexOfFirst { it } } } .collectIndexed { index, selectedPosition -> // Scroll the view to show the first selected affordance. if (selectedPosition != -1) { // We use "post" because we need to give the adapter item a pass to // update the view. quickAffordanceList.post { if (index == 0) { // don't animate on initial collection quickAffordanceList.scrollToPosition(selectedPosition) } else { quickAffordanceList.smoothScrollToPosition(selectedPosition) } } } } } launch { viewModel.dialog.distinctUntilChanged().collect { dialogRequest -> dialog?.dismiss() dialog = if (dialogRequest != null) { showDialog( context = view.context, request = dialogRequest, onDismissed = viewModel::onDialogDismissed ) } else { null } } } launch { viewModel.activityStartRequests.collect { intent -> if (intent != null) { view.context.startActivity(intent) viewModel.onActivityStarted() } } } } } } private fun showDialog( context: Context, request: DialogViewModel, onDismissed: () -> Unit, ): Dialog { return DialogViewBinder.show( context = context, viewModel = request, onDismissed = onDismissed, ) } } src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt +8 −0 Original line number Diff line number Diff line Loading @@ -29,8 +29,10 @@ import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUti import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) @Singleton class ThemePickerCustomizationOptionsBinder @Inject Loading Loading @@ -77,5 +79,11 @@ constructor(private val defaultCustomizationOptionsBinder: DefaultCustomizationO } } } ShortcutBottomSheetBinder.bind( view, viewModel.keyguardQuickAffordancePickerViewModel2, lifecycleOwner, ) } } Loading
res/layout/bottom_sheet_shortcut.xml +31 −6 Original line number Diff line number Diff line Loading @@ -14,11 +14,36 @@ ~ limitations under the License. --> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content"> android:layout_height="wrap_content" android:paddingHorizontal="16dp" android:paddingBottom="16dp" android:orientation="vertical"> <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/picker_fragment_background"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/quick_affordance_horizontal_list" android:layout_width="match_parent" android:layout_height="wrap_content" /> android:layout_height="wrap_content" android:clipChildren="false" android:clipToPadding="false"/> </FrameLayout> <FrameLayout android:layout_width="match_parent" 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> </LinearLayout> No newline at end of file
res/layout/quick_affordance_list_item.xml 0 → 100644 +63 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?><!-- ~ Copyright (C) 2024 The Android Open Source Project ~ ~ Licensed under the Apache License, Version 2.0 (the "License"); ~ you may not use this file except in compliance with the License. ~ You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, software ~ distributed under the License is distributed on an "AS IS" BASIS, ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ See the License for the specific language governing permissions and ~ limitations under the License. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="64dp" android:layout_height="wrap_content" android:divider="@drawable/vertical_divider_8dp" android:clipChildren="false" android:showDividers="middle"> <FrameLayout android:layout_width="64dp" android:layout_height="64dp" android:background="@drawable/option_item_background" android:clipChildren="false"> <ImageView android:id="@id/selection_border" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/option_item_border" android:alpha="0" android:importantForAccessibility="no" /> <ImageView android:id="@id/background" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/option_item_background" android:importantForAccessibility="no" /> <ImageView android:id="@id/foreground" android:layout_width="@dimen/keyguard_quick_affordance_icon_size" android:layout_height="@dimen/keyguard_quick_affordance_icon_size" android:layout_gravity="center" android:tint="@color/system_on_surface" /> </FrameLayout> <TextView android:id="@id/text" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:textColor="@color/system_on_surface" android:lines="2" android:hyphenationFrequency="normal" android:ellipsize="end" /> </LinearLayout> No newline at end of file
src/com/android/customization/picker/common/ui/view/KeyguardQuickAffordanceItemSpacing.kt 0 → 100644 +83 −0 Original line number Diff line number Diff line /* * Copyright (C) 2023 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.customization.picker.common.ui.view import android.graphics.Rect import android.view.View import androidx.recyclerview.widget.RecyclerView /** Item spacing used by the RecyclerView. */ class KeyguardQuickAffordanceItemSpacing() : RecyclerView.ItemDecoration() { override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { val itemIndex = parent.getChildAdapterPosition(view) val columnIndex = itemIndex / 2 val isRtl = parent.layoutManager?.layoutDirection == View.LAYOUT_DIRECTION_RTL val density = parent.context.resources.displayMetrics.density val itemCount = parent.adapter?.itemCount ?: 0 val columnCount = (itemCount + 1) / 2 when { columnCount == 1 -> { outRect.left = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex > 0 && columnIndex < columnCount - 1 -> { outRect.left = COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = COMMON_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex == 0 -> { outRect.left = if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.right = if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) } columnIndex == columnCount - 1 -> { outRect.right = if (!isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) outRect.left = if (isRtl) EDGE_ITEM_HORIZONTAL_SPACING_DP.toPx(density) else COMMON_HORIZONTAL_SPACING_DP.toPx(density) } } if (itemIndex % 2 == 0) { outRect.top = FIRST_ROW_TOP_SPACING_DP.toPx(density) outRect.bottom = FIRST_ROW_BOTTOM_SPACING_DP.toPx(density) } else { outRect.bottom = SECOND_ROW_BOTTOM_SPACING_DP.toPx(density) } } private fun Int.toPx(density: Float): Int { return (this * density).toInt() } companion object { const val EDGE_ITEM_HORIZONTAL_SPACING_DP = 20 const val COMMON_HORIZONTAL_SPACING_DP = 9 const val FIRST_ROW_TOP_SPACING_DP = 20 const val FIRST_ROW_BOTTOM_SPACING_DP = 8 const val SECOND_ROW_BOTTOM_SPACING_DP = 24 } }
src/com/android/wallpaper/customization/ui/binder/ShortcutBottomSheetBinder.kt 0 → 100644 +187 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wallpaper.customization.ui.binder 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.option.ui.adapter.OptionItemAdapter import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.collectIndexed import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) object ShortcutBottomSheetBinder { fun bind( view: View, 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 quickAffordanceList = view.requireViewById<RecyclerView>(R.id.quick_affordance_horizontal_list).apply { adapter = quickAffordanceAdapter layoutManager = GridLayoutManager( view.context.applicationContext, 2, GridLayoutManager.HORIZONTAL, false ) addItemDecoration(KeyguardQuickAffordanceItemSpacing()) } 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) var dialog: Dialog? = null lifecycleOwner.lifecycleScope.launch { lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { launch { viewModel.slots .map { slotById -> slotById.values } .collect { slots -> slotTabAdapter.setItems(slots.toList()) } } launch { viewModel.quickAffordances.collect { affordances -> quickAffordanceAdapter.setItems(affordances) } } launch { viewModel.quickAffordances .flatMapLatest { affordances -> combine(affordances.map { affordance -> affordance.isSelected }) { selectedFlags -> selectedFlags.indexOfFirst { it } } } .collectIndexed { index, selectedPosition -> // Scroll the view to show the first selected affordance. if (selectedPosition != -1) { // We use "post" because we need to give the adapter item a pass to // update the view. quickAffordanceList.post { if (index == 0) { // don't animate on initial collection quickAffordanceList.scrollToPosition(selectedPosition) } else { quickAffordanceList.smoothScrollToPosition(selectedPosition) } } } } } launch { viewModel.dialog.distinctUntilChanged().collect { dialogRequest -> dialog?.dismiss() dialog = if (dialogRequest != null) { showDialog( context = view.context, request = dialogRequest, onDismissed = viewModel::onDialogDismissed ) } else { null } } } launch { viewModel.activityStartRequests.collect { intent -> if (intent != null) { view.context.startActivity(intent) viewModel.onActivityStarted() } } } } } } private fun showDialog( context: Context, request: DialogViewModel, onDismissed: () -> Unit, ): Dialog { return DialogViewBinder.show( context = context, viewModel = request, onDismissed = onDismissed, ) } }
src/com/android/wallpaper/customization/ui/binder/ThemePickerCustomizationOptionBinder.kt +8 −0 Original line number Diff line number Diff line Loading @@ -29,8 +29,10 @@ import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUti import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationOptionsViewModel import javax.inject.Inject import javax.inject.Singleton import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.launch @OptIn(ExperimentalCoroutinesApi::class) @Singleton class ThemePickerCustomizationOptionsBinder @Inject Loading Loading @@ -77,5 +79,11 @@ constructor(private val defaultCustomizationOptionsBinder: DefaultCustomizationO } } } ShortcutBottomSheetBinder.bind( view, viewModel.keyguardQuickAffordancePickerViewModel2, lifecycleOwner, ) } }