Extend/shrink work button when scrolling
most of the change was from this CL: ag/19223926
moved scroll listener definition to WorkProfileManager.java
Added feature flag
bug: 194188980
test: Video - https://drive.google.com/file/d/18UM7UDNQz-Z8Q2Sh8VEKHm9LXRVJaWFM/view?usp=sharing
Change-Id: Ib80784e0f5108b28658141ca5e495a27fab34a3c
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 74316e2..ca08164 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -575,6 +575,10 @@
mAH.get(AdapterHolder.MAIN).setup(mViewPager.getChildAt(0), mPersonalMatcher);
mAH.get(AdapterHolder.WORK).setup(mViewPager.getChildAt(1), mWorkManager.getMatcher());
mAH.get(AdapterHolder.WORK).mRecyclerView.setId(R.id.apps_list_view_work);
+ if (FeatureFlags.ENABLE_EXPANDING_PAUSE_WORK_BUTTON.get()) {
+ mAH.get(AdapterHolder.WORK).mRecyclerView.addOnScrollListener(
+ mWorkManager.newScrollListener());
+ }
mViewPager.getPageIndicator().setActiveMarker(AdapterHolder.MAIN);
findViewById(R.id.tab_personal)
.setOnClickListener((View view) -> {
@@ -666,10 +670,10 @@
mViewPager = (AllAppsPagedView) newView;
mViewPager.initParentViews(this);
mViewPager.getPageIndicator().setOnActivePageChangedListener(this);
- if (mWorkManager.attachWorkModeSwitch()) {
- mWorkManager.getWorkModeSwitch().post(
- () -> mAH.get(AdapterHolder.WORK).applyPadding());
- }
+
+ mWorkManager.reset();
+ post(() -> mAH.get(AdapterHolder.WORK).applyPadding());
+
} else {
mWorkManager.detachWorkModeSwitch();
mViewPager = null;
diff --git a/src/com/android/launcher3/allapps/WorkModeSwitch.java b/src/com/android/launcher3/allapps/WorkModeSwitch.java
index aadd0b5..c9466a8 100644
--- a/src/com/android/launcher3/allapps/WorkModeSwitch.java
+++ b/src/com/android/launcher3/allapps/WorkModeSwitch.java
@@ -15,17 +15,19 @@
*/
package com.android.launcher3.allapps;
-import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP;
import static com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.getTabWidth;
+import android.animation.LayoutTransition;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
-import android.view.ViewGroup.MarginLayoutParams;
import android.view.WindowInsets;
-import android.widget.Button;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+import androidx.annotation.NonNull;
import androidx.core.graphics.Insets;
import androidx.core.view.WindowInsetsCompat;
@@ -37,55 +39,62 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
-
/**
* Work profile toggle switch shown at the bottom of AllApps work tab
*/
-public class WorkModeSwitch extends Button implements Insettable, View.OnClickListener,
- KeyboardInsetAnimationCallback.KeyboardInsetListener,
- PersonalWorkSlidingTabStrip.OnActivePageChangedListener {
+public class WorkModeSwitch extends LinearLayout implements Insettable,
+ KeyboardInsetAnimationCallback.KeyboardInsetListener {
private static final int FLAG_FADE_ONGOING = 1 << 1;
private static final int FLAG_TRANSLATION_ONGOING = 1 << 2;
private static final int FLAG_PROFILE_TOGGLE_ONGOING = 1 << 3;
+ private static final int SCROLL_THRESHOLD_DP = 10;
private final Rect mInsets = new Rect();
private final Rect mImeInsets = new Rect();
private int mFlags;
- private boolean mWorkEnabled;
- private boolean mOnWorkTab;
+ private final ActivityContext mActivityContext;
- public WorkModeSwitch(Context context) {
+ // Threshold when user scrolls up/down to determine when should button extend/collapse
+ private final int mScrollThreshold;
+ private ImageView mIcon;
+ private TextView mTextView;
+
+ public WorkModeSwitch(@NonNull Context context) {
this(context, null, 0);
}
- public WorkModeSwitch(Context context, AttributeSet attrs) {
+ public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs) {
this(context, attrs, 0);
}
- public WorkModeSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
+ public WorkModeSwitch(@NonNull Context context, @NonNull AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP);
+ mActivityContext = ActivityContext.lookupContext(getContext());
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
+
+ mIcon = findViewById(R.id.work_icon);
+ mTextView = findViewById(R.id.pause_text);
setSelected(true);
- setOnClickListener(this);
if (Utilities.ATLEAST_R) {
KeyboardInsetAnimationCallback keyboardInsetAnimationCallback =
new KeyboardInsetAnimationCallback(this);
setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
}
- ActivityContext activityContext = ActivityContext.lookupContext(getContext());
- DeviceProfile grid = activityContext.getDeviceProfile();
- setInsets(grid.getInsets());
- StringCache cache = activityContext.getStringCache();
+ setInsets(mActivityContext.getDeviceProfile().getInsets());
+ StringCache cache = mActivityContext.getStringCache();
if (cache != null) {
- setText(cache.workProfilePauseButton);
+ mTextView.setText(cache.workProfilePauseButton);
}
+
+ mIcon.setColorFilter(mTextView.getCurrentTextColor());
+ getLayoutTransition().enableTransitionType(LayoutTransition.CHANGING);
}
@Override
@@ -102,8 +111,6 @@
if (!dp.isGestureMode && dp.isTaskbarPresent) {
bottomMargin += dp.taskbarSize;
- } else {
- bottomMargin += insets.bottom;
}
lp.bottomMargin = bottomMargin;
@@ -113,58 +120,32 @@
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
- DeviceProfile dp = ActivityContext.lookupContext(getContext()).getDeviceProfile();
View parent = (View) getParent();
+ int allAppsLeftRightPadding = mActivityContext.getDeviceProfile().allAppsLeftRightPadding;
int size = parent.getWidth() - parent.getPaddingLeft() - parent.getPaddingRight()
- - 2 * dp.allAppsLeftRightPadding;
+ - 2 * allAppsLeftRightPadding;
int tabWidth = getTabWidth(getContext(), size);
- int shift = (size - tabWidth) / 2 + dp.allAppsLeftRightPadding;
+ int shift = (size - tabWidth) / 2 + allAppsLeftRightPadding;
setTranslationX(Utilities.isRtl(getResources()) ? shift : -shift);
}
@Override
- public void onActivePageChanged(int page) {
- mOnWorkTab = page == ActivityAllAppsContainerView.AdapterHolder.WORK;
- updateVisibility();
- }
-
- @Override
- public void onClick(View view) {
- if (Utilities.ATLEAST_P && isEnabled()) {
- setFlag(FLAG_PROFILE_TOGGLE_ONGOING);
- ActivityContext activityContext = ActivityContext.lookupContext(getContext());
- activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
- activityContext.getAppsView().getWorkManager().setWorkProfileEnabled(false);
- }
- }
-
- @Override
public boolean isEnabled() {
return super.isEnabled() && getVisibility() == VISIBLE && mFlags == 0;
}
- /**
- * Sets the enabled or disabled state of the button
- */
- public void updateCurrentState(boolean isEnabled) {
- removeFlag(FLAG_PROFILE_TOGGLE_ONGOING);
- if (mWorkEnabled != isEnabled) {
- mWorkEnabled = isEnabled;
- updateVisibility();
- }
- }
-
- private void updateVisibility() {
+ public void animateVisibility(boolean visible) {
clearAnimation();
- if (mWorkEnabled && mOnWorkTab) {
+ if (visible) {
setFlag(FLAG_FADE_ONGOING);
setVisibility(VISIBLE);
+ extend();
animate().alpha(1).withEndAction(() -> removeFlag(FLAG_FADE_ONGOING)).start();
} else if (getVisibility() != GONE) {
setFlag(FLAG_FADE_ONGOING);
animate().alpha(0).withEndAction(() -> {
removeFlag(FLAG_FADE_ONGOING);
- this.setVisibility(GONE);
+ setVisibility(GONE);
}).start();
}
}
@@ -213,4 +194,16 @@
private void removeFlag(int flag) {
mFlags &= ~flag;
}
+
+ public void extend() {
+ mTextView.setVisibility(VISIBLE);
+ }
+
+ public void shrink(){
+ mTextView.setVisibility(GONE);
+ }
+
+ public int getScrollThreshold() {
+ return mScrollThreshold;
+ }
}
diff --git a/src/com/android/launcher3/allapps/WorkProfileManager.java b/src/com/android/launcher3/allapps/WorkProfileManager.java
index cfac985..547b74c 100644
--- a/src/com/android/launcher3/allapps/WorkProfileManager.java
+++ b/src/com/android/launcher3/allapps/WorkProfileManager.java
@@ -17,6 +17,10 @@
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_DISABLED_CARD;
import static com.android.launcher3.allapps.BaseAllAppsAdapter.VIEW_TYPE_WORK_EDU_CARD;
+import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.MAIN;
+import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.SEARCH;
+import static com.android.launcher3.allapps.BaseAllAppsContainerView.AdapterHolder.WORK;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TURN_OFF_WORK_APPS_TAP;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_HAS_SHORTCUT_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_CHANGE_PERMISSION;
import static com.android.launcher3.model.BgDataModel.Callbacks.FLAG_QUIET_MODE_ENABLED;
@@ -28,14 +32,19 @@
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
+import android.view.View;
import androidx.annotation.IntDef;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
+import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.views.ActivityContext;
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip;
import java.lang.annotation.Retention;
@@ -104,8 +113,16 @@
@Override
public void onActivePageChanged(int page) {
+ updateWorkFAB(page);
+ }
+
+ private void updateWorkFAB(int page) {
if (mWorkModeSwitch != null) {
- mWorkModeSwitch.onActivePageChanged(page);
+ if (page == MAIN || page == SEARCH) {
+ mWorkModeSwitch.animateVisibility(false);
+ } else if (page == WORK && mCurrentState == STATE_ENABLED) {
+ mWorkModeSwitch.animateVisibility(true);
+ }
}
}
@@ -123,7 +140,12 @@
getAH().mAppsList.updateAdapterItems();
}
if (mWorkModeSwitch != null) {
- mWorkModeSwitch.updateCurrentState(currentState == STATE_ENABLED);
+ updateWorkFAB(mAllApps.getCurrentPage());
+ }
+ if (mCurrentState == STATE_ENABLED) {
+ attachWorkModeSwitch();
+ } else if (mCurrentState == STATE_DISABLED) {
+ detachWorkModeSwitch();
}
}
@@ -140,13 +162,16 @@
mWorkModeSwitch = (WorkModeSwitch) mAllApps.getLayoutInflater().inflate(
R.layout.work_mode_fab, mAllApps, false);
}
- if (mWorkModeSwitch.getParent() != mAllApps) {
+ if (mWorkModeSwitch.getParent() == null) {
mAllApps.addView(mWorkModeSwitch);
}
+ if (mAllApps.getCurrentPage() != WORK) {
+ mWorkModeSwitch.animateVisibility(false);
+ }
if (getAH() != null) {
getAH().applyPadding();
}
- mWorkModeSwitch.updateCurrentState(mCurrentState == STATE_ENABLED);
+ mWorkModeSwitch.setOnClickListener(this::onWorkFabClicked);
return true;
}
/**
@@ -169,7 +194,7 @@
}
private BaseAllAppsContainerView<?>.AdapterHolder getAH() {
- return mAllApps.mAH.get(BaseAllAppsContainerView.AdapterHolder.WORK);
+ return mAllApps.mAH.get(WORK);
}
public int getCurrentState() {
@@ -199,4 +224,40 @@
private boolean isEduSeen() {
return mPreferences.getInt(KEY_WORK_EDU_STEP, 0) != 0;
}
+
+ private void onWorkFabClicked(View view) {
+ if (Utilities.ATLEAST_P && mCurrentState == STATE_ENABLED && mWorkModeSwitch.isEnabled()) {
+ ActivityContext activityContext = ActivityContext.lookupContext(
+ mWorkModeSwitch.getContext());
+ activityContext.getStatsLogManager().logger().log(LAUNCHER_TURN_OFF_WORK_APPS_TAP);
+ setWorkProfileEnabled(false);
+ }
+ }
+
+ public RecyclerView.OnScrollListener newScrollListener() {
+ return new RecyclerView.OnScrollListener() {
+ int totalDelta = 0;
+ @Override
+ public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState){
+ if (newState == RecyclerView.SCROLL_STATE_IDLE) {
+ totalDelta = 0;
+ }
+ }
+ @Override
+ public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
+ WorkModeSwitch fab = getWorkModeSwitch();
+ if (fab == null){
+ return;
+ }
+ totalDelta = Utilities.boundToRange(totalDelta,
+ -fab.getScrollThreshold(), fab.getScrollThreshold()) + dy;
+ boolean isScrollAtTop = recyclerView.computeVerticalScrollOffset() == 0;
+ if ((isScrollAtTop || totalDelta < -fab.getScrollThreshold())) {
+ fab.extend();
+ } else if (totalDelta > fab.getScrollThreshold()) {
+ fab.shrink();
+ }
+ }
+ };
+ }
}
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index ce637ef..4658320 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -92,6 +92,10 @@
public static final BooleanFlag ENABLE_HIDE_HEADER = new DeviceFlag("ENABLE_HIDE_HEADER",
true, "Hide header on keyboard before typing in all apps");
+ public static final BooleanFlag ENABLE_EXPANDING_PAUSE_WORK_BUTTON = new DeviceFlag(
+ "ENABLE_EXPANDING_PAUSE_WORK_BUTTON", false,
+ "Expand and collapse pause work button while scrolling");
+
public static final BooleanFlag ENABLE_HIDE_HEADER_STATIC = new DeviceFlag(
"ENABLE_HIDE_HEADER_STATIC", false, "Hide keyboard suggestion strip");