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.systemui.bubbles; 17 18 import android.content.Context; 19 import android.content.res.TypedArray; 20 import android.graphics.Canvas; 21 import android.graphics.Path; 22 import android.graphics.Rect; 23 import android.util.AttributeSet; 24 import android.widget.ImageView; 25 26 import com.android.internal.graphics.ColorUtils; 27 import com.android.launcher3.icons.DotRenderer; 28 import com.android.systemui.R; 29 30 /** 31 * View that circle crops its contents and supports displaying a coloured dot on a top corner. 32 */ 33 public class BadgedImageView extends ImageView { 34 35 private Rect mTempBounds = new Rect(); 36 37 private DotRenderer mDotRenderer; 38 private DotRenderer.DrawParams mDrawParams; 39 private int mIconBitmapSize; 40 private int mDotColor; 41 private float mDotScale = 0f; 42 private boolean mShowDot; 43 private boolean mOnLeft; 44 45 /** Same as value in Launcher3 IconShape */ 46 static final int DEFAULT_PATH_SIZE = 100; 47 BadgedImageView(Context context)48 public BadgedImageView(Context context) { 49 this(context, null); 50 } 51 BadgedImageView(Context context, AttributeSet attrs)52 public BadgedImageView(Context context, AttributeSet attrs) { 53 this(context, attrs, 0); 54 } 55 BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr)56 public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr) { 57 this(context, attrs, defStyleAttr, 0); 58 } 59 BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)60 public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr, 61 int defStyleRes) { 62 super(context, attrs, defStyleAttr, defStyleRes); 63 mIconBitmapSize = getResources().getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size); 64 mDrawParams = new DotRenderer.DrawParams(); 65 66 TypedArray ta = context.obtainStyledAttributes( 67 new int[]{android.R.attr.colorBackgroundFloating}); 68 ta.recycle(); 69 } 70 71 @Override onDraw(Canvas canvas)72 public void onDraw(Canvas canvas) { 73 super.onDraw(canvas); 74 if (!mShowDot) { 75 return; 76 } 77 getDrawingRect(mTempBounds); 78 79 mDrawParams.color = mDotColor; 80 mDrawParams.iconBounds = mTempBounds; 81 mDrawParams.leftAlign = mOnLeft; 82 mDrawParams.scale = mDotScale; 83 84 if (mDotRenderer == null) { 85 Path circlePath = new Path(); 86 float radius = DEFAULT_PATH_SIZE * 0.5f; 87 circlePath.addCircle(radius /* x */, radius /* y */, radius, Path.Direction.CW); 88 mDotRenderer = new DotRenderer(mIconBitmapSize, circlePath, DEFAULT_PATH_SIZE); 89 } 90 mDotRenderer.draw(canvas, mDrawParams); 91 } 92 93 /** 94 * Set whether the dot should appear on left or right side of the view. 95 */ setDotOnLeft(boolean onLeft)96 void setDotOnLeft(boolean onLeft) { 97 mOnLeft = onLeft; 98 invalidate(); 99 } 100 getDotOnLeft()101 boolean getDotOnLeft() { 102 return mOnLeft; 103 } 104 105 /** 106 * Set whether the dot should show or not. 107 */ setShowDot(boolean showDot)108 void setShowDot(boolean showDot) { 109 mShowDot = showDot; 110 invalidate(); 111 } 112 113 /** 114 * @return whether the dot is being displayed. 115 */ isShowingDot()116 boolean isShowingDot() { 117 return mShowDot; 118 } 119 120 /** 121 * The colour to use for the dot. 122 */ setDotColor(int color)123 public void setDotColor(int color) { 124 mDotColor = ColorUtils.setAlphaComponent(color, 255 /* alpha */); 125 invalidate(); 126 } 127 128 /** 129 * @param iconPath The new icon path to use when calculating dot position. 130 */ drawDot(Path iconPath)131 public void drawDot(Path iconPath) { 132 mDotRenderer = new DotRenderer(mIconBitmapSize, iconPath, DEFAULT_PATH_SIZE); 133 invalidate(); 134 } 135 136 /** 137 * How big the dot should be, fraction from 0 to 1. 138 */ setDotScale(float fraction)139 void setDotScale(float fraction) { 140 mDotScale = fraction; 141 invalidate(); 142 } 143 144 /** 145 * Return dot position relative to bubble view container bounds. 146 */ getDotCenter()147 float[] getDotCenter() { 148 float[] dotPosition; 149 if (mOnLeft) { 150 dotPosition = mDotRenderer.getLeftDotPosition(); 151 } else { 152 dotPosition = mDotRenderer.getRightDotPosition(); 153 } 154 getDrawingRect(mTempBounds); 155 float dotCenterX = mTempBounds.width() * dotPosition[0]; 156 float dotCenterY = mTempBounds.height() * dotPosition[1]; 157 return new float[]{dotCenterX, dotCenterY}; 158 } 159 } 160