From 8a35c76427c8cc1619addaba91d47c4976b9eae0 Mon Sep 17 00:00:00 2001 From: Schneider Victor-tulias Date: Thu, 3 Sep 2020 14:30:10 -0700 Subject: [PATCH] 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 --- src/com/android/launcher3/Launcher.java | 5 ++ src/com/android/launcher3/folder/Folder.java | 95 ++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index cacd3fbe7f..2e36bc01dd 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -88,6 +88,7 @@ import android.view.Menu; 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 @@ public class Launcher extends StatefulActivity implements Launche 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 f1606ea747..c841b7b0f3 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.annotation.SuppressLint; 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.KeyEvent; 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 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo 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 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo 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 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo 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 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; + } + + } }