• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2020 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.systemui.media.controls.models.recommendation
18 
19 import android.view.LayoutInflater
20 import android.view.View
21 import android.view.ViewGroup
22 import android.widget.ImageView
23 import android.widget.SeekBar
24 import android.widget.TextView
25 import com.android.internal.widget.CachingIconView
26 import com.android.systemui.R
27 import com.android.systemui.media.controls.models.GutsViewHolder
28 import com.android.systemui.media.controls.ui.IlluminationDrawable
29 import com.android.systemui.util.animation.TransitionLayout
30 
31 private const val TAG = "RecommendationViewHolder"
32 
33 /** ViewHolder for a Smartspace media recommendation. */
34 class RecommendationViewHolder private constructor(itemView: View, updatedView: Boolean) {
35 
36     val recommendations = itemView as TransitionLayout
37 
38     // Recommendation screen
39     lateinit var cardIcon: ImageView
40     lateinit var mediaAppIcons: List<CachingIconView>
41     lateinit var mediaProgressBars: List<SeekBar>
42     lateinit var cardTitle: TextView
43 
44     val mediaCoverContainers =
45         listOf<ViewGroup>(
46             itemView.requireViewById(R.id.media_cover1_container),
47             itemView.requireViewById(R.id.media_cover2_container),
48             itemView.requireViewById(R.id.media_cover3_container)
49         )
50     val mediaTitles: List<TextView> =
51         if (updatedView) {
52             mediaCoverContainers.map { it.requireViewById(R.id.media_title) }
53         } else {
54             listOf(
55                 itemView.requireViewById(R.id.media_title1),
56                 itemView.requireViewById(R.id.media_title2),
57                 itemView.requireViewById(R.id.media_title3)
58             )
59         }
60     val mediaSubtitles: List<TextView> =
61         if (updatedView) {
62             mediaCoverContainers.map { it.requireViewById(R.id.media_subtitle) }
63         } else {
64             listOf(
65                 itemView.requireViewById(R.id.media_subtitle1),
66                 itemView.requireViewById(R.id.media_subtitle2),
67                 itemView.requireViewById(R.id.media_subtitle3)
68             )
69         }
70 
71     val mediaCoverItems: List<ImageView> =
72         if (updatedView) {
73             mediaCoverContainers.map { it.requireViewById(R.id.media_cover) }
74         } else {
75             listOf(
76                 itemView.requireViewById(R.id.media_cover1),
77                 itemView.requireViewById(R.id.media_cover2),
78                 itemView.requireViewById(R.id.media_cover3)
79             )
80         }
81     val gutsViewHolder = GutsViewHolder(itemView)
82 
83     init {
84         if (updatedView) {
85             mediaAppIcons = mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) }
86             cardTitle = itemView.requireViewById(R.id.media_rec_title)
87             mediaProgressBars =
88                 mediaCoverContainers.map {
89                     it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply {
90                         // Media playback is in the direction of tape, not time, so it stays LTR
91                         layoutDirection = View.LAYOUT_DIRECTION_LTR
92                     }
93                 }
94         } else {
95             cardIcon = itemView.requireViewById<ImageView>(R.id.recommendation_card_icon)
96         }
97         (recommendations.background as IlluminationDrawable).let { background ->
98             mediaCoverContainers.forEach { background.registerLightSource(it) }
99             background.registerLightSource(gutsViewHolder.cancel)
100             background.registerLightSource(gutsViewHolder.dismiss)
101             background.registerLightSource(gutsViewHolder.settings)
102         }
103     }
104 
105     fun marquee(start: Boolean, delay: Long) {
106         gutsViewHolder.marquee(start, delay, TAG)
107     }
108 
109     companion object {
110         /**
111          * Creates a RecommendationViewHolder.
112          *
113          * @param inflater LayoutInflater to use to inflate the layout.
114          * @param parent Parent of inflated view.
115          */
116         @JvmStatic
117         fun create(
118             inflater: LayoutInflater,
119             parent: ViewGroup,
120             updatedView: Boolean,
121         ): RecommendationViewHolder {
122             val itemView =
123                 if (updatedView) {
124                     inflater.inflate(
125                         R.layout.media_recommendations,
126                         parent,
127                         false /* attachToRoot */
128                     )
129                 } else {
130                     inflater.inflate(
131                         R.layout.media_smartspace_recommendations,
132                         parent,
133                         false /* attachToRoot */
134                     )
135                 }
136             // Because this media view (a TransitionLayout) is used to measure and layout the views
137             // in various states before being attached to its parent, we can't depend on the default
138             // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
139             itemView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
140             return RecommendationViewHolder(itemView, updatedView)
141         }
142 
143         // Res Ids for the control components on the recommendation view.
144         val controlsIds =
145             setOf(
146                 R.id.recommendation_card_icon,
147                 R.id.media_rec_title,
148                 R.id.media_cover1,
149                 R.id.media_cover2,
150                 R.id.media_cover3,
151                 R.id.media_cover,
152                 R.id.media_cover1_container,
153                 R.id.media_cover2_container,
154                 R.id.media_cover3_container,
155                 R.id.media_title1,
156                 R.id.media_title2,
157                 R.id.media_title3,
158                 R.id.media_title,
159                 R.id.media_subtitle1,
160                 R.id.media_subtitle2,
161                 R.id.media_subtitle3,
162                 R.id.media_subtitle,
163             )
164 
165         val mediaTitlesAndSubtitlesIds =
166             setOf(
167                 R.id.media_title1,
168                 R.id.media_title2,
169                 R.id.media_title3,
170                 R.id.media_title,
171                 R.id.media_subtitle1,
172                 R.id.media_subtitle2,
173                 R.id.media_subtitle3,
174                 R.id.media_subtitle,
175             )
176 
177         val mediaContainersIds =
178             setOf(
179                 R.id.media_cover1_container,
180                 R.id.media_cover2_container,
181                 R.id.media_cover3_container
182             )
183     }
184 }
185