blob: c0053d194ff65ba88138709bbbb9edb9f7b7ec7e [file] [log] [blame]
Mady Mellor3f2efdb2018-11-21 11:30:45 -08001/*
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 */
16package com.android.systemui.bubbles;
17
18import android.content.Context;
Joshua Tsuji580c0bf2019-01-28 13:28:21 -050019import android.content.res.TypedArray;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080020import android.graphics.Canvas;
Lyn Han4f01acc2019-06-12 13:06:31 -070021import android.graphics.Path;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080022import android.graphics.Rect;
23import android.util.AttributeSet;
24import android.widget.ImageView;
25
Lyn Han3fd6e6f2019-05-03 17:46:23 -070026import com.android.internal.graphics.ColorUtils;
Lyn Han4f01acc2019-06-12 13:06:31 -070027import com.android.launcher3.icons.DotRenderer;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080028import com.android.systemui.R;
29
30/**
31 * View that circle crops its contents and supports displaying a coloured dot on a top corner.
32 */
33public class BadgedImageView extends ImageView {
34
Mady Mellor3f2efdb2018-11-21 11:30:45 -080035 private Rect mTempBounds = new Rect();
Mady Mellor3f2efdb2018-11-21 11:30:45 -080036
Lyn Han0e82a3e2019-06-19 18:47:06 -070037 private DotRenderer mDotRenderer;
38 private DotRenderer.DrawParams mDrawParams;
Lyn Han4f01acc2019-06-12 13:06:31 -070039 private int mIconBitmapSize;
40 private int mDotColor;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080041 private float mDotScale = 0f;
Lyn Han4f01acc2019-06-12 13:06:31 -070042 private boolean mShowDot;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080043 private boolean mOnLeft;
44
Lyn Han4f01acc2019-06-12 13:06:31 -070045 /** Same as value in Launcher3 IconShape */
Lyn Hanecdd06e2019-07-10 18:19:37 -070046 static final int DEFAULT_PATH_SIZE = 100;
Lyn Han4f01acc2019-06-12 13:06:31 -070047
Mady Mellor3f2efdb2018-11-21 11:30:45 -080048 public BadgedImageView(Context context) {
49 this(context, null);
50 }
51
52 public BadgedImageView(Context context, AttributeSet attrs) {
53 this(context, attrs, 0);
54 }
55
56 public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
57 this(context, attrs, defStyleAttr, 0);
58 }
59
60 public BadgedImageView(Context context, AttributeSet attrs, int defStyleAttr,
61 int defStyleRes) {
62 super(context, attrs, defStyleAttr, defStyleRes);
Lyn Han1b4f25e2019-06-11 13:56:34 -070063 mIconBitmapSize = getResources().getDimensionPixelSize(R.dimen.bubble_icon_bitmap_size);
Lyn Han0e82a3e2019-06-19 18:47:06 -070064 mDrawParams = new DotRenderer.DrawParams();
Joshua Tsuji580c0bf2019-01-28 13:28:21 -050065
66 TypedArray ta = context.obtainStyledAttributes(
Lyn Han0e82a3e2019-06-19 18:47:06 -070067 new int[]{android.R.attr.colorBackgroundFloating});
Joshua Tsuji580c0bf2019-01-28 13:28:21 -050068 ta.recycle();
Mady Mellor3f2efdb2018-11-21 11:30:45 -080069 }
70
Mady Mellor3f2efdb2018-11-21 11:30:45 -080071 @Override
72 public void onDraw(Canvas canvas) {
Mady Mellor3f2efdb2018-11-21 11:30:45 -080073 super.onDraw(canvas);
Lyn Han0e82a3e2019-06-19 18:47:06 -070074 if (!mShowDot) {
75 return;
Mady Mellor3f2efdb2018-11-21 11:30:45 -080076 }
Lyn Han0e82a3e2019-06-19 18:47:06 -070077 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);
Mady Mellor3f2efdb2018-11-21 11:30:45 -080091 }
92
93 /**
94 * Set whether the dot should appear on left or right side of the view.
95 */
Lyn Han61d5d562019-07-01 17:39:38 -070096 void setDotOnLeft(boolean onLeft) {
Mady Mellor3f2efdb2018-11-21 11:30:45 -080097 mOnLeft = onLeft;
98 invalidate();
99 }
100
Lyn Han61d5d562019-07-01 17:39:38 -0700101 boolean getDotOnLeft() {
Joshua Tsuji6549e702019-05-02 13:13:16 -0400102 return mOnLeft;
103 }
104
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800105 /**
106 * Set whether the dot should show or not.
107 */
Lyn Han61d5d562019-07-01 17:39:38 -0700108 void setShowDot(boolean showDot) {
Lyn Han4f01acc2019-06-12 13:06:31 -0700109 mShowDot = showDot;
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800110 invalidate();
111 }
112
113 /**
114 * @return whether the dot is being displayed.
115 */
Lyn Han61d5d562019-07-01 17:39:38 -0700116 boolean isShowingDot() {
Lyn Han4f01acc2019-06-12 13:06:31 -0700117 return mShowDot;
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800118 }
119
120 /**
121 * The colour to use for the dot.
122 */
123 public void setDotColor(int color) {
Lyn Han4f01acc2019-06-12 13:06:31 -0700124 mDotColor = ColorUtils.setAlphaComponent(color, 255 /* alpha */);
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800125 invalidate();
126 }
127
128 /**
Lyn Han0e82a3e2019-06-19 18:47:06 -0700129 * @param iconPath The new icon path to use when calculating dot position.
130 */
131 public void drawDot(Path iconPath) {
132 mDotRenderer = new DotRenderer(mIconBitmapSize, iconPath, DEFAULT_PATH_SIZE);
133 invalidate();
134 }
135
136 /**
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800137 * How big the dot should be, fraction from 0 to 1.
138 */
Lyn Han61d5d562019-07-01 17:39:38 -0700139 void setDotScale(float fraction) {
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800140 mDotScale = fraction;
141 invalidate();
142 }
Lyn Han61d5d562019-07-01 17:39:38 -0700143
144 /**
145 * Return dot position relative to bubble view container bounds.
146 */
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 }
Mady Mellor3f2efdb2018-11-21 11:30:45 -0800159}