Merge changes from topic "AddWorkSchedulerInWorkProfileFlag" into main

* changes:
  Add work_scheduler_in_work_profile flag.
  Remove layoutTransitions for current FAB and use custom animation.
This commit is contained in:
Brandon Dayauon
2024-10-29 20:17:02 +00:00
committed by Android (Google) Code Review
5 changed files with 142 additions and 20 deletions
+7
View File
@@ -368,6 +368,13 @@ flag {
}
}
flag {
name: "work_scheduler_in_work_profile"
namespace: "launcher"
description: "Enables work scheduler view above the work pause button in work profile."
bug: "361589193"
}
flag {
name: "one_grid_specs"
namespace: "launcher"
@@ -19,6 +19,9 @@
<shape android:shape="rectangle">
<corners android:radius="@dimen/work_fab_radius" />
<solid android:color="@color/work_fab_bg_color" />
<padding
android:left="@dimen/work_mode_fab_background_horizontal_padding"
android:right="@dimen/work_mode_fab_background_horizontal_padding"/>
</shape>
</item>
</ripple>
+4 -6
View File
@@ -23,18 +23,16 @@
android:gravity="center_vertical"
android:background="@drawable/work_mode_fab_background"
android:forceHasOverlappingRendering="false"
android:contentDescription="@string/work_apps_pause_btn_text"
android:paddingStart="@dimen/work_mode_fab_background_start_padding"
android:paddingEnd="@dimen/work_mode_fab_background_end_padding"
android:animateLayoutChanges="true">
android:contentDescription="@string/work_apps_pause_btn_text">
<ImageView
android:id="@+id/work_icon"
android:layout_width="@dimen/work_fab_icon_size"
android:layout_height="@dimen/work_fab_icon_size"
android:layout_marginVertical="@dimen/work_fab_icon_vertical_margin"
android:importantForAccessibility="no"
android:layout_marginEnd="@dimen/work_fab_icon_end_margin"
android:src="@drawable/ic_corp_off"
android:tint="@color/work_fab_icon_color"
android:layout_marginStart="@dimen/work_fab_icon_start_margin_expanded"
android:scaleType="center"/>
<TextView
android:id="@+id/pause_text"
@@ -46,8 +44,8 @@
android:includeFontPadding="false"
android:textDirection="locale"
android:text="@string/work_apps_pause_btn_text"
android:layout_marginStart="@dimen/work_fab_text_start_margin"
android:layout_marginEnd="@dimen/work_fab_text_end_margin"
android:ellipsize="end"
android:maxLines="1"
style="@style/TextHeadline"/>
</com.android.launcher3.allapps.WorkModeSwitch>
+5 -4
View File
@@ -156,15 +156,16 @@
<dimen name="work_fab_height">56dp</dimen>
<dimen name="work_fab_radius">16dp</dimen>
<dimen name="work_fab_icon_size">24dp</dimen>
<dimen name="work_fab_icon_end_margin">12dp</dimen>
<dimen name="work_fab_text_end_margin">16dp</dimen>
<dimen name="work_fab_icon_vertical_margin">16dp</dimen>
<dimen name="work_fab_icon_start_margin_expanded">4dp</dimen>
<dimen name="work_fab_text_start_margin">8dp</dimen>
<dimen name="work_fab_text_end_margin">10dp</dimen>
<dimen name="work_card_padding_horizontal">10dp</dimen>
<dimen name="work_fab_width">214dp</dimen>
<dimen name="work_card_button_height">52dp</dimen>
<dimen name="work_fab_margin">16dp</dimen>
<dimen name="work_fab_margin_bottom">20dp</dimen>
<dimen name="work_mode_fab_background_start_padding">16dp</dimen>
<dimen name="work_mode_fab_background_end_padding">4dp</dimen>
<dimen name="work_mode_fab_background_horizontal_padding">16dp</dimen>
<dimen name="work_profile_footer_padding">20dp</dimen>
<dimen name="work_edu_card_margin">16dp</dimen>
<dimen name="work_edu_card_radius">16dp</dimen>
@@ -15,10 +15,18 @@
*/
package com.android.launcher3.allapps;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
@@ -26,10 +34,12 @@ import androidx.annotation.NonNull;
import androidx.core.graphics.Insets;
import androidx.core.view.WindowInsetsCompat;
import com.android.app.animation.Interpolators;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimatedPropertySetter;
import com.android.launcher3.anim.KeyboardInsetAnimationCallback;
import com.android.launcher3.model.StringCache;
import com.android.launcher3.views.ActivityContext;
@@ -39,9 +49,14 @@ import com.android.launcher3.views.ActivityContext;
public class WorkModeSwitch extends LinearLayout implements Insettable,
KeyboardInsetAnimationCallback.KeyboardInsetListener {
private static final int TEXT_EXPAND_OPACITY_DURATION = 300;
private static final int TEXT_COLLAPSE_OPACITY_DURATION = 50;
private static final int EXPAND_COLLAPSE_DURATION = 300;
private static final int TEXT_ALPHA_EXPAND_DELAY = 80;
private static final int TEXT_ALPHA_COLLAPSE_DELAY = 0;
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 FLAG_IS_EXPAND = 1 << 3;
private static final int SCROLL_THRESHOLD_DP = 10;
private final Rect mInsets = new Rect();
@@ -49,11 +64,15 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
private int mFlags;
private final ActivityContext mActivityContext;
private final Context mContext;
private final int mTextMarginStart;
private final int mTextMarginEnd;
private final int mIconMarginStart;
// Threshold when user scrolls up/down to determine when should button extend/collapse
private final int mScrollThreshold;
private TextView mTextView;
private ImageView mIcon;
private ValueAnimator mPauseFABAnim;
public WorkModeSwitch(@NonNull Context context) {
this(context, null, 0);
@@ -68,6 +87,12 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
mContext = context;
mScrollThreshold = Utilities.dpToPx(SCROLL_THRESHOLD_DP);
mActivityContext = ActivityContext.lookupContext(getContext());
mTextMarginStart = mContext.getResources().getDimensionPixelSize(
R.dimen.work_fab_text_start_margin);
mTextMarginEnd = mContext.getResources().getDimensionPixelSize(
R.dimen.work_fab_text_end_margin);
mIconMarginStart = mContext.getResources().getDimensionPixelSize(
R.dimen.work_fab_icon_start_margin_expanded);
}
@Override
@@ -75,11 +100,13 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
super.onFinishInflate();
mTextView = findViewById(R.id.pause_text);
mIcon = findViewById(R.id.work_icon);
setSelected(true);
KeyboardInsetAnimationCallback keyboardInsetAnimationCallback =
new KeyboardInsetAnimationCallback(this);
setWindowInsetsAnimationCallback(keyboardInsetAnimationCallback);
// Expand is the default state upon initialization.
addFlag(FLAG_IS_EXPAND);
setInsets(mActivityContext.getDeviceProfile().getInsets());
updateStringFromCache();
}
@@ -114,18 +141,18 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
@Override
public boolean isEnabled() {
return super.isEnabled() && getVisibility() == VISIBLE && mFlags == 0;
return super.isEnabled() && getVisibility() == VISIBLE;
}
public void animateVisibility(boolean visible) {
clearAnimation();
if (visible) {
setFlag(FLAG_FADE_ONGOING);
addFlag(FLAG_FADE_ONGOING);
setVisibility(VISIBLE);
extend();
animate().alpha(1).withEndAction(() -> removeFlag(FLAG_FADE_ONGOING)).start();
} else if (getVisibility() != GONE) {
setFlag(FLAG_FADE_ONGOING);
addFlag(FLAG_FADE_ONGOING);
animate().alpha(0).withEndAction(() -> {
removeFlag(FLAG_FADE_ONGOING);
setVisibility(GONE);
@@ -156,6 +183,79 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
super.setTranslationY(Math.min(translationY, -mInsets.bottom));
}
private void animatePillTransition(boolean isExpanding) {
if (!shouldAnimate(isExpanding)) {
return;
}
AnimatorSet animatorSet = new AnimatedPropertySetter().buildAnim();
mTextView.measure(0,0);
int currentWidth = mTextView.getWidth();
int fullWidth = mTextView.getMeasuredWidth();
float from = isExpanding ? 0 : currentWidth;
float to = isExpanding ? fullWidth : 0;
mPauseFABAnim = ObjectAnimator.ofFloat(from, to);
mPauseFABAnim.setDuration(EXPAND_COLLAPSE_DURATION);
mPauseFABAnim.setInterpolator(Interpolators.STANDARD);
mPauseFABAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float translation = (float) valueAnimator.getAnimatedValue();
float translationFraction = translation / fullWidth;
ViewGroup.MarginLayoutParams textViewLayoutParams =
(ViewGroup.MarginLayoutParams) mTextView.getLayoutParams();
textViewLayoutParams.width = (int) translation;
textViewLayoutParams.setMarginStart((int) (mTextMarginStart * translationFraction));
textViewLayoutParams.setMarginEnd((int) (mTextMarginEnd * translationFraction));
mTextView.setLayoutParams(textViewLayoutParams);
ViewGroup.MarginLayoutParams iconLayoutParams =
(ViewGroup.MarginLayoutParams) mIcon.getLayoutParams();
iconLayoutParams.setMarginStart((int) (mIconMarginStart * translationFraction));
mIcon.setLayoutParams(iconLayoutParams);
}
});
mPauseFABAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animator) {
if (isExpanding) {
addFlag(FLAG_IS_EXPAND);
} else {
mTextView.setVisibility(GONE);
removeFlag(FLAG_IS_EXPAND);
}
mTextView.setHorizontallyScrolling(false);
mTextView.setEllipsize(TextUtils.TruncateAt.END);
}
@Override
public void onAnimationStart(Animator animator) {
mTextView.setHorizontallyScrolling(true);
mTextView.setVisibility(VISIBLE);
mTextView.setEllipsize(null);
}
});
animatorSet.playTogether(mPauseFABAnim, updatePauseTextAlpha(isExpanding));
animatorSet.start();
}
private ValueAnimator updatePauseTextAlpha(boolean expand) {
float from = expand ? 0 : 1;
float to = expand ? 1 : 0;
ValueAnimator alphaAnim = ObjectAnimator.ofFloat(from, to);
alphaAnim.setDuration(expand ? TEXT_EXPAND_OPACITY_DURATION
: TEXT_COLLAPSE_OPACITY_DURATION);
alphaAnim.setStartDelay(expand ? TEXT_ALPHA_EXPAND_DELAY : TEXT_ALPHA_COLLAPSE_DELAY);
alphaAnim.setInterpolator(Interpolators.LINEAR);
alphaAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
mTextView.setAlpha((float) valueAnimator.getAnimatedValue());
}
});
return alphaAnim;
}
private void setInsets(Rect rect, Insets insets) {
rect.set(insets.left, insets.top, insets.right, insets.bottom);
}
@@ -166,7 +266,7 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
@Override
public void onTranslationStart() {
setFlag(FLAG_TRANSLATION_ONGOING);
addFlag(FLAG_TRANSLATION_ONGOING);
}
@Override
@@ -174,7 +274,7 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
removeFlag(FLAG_TRANSLATION_ONGOING);
}
private void setFlag(int flag) {
private void addFlag(int flag) {
mFlags |= flag;
}
@@ -182,12 +282,25 @@ public class WorkModeSwitch extends LinearLayout implements Insettable,
mFlags &= ~flag;
}
private boolean containsFlag(int flag) {
return (mFlags & flag) == flag;
}
public void extend() {
mTextView.setVisibility(VISIBLE);
animatePillTransition(true);
}
public void shrink(){
mTextView.setVisibility(GONE);
animatePillTransition(false);
}
/**
* Determines if the button should animate based on current state. It should animate the button
* only if it is not in the same state it is animating to.
*/
private boolean shouldAnimate(boolean expanding) {
return expanding != containsFlag(FLAG_IS_EXPAND)
&& (mPauseFABAnim == null || !mPauseFABAnim.isRunning());
}
public int getScrollThreshold() {