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 
17 package com.android.quickstep.views;
18 
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.util.FloatProperty;
22 import android.widget.Button;
23 
24 import com.android.launcher3.DeviceProfile;
25 import com.android.launcher3.statemanager.StatefulActivity;
26 import com.android.launcher3.touch.PagedOrientationHandler;
27 
28 public class ClearAllButton extends Button {
29 
30     public static final FloatProperty<ClearAllButton> VISIBILITY_ALPHA =
31             new FloatProperty<ClearAllButton>("visibilityAlpha") {
32                 @Override
33                 public Float get(ClearAllButton view) {
34                     return view.mVisibilityAlpha;
35                 }
36 
37                 @Override
38                 public void setValue(ClearAllButton view, float v) {
39                     view.setVisibilityAlpha(v);
40                 }
41             };
42 
43     public static final FloatProperty<ClearAllButton> DISMISS_ALPHA =
44             new FloatProperty<ClearAllButton>("dismissAlpha") {
45                 @Override
46                 public Float get(ClearAllButton view) {
47                     return view.mDismissAlpha;
48                 }
49 
50                 @Override
51                 public void setValue(ClearAllButton view, float v) {
52                     view.setDismissAlpha(v);
53                 }
54             };
55 
56     private final StatefulActivity mActivity;
57     private float mScrollAlpha = 1;
58     private float mContentAlpha = 1;
59     private float mVisibilityAlpha = 1;
60     private float mDismissAlpha = 1;
61     private float mFullscreenProgress = 1;
62     private float mGridProgress = 1;
63 
64     private boolean mIsRtl;
65     private float mNormalTranslationPrimary;
66     private float mFullscreenTranslationPrimary;
67     private float mGridTranslationPrimary;
68     private float mGridScrollOffset;
69     private float mScrollOffsetPrimary;
70     private float mSplitSelectScrollOffsetPrimary;
71 
72     private int mSidePadding;
73 
ClearAllButton(Context context, AttributeSet attrs)74     public ClearAllButton(Context context, AttributeSet attrs) {
75         super(context, attrs);
76         mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
77         mActivity = StatefulActivity.fromContext(context);
78     }
79 
80     @Override
onLayout(boolean changed, int left, int top, int right, int bottom)81     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
82         super.onLayout(changed, left, top, right, bottom);
83         PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
84         mSidePadding = orientationHandler.getClearAllSidePadding(getRecentsView(), mIsRtl);
85     }
86 
getRecentsView()87     private RecentsView getRecentsView() {
88         return (RecentsView) getParent();
89     }
90 
91     @Override
onRtlPropertiesChanged(int layoutDirection)92     public void onRtlPropertiesChanged(int layoutDirection) {
93         super.onRtlPropertiesChanged(layoutDirection);
94         mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
95     }
96 
97     @Override
hasOverlappingRendering()98     public boolean hasOverlappingRendering() {
99         return false;
100     }
101 
setContentAlpha(float alpha)102     public void setContentAlpha(float alpha) {
103         if (mContentAlpha != alpha) {
104             mContentAlpha = alpha;
105             updateAlpha();
106         }
107     }
108 
setVisibilityAlpha(float alpha)109     public void setVisibilityAlpha(float alpha) {
110         if (mVisibilityAlpha != alpha) {
111             mVisibilityAlpha = alpha;
112             updateAlpha();
113         }
114     }
115 
setDismissAlpha(float alpha)116     public void setDismissAlpha(float alpha) {
117         if (mDismissAlpha != alpha) {
118             mDismissAlpha = alpha;
119             updateAlpha();
120         }
121     }
122 
onRecentsViewScroll(int scroll, boolean gridEnabled)123     public void onRecentsViewScroll(int scroll, boolean gridEnabled) {
124         RecentsView recentsView = getRecentsView();
125         if (recentsView == null) {
126             return;
127         }
128 
129         PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
130         float orientationSize = orientationHandler.getPrimaryValue(getWidth(), getHeight());
131         if (orientationSize == 0) {
132             return;
133         }
134 
135         int clearAllScroll = recentsView.getClearAllScroll();
136         int adjustedScrollFromEdge = Math.abs(scroll - clearAllScroll);
137         float shift = Math.min(adjustedScrollFromEdge, orientationSize);
138         mNormalTranslationPrimary = mIsRtl ? -shift : shift;
139         if (!gridEnabled) {
140             mNormalTranslationPrimary += mSidePadding;
141         }
142         applyPrimaryTranslation();
143         applySecondaryTranslation();
144         mScrollAlpha = 1 - shift / orientationSize;
145         updateAlpha();
146     }
147 
updateAlpha()148     private void updateAlpha() {
149         final float alpha = mScrollAlpha * mContentAlpha * mVisibilityAlpha * mDismissAlpha;
150         setAlpha(alpha);
151         setClickable(Math.min(alpha, 1) == 1);
152     }
153 
setFullscreenTranslationPrimary(float fullscreenTranslationPrimary)154     public void setFullscreenTranslationPrimary(float fullscreenTranslationPrimary) {
155         mFullscreenTranslationPrimary = fullscreenTranslationPrimary;
156         applyPrimaryTranslation();
157     }
158 
setGridTranslationPrimary(float gridTranslationPrimary)159     public void setGridTranslationPrimary(float gridTranslationPrimary) {
160         mGridTranslationPrimary = gridTranslationPrimary;
161         applyPrimaryTranslation();
162     }
163 
setGridScrollOffset(float gridScrollOffset)164     public void setGridScrollOffset(float gridScrollOffset) {
165         mGridScrollOffset = gridScrollOffset;
166     }
167 
setScrollOffsetPrimary(float scrollOffsetPrimary)168     public void setScrollOffsetPrimary(float scrollOffsetPrimary) {
169         mScrollOffsetPrimary = scrollOffsetPrimary;
170     }
171 
setSplitSelectScrollOffsetPrimary(float splitSelectScrollOffsetPrimary)172     public void setSplitSelectScrollOffsetPrimary(float splitSelectScrollOffsetPrimary) {
173         mSplitSelectScrollOffsetPrimary = splitSelectScrollOffsetPrimary;
174     }
175 
getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled)176     public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
177         float scrollAdjustment = 0;
178         if (fullscreenEnabled) {
179             scrollAdjustment += mFullscreenTranslationPrimary;
180         }
181         if (gridEnabled) {
182             scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
183         }
184         scrollAdjustment += mScrollOffsetPrimary;
185         scrollAdjustment += mSplitSelectScrollOffsetPrimary;
186         return scrollAdjustment;
187     }
188 
getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled)189     public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
190         return getScrollAdjustment(fullscreenEnabled, gridEnabled);
191     }
192 
193     /**
194      * Adjust translation when this TaskView is about to be shown fullscreen.
195      *
196      * @param progress: 0 = no translation; 1 = translate according to TaskVIew translations.
197      */
setFullscreenProgress(float progress)198     public void setFullscreenProgress(float progress) {
199         mFullscreenProgress = progress;
200         applyPrimaryTranslation();
201     }
202 
203     /**
204      * Moves ClearAllButton between carousel and 2 row grid.
205      *
206      * @param gridProgress 0 = carousel; 1 = 2 row grid.
207      */
setGridProgress(float gridProgress)208     public void setGridProgress(float gridProgress) {
209         mGridProgress = gridProgress;
210         applyPrimaryTranslation();
211     }
212 
applyPrimaryTranslation()213     private void applyPrimaryTranslation() {
214         RecentsView recentsView = getRecentsView();
215         if (recentsView == null) {
216             return;
217         }
218 
219         PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
220         orientationHandler.getPrimaryViewTranslate().set(this,
221                 orientationHandler.getPrimaryValue(0f, getOriginalTranslationY())
222                         + mNormalTranslationPrimary + getFullscreenTrans(
223                         mFullscreenTranslationPrimary) + getGridTrans(mGridTranslationPrimary));
224     }
225 
applySecondaryTranslation()226     private void applySecondaryTranslation() {
227         RecentsView recentsView = getRecentsView();
228         if (recentsView == null) {
229             return;
230         }
231 
232         PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
233         orientationHandler.getSecondaryViewTranslate().set(this,
234                 orientationHandler.getSecondaryValue(0f, getOriginalTranslationY()));
235     }
236 
getFullscreenTrans(float endTranslation)237     private float getFullscreenTrans(float endTranslation) {
238         return mFullscreenProgress > 0 ? endTranslation : 0;
239     }
240 
getGridTrans(float endTranslation)241     private float getGridTrans(float endTranslation) {
242         return mGridProgress > 0 ? endTranslation : 0;
243     }
244 
245     /**
246      * Get the Y translation that is set in the original layout position, before scrolling.
247      */
getOriginalTranslationY()248     private float getOriginalTranslationY() {
249         DeviceProfile deviceProfile = mActivity.getDeviceProfile();
250         return deviceProfile.overviewShowAsGrid
251                 ? deviceProfile.overviewRowSpacing
252                 : deviceProfile.overviewTaskThumbnailTopMarginPx / 2.0f;
253     }
254 }
255