1 /* <lambda>null2 * Copyright 2023 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 package com.android.wallpaper.picker.preview.ui.binder 17 18 import android.view.View 19 import android.view.ViewStub 20 import android.view.animation.AccelerateDecelerateInterpolator 21 import androidx.core.view.doOnLayout 22 import androidx.core.view.isVisible 23 import androidx.lifecycle.Lifecycle 24 import androidx.lifecycle.LifecycleOwner 25 import androidx.lifecycle.lifecycleScope 26 import androidx.lifecycle.repeatOnLifecycle 27 import kotlinx.coroutines.flow.Flow 28 import kotlinx.coroutines.launch 29 30 object PreviewTooltipBinder { 31 interface TooltipViewModel { 32 val shouldShowTooltip: Flow<Boolean> 33 fun dismissTooltip() 34 } 35 36 fun bindSmallPreviewTooltip( 37 tooltipStub: ViewStub, 38 viewModel: TooltipViewModel, 39 lifecycleOwner: LifecycleOwner, 40 ) { 41 var tooltip: View? = null 42 lifecycleOwner.lifecycleScope.launch { 43 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 44 launch { 45 viewModel.shouldShowTooltip.collect { shouldShowTooltip -> 46 if (shouldShowTooltip && tooltip == null) { 47 tooltip = tooltipStub.inflate() 48 } 49 tooltip?.doOnLayout { 50 it.isVisible = true 51 it.alpha = if (shouldShowTooltip) 0f else 1f 52 it.pivotX = it.measuredWidth / 2f 53 it.pivotY = it.measuredHeight.toFloat() 54 it.scaleX = if (shouldShowTooltip) 0.2f else 1f 55 it.scaleY = if (shouldShowTooltip) 0.2f else 1f 56 57 if (shouldShowTooltip) { 58 it.animate() 59 .scaleX(1f) 60 .scaleY(1f) 61 .alpha(1f) 62 .setStartDelay(1000L) 63 .setDuration(200L) 64 .setInterpolator(AccelerateDecelerateInterpolator()) 65 .start() 66 } else { 67 it.animate() 68 .alpha(0f) 69 .setDuration(75L) 70 .setInterpolator(AccelerateDecelerateInterpolator()) 71 .withEndAction { tooltip?.isVisible = false } 72 .start() 73 } 74 } 75 } 76 } 77 } 78 } 79 } 80 81 fun bindFullPreviewTooltip( 82 tooltipStub: ViewStub, 83 viewModel: TooltipViewModel, 84 lifecycleOwner: LifecycleOwner, 85 ) { 86 var tooltip: View? = null 87 lifecycleOwner.lifecycleScope.launch { 88 lifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { 89 launch { 90 viewModel.shouldShowTooltip.collect { shouldShowTooltip -> 91 if (shouldShowTooltip && tooltip == null) { 92 tooltip = tooltipStub.inflate() 93 tooltip?.setOnClickListener { viewModel.dismissTooltip() } 94 } 95 tooltip?.doOnLayout { 96 it.isVisible = true 97 it.alpha = if (shouldShowTooltip) 0f else 1f 98 it.translationY = if (shouldShowTooltip) -20f else 0f 99 100 if (shouldShowTooltip) { 101 it.animate() 102 .alpha(1f) 103 .translationY(0f) 104 .setStartDelay(500L) 105 .setDuration(200L) 106 .setInterpolator(AccelerateDecelerateInterpolator()) 107 .start() 108 } else { 109 it.animate() 110 .alpha(0f) 111 .translationY(-20f) 112 .setDuration(75L) 113 .setInterpolator(AccelerateDecelerateInterpolator()) 114 .withEndAction { tooltip?.isVisible = false } 115 .start() 116 } 117 } 118 } 119 } 120 } 121 } 122 } 123 } 124