• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025 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.view
18 
19 import android.content.Context
20 import android.graphics.Canvas
21 import android.graphics.Path
22 import android.graphics.drawable.GradientDrawable
23 import android.util.AttributeSet
24 import android.view.Gravity
25 import android.widget.FrameLayout
26 import android.widget.TextView
27 import androidx.constraintlayout.widget.ConstraintLayout
28 import androidx.core.view.isVisible
29 import androidx.recyclerview.widget.RecyclerView
30 import com.android.wallpaper.R
31 
32 /**
33  * The wallpaper entry on the main screen. This view needs to be in a [ConstraintLayout].
34  *
35  * This view is used to display the wallpaper option in the customization screen. It has a collapsed
36  * state and an expanded state. The collapsed state shows a button that allows the user to select a
37  * wallpaper. The expanded state shows a carousel of wallpapers that are related to the selected
38  * wallpaper.
39  */
40 class WallpaperPickerEntry
41 @JvmOverloads
42 constructor(context: Context, attrs: AttributeSet? = null) : FrameLayout(context, attrs) {
43 
44     val collapsedButton: TextView
45     val moreWallpapersButton: TextView
46     val suggestedPhotosText: TextView
47     val wallpaperCarousel: RecyclerView
48 
49     private val backgroundLayout: FrameLayout
50     val background: GradientDrawable
51     private val expandedContainer: ConstraintLayout
52 
53     private val defaultCornerRadius: Float
54     private val expandedBackgroundTopCornerRadius: Float
55 
56     private var expandedWidth = 0
57     private var expandedHeight = 0
58     private var collapsedHeight = 0
59     private var collapsedWidth = 0
60 
61     init {
62         inflate(context, R.layout.wallpaper_picker_entry, this)
63 
64         collapsedButton =
65             requireViewById(R.id.customization_option_entry_wallpaper_collapsed_button)
66         moreWallpapersButton = requireViewById(R.id.more_wallpapers_button)
67         suggestedPhotosText = requireViewById(R.id.wallpaper_picker_entry_title)
68         wallpaperCarousel = requireViewById(R.id.wallpaper_carousel)
69 
70         backgroundLayout = requireViewById(R.id.wallpaper_picker_entry_background)
71         background = backgroundLayout.background as GradientDrawable
72         expandedContainer = requireViewById(R.id.wallpaper_picker_entry_expanded_container)
73 
74         defaultCornerRadius =
75             resources
76                 .getDimensionPixelSize(R.dimen.customization_option_entry_corner_radius_large)
77                 .toFloat()
78         expandedBackgroundTopCornerRadius =
79             resources
80                 .getDimensionPixelSize(R.dimen.wallpaper_picker_entry_background_top_corner_radius)
81                 .toFloat()
82 
83         clipChildren = false
84         clipToPadding = false
85 
<lambda>null86         post {
87             // Make fixed width and height of the container, so it does not shrink with parent.
88             expandedContainer.layoutParams =
89                 LayoutParams(expandedContainer.width, expandedContainer.height).apply {
90                     gravity = Gravity.CENTER
91                 }
92 
93             expandedWidth = width
94             expandedHeight = height
95             collapsedWidth =
96                 collapsedButton.width +
97                     resources.getDimensionPixelSize(
98                         R.dimen.customization_option_container_horizontal_padding
99                     ) * 4
100             collapsedHeight = collapsedButton.height
101         }
102     }
103 
dispatchDrawnull104     override fun dispatchDraw(canvas: Canvas) {
105         val clipPath = Path()
106 
107         clipPath.addRoundRect(
108             paddingStart.toFloat(),
109             0f,
110             paddingStart.toFloat() + backgroundLayout.width.toFloat(),
111             backgroundLayout.height.toFloat(),
112             background.cornerRadii ?: FloatArray(8),
113             Path.Direction.CW,
114         )
115         canvas.clipPath(clipPath)
116 
117         super.dispatchDraw(canvas)
118     }
119 
120     /**
121      * Set collapsing progress of the [WallpaperPickerEntry]
122      *
123      * @param progress 0.0 means fully expanded and 1.0 means fully collapsed
124      */
setProgressnull125     fun setProgress(progress: Float) {
126         collapsedButton.alpha = progress
127         collapsedButton.isVisible = progress > 0
128         expandedContainer.alpha = 1 - progress
129         val radii = background.cornerRadii ?: FloatArray(8)
130         val topCornerRadius =
131             expandedBackgroundTopCornerRadius -
132                 (expandedBackgroundTopCornerRadius - defaultCornerRadius) * progress
133         radii[0] = topCornerRadius
134         radii[1] = topCornerRadius
135         radii[2] = topCornerRadius
136         radii[3] = topCornerRadius
137         radii[4] = defaultCornerRadius
138         radii[5] = defaultCornerRadius
139         radii[6] = defaultCornerRadius
140         radii[7] = defaultCornerRadius
141         background.cornerRadii = radii
142 
143         val params = layoutParams as ConstraintLayout.LayoutParams
144 
145         params.width = (expandedWidth - (expandedWidth - collapsedWidth) * progress).toInt()
146         params.height = (expandedHeight - (expandedHeight - collapsedHeight) * progress).toInt()
147         layoutParams = params
148     }
149 }
150