1 /* 2 * Copyright (C) 2018 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 package com.android.launcher3.views; 17 18 import static com.android.launcher3.util.SystemUiController.UI_STATE_SCRIM_VIEW; 19 20 import android.content.Context; 21 import android.graphics.Canvas; 22 import android.graphics.Color; 23 import android.graphics.Rect; 24 import android.graphics.drawable.ColorDrawable; 25 import android.util.AttributeSet; 26 import android.view.View; 27 28 import androidx.core.graphics.ColorUtils; 29 30 import com.android.launcher3.BaseActivity; 31 import com.android.launcher3.Insettable; 32 import com.android.launcher3.util.SystemUiController; 33 34 /** 35 * Simple scrim which draws a flat color 36 */ 37 public class ScrimView extends View implements Insettable { 38 private static final float STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD = 0.9f; 39 40 private SystemUiController mSystemUiController; 41 42 private ScrimDrawingController mDrawingController; 43 private int mBackgroundColor; 44 private boolean mIsVisible = true; 45 ScrimView(Context context, AttributeSet attrs)46 public ScrimView(Context context, AttributeSet attrs) { 47 super(context, attrs); 48 setFocusable(false); 49 } 50 51 @Override setInsets(Rect insets)52 public void setInsets(Rect insets) { 53 } 54 55 @Override hasOverlappingRendering()56 public boolean hasOverlappingRendering() { 57 return false; 58 } 59 60 @Override onSetAlpha(int alpha)61 protected boolean onSetAlpha(int alpha) { 62 updateSysUiColors(); 63 return super.onSetAlpha(alpha); 64 } 65 66 @Override setBackgroundColor(int color)67 public void setBackgroundColor(int color) { 68 mBackgroundColor = color; 69 updateSysUiColors(); 70 super.setBackgroundColor(color); 71 } 72 73 @Override onVisibilityAggregated(boolean isVisible)74 public void onVisibilityAggregated(boolean isVisible) { 75 super.onVisibilityAggregated(isVisible); 76 mIsVisible = isVisible; 77 } 78 isFullyOpaque()79 public boolean isFullyOpaque() { 80 return mIsVisible && getAlpha() == 1 && Color.alpha(mBackgroundColor) == 255; 81 } 82 83 @Override onDraw(Canvas canvas)84 protected void onDraw(Canvas canvas) { 85 super.onDraw(canvas); 86 if (mDrawingController != null) { 87 mDrawingController.drawOnScrim(canvas); 88 } 89 } 90 91 @Override onVisibilityChanged(View changedView, int visibility)92 protected void onVisibilityChanged(View changedView, int visibility) { 93 super.onVisibilityChanged(changedView, visibility); 94 updateSysUiColors(); 95 } 96 updateSysUiColors()97 private void updateSysUiColors() { 98 // Use a light system UI (dark icons) if all apps is behind at least half of the 99 // status bar. 100 final float threshold = STATUS_BAR_COLOR_FORCE_UPDATE_THRESHOLD; 101 boolean forceChange = getVisibility() == VISIBLE 102 && getAlpha() > threshold 103 && (Color.alpha(mBackgroundColor) / 255f) > threshold; 104 if (forceChange) { 105 getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, !isScrimDark()); 106 } else { 107 getSystemUiController().updateUiState(UI_STATE_SCRIM_VIEW, 0); 108 } 109 } 110 getSystemUiController()111 private SystemUiController getSystemUiController() { 112 if (mSystemUiController == null) { 113 mSystemUiController = BaseActivity.fromContext(getContext()).getSystemUiController(); 114 } 115 return mSystemUiController; 116 } 117 isScrimDark()118 private boolean isScrimDark() { 119 if (!(getBackground() instanceof ColorDrawable)) { 120 throw new IllegalStateException( 121 "ScrimView must have a ColorDrawable background, this one has: " 122 + getBackground()); 123 } 124 return ColorUtils.calculateLuminance( 125 ((ColorDrawable) getBackground()).getColor()) < 0.5f; 126 } 127 128 /** 129 * Sets drawing controller. Invalidates ScrimView if drawerController has changed. 130 */ setDrawingController(ScrimDrawingController drawingController)131 public void setDrawingController(ScrimDrawingController drawingController) { 132 if (mDrawingController != drawingController) { 133 mDrawingController = drawingController; 134 invalidate(); 135 } 136 } 137 138 /** 139 * A Utility interface allowing for other surfaces to draw on ScrimView 140 */ 141 public interface ScrimDrawingController { 142 /** 143 * Called inside ScrimView#OnDraw 144 */ drawOnScrim(Canvas canvas)145 void drawOnScrim(Canvas canvas); 146 } 147 } 148