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.quickstep.views;
17 
18 import android.content.Context;
19 import android.graphics.Canvas;
20 import android.graphics.drawable.Drawable;
21 import android.util.AttributeSet;
22 import android.view.View;
23 
24 import com.android.launcher3.FastBitmapDrawable;
25 
26 import java.util.ArrayList;
27 
28 import androidx.annotation.NonNull;
29 
30 /**
31  * A view which draws a drawable stretched to fit its size. Unlike ImageView, it avoids relayout
32  * when the drawable changes.
33  */
34 public class IconView extends View {
35 
36     public interface OnScaleUpdateListener {
onScaleUpdate(float scale)37         public void onScaleUpdate(float scale);
38     }
39 
40     private Drawable mDrawable;
41 
42     private ArrayList<OnScaleUpdateListener> mScaleListeners;
43 
IconView(Context context)44     public IconView(Context context) {
45         super(context);
46     }
47 
IconView(Context context, AttributeSet attrs)48     public IconView(Context context, AttributeSet attrs) {
49         super(context, attrs);
50     }
51 
IconView(Context context, AttributeSet attrs, int defStyleAttr)52     public IconView(Context context, AttributeSet attrs, int defStyleAttr) {
53         super(context, attrs, defStyleAttr);
54     }
55 
setDrawable(Drawable d)56     public void setDrawable(Drawable d) {
57         if (mDrawable != null) {
58             mDrawable.setCallback(null);
59         }
60         mDrawable = d;
61         if (mDrawable != null) {
62             mDrawable.setCallback(this);
63             mDrawable.setBounds(0, 0, getWidth(), getHeight());
64         }
65         invalidate();
66     }
67 
getDrawable()68     public Drawable getDrawable() {
69         return mDrawable;
70     }
71 
72     @Override
onSizeChanged(int w, int h, int oldw, int oldh)73     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
74         super.onSizeChanged(w, h, oldw, oldh);
75         if (mDrawable != null) {
76             mDrawable.setBounds(0, 0, w, h);
77         }
78     }
79 
80     @Override
verifyDrawable(Drawable who)81     protected boolean verifyDrawable(Drawable who) {
82         return super.verifyDrawable(who) || who == mDrawable;
83     }
84 
85     @Override
drawableStateChanged()86     protected void drawableStateChanged() {
87         super.drawableStateChanged();
88 
89         final Drawable drawable = mDrawable;
90         if (drawable != null && drawable.isStateful()
91                 && drawable.setState(getDrawableState())) {
92             invalidateDrawable(drawable);
93         }
94     }
95 
96     @Override
invalidateDrawable(@onNull Drawable drawable)97     public void invalidateDrawable(@NonNull Drawable drawable) {
98         super.invalidateDrawable(drawable);
99         if (drawable instanceof FastBitmapDrawable && mScaleListeners != null) {
100             for (OnScaleUpdateListener listener : mScaleListeners) {
101                 listener.onScaleUpdate(((FastBitmapDrawable) drawable).getScale());
102             }
103         }
104     }
105 
106     @Override
onDraw(Canvas canvas)107     protected void onDraw(Canvas canvas) {
108         if (mDrawable != null) {
109             mDrawable.draw(canvas);
110         }
111     }
112 
113     @Override
hasOverlappingRendering()114     public boolean hasOverlappingRendering() {
115         return false;
116     }
117 
addUpdateScaleListener(OnScaleUpdateListener listener)118     public void addUpdateScaleListener(OnScaleUpdateListener listener) {
119         if (mScaleListeners == null) {
120             mScaleListeners = new ArrayList<>();
121         }
122         mScaleListeners.add(listener);
123         if (mDrawable instanceof FastBitmapDrawable) {
124             listener.onScaleUpdate(((FastBitmapDrawable) mDrawable).getScale());
125         }
126     }
127 
removeUpdateScaleListener(OnScaleUpdateListener listener)128     public void removeUpdateScaleListener(OnScaleUpdateListener listener) {
129         if (mScaleListeners != null) {
130             mScaleListeners.remove(listener);
131         }
132     }
133 }
134