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