• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 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 android.view.KeyEvent.ACTION_UP;
19 import static android.view.KeyEvent.KEYCODE_BACK;
20 
21 import android.content.Context;
22 import android.graphics.Canvas;
23 import android.graphics.RectF;
24 import android.util.AttributeSet;
25 import android.view.KeyEvent;
26 import android.view.MotionEvent;
27 import android.view.View;
28 import android.view.ViewTreeObserver;
29 
30 import androidx.annotation.NonNull;
31 import androidx.annotation.Nullable;
32 
33 import com.android.launcher3.AbstractFloatingView;
34 import com.android.launcher3.testing.TestLogging;
35 import com.android.launcher3.testing.shared.TestProtocol;
36 import com.android.launcher3.views.BaseDragLayer;
37 
38 /**
39  * Top-level ViewGroup that hosts the TaskbarView as well as Views created by it such as Folder.
40  */
41 public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
42 
43     private final TaskbarBackgroundRenderer mBackgroundRenderer;
44     private final ViewTreeObserver.OnComputeInternalInsetsListener mTaskbarInsetsComputer =
45             this::onComputeTaskbarInsets;
46 
47     // Initialized in init.
48     private TaskbarDragLayerController.TaskbarDragLayerCallbacks mControllerCallbacks;
49 
50     private float mTaskbarBackgroundOffset;
51 
TaskbarDragLayer(@onNull Context context)52     public TaskbarDragLayer(@NonNull Context context) {
53         this(context, null);
54     }
55 
TaskbarDragLayer(@onNull Context context, @Nullable AttributeSet attrs)56     public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs) {
57         this(context, attrs, 0);
58     }
59 
TaskbarDragLayer(@onNull Context context, @Nullable AttributeSet attrs, int defStyleAttr)60     public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs,
61             int defStyleAttr) {
62         this(context, attrs, defStyleAttr, 0);
63     }
64 
TaskbarDragLayer(@onNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)65     public TaskbarDragLayer(@NonNull Context context, @Nullable AttributeSet attrs,
66             int defStyleAttr, int defStyleRes) {
67         super(context, attrs, 1 /* alphaChannelCount */);
68         mBackgroundRenderer = new TaskbarBackgroundRenderer(mActivity);
69         mBackgroundRenderer.getPaint().setAlpha(0);
70     }
71 
init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks)72     public void init(TaskbarDragLayerController.TaskbarDragLayerCallbacks callbacks) {
73         mControllerCallbacks = callbacks;
74 
75         recreateControllers();
76     }
77 
78     @Override
recreateControllers()79     public void recreateControllers() {
80         mControllers = mControllerCallbacks.getTouchControllers();
81     }
82 
onComputeTaskbarInsets(ViewTreeObserver.InternalInsetsInfo insetsInfo)83     private void onComputeTaskbarInsets(ViewTreeObserver.InternalInsetsInfo insetsInfo) {
84         if (mControllerCallbacks != null) {
85             mControllerCallbacks.updateInsetsTouchability(insetsInfo);
86         }
87     }
88 
onDestroy(boolean forceDestroy)89     protected void onDestroy(boolean forceDestroy) {
90         if (forceDestroy) {
91             getViewTreeObserver().removeOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
92         }
93     }
94 
onDestroy()95     protected void onDestroy() {
96         onDestroy(!TaskbarManager.FLAG_HIDE_NAVBAR_WINDOW);
97     }
98 
99     @Override
onAttachedToWindow()100     protected void onAttachedToWindow() {
101         super.onAttachedToWindow();
102         getViewTreeObserver().addOnComputeInternalInsetsListener(mTaskbarInsetsComputer);
103     }
104 
105     @Override
onDetachedFromWindow()106     protected void onDetachedFromWindow() {
107         super.onDetachedFromWindow();
108 
109         onDestroy(true);
110     }
111 
112     @Override
canFindActiveController()113     protected boolean canFindActiveController() {
114         // Unlike super class, we want to be able to find controllers when touches occur in the
115         // gesture area. For example, this allows Folder to close itself when touching the Taskbar.
116         return true;
117     }
118 
119     @Override
onViewRemoved(View child)120     public void onViewRemoved(View child) {
121         super.onViewRemoved(child);
122         if (mControllerCallbacks != null) {
123             mControllerCallbacks.onDragLayerViewRemoved();
124         }
125     }
126 
127     @Override
dispatchDraw(Canvas canvas)128     protected void dispatchDraw(Canvas canvas) {
129         float backgroundHeight = mControllerCallbacks.getTaskbarBackgroundHeight()
130                 * (1f - mTaskbarBackgroundOffset);
131         mBackgroundRenderer.setBackgroundHeight(backgroundHeight);
132         mBackgroundRenderer.draw(canvas);
133         super.dispatchDraw(canvas);
134     }
135 
136     /**
137      * Sets the alpha of the background color behind all the Taskbar contents.
138      * @param alpha 0 is fully transparent, 1 is fully opaque.
139      */
setTaskbarBackgroundAlpha(float alpha)140     protected void setTaskbarBackgroundAlpha(float alpha) {
141         mBackgroundRenderer.getPaint().setAlpha((int) (alpha * 255));
142         invalidate();
143     }
144 
145     /**
146      * Sets the translation of the background color behind all the Taskbar contents.
147      * @param offset 0 is fully onscreen, 1 is fully offscreen.
148      */
setTaskbarBackgroundOffset(float offset)149     protected void setTaskbarBackgroundOffset(float offset) {
150         mTaskbarBackgroundOffset = offset;
151         invalidate();
152     }
153 
154     /**
155      * Sets the roundness of the round corner above Taskbar.
156      * @param cornerRoundness 0 has no round corner, 1 has complete round corner.
157      */
setCornerRoundness(float cornerRoundness)158     protected void setCornerRoundness(float cornerRoundness) {
159         mBackgroundRenderer.setCornerRoundness(cornerRoundness);
160         invalidate();
161     }
162 
163     /*
164      * Sets the translation of the background during the swipe up gesture.
165      */
setBackgroundTranslationYForSwipe(float translationY)166     protected void setBackgroundTranslationYForSwipe(float translationY) {
167         mBackgroundRenderer.setTranslationYForSwipe(translationY);
168         invalidate();
169     }
170 
171     /*
172      * Sets the translation of the background during the spring on stash animation.
173      */
setBackgroundTranslationYForStash(float translationY)174     protected void setBackgroundTranslationYForStash(float translationY) {
175         mBackgroundRenderer.setTranslationYForStash(translationY);
176         invalidate();
177     }
178 
179     /** Returns the bounds in DragLayer coordinates of where the transient background was drawn. */
getLastDrawnTransientRect()180     protected RectF getLastDrawnTransientRect() {
181         return mBackgroundRenderer.getLastDrawnTransientRect();
182     }
183 
184     @Override
dispatchTouchEvent(MotionEvent ev)185     public boolean dispatchTouchEvent(MotionEvent ev) {
186         TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
187         return super.dispatchTouchEvent(ev);
188     }
189 
190     /** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */
191     @Override
dispatchKeyEvent(KeyEvent event)192     public boolean dispatchKeyEvent(KeyEvent event) {
193         if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
194             AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
195             if (topView != null && topView.canHandleBack()) {
196                 topView.onBackInvoked();
197                 // Handled by the floating view.
198                 return true;
199             }
200         }
201         return super.dispatchKeyEvent(event);
202     }
203 }
204