Revert "Removing insets controller animation as part of all-apps..."

Revert "Moving insets animation to StateHandler so that it can b..."

Revert submission 13810332-insetcontroller

Reason for revert: QsbLayout#getEditText() return object is changed, but extended class HotseatQsbWidget wasn't updated.

https://android-build.googleplex.com/builds/submitted/7197042/aosp_crosshatch-userdebug/latest/view/logs/build_error.log

Reverted Changes:
If6a088d14:Removing insets controller animation as part of al...
I296415604:Moving insets animation to StateHandler so that it...

Change-Id: I4eb33772acd887d6e1d92a9ecde41cf1e0687896
This commit is contained in:
Pasty Chang
2021-03-10 06:58:51 +00:00
parent 0724113b3d
commit 13358f65ab
10 changed files with 399 additions and 31 deletions
@@ -63,7 +63,6 @@ import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.ActivityOptionsCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.util.List;
import java.util.stream.Stream;
/**
@@ -245,12 +244,15 @@ public abstract class BaseQuickstepLauncher extends Launcher
}
@Override
protected void collectStateHandlers(List<StateHandler> out) {
super.collectStateHandlers(out);
out.add(getDepthController());
out.add(new RecentsViewStateController(this));
out.add(new BackButtonAlphaHandler(this));
out.add(getTaskbarStateHandler());
protected StateHandler<LauncherState>[] createStateHandlers() {
return new StateHandler[] {
getAllAppsController(),
getWorkspace(),
getDepthController(),
new RecentsViewStateController(this),
new BackButtonAlphaHandler(this),
getTaskbarStateHandler(),
};
}
public DepthController getDepthController() {
@@ -71,7 +71,6 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.List;
/**
* A recents activity that shows the recently launched tasks as swipable task cards.
@@ -318,8 +317,8 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
}
@Override
protected void collectStateHandlers(List<StateHandler> out) {
out.add(new FallbackRecentsStateController(this));
protected StateHandler<RecentsState>[] createStateHandlers() {
return new StateHandler[] { new FallbackRecentsStateController(this) };
}
@Override
+2 -4
View File
@@ -2761,10 +2761,8 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
return super.onKeyUp(keyCode, event);
}
@Override
protected void collectStateHandlers(List<StateHandler> out) {
out.add(getAllAppsController());
out.add(getWorkspace());
protected StateHandler<LauncherState>[] createStateHandlers() {
return new StateHandler[] { getAllAppsController(), getWorkspace() };
}
public TouchController[] createTouchControllers() {
@@ -0,0 +1,315 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.allapps;
import android.annotation.TargetApi;
import android.graphics.Insets;
import android.os.Build;
import android.util.Log;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;
import android.view.animation.Interpolator;
import android.view.animation.LinearInterpolator;
import androidx.annotation.Nullable;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.UiThreadHelper;
/**
* Handles IME over all apps to be synchronously transitioning along with the passed in
* root inset.
*/
public class AllAppsInsetTransitionController {
private static final boolean DEBUG = true;
private static final String TAG = "AllAppsInsetTransitionController";
private static final Interpolator LINEAR = new LinearInterpolator();
private WindowInsetsAnimationController mAnimationController;
private WindowInsetsAnimationControlListener mCurrentRequest;
private Runnable mSearchEduRunnable;
private float mAllAppsHeight;
private int mDownInsetBottom;
private boolean mShownAtDown;
private int mHiddenInsetBottom;
private int mShownInsetBottom;
private float mDown, mCurrent;
private View mApps;
/**
*
*/
public boolean showSearchEduIfNecessary() {
if (mSearchEduRunnable == null) {
return false;
}
mSearchEduRunnable.run();
return true;
}
public void setSearchEduRunnable(Runnable eduRunnable) {
mSearchEduRunnable = eduRunnable;
}
// Only purpose of these states is to keep track of fast fling transition
enum State {
RESET, DRAG_START_BOTTOM, DRAG_START_BOTTOM_IME_CANCELLED,
FLING_END_TOP, FLING_END_TOP_IME_CANCELLED,
DRAG_START_TOP, FLING_END_BOTTOM
}
private State mState;
public AllAppsInsetTransitionController(float allAppsHeight, View appsView) {
mAllAppsHeight = allAppsHeight;
mApps = appsView;
}
public void show() {
mApps.getWindowInsetsController().show(WindowInsets.Type.ime());
}
public void hide() {
if (!Utilities.ATLEAST_R) return;
WindowInsets insets = mApps.getRootWindowInsets();
if (insets == null) return;
boolean imeVisible = insets.isVisible(WindowInsets.Type.ime());
if (DEBUG) {
Log.d(TAG, "\nhide imeVisible=" + imeVisible);
}
if (insets.isVisible(WindowInsets.Type.ime())) {
mApps.getWindowInsetsController().hide(WindowInsets.Type.ime());
}
}
/**
* Initializes member variables and requests for the {@link WindowInsetsAnimationController}
* object.
*
* @param progress value between 0..1
*/
@TargetApi(Build.VERSION_CODES.R)
public void onDragStart(float progress) {
if (!Utilities.ATLEAST_R) return;
// Until getRootWindowInsets().isVisible(...) method returns correct value,
// only support InsetController based IME transition during swipe up and
// NOT swipe down
if (Float.compare(progress, 0f) == 0) return;
setState(true, false, progress);
mDown = progress * mAllAppsHeight;
// Below two values are sometimes incorrect. Possibly a platform bug
// mDownInsetBottom = mApps.getRootWindowInsets().getInsets(WindowInsets.Type.ime()).bottom;
// mShownAtDown = mApps.getRootWindowInsets().isVisible(WindowInsets.Type.ime());
if (DEBUG) {
Log.d(TAG, "\nonDragStart progress=" + progress
+ " mDownInsets=" + mDownInsetBottom
+ " mShownAtDown=" + mShownAtDown);
}
mApps.getWindowInsetsController().controlWindowInsetsAnimation(
WindowInsets.Type.ime(), -1 /* no predetermined duration */, LINEAR, null,
mCurrentRequest = new WindowInsetsAnimationControlListener() {
@Override
public void onReady(WindowInsetsAnimationController controller, int types) {
if (DEBUG) {
Log.d(TAG, "Listener.onReady " + (mCurrentRequest == this));
}
if (controller != null) {
if (mCurrentRequest == this && !handleFinishOnFling(controller)) {
mAnimationController = controller;
} else {
controller.finish(false /* just don't show */);
}
}
}
@Override
public void onFinished(WindowInsetsAnimationController controller) {
// when screen lock happens, then this method get called
if (DEBUG) {
Log.d(TAG, "Listener.onFinished ctrl=" + controller
+ " mAnimationController=" + mAnimationController);
}
if (mAnimationController != null) {
mAnimationController.finish(true);
mAnimationController = null;
}
}
@Override
public void onCancelled(@Nullable WindowInsetsAnimationController controller) {
if (DEBUG) {
// Keep the verbose logging to chase down IME not showing up issue.
// b/178904132
Log.e(TAG, "Listener.onCancelled ctrl=" + controller
+ " mAnimationController=" + mAnimationController,
new Exception());
}
if (mState == State.DRAG_START_BOTTOM) {
mState = State.DRAG_START_BOTTOM_IME_CANCELLED;
}
mAnimationController = null;
if (controller != null) {
controller.finish(true);
}
}
});
}
/**
* If IME bounds after touch sequence finishes, call finish.
*/
private boolean handleFinishOnFling(WindowInsetsAnimationController controller) {
if (!Utilities.ATLEAST_R) return false;
if (mState == State.FLING_END_TOP) {
controller.finish(true);
return true;
} else if (mState == State.FLING_END_BOTTOM) {
controller.finish(false);
return true;
}
return false;
}
/**
* Handles the translation using the progress.
*
* @param progress value between 0..1
*/
@TargetApi(Build.VERSION_CODES.R)
public void setProgress(float progress) {
if (!Utilities.ATLEAST_R) return;
// progress that equals to 0 or 1 is error prone. Do not use them.
// Instead use onDragStart and onAnimationEnd
if (mAnimationController == null || progress <= 0f || progress >= 1f) return;
mCurrent = progress * mAllAppsHeight;
mHiddenInsetBottom = mAnimationController.getHiddenStateInsets().bottom; // 0
mShownInsetBottom = mAnimationController.getShownStateInsets().bottom; // 1155
int shift = mShownAtDown ? 0 : (int) (mAllAppsHeight - mShownInsetBottom);
int inset = (int) (mDownInsetBottom + (mDown - mCurrent) - shift);
final int start = mShownAtDown ? mShownInsetBottom : mHiddenInsetBottom;
final int end = mShownAtDown ? mHiddenInsetBottom : mShownInsetBottom;
inset = Math.max(inset, mHiddenInsetBottom);
inset = Math.min(inset, mShownInsetBottom);
if (DEBUG && false) {
Log.d(TAG, "updateInset mCurrent=" + mCurrent + " mDown="
+ mDown + " hidden=" + mHiddenInsetBottom
+ " shown=" + mShownInsetBottom
+ " mDownInsets.bottom=" + mDownInsetBottom + " inset=" + inset
+ " shift= " + shift);
}
mAnimationController.setInsetsAndAlpha(
Insets.of(0, 0, 0, inset),
1f, (inset - start) / (float) (end - start));
}
/**
* Report to the animation controller that we no longer plan to translate anymore.
*
* @param progress value between 0..1
*/
@TargetApi(Build.VERSION_CODES.R)
public void onAnimationEnd(float progress) {
if (DEBUG) {
Log.d(TAG, "onAnimationEnd progress=" + progress
+ " mAnimationController=" + mAnimationController);
}
if (mState == null) {
// only called when launcher restarting.
UiThreadHelper.hideKeyboardAsync(mApps.getContext(), mApps.getWindowToken());
}
setState(false, true, progress);
if (mAnimationController == null) {
if (mState == State.FLING_END_TOP_IME_CANCELLED) {
mApps.getWindowInsetsController().show(WindowInsets.Type.ime());
}
return;
}
/* handle finish */
if (mState == State.FLING_END_TOP) {
mAnimationController.finish(true /* show */);
} else {
if (Float.compare(progress, 1f) == 0 /* bottom */) {
mAnimationController.finish(false /* gone */);
} else {
mAnimationController.finish(mShownAtDown);
}
}
/* handle finish */
if (DEBUG) {
Log.d(TAG, "endTranslation progress=" + progress
+ " mAnimationController=" + mAnimationController);
}
mAnimationController = null;
mCurrentRequest = null;
setState(false, false, progress);
}
private void setState(boolean start, boolean end, float progress) {
State state = State.RESET;
if (start && end) {
throw new IllegalStateException("drag start and end cannot happen in same call");
}
if (start) {
if (Float.compare(progress, 1f) == 0) {
state = State.DRAG_START_BOTTOM;
} else if (Float.compare(progress, 0f) == 0) {
state = State.DRAG_START_TOP;
}
} else if (end) {
if (Float.compare(progress, 1f) == 0 && mState == State.DRAG_START_TOP) {
state = State.FLING_END_BOTTOM;
} else if (Float.compare(progress, 0f) == 0) {
if (mState == State.DRAG_START_BOTTOM) {
state = State.FLING_END_TOP;
} else if (mState == State.DRAG_START_BOTTOM_IME_CANCELLED) {
state = State.FLING_END_TOP_IME_CANCELLED;
}
}
}
if (DEBUG) {
Log.d(TAG, "setState " + mState + " -> " + state);
}
mState = state;
}
}
@@ -33,15 +33,18 @@ import static com.android.launcher3.util.SystemUiController.UI_STATE_ALLAPPS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ObjectAnimator;
import android.content.SharedPreferences;
import android.util.FloatProperty;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.EditText;
import androidx.core.os.BuildCompat;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
@@ -60,8 +63,8 @@ import com.android.launcher3.views.ScrimView;
* If release velocity < THRES1, snap according to either top or bottom depending on whether it's
* closer to top or closer to the page indicator.
*/
public class AllAppsTransitionController
implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
public class AllAppsTransitionController implements StateHandler<LauncherState>,
OnDeviceProfileChangeListener, SharedPreferences.OnSharedPreferenceChangeListener {
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
@@ -78,6 +81,7 @@ public class AllAppsTransitionController
};
private static final int APPS_VIEW_ALPHA_CHANNEL_INDEX = 0;
private static final String PREF_KEY_SHOW_SEARCH_IME = "pref_search_show_ime";
private AllAppsContainerView mAppsView;
private ScrimView mScrimView;
@@ -95,6 +99,8 @@ public class AllAppsTransitionController
private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent
private float mScrollRangeDelta = 0;
private AllAppsInsetTransitionController mInsetController;
private boolean mSearchImeEnabled;
public AllAppsTransitionController(Launcher l) {
mLauncher = l;
@@ -103,12 +109,19 @@ public class AllAppsTransitionController
mIsVerticalLayout = mLauncher.getDeviceProfile().isVerticalBarLayout();
mLauncher.addOnDeviceProfileChangeListener(this);
onSharedPreferenceChanged(mLauncher.getSharedPrefs(), PREF_KEY_SHOW_SEARCH_IME);
mLauncher.getSharedPrefs().registerOnSharedPreferenceChangeListener(this);
}
public float getShiftRange() {
return mShiftRange;
}
public AllAppsInsetTransitionController getInsetController() {
return mInsetController;
}
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
mIsVerticalLayout = dp.isVerticalBarLayout();
@@ -133,7 +146,14 @@ public class AllAppsTransitionController
mProgress = progress;
mScrimView.setProgress(progress);
mAppsView.setTranslationY(progress * mShiftRange);
float shiftCurrent = progress * mShiftRange;
mAppsView.setTranslationY(shiftCurrent);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mSearchImeEnabled) {
if (mInsetController == null) {
setupInsetTransitionController();
}
mInsetController.setProgress(progress);
}
}
public float getProgress() {
@@ -222,13 +242,18 @@ public class AllAppsTransitionController
public void setupViews(AllAppsContainerView appsView, ScrimView scrimView) {
mAppsView = appsView;
mScrimView = scrimView;
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && Utilities.ATLEAST_R) {
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && BuildCompat.isAtLeastR()) {
setupInsetTransitionController();
}
}
private void setupInsetTransitionController() {
mInsetController = new AllAppsInsetTransitionController(mShiftRange, mAppsView);
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
/**
* Updates the total scroll range but does not update the UI.
*/
@@ -249,5 +274,23 @@ public class AllAppsTransitionController
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.reset(false /* animate */);
}
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mSearchImeEnabled
&& BuildCompat.isAtLeastR()) {
mInsetController.onAnimationEnd(mProgress);
if (Float.compare(mProgress, 0f) == 0) {
EditText editText = mAppsView.getSearchUiManager().getEditText();
if (editText != null && !mInsetController.showSearchEduIfNecessary()) {
editText.requestFocus();
}
}
// TODO: should make the controller hide synchronously
}
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String s) {
if (s.equals(PREF_KEY_SHOW_SEARCH_IME)) {
mSearchImeEnabled = sharedPreferences.getBoolean(s, true);
}
}
}
@@ -20,10 +20,10 @@ import static com.android.launcher3.LauncherState.ALL_APPS_HEADER;
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.animation.Interpolator;
import android.widget.EditText;
import androidx.annotation.Nullable;
import com.android.launcher3.ExtendedEditText;
import com.android.launcher3.anim.PropertySetter;
/**
@@ -75,7 +75,7 @@ public interface SearchUiManager {
* @return the edit text object
*/
@Nullable
ExtendedEditText getEditText();
EditText getEditText();
/**
* sets highlight result's title
@@ -32,6 +32,7 @@ import android.view.KeyEvent;
import android.view.View;
import android.view.ViewGroup.MarginLayoutParams;
import android.view.animation.Interpolator;
import android.widget.EditText;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -229,7 +230,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText
}
@Override
public ExtendedEditText getEditText() {
public EditText getEditText() {
return this;
}
}
@@ -26,12 +26,14 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.testing.TestProtocol;
import java.io.PrintWriter;
import java.util.ArrayList;
@@ -88,9 +90,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
public StateHandler[] getStateHandlers() {
if (mStateHandlers == null) {
ArrayList<StateHandler> handlers = new ArrayList<>();
mActivity.collectStateHandlers(handlers);
mStateHandlers = handlers.toArray(new StateHandler[handlers.size()]);
mStateHandlers = mActivity.createStateHandlers();
}
return mStateHandlers;
}
@@ -30,8 +30,6 @@ import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.views.BaseDragLayer;
import java.util.List;
/**
* Abstract activity with state management
* @param <STATE_TYPE> Type of state object
@@ -48,7 +46,7 @@ public abstract class StatefulActivity<STATE_TYPE extends BaseState<STATE_TYPE>>
/**
* Create handlers to control the property changes for this activity
*/
protected abstract void collectStateHandlers(List<StateHandler> out);
protected abstract StateHandler<STATE_TYPE>[] createStateHandlers();
/**
* Returns true if the activity is in the provided state
@@ -38,19 +38,24 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.os.SystemClock;
import android.util.Log;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import androidx.core.os.BuildCompat;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.TouchController;
@@ -260,6 +265,13 @@ public abstract class AbstractStateChangeTouchController
}
mCanBlockFling = mFromState == NORMAL;
mFlingBlockCheck.unblockFling();
// Must be called after all the animation controllers have been paused
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()
&& BuildCompat.isAtLeastR()
&& (mToState == ALL_APPS || mToState == NORMAL)) {
mLauncher.getAllAppsController().getInsetController().onDragStart(
mFromState == NORMAL ? 1f : 0f);
}
}
@Override