blob: 45b35d014e70519674cd0c534beb3b0f86e88472 [file] [log] [blame]
Jorim Jaggia8b48e12014-05-19 20:26:46 +02001/*
2 * Copyright (C) 2014 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
17package com.android.systemui.statusbar;
18
19import android.content.Context;
Selim Cinek697178b2014-07-02 19:40:30 +020020import android.content.res.ColorStateList;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020021import android.graphics.Canvas;
22import android.graphics.PorterDuff;
23import android.graphics.drawable.Drawable;
Selim Cinek0fe07392017-11-09 13:26:34 -080024import android.graphics.drawable.GradientDrawable;
25import android.graphics.drawable.LayerDrawable;
Selim Cinek697178b2014-07-02 19:40:30 +020026import android.graphics.drawable.RippleDrawable;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020027import android.util.AttributeSet;
28import android.view.View;
29
Selim Cinek0fe07392017-11-09 13:26:34 -080030import com.android.systemui.R;
31
Jorim Jaggia8b48e12014-05-19 20:26:46 +020032/**
33 * A view that can be used for both the dimmed and normal background of an notification.
34 */
35public class NotificationBackgroundView extends View {
36
Selim Cinek0fe07392017-11-09 13:26:34 -080037 private final boolean mDontModifyCorners;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020038 private Drawable mBackground;
39 private int mClipTopAmount;
40 private int mActualHeight;
Selim Cineka686b2c2016-10-26 13:58:27 -070041 private int mClipBottomAmount;
Selim Cinek588423a2017-08-17 16:42:51 -070042 private int mTintColor;
Selim Cinek0fe07392017-11-09 13:26:34 -080043 private float[] mCornerRadii = new float[8];
Selim Cinek515b2032017-11-15 10:20:19 -080044 private boolean mBottomIsRounded;
45 private int mBackgroundTop;
Selim Cinek2871bef2017-11-22 08:40:00 -080046 private boolean mBottomAmountClips = true;
Jorim Jaggia8b48e12014-05-19 20:26:46 +020047
48 public NotificationBackgroundView(Context context, AttributeSet attrs) {
49 super(context, attrs);
Selim Cinek0fe07392017-11-09 13:26:34 -080050 mDontModifyCorners = getResources().getBoolean(
51 R.bool.config_clipNotificationsToOutline);
Jorim Jaggia8b48e12014-05-19 20:26:46 +020052 }
53
54 @Override
Jorim Jaggia8b48e12014-05-19 20:26:46 +020055 protected void onDraw(Canvas canvas) {
Selim Cinek515b2032017-11-15 10:20:19 -080056 if (mClipTopAmount + mClipBottomAmount < mActualHeight - mBackgroundTop) {
57 canvas.save();
58 canvas.clipRect(0, mClipTopAmount, getWidth(), mActualHeight - mClipBottomAmount);
59 draw(canvas, mBackground);
60 canvas.restore();
61 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +020062 }
63
64 private void draw(Canvas canvas, Drawable drawable) {
Selim Cinek515b2032017-11-15 10:20:19 -080065 if (drawable != null) {
66 int bottom = mActualHeight;
Selim Cinek2871bef2017-11-22 08:40:00 -080067 if (mBottomIsRounded && mBottomAmountClips) {
Selim Cinek515b2032017-11-15 10:20:19 -080068 bottom -= mClipBottomAmount;
69 }
Selim Cinekb95fd182017-12-21 13:03:32 -080070 drawable.setBounds(0, mBackgroundTop, getWidth(), bottom);
Jorim Jaggia8b48e12014-05-19 20:26:46 +020071 drawable.draw(canvas);
72 }
73 }
74
75 @Override
76 protected boolean verifyDrawable(Drawable who) {
77 return super.verifyDrawable(who) || who == mBackground;
78 }
79
80 @Override
81 protected void drawableStateChanged() {
82 drawableStateChanged(mBackground);
83 }
84
85 private void drawableStateChanged(Drawable d) {
86 if (d != null && d.isStateful()) {
87 d.setState(getDrawableState());
88 }
89 }
90
Selim Cinek697178b2014-07-02 19:40:30 +020091 @Override
92 public void drawableHotspotChanged(float x, float y) {
93 if (mBackground != null) {
94 mBackground.setHotspot(x, y);
95 }
96 }
97
Jorim Jaggia8b48e12014-05-19 20:26:46 +020098 /**
99 * Sets a background drawable. As we need to change our bounds independently of layout, we need
100 * the notion of a background independently of the regular View background..
101 */
102 public void setCustomBackground(Drawable background) {
103 if (mBackground != null) {
104 mBackground.setCallback(null);
105 unscheduleDrawable(mBackground);
106 }
107 mBackground = background;
Selim Cinek0fe07392017-11-09 13:26:34 -0800108 mBackground.mutate();
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200109 if (mBackground != null) {
110 mBackground.setCallback(this);
Selim Cinek588423a2017-08-17 16:42:51 -0700111 setTint(mTintColor);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200112 }
Jorim Jaggib7303a32015-08-19 16:51:36 -0700113 if (mBackground instanceof RippleDrawable) {
114 ((RippleDrawable) mBackground).setForceSoftware(true);
115 }
Selim Cinek0fe07392017-11-09 13:26:34 -0800116 updateBackgroundRadii();
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200117 invalidate();
118 }
119
Selim Cinek697178b2014-07-02 19:40:30 +0200120 public void setCustomBackground(int drawableResId) {
121 final Drawable d = mContext.getDrawable(drawableResId);
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200122 setCustomBackground(d);
123 }
124
Selim Cinek697178b2014-07-02 19:40:30 +0200125 public void setTint(int tintColor) {
Selim Cinek697178b2014-07-02 19:40:30 +0200126 if (tintColor != 0) {
127 mBackground.setColorFilter(tintColor, PorterDuff.Mode.SRC_ATOP);
Selim Cinek697178b2014-07-02 19:40:30 +0200128 } else {
129 mBackground.clearColorFilter();
Selim Cinek697178b2014-07-02 19:40:30 +0200130 }
Selim Cinek588423a2017-08-17 16:42:51 -0700131 mTintColor = tintColor;
Selim Cinek697178b2014-07-02 19:40:30 +0200132 invalidate();
133 }
134
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200135 public void setActualHeight(int actualHeight) {
136 mActualHeight = actualHeight;
137 invalidate();
138 }
139
140 public int getActualHeight() {
141 return mActualHeight;
142 }
143
144 public void setClipTopAmount(int clipTopAmount) {
145 mClipTopAmount = clipTopAmount;
146 invalidate();
147 }
148
Selim Cineka686b2c2016-10-26 13:58:27 -0700149 public void setClipBottomAmount(int clipBottomAmount) {
150 mClipBottomAmount = clipBottomAmount;
151 invalidate();
152 }
153
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200154 @Override
155 public boolean hasOverlappingRendering() {
156
157 // Prevents this view from creating a layer when alpha is animating.
158 return false;
159 }
Selim Cinekb2da91b2014-09-02 17:35:20 +0200160
161 public void setState(int[] drawableState) {
162 mBackground.setState(drawableState);
163 }
164
165 public void setRippleColor(int color) {
166 if (mBackground instanceof RippleDrawable) {
167 RippleDrawable ripple = (RippleDrawable) mBackground;
168 ripple.setColor(ColorStateList.valueOf(color));
169 }
170 }
Selim Cinekec29d342017-05-05 18:31:49 -0700171
172 public void setDrawableAlpha(int drawableAlpha) {
173 mBackground.setAlpha(drawableAlpha);
174 }
Selim Cinek0fe07392017-11-09 13:26:34 -0800175
176 public void setRoundness(float topRoundness, float bottomRoundNess) {
Selim Cinek515b2032017-11-15 10:20:19 -0800177 mBottomIsRounded = bottomRoundNess != 0.0f;
Selim Cinek0fe07392017-11-09 13:26:34 -0800178 mCornerRadii[0] = topRoundness;
179 mCornerRadii[1] = topRoundness;
180 mCornerRadii[2] = topRoundness;
181 mCornerRadii[3] = topRoundness;
182 mCornerRadii[4] = bottomRoundNess;
183 mCornerRadii[5] = bottomRoundNess;
184 mCornerRadii[6] = bottomRoundNess;
185 mCornerRadii[7] = bottomRoundNess;
186 updateBackgroundRadii();
187 }
188
Selim Cinek2871bef2017-11-22 08:40:00 -0800189 public void setBottomAmountClips(boolean clips) {
190 if (clips != mBottomAmountClips) {
191 mBottomAmountClips = clips;
192 invalidate();
193 }
194 }
Selim Cinek0fe07392017-11-09 13:26:34 -0800195
196 private void updateBackgroundRadii() {
197 if (mDontModifyCorners) {
198 return;
199 }
200 if (mBackground instanceof LayerDrawable) {
201 GradientDrawable gradientDrawable =
202 (GradientDrawable) ((LayerDrawable) mBackground).getDrawable(0);
203 gradientDrawable.setCornerRadii(mCornerRadii);
204 }
205 }
206
Selim Cinek515b2032017-11-15 10:20:19 -0800207 public void setBackgroundTop(int backgroundTop) {
208 mBackgroundTop = backgroundTop;
209 invalidate();
210 }
Jorim Jaggia8b48e12014-05-19 20:26:46 +0200211}