1 /*
2  * Copyright (C) 2020 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.statusbar;
17 
18 import android.annotation.NonNull;
19 import android.annotation.Nullable;
20 import android.content.res.Resources;
21 import android.graphics.Canvas;
22 import android.graphics.Color;
23 import android.graphics.Paint;
24 import android.graphics.Rect;
25 import android.graphics.drawable.Drawable;
26 import android.graphics.drawable.DrawableWrapper;
27 import android.util.AttributeSet;
28 
29 import com.android.systemui.R;
30 
31 import org.xmlpull.v1.XmlPullParser;
32 import org.xmlpull.v1.XmlPullParserException;
33 
34 import java.io.IOException;
35 
36 /**
37  * The screen record drawable draws a colored background and either a countdown or circle to
38  * indicate that the screen is being recorded.
39  */
40 public class ScreenRecordDrawable extends DrawableWrapper {
41     private Drawable mFillDrawable;
42     private Drawable mIconDrawable;
43     private int mHorizontalPadding;
44     private int mLevel;
45     private float mTextSize;
46     private int mIconRadius;
47     private int mWidthPx;
48     private int mHeightPx;
49     private Paint mPaint;
50 
51     /** No-arg constructor used by drawable inflation. */
ScreenRecordDrawable()52     public ScreenRecordDrawable() {
53         super(null);
54     }
55 
56     @Override
inflate(@onNull Resources r, @NonNull XmlPullParser parser, @NonNull AttributeSet attrs, @Nullable Resources.Theme theme)57     public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
58             @NonNull AttributeSet attrs, @Nullable Resources.Theme theme)
59             throws XmlPullParserException, IOException {
60         super.inflate(r, parser, attrs, theme);
61         setDrawable(r.getDrawable(R.drawable.ic_screen_record_background, theme).mutate());
62         mFillDrawable = r.getDrawable(R.drawable.ic_screen_record_background, theme).mutate();
63         mIconDrawable = r.getDrawable(R.drawable.ic_screenrecord, theme).mutate();
64         mHorizontalPadding = r.getDimensionPixelSize(R.dimen.status_bar_horizontal_padding);
65 
66         mTextSize = r.getDimensionPixelSize(R.dimen.screenrecord_status_text_size);
67         mIconRadius = r.getDimensionPixelSize(R.dimen.screenrecord_status_icon_radius);
68         mLevel = attrs.getAttributeIntValue(null, "level", 0);
69 
70         mPaint = new Paint();
71         mPaint.setTextAlign(Paint.Align.CENTER);
72         mPaint.setColor(Color.WHITE);
73         mPaint.setTextSize(mTextSize);
74         mPaint.setFakeBoldText(true);
75 
76         mWidthPx = r.getDimensionPixelSize(R.dimen.screenrecord_status_icon_width);
77         mHeightPx = r.getDimensionPixelSize(R.dimen.screenrecord_status_icon_height);
78     }
79 
80     @Override
getIntrinsicWidth()81     public int getIntrinsicWidth() {
82         return mWidthPx;
83     }
84 
85     @Override
getIntrinsicHeight()86     public int getIntrinsicHeight() {
87         return mHeightPx;
88     }
89 
90     @Override
canApplyTheme()91     public boolean canApplyTheme() {
92         return mFillDrawable.canApplyTheme() || super.canApplyTheme();
93     }
94 
95     @Override
applyTheme(Resources.Theme t)96     public void applyTheme(Resources.Theme t) {
97         super.applyTheme(t);
98         mFillDrawable.applyTheme(t);
99     }
100 
101     @Override
onBoundsChange(Rect bounds)102     protected void onBoundsChange(Rect bounds) {
103         super.onBoundsChange(bounds);
104         mFillDrawable.setBounds(bounds);
105     }
106 
107     @Override
onLayoutDirectionChanged(int layoutDirection)108     public boolean onLayoutDirectionChanged(int layoutDirection) {
109         mFillDrawable.setLayoutDirection(layoutDirection);
110         return super.onLayoutDirectionChanged(layoutDirection);
111     }
112 
113     @Override
draw(Canvas canvas)114     public void draw(Canvas canvas) {
115         super.draw(canvas);
116         mFillDrawable.draw(canvas);
117 
118         Rect b = mFillDrawable.getBounds();
119         if (mLevel > 0) {
120             String val = String.valueOf(mLevel);
121             Rect textBounds = new Rect();
122             mPaint.getTextBounds(val, 0, val.length(), textBounds);
123             canvas.drawText(val, b.centerX(), b.centerY() + textBounds.height() / 2, mPaint);
124         } else {
125             Rect iconBounds = new Rect(b.centerX() - mIconRadius,
126                     b.centerY() - mIconRadius,
127                     b.centerX() + mIconRadius,
128                     b.centerY() + mIconRadius);
129             mIconDrawable.setBounds(iconBounds);
130             mIconDrawable.draw(canvas);
131         }
132     }
133 
134     @Override
getPadding(Rect padding)135     public boolean getPadding(Rect padding) {
136         padding.left += mHorizontalPadding;
137         padding.right += mHorizontalPadding;
138         return true;
139     }
140 
141     @Override
setAlpha(int alpha)142     public void setAlpha(int alpha) {
143         super.setAlpha(alpha);
144         mFillDrawable.setAlpha(alpha);
145     }
146 
147     @Override
setVisible(boolean visible, boolean restart)148     public boolean setVisible(boolean visible, boolean restart) {
149         mFillDrawable.setVisible(visible, restart);
150         return super.setVisible(visible, restart);
151     }
152 
153     @Override
mutate()154     public Drawable mutate() {
155         mFillDrawable.mutate();
156         return super.mutate();
157     }
158 }
159