1 /* 2 * 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) { 35 36 val recommendations = itemView as TransitionLayout 37 38 // Recommendation screen 39 val cardTitle: TextView = itemView.requireViewById(R.id.media_rec_title) 40 41 val mediaCoverContainers = 42 listOf<ViewGroup>( 43 itemView.requireViewById(R.id.media_cover1_container), 44 itemView.requireViewById(R.id.media_cover2_container), 45 itemView.requireViewById(R.id.media_cover3_container) 46 ) 47 val mediaAppIcons: List<CachingIconView> = 48 mediaCoverContainers.map { it.requireViewById(R.id.media_rec_app_icon) } 49 val mediaTitles: List<TextView> = 50 mediaCoverContainers.map { it.requireViewById(R.id.media_title) } 51 val mediaSubtitles: List<TextView> = 52 mediaCoverContainers.map { it.requireViewById(R.id.media_subtitle) } 53 val mediaProgressBars: List<SeekBar> = 54 mediaCoverContainers.map { 55 it.requireViewById<SeekBar?>(R.id.media_progress_bar).apply { 56 // Media playback is in the direction of tape, not time, so it stays LTR 57 layoutDirection = View.LAYOUT_DIRECTION_LTR 58 } 59 } 60 61 val mediaCoverItems: List<ImageView> = 62 mediaCoverContainers.map { it.requireViewById(R.id.media_cover) } 63 val gutsViewHolder = GutsViewHolder(itemView) 64 65 init { 66 (recommendations.background as IlluminationDrawable).let { background -> 67 mediaCoverContainers.forEach { background.registerLightSource(it) } 68 background.registerLightSource(gutsViewHolder.cancel) 69 background.registerLightSource(gutsViewHolder.dismiss) 70 background.registerLightSource(gutsViewHolder.settings) 71 } 72 } 73 74 fun marquee(start: Boolean, delay: Long) { 75 gutsViewHolder.marquee(start, delay, TAG) 76 } 77 78 companion object { 79 /** 80 * Creates a RecommendationViewHolder. 81 * 82 * @param inflater LayoutInflater to use to inflate the layout. 83 * @param parent Parent of inflated view. 84 */ 85 @JvmStatic 86 fun create(inflater: LayoutInflater, parent: ViewGroup): RecommendationViewHolder { 87 val itemView = 88 inflater.inflate(R.layout.media_recommendations, parent, false /* attachToRoot */) 89 // Because this media view (a TransitionLayout) is used to measure and layout the views 90 // in various states before being attached to its parent, we can't depend on the default 91 // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction. 92 itemView.layoutDirection = View.LAYOUT_DIRECTION_LOCALE 93 return RecommendationViewHolder(itemView) 94 } 95 96 // Res Ids for the control components on the recommendation view. 97 val controlsIds = 98 setOf( 99 R.id.media_rec_title, 100 R.id.media_cover, 101 R.id.media_cover1_container, 102 R.id.media_cover2_container, 103 R.id.media_cover3_container, 104 R.id.media_title, 105 R.id.media_subtitle, 106 ) 107 108 val mediaTitlesAndSubtitlesIds = 109 setOf( 110 R.id.media_title, 111 R.id.media_subtitle, 112 ) 113 114 val mediaContainersIds = 115 setOf( 116 R.id.media_cover1_container, 117 R.id.media_cover2_container, 118 R.id.media_cover3_container 119 ) 120 121 val backgroundId = R.id.sizing_view 122 } 123 } 124