Add folder UI animation.
Test: manual
Fixing b/144948355. The entire launcher was panning up when the user
would try to edit a folder name if that folder's name field would have
otherwise been obscured by the keyboard. This had the effect of
obscuring the smartspace. Added an animation to the folder UI to bring
it above the keyboard during text editing.
Change-Id: I0f95aae27fc7426f1025135ea6d4fa142a21cf43
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index cacd3fb..2e36bc0 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -88,6 +88,7 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
+import android.view.WindowManager;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.OvershootInterpolator;
import android.widget.Toast;
@@ -466,6 +467,10 @@
mUserChangedCallbackCloseable = UserCache.INSTANCE.get(this).addUserChangeListener(
() -> getStateManager().goToState(NORMAL));
+
+ if (Utilities.ATLEAST_R) {
+ getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
+ }
}
protected LauncherOverlayManager getDefaultOverlay() {
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index f1606ea..c841b7b 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -17,6 +17,7 @@
package com.android.launcher3.folder;
import static android.text.TextUtils.isEmpty;
+import static android.view.WindowInsetsAnimation.Callback.DISPATCH_MODE_STOP;
import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY;
import static com.android.launcher3.LauncherState.NORMAL;
@@ -34,8 +35,10 @@
import android.appwidget.AppWidgetHostView;
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Insets;
import android.graphics.Path;
import android.graphics.Rect;
+import android.os.Build;
import android.text.InputType;
import android.text.Selection;
import android.text.TextUtils;
@@ -47,11 +50,16 @@
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
+import android.view.WindowInsets;
+import android.view.WindowInsetsAnimation;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
+import androidx.annotation.NonNull;
+import androidx.annotation.RequiresApi;
+
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.Alarm;
import com.android.launcher3.BubbleTextView;
@@ -252,6 +260,13 @@
int measureSpec = MeasureSpec.UNSPECIFIED;
mFooter.measure(measureSpec, measureSpec);
mFooterHeight = mFooter.getMeasuredHeight();
+
+ if (Utilities.ATLEAST_R) {
+ WindowInsetsAnimation.Callback cb = new FolderWindowInsetsAnimationCallback(
+ DISPATCH_MODE_STOP, this);
+
+ setWindowInsetsAnimationCallback(cb);
+ }
}
public boolean onLongClick(View v) {
@@ -373,6 +388,26 @@
return false;
}
+ @Override
+ public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
+ if (Utilities.ATLEAST_R) {
+ this.setTranslationY(0);
+
+ if (windowInsets.isVisible(WindowInsets.Type.ime())) {
+ Insets keyboardInsets = windowInsets.getInsets(WindowInsets.Type.ime());
+ int folderHeightFromBottom = getHeightFromBottom();
+
+ if (keyboardInsets.bottom > folderHeightFromBottom) {
+ // Translate this folder above the keyboard, then add the folder name's padding
+ this.setTranslationY(folderHeightFromBottom - keyboardInsets.bottom
+ - mFolderName.getPaddingBottom());
+ }
+ }
+ }
+
+ return windowInsets;
+ }
+
public FolderIcon getFolderIcon() {
return mFolderIcon;
}
@@ -1646,4 +1681,64 @@
mLauncher.getUserEventDispatcher()
.logLauncherEvent(mInfo.getFolderLabelStateLauncherEvent(fromState, toState));
}
+
+ /** Returns the height of the current folder's bottom edge from the bottom of the screen. */
+ private int getHeightFromBottom() {
+ DragLayer.LayoutParams layoutParams = (DragLayer.LayoutParams) getLayoutParams();
+ int folderBottomPx = layoutParams.y + layoutParams.height;
+ int windowBottomPx = mLauncher.getDeviceProfile().heightPx;
+
+ return windowBottomPx - folderBottomPx;
+ }
+
+ /** Callback that animates a folder sliding up above the ime. */
+ @RequiresApi(api = Build.VERSION_CODES.R)
+ private static class FolderWindowInsetsAnimationCallback
+ extends WindowInsetsAnimation.Callback {
+
+ private final Folder mFolder;
+ float mFolderTranslationStart;
+ float mFolderTranslationEnd;
+
+ FolderWindowInsetsAnimationCallback(int dispatchMode, Folder folder) {
+ super(dispatchMode);
+
+ mFolder = folder;
+ }
+
+ @Override
+ public void onPrepare(@NonNull WindowInsetsAnimation animation) {
+ mFolderTranslationStart = mFolder.getTranslationY();
+ }
+
+ @NonNull
+ @Override
+ public WindowInsetsAnimation.Bounds onStart(
+ @NonNull WindowInsetsAnimation animation,
+ @NonNull WindowInsetsAnimation.Bounds bounds) {
+ mFolderTranslationEnd = mFolder.getTranslationY();
+
+ mFolder.setTranslationY(mFolderTranslationStart);
+
+ return super.onStart(animation, bounds);
+ }
+
+ @NonNull
+ @Override
+ public WindowInsets onProgress(@NonNull WindowInsets windowInsets,
+ @NonNull List<WindowInsetsAnimation> list) {
+ if (list.size() == 0) {
+ mFolder.setTranslationY(0);
+
+ return windowInsets;
+ }
+ float progress = list.get(0).getInterpolatedFraction();
+
+ mFolder.setTranslationY(
+ Utilities.mapRange(progress, mFolderTranslationStart, mFolderTranslationEnd));
+
+ return windowInsets;
+ }
+
+ }
}