1 /*
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 
17 package com.android.systemui.statusbar;
18 
19 import android.content.Context;
20 import android.graphics.Canvas;
21 import android.graphics.Rect;
22 import android.graphics.drawable.AnimatedVectorDrawable;
23 import android.graphics.drawable.Drawable;
24 import android.util.AttributeSet;
25 import android.view.View;
26 import android.view.ViewGroup;
27 import android.widget.Button;
28 import com.android.systemui.R;
29 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
30 
31 public class DismissViewButton extends Button {
32     private AnimatedVectorDrawable mAnimatedDismissDrawable;
33     private final Drawable mStaticDismissDrawable;
34     private Drawable mActiveDrawable;
35 
DismissViewButton(Context context)36     public DismissViewButton(Context context) {
37         this(context, null);
38     }
39 
DismissViewButton(Context context, AttributeSet attrs)40     public DismissViewButton(Context context, AttributeSet attrs) {
41         this(context, attrs, 0);
42     }
43 
DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr)44     public DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr) {
45         this(context, attrs, defStyleAttr, 0);
46     }
47 
DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)48     public DismissViewButton(Context context, AttributeSet attrs, int defStyleAttr,
49             int defStyleRes) {
50         super(context, attrs, defStyleAttr, defStyleRes);
51         mAnimatedDismissDrawable = (AnimatedVectorDrawable) getContext().getDrawable(
52                 R.drawable.dismiss_all_shape_animation).mutate();
53         mAnimatedDismissDrawable.setCallback(this);
54         mAnimatedDismissDrawable.setBounds(0,
55                 0,
56                 mAnimatedDismissDrawable.getIntrinsicWidth(),
57                 mAnimatedDismissDrawable.getIntrinsicHeight());
58         mStaticDismissDrawable = getContext().getDrawable(R.drawable.dismiss_all_shape);
59         mStaticDismissDrawable.setBounds(0,
60                 0,
61                 mStaticDismissDrawable.getIntrinsicWidth(),
62                 mStaticDismissDrawable.getIntrinsicHeight());
63         mStaticDismissDrawable.setCallback(this);
64         mActiveDrawable = mStaticDismissDrawable;
65     }
66 
67     @Override
onDraw(Canvas canvas)68     protected void onDraw(Canvas canvas) {
69         super.onDraw(canvas);
70         canvas.save();
71         int drawableHeight = mActiveDrawable.getBounds().height();
72         boolean isRtl = (getLayoutDirection() == View.LAYOUT_DIRECTION_RTL);
73         int dx = isRtl ? getWidth() / 2 + drawableHeight / 2 : getWidth() / 2 - drawableHeight / 2;
74         canvas.translate(dx, getHeight() / 2.0f + drawableHeight /
75                 2.0f);
76         canvas.scale(isRtl ? -1.0f : 1.0f, -1.0f);
77         mActiveDrawable.draw(canvas);
78         canvas.restore();
79     }
80 
81     @Override
performClick()82     public boolean performClick() {
83         if (!mAnimatedDismissDrawable.isRunning()) {
84             mActiveDrawable = mAnimatedDismissDrawable;
85             mAnimatedDismissDrawable.start();
86         }
87         return super.performClick();
88     }
89 
90     @Override
verifyDrawable(Drawable who)91     protected boolean verifyDrawable(Drawable who) {
92         return super.verifyDrawable(who)
93                 || who == mAnimatedDismissDrawable
94                 || who == mStaticDismissDrawable;
95     }
96 
97     @Override
hasOverlappingRendering()98     public boolean hasOverlappingRendering() {
99         return false;
100     }
101 
102     /**
103      * This method returns the drawing rect for the view which is different from the regular
104      * drawing rect, since we layout all children in the {@link NotificationStackScrollLayout} at
105      * position 0 and usually the translation is neglected. The standard implementation doesn't
106      * account for translation.
107      *
108      * @param outRect The (scrolled) drawing bounds of the view.
109      */
110     @Override
getDrawingRect(Rect outRect)111     public void getDrawingRect(Rect outRect) {
112         super.getDrawingRect(outRect);
113         float translationX = ((ViewGroup) mParent).getTranslationX();
114         float translationY = ((ViewGroup) mParent).getTranslationY();
115         outRect.left += translationX;
116         outRect.right += translationX;
117         outRect.top += translationY;
118         outRect.bottom += translationY;
119     }
120 
showButton()121     public void showButton() {
122         mActiveDrawable = mStaticDismissDrawable;
123         invalidate();
124     }
125 
126     /**
127      * @return Whether the button is currently static and not being animated.
128      */
isButtonStatic()129     public boolean isButtonStatic() {
130         return mActiveDrawable == mStaticDismissDrawable;
131     }
132 }
133