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
This commit is contained in:
Schneider Victor-tulias
2020-09-03 14:30:10 -07:00
parent 1aee9da5b8
commit 8a35c76427
2 changed files with 100 additions and 0 deletions
+5
View File
@@ -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<LauncherState> 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() {
@@ -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<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;
}
}
}