• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.launcher3.taskbar;
17 
18 import static com.android.quickstep.util.BorderAnimator.DEFAULT_BORDER_COLOR;
19 
20 import android.animation.Animator;
21 import android.content.Context;
22 import android.content.res.Resources;
23 import android.graphics.Bitmap;
24 import android.graphics.Canvas;
25 import android.util.AttributeSet;
26 import android.widget.ImageView;
27 
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 import androidx.constraintlayout.widget.ConstraintLayout;
31 
32 import com.android.launcher3.R;
33 import com.android.quickstep.util.BorderAnimator;
34 import com.android.systemui.shared.recents.model.Task;
35 import com.android.systemui.shared.recents.model.ThumbnailData;
36 
37 import java.util.function.Consumer;
38 
39 /**
40  * A view that displays a recent task during a keyboard quick switch.
41  */
42 public class KeyboardQuickSwitchTaskView extends ConstraintLayout {
43 
44     @NonNull private final BorderAnimator mBorderAnimator;
45 
46     @Nullable private ImageView mThumbnailView1;
47     @Nullable private ImageView mThumbnailView2;
48 
KeyboardQuickSwitchTaskView(@onNull Context context)49     public KeyboardQuickSwitchTaskView(@NonNull Context context) {
50         this(context, null);
51     }
52 
KeyboardQuickSwitchTaskView(@onNull Context context, @Nullable AttributeSet attrs)53     public KeyboardQuickSwitchTaskView(@NonNull Context context, @Nullable AttributeSet attrs) {
54         this(context, attrs, 0);
55     }
56 
KeyboardQuickSwitchTaskView( @onNull Context context, @Nullable AttributeSet attrs, int defStyleAttr)57     public KeyboardQuickSwitchTaskView(
58             @NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
59         this(context, attrs, defStyleAttr, 0);
60     }
61 
KeyboardQuickSwitchTaskView( @onNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)62     public KeyboardQuickSwitchTaskView(
63             @NonNull Context context,
64             @Nullable AttributeSet attrs,
65             int defStyleAttr,
66             int defStyleRes) {
67         super(context, attrs, defStyleAttr, defStyleRes);
68         setWillNotDraw(false);
69         Resources resources = context.getResources();
70         mBorderAnimator = new BorderAnimator(
71                 /* borderBoundsBuilder= */ bounds -> bounds.set(0, 0, getWidth(), getHeight()),
72                 /* borderWidthPx= */ resources.getDimensionPixelSize(
73                         R.dimen.keyboard_quick_switch_border_width),
74                 /* borderRadiusPx= */ resources.getDimensionPixelSize(
75                         R.dimen.keyboard_quick_switch_task_view_radius),
76                 /* borderColor= */ attrs == null
77                         ? DEFAULT_BORDER_COLOR
78                         : context.getTheme()
79                                 .obtainStyledAttributes(
80                                         attrs,
81                                         R.styleable.TaskView,
82                                         defStyleAttr,
83                                         defStyleRes)
84                                 .getColor(
85                                         R.styleable.TaskView_borderColor,
86                                         DEFAULT_BORDER_COLOR),
87                 /* invalidateViewCallback= */ KeyboardQuickSwitchTaskView.this::invalidate);
88     }
89 
90     @Override
onFinishInflate()91     protected void onFinishInflate() {
92         super.onFinishInflate();
93 
94         mThumbnailView1 = findViewById(R.id.thumbnail1);
95         mThumbnailView2 = findViewById(R.id.thumbnail2);
96     }
97 
98     @NonNull
getFocusAnimator(boolean focused)99     protected Animator getFocusAnimator(boolean focused) {
100         return mBorderAnimator.buildAnimator(focused);
101     }
102 
103     @Override
draw(Canvas canvas)104     public void draw(Canvas canvas) {
105         super.draw(canvas);
106         mBorderAnimator.drawBorder(canvas);
107     }
108 
setThumbnails( @onNull Task task1, @Nullable Task task2, @Nullable ThumbnailUpdateFunction thumbnailUpdateFunction, @Nullable TitleUpdateFunction titleUpdateFunction)109     protected void setThumbnails(
110             @NonNull Task task1,
111             @Nullable Task task2,
112             @Nullable ThumbnailUpdateFunction thumbnailUpdateFunction,
113             @Nullable TitleUpdateFunction titleUpdateFunction) {
114         applyThumbnail(mThumbnailView1, task1, thumbnailUpdateFunction);
115         applyThumbnail(mThumbnailView2, task2, thumbnailUpdateFunction);
116 
117         if (titleUpdateFunction == null) {
118             setContentDescription(task2 == null
119                     ? task1.titleDescription
120                     : getContext().getString(
121                             R.string.quick_switch_split_task,
122                             task1.titleDescription,
123                             task2.titleDescription));
124             return;
125         }
126         titleUpdateFunction.updateTitleInBackground(task1, t ->
127                 setContentDescription(task1.titleDescription));
128         if (task2 == null) {
129             return;
130         }
131         titleUpdateFunction.updateTitleInBackground(task2, t ->
132                 setContentDescription(getContext().getString(
133                         R.string.quick_switch_split_task,
134                         task1.titleDescription,
135                         task2.titleDescription)));
136     }
137 
applyThumbnail( @ullable ImageView thumbnailView, @Nullable Task task, @Nullable ThumbnailUpdateFunction updateFunction)138     private void applyThumbnail(
139             @Nullable ImageView thumbnailView,
140             @Nullable Task task,
141             @Nullable ThumbnailUpdateFunction updateFunction) {
142         if (thumbnailView == null) {
143             return;
144         }
145         if (task == null) {
146             return;
147         }
148         if (updateFunction == null) {
149             applyThumbnail(thumbnailView, task.thumbnail);
150             return;
151         }
152         updateFunction.updateThumbnailInBackground(
153                 task, thumbnailData -> applyThumbnail(thumbnailView, thumbnailData));
154     }
155 
applyThumbnail( @onNull ImageView thumbnailView, ThumbnailData thumbnailData)156     private void applyThumbnail(
157             @NonNull ImageView thumbnailView, ThumbnailData thumbnailData) {
158         Bitmap bm = thumbnailData == null ? null : thumbnailData.thumbnail;
159 
160         thumbnailView.setVisibility(VISIBLE);
161         thumbnailView.setImageBitmap(bm);
162     }
163 
164     protected interface ThumbnailUpdateFunction {
165 
updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback)166         void updateThumbnailInBackground(Task task, Consumer<ThumbnailData> callback);
167     }
168 
169     protected interface TitleUpdateFunction {
170 
updateTitleInBackground(Task task, Consumer<Task> callback)171         void updateTitleInBackground(Task task, Consumer<Task> callback);
172     }
173 }
174