1 /* 2 * Copyright (C) 2022 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.statusbar.pipeline.shared.ui.view 18 19 import android.content.Context 20 import android.graphics.Rect 21 import android.util.AttributeSet 22 import android.view.Gravity 23 import com.android.systemui.R 24 import com.android.systemui.plugins.DarkIconDispatcher 25 import com.android.systemui.statusbar.BaseStatusBarFrameLayout 26 import com.android.systemui.statusbar.StatusBarIconView 27 import com.android.systemui.statusbar.StatusBarIconView.STATE_DOT 28 import com.android.systemui.statusbar.StatusBarIconView.STATE_HIDDEN 29 import com.android.systemui.statusbar.pipeline.shared.ui.binder.ModernStatusBarViewBinding 30 31 /** 32 * A new and more modern implementation of [BaseStatusBarFrameLayout] that gets updated by view 33 * binders communicating via [ModernStatusBarViewBinding]. 34 */ 35 open class ModernStatusBarView(context: Context, attrs: AttributeSet?) : 36 BaseStatusBarFrameLayout(context, attrs) { 37 38 private lateinit var slot: String 39 internal lateinit var binding: ModernStatusBarViewBinding 40 41 @StatusBarIconView.VisibleState 42 private var iconVisibleState: Int = STATE_HIDDEN 43 set(value) { 44 if (field == value) { 45 return 46 } 47 field = value 48 binding.onVisibilityStateChanged(value) 49 } 50 51 override fun getSlot() = slot 52 53 override fun onDarkChanged(areas: ArrayList<Rect>?, darkIntensity: Float, tint: Int) { 54 val newTint = DarkIconDispatcher.getTint(areas, this, tint) 55 binding.onIconTintChanged(newTint) 56 binding.onDecorTintChanged(newTint) 57 } 58 59 override fun setStaticDrawableColor(color: Int) { 60 binding.onIconTintChanged(color) 61 } 62 63 override fun setDecorColor(color: Int) { 64 binding.onDecorTintChanged(color) 65 } 66 67 override fun setVisibleState(@StatusBarIconView.VisibleState state: Int, animate: Boolean) { 68 iconVisibleState = state 69 } 70 71 @StatusBarIconView.VisibleState 72 override fun getVisibleState(): Int { 73 return iconVisibleState 74 } 75 76 override fun isIconVisible(): Boolean { 77 return binding.getShouldIconBeVisible() 78 } 79 80 /** See [StatusBarIconView.getDrawingRect]. */ 81 override fun getDrawingRect(outRect: Rect) { 82 super.getDrawingRect(outRect) 83 val translationX = translationX.toInt() 84 val translationY = translationY.toInt() 85 outRect.left += translationX 86 outRect.right += translationX 87 outRect.top += translationY 88 outRect.bottom += translationY 89 } 90 91 /** 92 * Initializes this view. 93 * 94 * Creates a dot view, and uses [bindingCreator] to get and set the binding. 95 */ 96 fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { 97 // The dot view requires [slot] to be set, and the [binding] may require an instantiated dot 98 // view. So, this is the required order. 99 this.slot = slot 100 initDotView() 101 this.binding = bindingCreator.invoke() 102 } 103 104 /** Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view. */ 105 private fun initDotView() { 106 // TODO(b/238425913): Could we just have this dot view be part of the layout with a dot 107 // drawable so we don't need to inflate it manually? Would that not work with animations? 108 val dotView = 109 StatusBarIconView(mContext, slot, null).also { 110 it.id = R.id.status_bar_dot 111 // Hard-code this view to always be in the DOT state so that whenever it's visible 112 // it will show a dot 113 it.visibleState = STATE_DOT 114 } 115 116 val width = mContext.resources.getDimensionPixelSize(R.dimen.status_bar_icon_size_sp) 117 val lp = LayoutParams(width, width) 118 lp.gravity = Gravity.CENTER_VERTICAL or Gravity.START 119 addView(dotView, lp) 120 } 121 } 122