• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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.allapps;
17 
18 import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
19 
20 import android.content.Context;
21 import android.graphics.Rect;
22 import android.util.AttributeSet;
23 import android.view.View;
24 import android.view.WindowInsets;
25 import android.widget.ImageView;
26 import android.widget.LinearLayout;
27 import android.widget.TextView;
28 
29 import androidx.annotation.NonNull;
30 import androidx.core.graphics.Insets;
31 import androidx.core.view.WindowInsetsCompat;
32 
33 import com.android.launcher3.DeviceProfile;
34 import com.android.launcher3.Insettable;
35 import com.android.launcher3.R;
36 import com.android.launcher3.Utilities;
37 import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
38 import com.android.launcher3.logging.StatsLogManager;
39 import com.android.launcher3.model.StringCache;
40 import com.android.launcher3.views.ActivityContext;
41 /**
42  * Work profile toggle switch shown at the bottom of AllApps work tab
43  */
44 public class WorkModeSwitch extends LinearLayout implements Insettable,
45         KeyboardInsetAnimationCallback.KeyboardInsetListener {
46 
47     private static final int FLAG_FADE_ONGOING = 1 << 1;
48     private static final int FLAG_TRANSLATION_ONGOING = 1 << 2;
49     private static final int FLAG_PROFILE_TOGGLE_ONGOING = 1 << 3;
50     private static final int SCROLL_THRESHOLD_DP = 10;
51 
52     private final Rect mInsets = new Rect();
53     private final Rect mImeInsets = new Rect();
54     private int mFlags;
55     private final ActivityContext mActivityContext;
56 
57     // Threshold when user scrolls up/down to determine when should button extend/collapse
58     private final int mScrollThreshold;
59     private ImageView mIcon;
60     private TextView mTextView;
61     private final StatsLogManager mStatsLogManager;
62 
63 
WorkModeSwitch(@onNull Context context)64     public WorkModeSwitch(@NonNull Context context) {
65         this(context, null, 0);
66     }
67 
WorkModeSwitch(@onNull Context context, @NonNull AttributeSet attrs)68     public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs) {
69         this(context, attrs, 0);
70     }
71 
WorkModeSwitch(@onNull Context context, @NonNull AttributeSet attrs, int defStyleAttr)72     public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {
73         super(context, attrs, defStyleAttr);
74         mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP);
75         mActivityContext = ActivityContext.lookupContext(getContext());
76         mStatsLogManager = mActivityContext.getStatsLogManager();
77     }
78 
79     @Override
onFinishInflate()80     protected void onFinishInflate() {
81         super.onFinishInflate();
82 
83         mIcon = findViewById(R.id.work_icon);
84         mTextView = findViewById(R.id.pause_text);
85         setSelected(true);
86         if (Utilities.ATLEAST_R) {
87             KeyboardInsetAnimationCallback keyboardInsetAnimationCallback =
88                     new KeyboardInsetAnimationCallback(this);
89             setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
90         }
91 
92         setInsets(mActivityContext.getDeviceProfile().getInsets());
93         updateStringFromCache();
94     }
95 
96     @Override
setInsets(Rect insets)97     public void setInsets(Rect insets) {
98         mInsets.set(insets);
99         updateTranslationY();
100         MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
101         if (lp != null) {
102             int bottomMargin = getResources().getDimensionPixelSize(R.dimen.work_fab_margin_bottom);
103             DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
104             if (mActivityContext.getAppsView().isSearchBarFloating()) {
105                 bottomMargin += dp.hotseatQsbHeight;
106             }
107 
108             if (!dp.isGestureMode && dp.isTaskbarPresent) {
109                 bottomMargin += dp.taskbarHeight;
110             }
111 
112             lp.bottomMargin = bottomMargin;
113         }
114     }
115 
116     @Override
onLayout(boolean changed, int left, int top, int right, int bottom)117     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
118         super.onLayout(changed, left, top, right, bottom);
119         View parent = (View) getParent();
120         int allAppsLeftRightPadding = mActivityContext.getDeviceProfile().allAppsLeftRightPadding;
121         int size = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight()
122                 - 2 * allAppsLeftRightPadding;
123         int tabWidth = getTabWidth(getContext(), size);
124         int shift = (size - tabWidth) / 2 + allAppsLeftRightPadding;
125         setTranslationX(Utilities.isRtl(getResources()) ? shift : -shift);
126     }
127 
128     @Override
isEnabled()129     public boolean isEnabled() {
130         return super.isEnabled() && getVisibility() == VISIBLE && mFlags == 0;
131     }
132 
animateVisibility(boolean visible)133     public void animateVisibility(boolean visible) {
134         clearAnimation();
135         if (visible) {
136             setFlag(FLAG_FADE_ONGOING);
137             setVisibility(VISIBLE);
138             extend();
139             animate().alpha(1).withEndAction(() -> removeFlag(FLAG_FADE_ONGOING)).start();
140         } else if (getVisibility() != GONE) {
141             setFlag(FLAG_FADE_ONGOING);
142             animate().alpha(0).withEndAction(() -> {
143                 removeFlag(FLAG_FADE_ONGOING);
144                 setVisibility(GONE);
145             }).start();
146         }
147     }
148 
149     @Override
onApplyWindowInsets(WindowInsets insets)150     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
151         WindowInsetsCompat windowInsetsCompat =
152                 WindowInsetsCompat.toWindowInsetsCompat(insets, this);
153         if (windowInsetsCompat.isVisible(WindowInsetsCompat.Type.ime())) {
154             setInsets(mImeInsets, windowInsetsCompat.getInsets(WindowInsetsCompat.Type.ime()));
155         } else {
156             mImeInsets.setEmpty();
157         }
158         updateTranslationY();
159         return super.onApplyWindowInsets(insets);
160     }
161 
updateTranslationY()162     void updateTranslationY() {
163         setTranslationY(-mImeInsets.bottom);
164     }
165 
166     @Override
setTranslationY(float translationY)167     public void setTranslationY(float translationY) {
168         // Always translate at least enough for nav bar insets.
169         super.setTranslationY(Math.min(translationY, -mInsets.bottom));
170     }
171 
setInsets(Rect rect, Insets insets)172     private void setInsets(Rect rect, Insets insets) {
173         rect.set(insets.left, insets.top, insets.right, insets.bottom);
174     }
175 
getImeInsets()176     public Rect getImeInsets() {
177         return mImeInsets;
178     }
179 
180     @Override
onTranslationStart()181     public void onTranslationStart() {
182         setFlag(FLAG_TRANSLATION_ONGOING);
183     }
184 
185     @Override
onTranslationEnd()186     public void onTranslationEnd() {
187         removeFlag(FLAG_TRANSLATION_ONGOING);
188     }
189 
setFlag(int flag)190     private void setFlag(int flag) {
191         mFlags |= flag;
192     }
193 
removeFlag(int flag)194     private void removeFlag(int flag) {
195         mFlags &= ~flag;
196     }
197 
extend()198     public void extend() {
199         mTextView.setVisibility(VISIBLE);
200     }
201 
shrink()202     public void shrink(){
203         mTextView.setVisibility(GONE);
204     }
205 
getScrollThreshold()206     public int getScrollThreshold() {
207         return mScrollThreshold;
208     }
209 
updateStringFromCache()210     public void updateStringFromCache(){
211         StringCache cache = mActivityContext.getStringCache();
212         if (cache != null) {
213             mTextView.setText(cache.workProfilePauseButton);
214         }
215     }
216 }
217