Merge "Add InsetTransitionController to device search" into ub-launcher3-master

This commit is contained in:
Hyunyoung Song
2020-07-24 22:04:19 +00:00
committed by Android (Google) Code Review
5 changed files with 239 additions and 71 deletions
-1
View File
@@ -1550,7 +1550,6 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
mOverlayManager.onActivityDestroyed(this);
mAppTransitionManager.unregisterRemoteAnimations();
mUserChangedCallbackCloseable.close();
mAllAppsController.onActivityDestroyed();
}
public LauncherAccessibilityDelegate getAccessibilityDelegate() {
@@ -0,0 +1,186 @@
/*
* 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.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 androidx.annotation.RequiresApi;
import androidx.core.os.BuildCompat;
/**
* Handles IME over all apps to be synchronously transitioning along with the passed in
* root inset.
*/
public class AllAppsInsetTransitionController {
private static final boolean DEBUG = false;
private static final String TAG = "AllAppsInsetTransitionController";
private static final Interpolator LINEAR = new LinearInterpolator();
private WindowInsetsAnimationController mAnimationController;
private WindowInsetsAnimationControlListener mCurrentRequest;
private float mAllAppsHeight;
private int mDownInsetBottom;
private boolean mShownAtDown;
private int mHiddenInsetBottom;
private int mShownInsetBottom;
private float mDown, mCurrent;
private View mApps;
public AllAppsInsetTransitionController(float allAppsHeight, View appsView) {
mAllAppsHeight = allAppsHeight;
mApps = appsView;
}
/**
* Initializes member variables and requests for the {@link WindowInsetsAnimationController}
* object.
*
* @param progress value between 0..1
*/
@RequiresApi(api = Build.VERSION_CODES.R)
public void onDragStart(float progress) {
if (!BuildCompat.isAtLeastR()) return;
onAnimationEnd(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());
// override this value based on what it should actually be.
mShownAtDown = Float.compare(progress, 1f) == 0 ? false : true;
mDownInsetBottom = mShownAtDown ? mShownInsetBottom : mHiddenInsetBottom;
if (DEBUG) {
Log.d(TAG, "\nonDragStart 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 (mCurrentRequest == this) {
mAnimationController = controller;
} else {
controller.finish(mShownAtDown);
}
}
@Override
public void onFinished(WindowInsetsAnimationController controller) {
// when screen lock happens, then this method get called
mAnimationController.finish(false);
mAnimationController = null;
if (DEBUG) {
Log.d(TAG, "Listener.onFinished ctrl=" + controller);
}
}
@Override
public void onCancelled(@Nullable WindowInsetsAnimationController controller) {
mAnimationController = null;
if (controller != null) {
controller.finish(mShownAtDown);
}
if (DEBUG) {
Log.d(TAG, "Listener.onCancelled ctrl=" + controller);
}
}
});
}
/**
* Handles the translation using the progress.
*
* @param progress value between 0..1
*/
@RequiresApi(api = 30)
public void setProgress(float progress) {
if (!BuildCompat.isAtLeastR()) 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);
if (DEBUG) {
Log.d(TAG, "updateInset mCurrent=" + mCurrent + " mDown="
+ mDown + " hidden=" + mHiddenInsetBottom
+ " shown=" + mShownInsetBottom
+ " mDownInsets.bottom=" + mDownInsetBottom + " inset:" + inset
+ " shift: " + shift);
}
final int start = mShownAtDown ? mShownInsetBottom : mHiddenInsetBottom;
final int end = mShownAtDown ? mHiddenInsetBottom : mShownInsetBottom;
inset = Math.max(inset, mHiddenInsetBottom);
inset = Math.min(inset, mShownInsetBottom);
Log.d(TAG, "updateInset inset:" + inset);
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
*/
@RequiresApi(api = 30)
public void onAnimationEnd(float progress) {
if (DEBUG) {
Log.d(TAG, "endTranslation progress=" + progress
+ " mAnimationController=" + mAnimationController);
}
if (mAnimationController == null) return;
if (Float.compare(progress, 1f) == 0 /* bottom */) {
mAnimationController.finish(false /* gone */);
}
if (Float.compare(progress, 0f) == 0 /* top */) {
mAnimationController.finish(true /* show */);
}
mAnimationController = null;
mCurrentRequest = null;
}
}
@@ -1,3 +1,18 @@
/*
* Copyright (C) 2015 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 static com.android.launcher3.LauncherState.ALL_APPS_CONTENT;
@@ -14,31 +29,28 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FA
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_HEADER_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
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.Context;
import android.util.FloatProperty;
import android.view.View;
import android.view.ViewGroup;
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.R;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.views.ScrimView;
import com.android.systemui.plugins.AllAppsSearchPlugin;
import com.android.systemui.plugins.PluginListener;
/**
* Handles AllApps view transition.
@@ -51,7 +63,7 @@ import com.android.systemui.plugins.PluginListener;
* closer to top or closer to the page indicator.
*/
public class AllAppsTransitionController implements StateHandler<LauncherState>,
OnDeviceProfileChangeListener, PluginListener<AllAppsSearchPlugin> {
OnDeviceProfileChangeListener {
public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
@@ -85,10 +97,7 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
private float mProgress; // [0, 1], mShiftRange * mProgress = shiftCurrent
private float mScrollRangeDelta = 0;
// plugin related variables
private AllAppsSearchPlugin mPlugin;
private View mPluginContent;
private AllAppsInsetTransitionController mInsetController;
public AllAppsTransitionController(Launcher l) {
mLauncher = l;
@@ -103,6 +112,10 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
return mShiftRange;
}
public AllAppsInsetTransitionController getInsetController() {
return mInsetController;
}
@Override
public void onDeviceProfileChanged(DeviceProfile dp) {
mIsVerticalLayout = dp.isVerticalBarLayout();
@@ -130,8 +143,8 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
float shiftCurrent = progress * mShiftRange;
mAppsView.setTranslationY(shiftCurrent);
if (mPlugin != null) {
mPlugin.setProgress(progress);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
mInsetController.setProgress(progress);
}
}
@@ -201,16 +214,12 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
Interpolator headerFade = config.getInterpolator(ANIM_ALL_APPS_HEADER_FADE, allAppsFade);
if (mPlugin == null) {
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra,
hasAllAppsContent, setter, headerFade, allAppsFade);
} else {
setter.setViewAlpha(mPluginContent, hasAllAppsContent ? 1 : 0, allAppsFade);
setter.setViewAlpha(mAppsView.getContentView(), 0, allAppsFade);
setter.setViewAlpha(mAppsView.getScrollBar(), 0, allAppsFade);
}
setter.setViewAlpha(mAppsView.getContentView(), hasAllAppsContent ? 1 : 0, allAppsFade);
setter.setViewAlpha(mAppsView.getScrollBar(), hasAllAppsContent ? 1 : 0, allAppsFade);
mAppsView.getFloatingHeaderView().setContentVisibility(hasHeaderExtra,
hasAllAppsContent, setter, headerFade, allAppsFade);
mAppsView.getSearchUiManager().setContentVisibility(visibleElements, setter, allAppsFade);
setter.setInt(mScrimView, ScrimView.DRAG_HANDLE_ALPHA,
@@ -228,8 +237,12 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
public void setupViews(AllAppsContainerView appsView, ScrimView scrimView) {
mAppsView = appsView;
mScrimView = scrimView;
PluginManagerWrapper.INSTANCE.get(mLauncher)
.addPluginListener(this, AllAppsSearchPlugin.class, false);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && BuildCompat.isAtLeastR()) {
mInsetController = new AllAppsInsetTransitionController(mShiftRange, mAppsView);
mLauncher.getSystemUiController().updateUiState(UI_STATE_ALLAPPS,
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
}
}
/**
@@ -252,47 +265,11 @@ public class AllAppsTransitionController implements StateHandler<LauncherState>,
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.reset(false /* animate */);
}
updatePluginAnimationEnd();
}
@Override
public void onPluginConnected(AllAppsSearchPlugin plugin, Context context) {
mPlugin = plugin;
mPluginContent = mLauncher.getLayoutInflater().inflate(
R.layout.all_apps_content_layout, mAppsView, false);
mAppsView.addView(mPluginContent);
mPluginContent.setAlpha(0f);
mPlugin.setup((ViewGroup) mPluginContent, mLauncher, mShiftRange);
}
@Override
public void onPluginDisconnected(AllAppsSearchPlugin plugin) {
mPlugin = null;
mAppsView.removeView(mPluginContent);
}
public void onActivityDestroyed() {
PluginManagerWrapper.INSTANCE.get(mLauncher).removePluginListener(this);
}
/** Used for the plugin to signal when drag starts happens
* @param toAllApps*/
public void onDragStart(boolean toAllApps) {
if (mPlugin == null) return;
if (toAllApps) {
EditText editText = mAppsView.getSearchUiManager().setTextSearchEnabled(true);
mPlugin.setEditText(editText);
}
mPlugin.onDragStart(toAllApps ? 1f : 0f);
}
private void updatePluginAnimationEnd() {
if (mPlugin == null) return;
mPlugin.onAnimationEnd(mProgress);
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.getSearchUiManager().setTextSearchEnabled(false);
mPlugin.setEditText(null);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && BuildCompat.isAtLeastR()) {
mInsetController.onAnimationEnd(mProgress);
if (Float.compare(mProgress, 1f) == 0) {
mAppsView.getSearchUiManager().setTextSearchEnabled(true).requestFocus();
}
}
}
}
@@ -37,6 +37,8 @@ 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;
@@ -44,6 +46,7 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
@@ -265,8 +268,10 @@ public abstract class AbstractStateChangeTouchController
mCanBlockFling = mFromState == NORMAL;
mFlingBlockCheck.unblockFling();
// Must be called after all the animation controllers have been paused
if (mToState == ALL_APPS || mToState == NORMAL) {
mLauncher.getAllAppsController().onDragStart(mToState == ALL_APPS);
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && BuildCompat.isAtLeastR()
&& (mToState == ALL_APPS || mToState == NORMAL)) {
mLauncher.getAllAppsController().getInsetController().onDragStart(
mToState == ALL_APPS ? 0 : 1);
}
}
@@ -33,6 +33,7 @@ public class SystemUiController {
public static final int UI_STATE_SCRIM_VIEW = 1;
public static final int UI_STATE_WIDGET_BOTTOM_SHEET = 2;
public static final int UI_STATE_OVERVIEW = 3;
public static final int UI_STATE_ALLAPPS = 4;
public static final int FLAG_LIGHT_NAV = 1 << 0;
public static final int FLAG_DARK_NAV = 1 << 1;
@@ -40,7 +41,7 @@ public class SystemUiController {
public static final int FLAG_DARK_STATUS = 1 << 3;
private final Window mWindow;
private final int[] mStates = new int[4];
private final int[] mStates = new int[5];
public SystemUiController(Window window) {
mWindow = window;