• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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.ui.view
18 
19 import android.graphics.Typeface
20 import android.view.LayoutInflater
21 import android.view.View
22 import android.view.ViewGroup
23 import android.widget.ImageButton
24 import android.widget.ImageView
25 import android.widget.SeekBar
26 import android.widget.TextView
27 import androidx.constraintlayout.widget.Barrier
28 import com.android.internal.widget.CachingIconView
29 import com.android.systemui.FontStyles.GSF_HEADLINE_SMALL
30 import com.android.systemui.FontStyles.GSF_LABEL_LARGE
31 import com.android.systemui.FontStyles.GSF_LABEL_MEDIUM
32 import com.android.systemui.FontStyles.GSF_TITLE_MEDIUM
33 import com.android.systemui.res.R
34 import com.android.systemui.surfaceeffects.loadingeffect.LoadingEffectView
35 import com.android.systemui.surfaceeffects.ripple.MultiRippleView
36 import com.android.systemui.surfaceeffects.turbulencenoise.TurbulenceNoiseView
37 import com.android.systemui.util.animation.TransitionLayout
38 
39 private const val TAG = "MediaViewHolder"
40 
41 /** Holder class for media player view */
42 class MediaViewHolder constructor(itemView: View) {
43     val player = itemView as TransitionLayout
44 
45     // Player information
46     val albumView = itemView.requireViewById<ImageView>(R.id.album_art)
47     val multiRippleView = itemView.requireViewById<MultiRippleView>(R.id.touch_ripple_view)
48     val turbulenceNoiseView =
49         itemView.requireViewById<TurbulenceNoiseView>(R.id.turbulence_noise_view)
50     val loadingEffectView = itemView.requireViewById<LoadingEffectView>(R.id.loading_effect_view)
51     val appIcon = itemView.requireViewById<ImageView>(R.id.icon)
52     val titleText = itemView.requireViewById<TextView>(R.id.header_title)
53     val artistText = itemView.requireViewById<TextView>(R.id.header_artist)
54     val explicitIndicator = itemView.requireViewById<CachingIconView>(R.id.media_explicit_indicator)
55 
56     // Output switcher
57     val seamless = itemView.requireViewById<ViewGroup>(R.id.media_seamless)
58     val seamlessIcon = itemView.requireViewById<ImageView>(R.id.media_seamless_image)
59     val seamlessText = itemView.requireViewById<TextView>(R.id.media_seamless_text)
60     val seamlessButton = itemView.requireViewById<View>(R.id.media_seamless_button)
61 
62     // Seekbar views
63     val seekBar = itemView.requireViewById<SeekBar>(R.id.media_progress_bar)
64     // These views are only shown while the user is actively scrubbing
65     val scrubbingElapsedTimeView: TextView =
66         itemView.requireViewById(R.id.media_scrubbing_elapsed_time)
67     val scrubbingTotalTimeView: TextView = itemView.requireViewById(R.id.media_scrubbing_total_time)
68 
69     val gutsViewHolder = GutsViewHolder(itemView)
70 
71     // Action Buttons
72     val actionPlayPause = itemView.requireViewById<ImageButton>(R.id.actionPlayPause)
73     val actionNext = itemView.requireViewById<ImageButton>(R.id.actionNext)
74     val actionPrev = itemView.requireViewById<ImageButton>(R.id.actionPrev)
75     val action0 = itemView.requireViewById<ImageButton>(R.id.action0)
76     val action1 = itemView.requireViewById<ImageButton>(R.id.action1)
77     val action2 = itemView.requireViewById<ImageButton>(R.id.action2)
78     val action3 = itemView.requireViewById<ImageButton>(R.id.action3)
79     val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
80 
81     val actionsTopBarrier = itemView.requireViewById<Barrier>(R.id.media_action_barrier_top)
82 
getActionnull83     fun getAction(id: Int): ImageButton {
84         return when (id) {
85             R.id.actionPlayPause -> actionPlayPause
86             R.id.actionNext -> actionNext
87             R.id.actionPrev -> actionPrev
88             R.id.action0 -> action0
89             R.id.action1 -> action1
90             R.id.action2 -> action2
91             R.id.action3 -> action3
92             R.id.action4 -> action4
93             else -> {
94                 throw IllegalArgumentException()
95             }
96         }
97     }
98 
getTransparentActionButtonsnull99     fun getTransparentActionButtons(): List<ImageButton> {
100         return listOf(actionNext, actionPrev, action0, action1, action2, action3, action4)
101     }
102 
marqueenull103     fun marquee(start: Boolean, delay: Long) {
104         gutsViewHolder.marquee(start, delay, TAG)
105     }
106 
107     companion object {
108         /**
109          * Creates a MediaViewHolder.
110          *
111          * @param inflater LayoutInflater to use to inflate the layout.
112          * @param parent Parent of inflated view.
113          */
114         @JvmStatic
createnull115         fun create(inflater: LayoutInflater, parent: ViewGroup): MediaViewHolder {
116             val mediaView = inflater.inflate(R.layout.media_session_view, parent, false)
117             mediaView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
118             // Because this media view (a TransitionLayout) is used to measure and layout the views
119             // in various states before being attached to its parent, we can't depend on the default
120             // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
121             mediaView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE
122             return MediaViewHolder(mediaView).apply {
123                 // Media playback is in the direction of tape, not time, so it stays LTR
124                 seekBar.layoutDirection = View.LAYOUT_DIRECTION_LTR
125             }
126         }
127 
128         val controlsIds =
129             setOf(
130                 R.id.icon,
131                 R.id.app_name,
132                 R.id.header_title,
133                 R.id.header_artist,
134                 R.id.media_explicit_indicator,
135                 R.id.media_seamless,
136                 R.id.media_progress_bar,
137                 R.id.actionPlayPause,
138                 R.id.actionNext,
139                 R.id.actionPrev,
140                 R.id.action0,
141                 R.id.action1,
142                 R.id.action2,
143                 R.id.action3,
144                 R.id.action4,
145                 R.id.icon,
146                 R.id.media_scrubbing_elapsed_time,
147                 R.id.media_scrubbing_total_time,
148             )
149 
150         // Buttons used for notification-based actions
151         val genericButtonIds =
152             setOf(R.id.action0, R.id.action1, R.id.action2, R.id.action3, R.id.action4)
153 
154         val expandedBottomActionIds =
155             setOf(
156                 R.id.media_progress_bar,
157                 R.id.actionPrev,
158                 R.id.actionNext,
159                 R.id.action0,
160                 R.id.action1,
161                 R.id.action2,
162                 R.id.action3,
163                 R.id.action4,
164                 R.id.media_scrubbing_elapsed_time,
165                 R.id.media_scrubbing_total_time,
166             )
167 
168         val detailIds =
169             setOf(
170                 R.id.header_title,
171                 R.id.header_artist,
172                 R.id.media_explicit_indicator,
173                 R.id.actionPlayPause,
174             )
175 
176         val backgroundIds =
177             setOf(
178                 R.id.album_art,
179                 R.id.turbulence_noise_view,
180                 R.id.loading_effect_view,
181                 R.id.touch_ripple_view,
182             )
183 
184         val headlineSmallTF: Typeface = Typeface.create(GSF_HEADLINE_SMALL, Typeface.NORMAL)
185         val titleMediumTF: Typeface = Typeface.create(GSF_TITLE_MEDIUM, Typeface.NORMAL)
186         val labelMediumTF: Typeface = Typeface.create(GSF_LABEL_MEDIUM, Typeface.NORMAL)
187         val labelLargeTF: Typeface = Typeface.create(GSF_LABEL_LARGE, Typeface.NORMAL)
188     }
189 }
190