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.plugins.DarkIconDispatcher 24 import com.android.systemui.res.R 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 getSlotnull51 override fun getSlot() = slot 52 53 override fun onDarkChanged(areas: ArrayList<Rect>?, darkIntensity: Float, tint: Int) { 54 // nop 55 } 56 onDarkChangedWithContrastnull57 override fun onDarkChangedWithContrast(areas: ArrayList<Rect>, tint: Int, contrastTint: Int) { 58 val newTint = DarkIconDispatcher.getTint(areas, this, tint) 59 val contrast = DarkIconDispatcher.getInverseTint(areas, this, contrastTint) 60 61 binding.onIconTintChanged(newTint, contrast) 62 binding.onDecorTintChanged(newTint) 63 } 64 setStaticDrawableColornull65 override fun setStaticDrawableColor(color: Int) { 66 // nop 67 } 68 setStaticDrawableColornull69 override fun setStaticDrawableColor(color: Int, foregroundColor: Int) { 70 binding.onIconTintChanged(color, foregroundColor) 71 } 72 setDecorColornull73 override fun setDecorColor(color: Int) { 74 binding.onDecorTintChanged(color) 75 } 76 setVisibleStatenull77 override fun setVisibleState(@StatusBarIconView.VisibleState state: Int, animate: Boolean) { 78 iconVisibleState = state 79 } 80 81 @StatusBarIconView.VisibleState getVisibleStatenull82 override fun getVisibleState(): Int { 83 return iconVisibleState 84 } 85 isIconVisiblenull86 override fun isIconVisible(): Boolean { 87 return binding.getShouldIconBeVisible() 88 } 89 90 /** See [StatusBarIconView.getDrawingRect]. */ getDrawingRectnull91 override fun getDrawingRect(outRect: Rect) { 92 super.getDrawingRect(outRect) 93 val translationX = translationX.toInt() 94 val translationY = translationY.toInt() 95 outRect.left += translationX 96 outRect.right += translationX 97 outRect.top += translationY 98 outRect.bottom += translationY 99 } 100 101 /** 102 * Initializes this view. 103 * 104 * Creates a dot view, and uses [bindingCreator] to get and set the binding. 105 */ initViewnull106 open fun initView(slot: String, bindingCreator: () -> ModernStatusBarViewBinding) { 107 // The dot view requires [slot] to be set, and the [binding] may require an instantiated dot 108 // view. So, this is the required order. 109 this.slot = slot 110 initDotView() 111 this.binding = bindingCreator.invoke() 112 } 113 114 /** Creates a [StatusBarIconView] that is always in DOT mode and adds it to this view. */ initDotViewnull115 private fun initDotView() { 116 // TODO(b/238425913): Could we just have this dot view be part of the layout with a dot 117 // drawable so we don't need to inflate it manually? Would that not work with animations? 118 val dotView = 119 StatusBarIconView(mContext, slot, null).also { 120 it.id = R.id.status_bar_dot 121 // Hard-code this view to always be in the DOT state so that whenever it's visible 122 // it will show a dot 123 it.visibleState = STATE_DOT 124 } 125 126 val width = mContext.resources.getDimensionPixelSize(R.dimen.status_bar_icon_size_sp) 127 val lp = LayoutParams(width, width) 128 lp.gravity = Gravity.CENTER_VERTICAL or Gravity.START 129 addView(dotView, lp) 130 } 131 } 132