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; + } + + } }