Snap for 8082780 from f2172eba8c to tm-release

Change-Id: I516d737b5d3b878c9bc3b500c69a4b3693e9a740
This commit is contained in:
Android Build Coastguard Worker
2022-01-15 04:09:44 +00:00
18 changed files with 276 additions and 76 deletions
@@ -36,6 +36,7 @@ import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_N
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_QUICK_SETTINGS_EXPANDED;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
import static com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo.TOUCHABLE_INSETS_REGION;
import android.animation.ArgbEvaluator;
import android.animation.ObjectAnimator;
@@ -55,9 +56,11 @@ import android.util.Property;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnAttachStateChangeListener;
import android.view.View.OnClickListener;
import android.view.View.OnHoverListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
@@ -68,10 +71,13 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AlphaUpdateListener;
import com.android.launcher3.taskbar.TaskbarNavButtonController.TaskbarButton;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.launcher3.util.TouchController;
import com.android.launcher3.views.BaseDragLayer;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.rotation.FloatingRotationButton;
import com.android.systemui.shared.rotation.RotationButton;
import com.android.systemui.shared.rotation.RotationButtonController;
import com.android.systemui.shared.system.ViewTreeObserverWrapper;
import java.util.ArrayList;
import java.util.function.IntPredicate;
@@ -98,6 +104,8 @@ public class NavbarButtonsViewController {
private static final int MASK_IME_SWITCHER_VISIBLE = FLAG_SWITCHER_SUPPORTED | FLAG_IME_VISIBLE;
private static final String NAV_BUTTONS_SEPARATE_WINDOW_TITLE = "Taskbar Nav Buttons";
private final ArrayList<StatePropertyHolder> mPropertyHolders = new ArrayList<>();
private final ArrayList<ImageView> mAllButtons = new ArrayList<>();
private int mState;
@@ -134,6 +142,12 @@ public class NavbarButtonsViewController {
private View mHomeButton;
private FloatingRotationButton mFloatingRotationButton;
// Variables for moving nav buttons to a separate window above IME
private boolean mAreNavButtonsInSeparateWindow = false;
private BaseDragLayer<TaskbarActivityContext> mSeparateWindowParent; // Initialized in init.
private final ViewTreeObserverWrapper.OnComputeInsetsListener mSeparateWindowInsetsComputer =
this::onComputeInsetsForSeparateWindow;
public NavbarButtonsViewController(TaskbarActivityContext context, FrameLayout navButtonsView) {
mContext = context;
mNavButtonsView = navButtonsView;
@@ -321,6 +335,21 @@ public class NavbarButtonsViewController {
R.id.notifications_button);
}
// Initialize things needed to move nav buttons to separate window.
mSeparateWindowParent = new BaseDragLayer<TaskbarActivityContext>(mContext, null, 0) {
@Override
public void recreateControllers() {
mControllers = new TouchController[0];
}
@Override
protected boolean canFindActiveController() {
// We don't have any controllers, but we don't want any floating views such as
// folder to intercept, either. This ensures nav buttons can always be pressed.
return false;
}
};
mSeparateWindowParent.recreateControllers();
}
private void initButtons(ViewGroup navContainer, ViewGroup endContainer,
@@ -456,7 +485,7 @@ public class NavbarButtonsViewController {
/**
* Adds the bounds corresponding to all visible buttons to provided region
*/
public void addVisibleButtonsRegion(TaskbarDragLayer parent, Region outRegion) {
public void addVisibleButtonsRegion(BaseDragLayer<?> parent, Region outRegion) {
int count = mAllButtons.size();
for (int i = 0; i < count; i++) {
View button = mAllButtons.get(i);
@@ -561,6 +590,59 @@ public class NavbarButtonsViewController {
if (mFloatingRotationButton != null) {
mFloatingRotationButton.hide();
}
moveNavButtonsBackToTaskbarWindow();
}
/**
* Moves mNavButtonsView from TaskbarDragLayer to a placeholder BaseDragLayer on a new window.
*/
public void moveNavButtonsToNewWindow() {
if (mAreNavButtonsInSeparateWindow) {
return;
}
mSeparateWindowParent.addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View view) {
ViewTreeObserverWrapper.addOnComputeInsetsListener(
mSeparateWindowParent.getViewTreeObserver(), mSeparateWindowInsetsComputer);
}
@Override
public void onViewDetachedFromWindow(View view) {
mSeparateWindowParent.removeOnAttachStateChangeListener(this);
ViewTreeObserverWrapper.removeOnComputeInsetsListener(
mSeparateWindowInsetsComputer);
}
});
mAreNavButtonsInSeparateWindow = true;
mContext.getDragLayer().removeView(mNavButtonsView);
mSeparateWindowParent.addView(mNavButtonsView);
WindowManager.LayoutParams windowLayoutParams = mContext.createDefaultWindowLayoutParams();
windowLayoutParams.setTitle(NAV_BUTTONS_SEPARATE_WINDOW_TITLE);
mContext.addWindowView(mSeparateWindowParent, windowLayoutParams);
}
/**
* Moves mNavButtonsView from its temporary window and reattaches it to TaskbarDragLayer.
*/
public void moveNavButtonsBackToTaskbarWindow() {
if (!mAreNavButtonsInSeparateWindow) {
return;
}
mAreNavButtonsInSeparateWindow = false;
mContext.removeWindowView(mSeparateWindowParent);
mSeparateWindowParent.removeView(mNavButtonsView);
mContext.getDragLayer().addView(mNavButtonsView);
}
private void onComputeInsetsForSeparateWindow(ViewTreeObserverWrapper.InsetsInfo insetsInfo) {
addVisibleButtonsRegion(mSeparateWindowParent, insetsInfo.touchableRegion);
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
}
private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
@@ -16,6 +16,7 @@
package com.android.launcher3.taskbar;
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL;
@@ -189,21 +190,7 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
public void init(TaskbarSharedState sharedState) {
mLastRequestedNonFullscreenHeight = getDefaultTaskbarWindowHeight();
mWindowLayoutParams = new WindowManager.LayoutParams(
MATCH_PARENT,
mLastRequestedNonFullscreenHeight,
TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
mWindowLayoutParams.setTitle(WINDOW_TITLE);
mWindowLayoutParams.packageName = getPackageName();
mWindowLayoutParams.gravity = Gravity.BOTTOM;
mWindowLayoutParams.setFitInsetsTypes(0);
mWindowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
mWindowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
mWindowLayoutParams.privateFlags =
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
mWindowLayoutParams = createDefaultWindowLayoutParams();
WindowManagerWrapper wmWrapper = WindowManagerWrapper.getInstance();
wmWrapper.setProvidesInsetsTypes(
@@ -224,6 +211,27 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
mWindowManager.addView(mDragLayer, mWindowLayoutParams);
}
/** Creates LayoutParams for adding a view directly to WindowManager as a new window */
public WindowManager.LayoutParams createDefaultWindowLayoutParams() {
WindowManager.LayoutParams windowLayoutParams = new WindowManager.LayoutParams(
MATCH_PARENT,
mLastRequestedNonFullscreenHeight,
TYPE_NAVIGATION_BAR_PANEL,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_SLIPPERY,
PixelFormat.TRANSLUCENT);
windowLayoutParams.setTitle(WINDOW_TITLE);
windowLayoutParams.packageName = getPackageName();
windowLayoutParams.gravity = Gravity.BOTTOM;
windowLayoutParams.setFitInsetsTypes(0);
windowLayoutParams.receiveInsetsIgnoringZOrder = true;
windowLayoutParams.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
windowLayoutParams.layoutInDisplayCutoutMode = LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
windowLayoutParams.privateFlags =
WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
return windowLayoutParams;
}
public void onConfigurationChanged(@Config int configChanges) {
mControllers.onConfigurationChanged(configChanges);
}
@@ -270,14 +278,6 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
return mViewCache;
}
@Override
public boolean supportsIme() {
// Currently we don't support IME because we have FLAG_NOT_FOCUSABLE. We can remove that
// flag when opening a floating view that needs IME (such as Folder), but then that means
// Taskbar will be below IME and thus users can't click the back button.
return false;
}
@Override
public View.OnClickListener getItemOnClickListener() {
return this::onTaskbarIconClicked;
@@ -505,6 +505,42 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
return mTaskbarHeightForIme;
}
/**
* Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
* window.
*/
public void setTaskbarWindowFocusable(boolean focusable) {
if (focusable) {
mWindowLayoutParams.flags &= ~FLAG_NOT_FOCUSABLE;
} else {
mWindowLayoutParams.flags |= FLAG_NOT_FOCUSABLE;
}
mWindowManager.updateViewLayout(mDragLayer, mWindowLayoutParams);
}
/**
* Either adds or removes {@link WindowManager.LayoutParams#FLAG_NOT_FOCUSABLE} on the taskbar
* window. If we're now focusable, also move nav buttons to a separate window above IME.
*/
public void setTaskbarWindowFocusableForIme(boolean focusable) {
if (focusable) {
mControllers.navbarButtonsViewController.moveNavButtonsToNewWindow();
} else {
mControllers.navbarButtonsViewController.moveNavButtonsBackToTaskbarWindow();
}
setTaskbarWindowFocusable(focusable);
}
/** Adds the given view to WindowManager with the provided LayoutParams (creates new window). */
public void addWindowView(View view, WindowManager.LayoutParams windowLayoutParams) {
mWindowManager.addView(view, windowLayoutParams);
}
/** Removes the given view from WindowManager. See {@link #addWindowView}. */
public void removeWindowView(View view) {
mWindowManager.removeViewImmediate(view);
}
protected void onTaskbarIconClicked(View view) {
Object tag = view.getTag();
if (tag instanceof Task) {
@@ -514,6 +550,17 @@ public class TaskbarActivityContext extends ContextThemeWrapper implements Activ
} else if (tag instanceof FolderInfo) {
FolderIcon folderIcon = (FolderIcon) view;
Folder folder = folderIcon.getFolder();
folder.setOnFolderStateChangedListener(newState -> {
if (newState == Folder.STATE_OPEN) {
setTaskbarWindowFocusableForIme(true);
} else if (newState == Folder.STATE_CLOSED) {
// Defer by a frame to ensure we're no longer fullscreen and thus won't jump.
getDragLayer().post(() -> setTaskbarWindowFocusableForIme(false));
folder.setOnFolderStateChangedListener(null);
}
});
setTaskbarWindowFullscreen(true);
getDragLayer().post(() -> {
@@ -15,17 +15,22 @@
*/
package com.android.launcher3.taskbar;
import static android.view.KeyEvent.ACTION_UP;
import static android.view.KeyEvent.KEYCODE_BACK;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.R;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.TestProtocol;
@@ -187,4 +192,17 @@ public class TaskbarDragLayer extends BaseDragLayer<TaskbarActivityContext> {
TestLogging.recordMotionEvent(TestProtocol.SEQUENCE_MAIN, "Touch event", ev);
return super.dispatchTouchEvent(ev);
}
/** Called while Taskbar window is focusable, e.g. when pressing back while a folder is open */
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
if (topView != null && topView.onBackPressed()) {
// Handled by the floating view.
return true;
}
}
return super.dispatchKeyEvent(event);
}
}
@@ -27,6 +27,7 @@ import android.animation.ObjectAnimator;
import androidx.annotation.NonNull;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.statemanager.StateManager;
@@ -256,6 +257,10 @@ import java.util.function.Supplier;
if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
boolean goingToLauncher = hasAnyFlag(FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING);
if (goingToLauncher) {
// Handle closing open popups when going home/overview
AbstractFloatingView.closeAllOpenViews(mControllers.taskbarActivityContext);
}
animatorSet.play(mTaskbarBackgroundAlpha.animateToValue(goingToLauncher ? 0 : 1)
.setDuration(duration));
}
@@ -154,6 +154,15 @@ public class TaskbarPopupController {
.filter(Objects::nonNull)
.collect(Collectors.toList()));
container.requestFocus();
// Make focusable to receive back events
mControllers.taskbarActivityContext.setTaskbarWindowFocusable(true);
container.setOnCloseCallback(() -> {
mControllers.taskbarActivityContext.getDragLayer().post(
() -> mControllers.taskbarActivityContext.setTaskbarWindowFocusable(false));
container.setOnCloseCallback(null);
});
return container;
}
@@ -1410,7 +1410,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
.setContext(mContext)
.setTaskId(runningTaskTarget.taskId)
.setComponentName(taskInfo.topActivity)
.setLeash(runningTaskTarget.leash.getSurfaceControl())
.setLeash(runningTaskTarget.leash)
.setSourceRectHint(
runningTaskTarget.taskInfo.pictureInPictureParams.getSourceRectHint())
.setAppBounds(taskInfo.configuration.windowConfiguration.getBounds())
@@ -419,7 +419,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
RemoteAnimationTargets targets = new RemoteAnimationTargets(
appTargets, wallpaperTargets, nonAppTargets, MODE_OPENING);
for (RemoteAnimationTargetCompat app : targets.apps) {
new Transaction().setAlpha(app.leash.getSurfaceControl(), 1).apply();
new Transaction().setAlpha(app.leash, 1).apply();
}
AnimatorSet anim = new AnimatorSet();
anim.play(controller.getAnimationPlayer());
@@ -469,7 +469,7 @@ public final class TaskViewUtils {
for (RemoteAnimationTargetCompat appTarget : appTargets) {
final int taskId = appTarget.taskInfo != null ? appTarget.taskInfo.taskId : -1;
final int mode = appTarget.mode;
final SurfaceControl leash = appTarget.leash.getSurfaceControl();
final SurfaceControl leash = appTarget.leash;
if (leash == null) {
continue;
}
@@ -484,7 +484,7 @@ public final class TaskViewUtils {
}
for (int i = 0; i < nonAppTargets.length; ++i) {
final SurfaceControl leash = appTargets[i].leash.getSurfaceControl();
final SurfaceControl leash = appTargets[i].leash;
if (nonAppTargets[i].windowType == TYPE_DOCK_DIVIDER && leash != null) {
openingTargets.add(leash);
}
@@ -611,7 +611,7 @@ public final class TaskViewUtils {
boolean hasSurfaceToAnimate = false;
for (int i = 0; i < nonApps.length; ++i) {
final RemoteAnimationTargetCompat targ = nonApps[i];
final SurfaceControl leash = targ.leash.getSurfaceControl();
final SurfaceControl leash = targ.leash;
if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) {
auxiliarySurfaces.add(leash);
hasSurfaceToAnimate = true;
@@ -174,10 +174,10 @@ public class TransformParams {
RemoteAnimationTargetCompat app = targets.unfilteredApps[i];
if (app.mode == targets.targetMode) {
if (app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_RECENTS) {
return app.leash.getSurfaceControl();
return app.leash;
}
} else {
return app.leash.getSurfaceControl();
return app.leash;
}
}
return null;
+8
View File
@@ -187,6 +187,10 @@
<attr name="minCellHeight" format="float" />
<attr name="minCellWidth" format="float" />
<!-- defaults to minCellHeight, if not specified -->
<attr name="minCellHeightLandscape" format="float" />
<!-- defaults to minCellWidth, if not specified -->
<attr name="minCellWidthLandscape" format="float" />
<!-- defaults to minCellHeight, if not specified -->
<attr name="minCellHeightTwoPanelPortrait" format="float" />
<!-- defaults to minCellWidth, if not specified -->
<attr name="minCellWidthTwoPanelPortrait" format="float" />
@@ -244,6 +248,8 @@
<!-- defaults to borderSpaceDps, if not specified -->
<attr name="hotseatBorderSpace" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
<attr name="hotseatBorderSpaceLandscape" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
<attr name="hotseatBorderSpaceTwoPanelLandscape" format="float" />
<!-- defaults to hotseatBorderSpace, if not specified -->
<attr name="hotseatBorderSpaceTwoPanelPortrait" format="float" />
@@ -270,6 +276,8 @@
<!-- Margin on left and right of the workspace when GridDisplayOption#isScalable is true -->
<attr name="horizontalMargin" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginLandscape" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginTwoPanelLandscape" format="float"/>
<!-- defaults to horizontalMargin if not specified -->
<attr name="horizontalMarginTwoPanelPortrait" format="float"/>
+13 -3
View File
@@ -238,9 +238,19 @@ public class CellLayout extends ViewGroup {
mActivity = ActivityContext.lookupContext(context);
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
mBorderSpace = mContainerType == FOLDER
? new Point(deviceProfile.folderCellLayoutBorderSpacePx)
: new Point(deviceProfile.cellLayoutBorderSpacePx);
switch (mContainerType) {
case FOLDER:
mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
break;
case HOTSEAT:
mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
deviceProfile.hotseatBorderSpace);
break;
case WORKSPACE:
default:
mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
break;
}
mCellWidth = mCellHeight = -1;
mFixedCellWidth = mFixedCellHeight = -1;
+2 -1
View File
@@ -161,7 +161,7 @@ public class DeviceProfile {
public final int hotseatBarSidePaddingStartPx;
public final int hotseatBarSidePaddingEndPx;
public final int hotseatQsbHeight;
public final int hotseatBorderSpace;
public int hotseatBorderSpace;
public final float qsbBottomMarginOriginalPx;
public int qsbBottomMarginPx;
@@ -716,6 +716,7 @@ public class DeviceProfile {
}
// Hotseat
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
updateHotseatIconSize(iconSizePx);
if (!isVerticalLayout) {
@@ -794,6 +794,11 @@ public class InvariantDeviceProfile {
x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidth, 0);
y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeight, 0);
minCellSize[INDEX_DEFAULT] = new PointF(x, y);
x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthLandscape,
minCellSize[INDEX_DEFAULT].x);
y = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightLandscape,
minCellSize[INDEX_DEFAULT].y);
minCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
x = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthTwoPanelPortrait,
@@ -896,7 +901,9 @@ public class InvariantDeviceProfile {
horizontalMargin[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMargin, 0);
horizontalMargin[INDEX_LANDSCAPE] = horizontalMargin[INDEX_DEFAULT];
horizontalMargin[INDEX_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMarginLandscape,
horizontalMargin[INDEX_DEFAULT]);
horizontalMargin[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_horizontalMarginTwoPanelLandscape,
horizontalMargin[INDEX_DEFAULT]);
@@ -906,7 +913,9 @@ public class InvariantDeviceProfile {
hotseatBorderSpaces[INDEX_DEFAULT] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBorderSpace, borderSpace);
hotseatBorderSpaces[INDEX_LANDSCAPE] = hotseatBorderSpaces[INDEX_DEFAULT];
hotseatBorderSpaces[INDEX_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBorderSpaceLandscape,
hotseatBorderSpaces[INDEX_DEFAULT]);
hotseatBorderSpaces[INDEX_TWO_PANEL_LANDSCAPE] = a.getFloat(
R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelLandscape,
hotseatBorderSpaces[INDEX_DEFAULT]);
+1 -1
View File
@@ -229,7 +229,7 @@ public final class Utilities {
offsetPoints(coord, v.getLeft(), v.getTop());
scale *= v.getScaleX();
v = (View) v.getParent();
v = v.getParent() instanceof View ? (View) v.getParent() : null;
}
return scale;
}
+42 -24
View File
@@ -57,6 +57,7 @@ import android.view.animation.AnimationUtils;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import androidx.core.content.res.ResourcesCompat;
@@ -101,6 +102,8 @@ import com.android.launcher3.views.BaseDragLayer;
import com.android.launcher3.views.ClipPathView;
import com.android.launcher3.widget.PendingAddShortcutInfo;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -130,10 +133,13 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
*/
private static final int MIN_CONTENT_DIMEN = 5;
static final int STATE_NONE = -1;
static final int STATE_SMALL = 0;
static final int STATE_ANIMATING = 1;
static final int STATE_OPEN = 2;
public static final int STATE_CLOSED = 0;
public static final int STATE_ANIMATING = 1;
public static final int STATE_OPEN = 2;
@Retention(RetentionPolicy.SOURCE)
@IntDef({STATE_CLOSED, STATE_ANIMATING, STATE_OPEN})
public @interface FolderState {}
/**
* Time for which the scroll hint is shown before automatically changing page.
@@ -198,13 +204,12 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
@ViewDebug.ExportedProperty(category = "launcher",
mapping = {
@ViewDebug.IntToString(from = STATE_NONE, to = "STATE_NONE"),
@ViewDebug.IntToString(from = STATE_SMALL, to = "STATE_SMALL"),
@ViewDebug.IntToString(from = STATE_CLOSED, to = "STATE_CLOSED"),
@ViewDebug.IntToString(from = STATE_ANIMATING, to = "STATE_ANIMATING"),
@ViewDebug.IntToString(from = STATE_OPEN, to = "STATE_OPEN"),
})
@Thunk
int mState = STATE_NONE;
private int mState = STATE_CLOSED;
private OnFolderStateChangedListener mOnFolderStateChangedListener;
@ViewDebug.ExportedProperty(category = "launcher")
private boolean mRearrangeOnClose = false;
boolean mItemsInvalidated = false;
@@ -277,19 +282,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
mPageIndicator = findViewById(R.id.folder_page_indicator);
mFolderName = findViewById(R.id.folder_name);
mFolderName.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.folderLabelTextSizePx);
if (mActivityContext.supportsIme()) {
mFolderName.setOnBackKeyListener(this);
mFolderName.setOnFocusChangeListener(this);
mFolderName.setOnEditorActionListener(this);
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType()
& ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
| InputType.TYPE_TEXT_FLAG_CAP_WORDS);
mFolderName.forceDisableSuggestions(true);
} else {
mFolderName.setEnabled(false);
}
mFolderName.setOnBackKeyListener(this);
mFolderName.setOnFocusChangeListener(this);
mFolderName.setOnEditorActionListener(this);
mFolderName.setSelectAllOnFocus(true);
mFolderName.setInputType(mFolderName.getInputType()
& ~InputType.TYPE_TEXT_FLAG_AUTO_CORRECT
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS
| InputType.TYPE_TEXT_FLAG_CAP_WORDS);
mFolderName.forceDisableSuggestions(true);
mFooter = findViewById(R.id.folder_footer);
mFooterHeight = getResources().getDimensionPixelSize(R.dimen.folder_label_height);
@@ -561,7 +562,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
a.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mState = STATE_ANIMATING;
setState(STATE_ANIMATING);
mCurrentAnimator = a;
}
@@ -686,7 +687,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
@Override
public void onAnimationEnd(Animator animation) {
mState = STATE_OPEN;
setState(STATE_OPEN);
announceAccessibilityChanges();
AccessibilityManagerCompat.sendFolderOpenedEventToTest(getContext());
@@ -862,7 +863,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
}
mSuppressFolderDeletion = false;
clearDragInfo();
mState = STATE_SMALL;
setState(STATE_CLOSED);
mContent.setCurrentPage(0);
}
@@ -1655,4 +1656,21 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
return windowBottomPx - folderBottomPx;
}
private void setState(@FolderState int newState) {
mState = newState;
if (mOnFolderStateChangedListener != null) {
mOnFolderStateChangedListener.onFolderStateChanged(mState);
}
}
public void setOnFolderStateChangedListener(@Nullable OnFolderStateChangedListener listener) {
mOnFolderStateChangedListener = listener;
}
/** Listener that can be registered via {@link Folder#setOnFolderStateChangedListener} */
public interface OnFolderStateChangedListener {
/** See {@link Folder.FolderState} */
void onFolderStateChanged(@FolderState int newState);
}
}
@@ -48,7 +48,7 @@ import android.view.ViewTreeObserver;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.InsettableFrameLayout;
@@ -120,7 +120,7 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
private final GradientDrawable mRoundedTop;
private final GradientDrawable mRoundedBottom;
private Runnable mOnCloseCallback = () -> { };
@Nullable private Runnable mOnCloseCallback = null;
// The rect string of the view that the arrow is attached to, in screen reference frame.
protected int mArrowColor;
@@ -766,7 +766,6 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
}
}
protected void animateClose() {
if (!mIsOpen) {
return;
@@ -816,7 +815,9 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
mDeferContainerRemoval = false;
getPopupContainer().removeView(this);
getPopupContainer().removeView(mArrow);
mOnCloseCallback.run();
if (mOnCloseCallback != null) {
mOnCloseCallback.run();
}
if (mColorExtractors != null) {
mColorExtractors.forEach(e -> e.setListener(null));
}
@@ -825,7 +826,7 @@ public abstract class ArrowPopup<T extends Context & ActivityContext>
/**
* Callback to be called when the popup is closed
*/
public void setOnCloseCallback(@NonNull Runnable callback) {
public void setOnCloseCallback(@Nullable Runnable callback) {
mOnCloseCallback = callback;
}
@@ -28,7 +28,6 @@ import android.os.Message;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import com.android.launcher3.BaseActivity;
import com.android.launcher3.views.ActivityContext;
/**
@@ -56,7 +55,7 @@ public class UiThreadHelper {
STATS_LOGGER_KEY,
Message.obtain(
HANDLER.get(root.getContext()),
() -> BaseActivity.fromContext(root.getContext())
() -> ActivityContext.lookupContext(root.getContext())
.getStatsLogManager()
.logger()
.log(LAUNCHER_ALLAPPS_KEYBOARD_CLOSED)
@@ -124,13 +124,6 @@ public interface ActivityContext {
return true;
}
/**
* Returns whether we can show the IME for elements hosted by this ActivityContext.
*/
default boolean supportsIme() {
return true;
}
/**
* Called just before logging the given item.
*/