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:
committed by
Android (Google) Code Review
commit
0b2acd6516
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user