1 /* <lambda>null2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.wallpaper.picker.customization.ui.binder 18 19 import android.view.View 20 import androidx.constraintlayout.motion.widget.MotionLayout 21 import androidx.core.view.doOnLayout 22 import androidx.lifecycle.Lifecycle 23 import androidx.lifecycle.LifecycleOwner 24 import androidx.lifecycle.lifecycleScope 25 import androidx.lifecycle.repeatOnLifecycle 26 import androidx.recyclerview.widget.RecyclerView 27 import androidx.viewpager2.widget.ViewPager2 28 import com.android.wallpaper.R 29 import com.android.wallpaper.model.Screen 30 import com.android.wallpaper.model.Screen.HOME_SCREEN 31 import com.android.wallpaper.model.Screen.LOCK_SCREEN 32 import com.android.wallpaper.picker.customization.ui.CustomizationPickerActivity2 33 import com.android.wallpaper.picker.customization.ui.util.CustomizationOptionUtil.CustomizationOption 34 import com.android.wallpaper.picker.customization.ui.viewmodel.ColorUpdateViewModel 35 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2 36 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2.PickerScreen.CUSTOMIZATION_OPTION 37 import com.android.wallpaper.picker.customization.ui.viewmodel.CustomizationPickerViewModel2.PickerScreen.MAIN 38 import kotlinx.coroutines.launch 39 40 object CustomizationPickerBinder2 { 41 42 private const val ALPHA_SELECTED_PREVIEW = 1f 43 private const val ALPHA_NON_SELECTED_PREVIEW = 0.4f 44 private const val LOCK_SCREEN_PREVIEW_POSITION = 0 45 private const val HOME_SCREEN_PREVIEW_POSITION = 1 46 47 /** 48 * @return Callback for the [CustomizationPickerActivity2] to set 49 * [CustomizationPickerViewModel2]'s screen state to null, which infers to the main screen. We 50 * need this callback to handle the back navigation in [CustomizationPickerActivity2]. 51 */ 52 fun bind( 53 view: View, 54 lockScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>, 55 homeScreenCustomizationOptionEntries: List<Pair<CustomizationOption, View>>, 56 customizationOptionFloatingSheetViewMap: Map<CustomizationOption, View>?, 57 viewModel: CustomizationPickerViewModel2, 58 colorUpdateViewModel: ColorUpdateViewModel, 59 customizationOptionsBinder: CustomizationOptionsBinder, 60 lifecycleOwner: LifecycleOwner, 61 navigateToPrimary: () -> Unit, 62 navigateToSecondary: (screen: CustomizationOption) -> Unit, 63 navigateToCategoriesScreen: (screen: Screen) -> Unit, 64 ) { 65 val optionContainer = 66 view.requireViewById<MotionLayout>(R.id.customization_option_container) 67 val pager = view.requireViewById<ViewPager2>(R.id.preview_pager) 68 pager.registerOnPageChangeCallback( 69 object : ViewPager2.OnPageChangeCallback() { 70 override fun onPageSelected(position: Int) { 71 viewModel.selectPreviewScreen( 72 if (position == LOCK_SCREEN_PREVIEW_POSITION) LOCK_SCREEN else HOME_SCREEN 73 ) 74 } 75 } 76 ) 77 val mediumAnimTimeMs = 78 view.resources.getInteger(android.R.integer.config_mediumAnimTime).toLong() 79 pager.doOnLayout { 80 // RecyclerView items can only be reliably retrieved on layout. 81 val lockScreenPreview = 82 (pager.getChildAt(0) as? RecyclerView) 83 ?.findViewHolderForAdapterPosition(LOCK_SCREEN_PREVIEW_POSITION) 84 ?.itemView 85 val homeScreenPreview = 86 (pager.getChildAt(0) as? RecyclerView) 87 ?.findViewHolderForAdapterPosition(HOME_SCREEN_PREVIEW_POSITION) 88 ?.itemView 89 val fadePreview = { position: Int -> 90 lockScreenPreview?.apply { 91 findViewById<View>(R.id.wallpaper_surface) 92 .animate() 93 .alpha( 94 if (position == LOCK_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW 95 else ALPHA_NON_SELECTED_PREVIEW 96 ) 97 .setDuration(mediumAnimTimeMs) 98 .start() 99 findViewById<View>(R.id.workspace_surface) 100 .animate() 101 .alpha( 102 if (position == LOCK_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW 103 else ALPHA_NON_SELECTED_PREVIEW 104 ) 105 .setDuration(mediumAnimTimeMs) 106 .start() 107 } 108 homeScreenPreview?.apply { 109 findViewById<View>(R.id.wallpaper_surface) 110 .animate() 111 .alpha( 112 if (position == HOME_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW 113 else ALPHA_NON_SELECTED_PREVIEW 114 ) 115 .setDuration(mediumAnimTimeMs) 116 .start() 117 findViewById<View>(R.id.workspace_surface) 118 .animate() 119 .alpha( 120 if (position == HOME_SCREEN_PREVIEW_POSITION) ALPHA_SELECTED_PREVIEW 121 else ALPHA_NON_SELECTED_PREVIEW 122 ) 123 .setDuration(mediumAnimTimeMs) 124 .start() 125 } 126 } 127 fadePreview(pager.currentItem) 128 pager.registerOnPageChangeCallback( 129 object : ViewPager2.OnPageChangeCallback() { 130 override fun onPageSelected(position: Int) { 131 super.onPageSelected(position) 132 fadePreview(position) 133 } 134 } 135 ) 136 } 137 138 lifecycleOwner.lifecycleScope.launch { 139 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 140 launch { 141 viewModel.screen.collect { (screen, option) -> 142 when (screen) { 143 MAIN -> navigateToPrimary() 144 CUSTOMIZATION_OPTION -> option?.let(navigateToSecondary) 145 } 146 } 147 } 148 149 launch { 150 viewModel.selectedPreviewScreen.collect { 151 when (it) { 152 LOCK_SCREEN -> { 153 pager.currentItem = 0 154 optionContainer.transitionToStart() 155 } 156 HOME_SCREEN -> { 157 pager.currentItem = 1 158 optionContainer.transitionToEnd() 159 } 160 } 161 } 162 } 163 } 164 } 165 166 customizationOptionsBinder.bind( 167 view, 168 lockScreenCustomizationOptionEntries, 169 homeScreenCustomizationOptionEntries, 170 customizationOptionFloatingSheetViewMap, 171 viewModel, 172 colorUpdateViewModel, 173 lifecycleOwner, 174 navigateToCategoriesScreen, 175 ) 176 } 177 } 178