Merge "Rotate overview only if system rotation allowed" into ub-launcher3-rvc-dev
diff --git a/quickstep/recents_ui_overrides/res/layout/overview_panel.xml b/quickstep/recents_ui_overrides/res/layout/overview_panel.xml
index eac0bfa..fe57e9b 100644
--- a/quickstep/recents_ui_overrides/res/layout/overview_panel.xml
+++ b/quickstep/recents_ui_overrides/res/layout/overview_panel.xml
@@ -13,12 +13,20 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<com.android.quickstep.views.LauncherRecentsView
- xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:accessibilityPaneTitle="@string/accessibility_recent_apps"
- android:clipChildren="false"
- android:clipToPadding="false"
- android:theme="@style/HomeScreenElementTheme"
- android:visibility="invisible" />
+<merge xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <com.android.quickstep.views.LauncherRecentsView
+ android:id="@+id/overview_panel"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:accessibilityPaneTitle="@string/accessibility_recent_apps"
+ android:clipChildren="false"
+ android:clipToPadding="false"
+ android:theme="@style/HomeScreenElementTheme"
+ android:visibility="invisible" />
+
+ <include
+ android:id="@+id/overview_actions_view"
+ layout="@layout/overview_actions_container" />
+
+</merge>
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index 8af26c6..7520688 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -19,11 +19,13 @@
import static com.android.launcher3.graphics.IconShape.getShape;
import android.content.Context;
+import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
-import android.graphics.DashPathEffect;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.Rect;
+import android.os.Process;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.ViewGroup;
@@ -39,6 +41,7 @@
import com.android.launcher3.graphics.IconPalette;
import com.android.launcher3.hybridhotseat.HotseatPredictionController;
import com.android.launcher3.icons.IconNormalizer;
+import com.android.launcher3.icons.LauncherIcons;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
@@ -51,13 +54,18 @@
public class PredictedAppIcon extends DoubleShadowBubbleTextView implements
LauncherAccessibilityDelegate.AccessibilityActionHandler {
+ private static final int RING_SHADOW_COLOR = 0x99000000;
private static final float RING_EFFECT_RATIO = 0.11f;
boolean mIsDrawingDot = false;
private final DeviceProfile mDeviceProfile;
private final Paint mIconRingPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+ private final Path mRingPath = new Path();
private boolean mIsPinned = false;
- private int mNormalizedIconRadius;
+ private final int mNormalizedIconRadius;
+ private final BlurMaskFilter mShadowFilter;
+ private int mPlateColor;
+
public PredictedAppIcon(Context context) {
this(context, null, 0);
@@ -73,13 +81,18 @@
mNormalizedIconRadius = IconNormalizer.getNormalizedCircleSize(getIconSize()) / 2;
setOnClickListener(ItemClickHandler.INSTANCE);
setOnFocusChangeListener(Launcher.getLauncher(context).getFocusHandler());
+ int shadowSize = context.getResources().getDimensionPixelSize(
+ R.dimen.blur_size_thin_outline);
+ mShadowFilter = new BlurMaskFilter(shadowSize, BlurMaskFilter.Blur.OUTER);
}
@Override
public void onDraw(Canvas canvas) {
int count = canvas.save();
if (!mIsPinned) {
- drawEffect(canvas);
+ boolean isBadged = getTag() instanceof WorkspaceItemInfo
+ && !Process.myUserHandle().equals(((ItemInfo) getTag()).user);
+ drawEffect(canvas, isBadged);
canvas.translate(getWidth() * RING_EFFECT_RATIO, getHeight() * RING_EFFECT_RATIO);
canvas.scale(1 - 2 * RING_EFFECT_RATIO, 1 - 2 * RING_EFFECT_RATIO);
}
@@ -102,7 +115,7 @@
public void applyFromWorkspaceItem(WorkspaceItemInfo info) {
super.applyFromWorkspaceItem(info);
int color = IconPalette.getMutedColor(info.bitmap.color, 0.54f);
- mIconRingPaint.setColor(ColorUtils.setAlphaComponent(color, 200));
+ mPlateColor = ColorUtils.setAlphaComponent(color, 200);
if (mIsPinned) {
setContentDescription(info.contentDescription);
} else {
@@ -174,9 +187,25 @@
return getPaddingTop() + mDeviceProfile.folderIconOffsetYPx;
}
- private void drawEffect(Canvas canvas) {
- getShape().drawShape(canvas, getOutlineOffsetX(), getOutlineOffsetY(),
- mNormalizedIconRadius, mIconRingPaint);
+ private void drawEffect(Canvas canvas, boolean isBadged) {
+ mRingPath.reset();
+ getShape().addToPath(mRingPath, getOutlineOffsetX(), getOutlineOffsetY(),
+ mNormalizedIconRadius);
+ if (isBadged) {
+ float outlineSize = mNormalizedIconRadius * RING_EFFECT_RATIO * 2;
+ float iconSize = getIconSize() * (1 - 2 * RING_EFFECT_RATIO);
+ float badgeSize = LauncherIcons.getBadgeSizeForIconSize((int) iconSize) + outlineSize;
+ float badgeInset = mNormalizedIconRadius * 2 - badgeSize;
+ getShape().addToPath(mRingPath, getOutlineOffsetX() + badgeInset,
+ getOutlineOffsetY() + badgeInset, badgeSize / 2);
+
+ }
+ mIconRingPaint.setColor(RING_SHADOW_COLOR);
+ mIconRingPaint.setMaskFilter(mShadowFilter);
+ canvas.drawPath(mRingPath, mIconRingPaint);
+ mIconRingPaint.setColor(mPlateColor);
+ mIconRingPaint.setMaskFilter(null);
+ canvas.drawPath(mRingPath, mIconRingPaint);
}
/**
@@ -205,10 +234,8 @@
mOffsetX = icon.getOutlineOffsetX();
mOffsetY = icon.getOutlineOffsetY();
mIconRadius = icon.mNormalizedIconRadius;
- mOutlinePaint.setStyle(Paint.Style.STROKE);
- mOutlinePaint.setStrokeWidth(5);
- mOutlinePaint.setPathEffect(new DashPathEffect(new float[]{15, 15}, 0));
- mOutlinePaint.setColor(Color.argb(100, 245, 245, 245));
+ mOutlinePaint.setStyle(Paint.Style.FILL);
+ mOutlinePaint.setColor(Color.argb(24, 245, 245, 245));
}
/**
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 2b13a1e..2f55fda 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -15,20 +15,14 @@
*/
package com.android.launcher3.uioverrides;
-import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherState.OVERVIEW_BUTTONS;
-import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE_IN_OUT;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
import android.annotation.TargetApi;
import android.os.Build;
import android.util.FloatProperty;
-import android.view.Surface;
-import android.view.View;
-import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
@@ -38,6 +32,7 @@
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.anim.PropertySetter;
import com.android.launcher3.states.StateAnimationConfig;
+import com.android.launcher3.util.MultiValueAlpha;
import com.android.quickstep.views.ClearAllButton;
import com.android.quickstep.views.LauncherRecentsView;
import com.android.quickstep.views.RecentsView;
@@ -61,7 +56,7 @@
mRecentsView.updateEmptyMessage();
mRecentsView.resetTaskVisuals();
}
- setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state, LINEAR);
+ setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, state);
mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress());
}
@@ -79,23 +74,17 @@
AnimationSuccessListener.forRunnable(mRecentsView::resetTaskVisuals));
}
- setAlphas(builder, toState,
- config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT));
+ setAlphas(builder, toState);
builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS,
toState.getOverviewFullscreenProgress(), LINEAR);
}
- private void setAlphas(PropertySetter propertySetter, LauncherState state,
- Interpolator actionInterpolator) {
+ private void setAlphas(PropertySetter propertySetter, LauncherState state) {
float buttonAlpha = (state.getVisibleElements(mLauncher) & OVERVIEW_BUTTONS) != 0 ? 1 : 0;
propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA,
buttonAlpha, LINEAR);
-
- View actionsView = mLauncher.getActionsView();
- int launcherRotation = mRecentsView.getPagedViewOrientedState().getLauncherRotation();
- if (actionsView != null && launcherRotation == Surface.ROTATION_0) {
- propertySetter.setViewAlpha(actionsView, buttonAlpha, actionInterpolator);
- }
+ propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(),
+ MultiValueAlpha.VALUE, buttonAlpha, LINEAR);
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
index 33fe5a9..fd17551 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/ImageActionsApi.java
@@ -42,9 +42,10 @@
public class ImageActionsApi {
private static final String TAG = BuildConfig.APPLICATION_ID + "ImageActionsApi";
- private final Context mContext;
- private final Supplier<Bitmap> mBitmapSupplier;
- private final SystemUiProxy mSystemUiProxy;
+
+ protected final Context mContext;
+ protected final Supplier<Bitmap> mBitmapSupplier;
+ protected final SystemUiProxy mSystemUiProxy;
public ImageActionsApi(Context context, Supplier<Bitmap> bitmapSupplier) {
mContext = context;
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
index 42d944f..52a2558 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/RecentsActivity.java
@@ -71,6 +71,7 @@
mRecentsRootView = findViewById(R.id.drag_layer);
mFallbackRecentsView = findViewById(R.id.overview_panel);
mRecentsRootView.recreateControllers();
+ mFallbackRecentsView.init(findViewById(R.id.overview_actions_view));
}
@Override
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
index fbf29af..147f933 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TaskOverlayFactory.java
@@ -16,7 +16,6 @@
package com.android.quickstep;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.util.MainThreadInitializedObject.forOverride;
import android.content.Context;
@@ -84,47 +83,47 @@
/**
* Overlay on each task handling Overview Action Buttons.
*/
- public static class TaskOverlay {
+ public static class TaskOverlay<T extends OverviewActionsView> {
private final Context mApplicationContext;
- private OverviewActionsView mActionsView;
- private final TaskThumbnailView mThumbnailView;
+ protected final TaskThumbnailView mThumbnailView;
+ private T mActionsView;
protected TaskOverlay(TaskThumbnailView taskThumbnailView) {
mApplicationContext = taskThumbnailView.getContext().getApplicationContext();
mThumbnailView = taskThumbnailView;
}
+ protected T getActionsView() {
+ if (mActionsView == null) {
+ mActionsView = BaseActivity.fromContext(mThumbnailView.getContext()).findViewById(
+ R.id.overview_actions_view);
+ }
+ return mActionsView;
+ }
+
/**
* Called when the current task is interactive for the user
*/
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix) {
ImageActionsApi imageApi = new ImageActionsApi(
mApplicationContext, mThumbnailView::getThumbnail);
+ getActionsView().setCallbacks(new OverlayUICallbacks() {
+ @Override
+ public void onShare() {
+ imageApi.startShareActivity();
+ }
- if (mActionsView == null && ENABLE_OVERVIEW_ACTIONS.get()
- && SysUINavigationMode.removeShelfFromOverview(mApplicationContext)) {
- mActionsView = BaseActivity.fromContext(mThumbnailView.getContext()).findViewById(
- R.id.overview_actions_view);
- }
- if (mActionsView != null) {
- mActionsView.setListener(new OverviewActionsView.Listener() {
- @Override
- public void onShare() {
- imageApi.startShareActivity();
- }
-
- @Override
- public void onScreenshot() {
- imageApi.saveScreenshot(mThumbnailView.getThumbnail(),
- getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key.id);
- }
- });
- }
-
+ @Override
+ public void onScreenshot() {
+ imageApi.saveScreenshot(mThumbnailView.getThumbnail(),
+ getTaskSnapshotBounds(), getTaskSnapshotInsets(), task.key.id);
+ }
+ });
}
+
/**
* Called when the overlay is no longer used.
*/
@@ -161,4 +160,16 @@
return Insets.of(0, 0, 0, 0);
}
}
+
+ /**
+ * Callbacks the Ui can generate. This is the only way for a Ui to call methods on the
+ * controller.
+ */
+ public interface OverlayUICallbacks {
+ /** User has indicated they want to share the current task. */
+ void onShare();
+
+ /** User has indicated they want to screenshot the current task. */
+ void onScreenshot();
+ }
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
index 0b5221e..9b5a935 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java
@@ -498,7 +498,10 @@
}
}
- ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
+ if (mUncheckedConsumer != InputConsumer.NO_OP) {
+ ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
+ }
+
boolean cleanUpConsumer = (action == ACTION_UP || action == ACTION_CANCEL)
&& mConsumer != null
&& !mConsumer.getActiveConsumerInHierarchy().isConsumerDetachedFromGesture();
@@ -802,6 +805,7 @@
if (mGestureState != null) {
mGestureState.dump(pw);
}
+ SysUINavigationMode.INSTANCE.get(this).dump(pw);
pw.println("TouchState:");
BaseDraggingActivity createdOverviewActivity = mOverviewComponentObserver == null ? null
: mOverviewComponentObserver.getActivityInterface().getCreatedActivity();
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
index dc0c194..6d1bf11 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -30,6 +30,7 @@
import com.android.launcher3.Utilities;
import com.android.quickstep.RecentsActivity;
import com.android.quickstep.util.LayoutUtils;
+import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
@@ -67,6 +68,11 @@
public FallbackRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
+ }
+
+ @Override
+ public void init(OverviewActionsView actionsView) {
+ super.init(actionsView);
setOverviewStateEnabled(true);
setOverlayEnabled(true);
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
index 87b0ad2..78d75c5 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -47,7 +47,6 @@
import com.android.launcher3.appprediction.PredictionUiStateManager.Client;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.statehandlers.DepthController;
-import com.android.launcher3.states.RotationHelper;
import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
import com.android.launcher3.util.TraceHelper;
import com.android.launcher3.views.ScrimView;
@@ -98,11 +97,16 @@
public LauncherRecentsView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
- setContentAlpha(0);
mActivity.getStateManager().addStateListener(this);
}
@Override
+ public void init(OverviewActionsView actionsView) {
+ super.init(actionsView);
+ setContentAlpha(0);
+ }
+
+ @Override
public void startHome() {
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
switchToScreenshot(null,
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
index 6a37e2b..93e68c0 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,34 +16,59 @@
package com.android.quickstep.views;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
+import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
+
import android.content.Context;
import android.util.AttributeSet;
-import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.widget.FrameLayout;
+import androidx.annotation.IntDef;
import androidx.annotation.Nullable;
import com.android.launcher3.R;
+import com.android.launcher3.util.MultiValueAlpha;
+import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
+import com.android.quickstep.TaskOverlayFactory.OverlayUICallbacks;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
/**
* View for showing action buttons in Overview
*/
-public class OverviewActionsView extends FrameLayout {
+public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayout
+ implements OnClickListener {
- private final View mScreenshotButton;
- private final View mShareButton;
+ @IntDef(flag = true, value = {
+ HIDDEN_UNSUPPORTED_NAVIGATION,
+ HIDDEN_DISABLED_FEATURE,
+ HIDDEN_NON_ZERO_ROTATION,
+ HIDDEN_NO_TASKS,
+ HIDDEN_GESTURE_RUNNING,
+ HIDDEN_NO_RECENTS})
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface ActionsHiddenFlags { }
- /**
- * Listener for taps on the various actions.
- */
- public interface Listener {
- /** User has initiated the share actions. */
- void onShare();
+ public static final int HIDDEN_UNSUPPORTED_NAVIGATION = 1 << 0;
+ public static final int HIDDEN_DISABLED_FEATURE = 1 << 1;
+ public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 2;
+ public static final int HIDDEN_NO_TASKS = 1 << 3;
+ public static final int HIDDEN_GESTURE_RUNNING = 1 << 4;
+ public static final int HIDDEN_NO_RECENTS = 1 << 5;
- /** User has initiated the screenshot action. */
- void onScreenshot();
- }
+ private static final int INDEX_CONTENT_ALPHA = 0;
+ private static final int INDEX_VISIBILITY_ALPHA = 1;
+ private static final int INDEX_HIDDEN_FLAGS_ALPHA = 2;
+
+ private final MultiValueAlpha mMultiValueAlpha;
+
+ @ActionsHiddenFlags
+ private int mHiddenFlags;
+
+ protected T mCallbacks;
public OverviewActionsView(Context context) {
this(context, null);
@@ -54,26 +79,62 @@
}
public OverviewActionsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
- this(context, attrs, defStyleAttr, 0);
+ super(context, attrs, defStyleAttr, 0);
+ mMultiValueAlpha = new MultiValueAlpha(this, 3);
}
- public OverviewActionsView(Context context, AttributeSet attrs, int defStyleAttr,
- int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- LayoutInflater.from(context).inflate(R.layout.overview_actions, this, true);
- mShareButton = findViewById(R.id.action_share);
- mScreenshotButton = findViewById(R.id.action_screenshot);
+ @Override
+ protected void onFinishInflate() {
+ super.onFinishInflate();
+ findViewById(R.id.action_share).setOnClickListener(this);
+ findViewById(R.id.action_screenshot).setOnClickListener(this);
}
/**
* Set listener for callbacks on action button taps.
*
- * @param listener for callbacks, or {@code null} to clear the listener.
+ * @param callbacks for callbacks, or {@code null} to clear the listener.
*/
- public void setListener(@Nullable OverviewActionsView.Listener listener) {
- mShareButton.setOnClickListener(
- listener == null ? null : view -> listener.onShare());
- mScreenshotButton.setOnClickListener(
- listener == null ? null : view -> listener.onScreenshot());
+ public void setCallbacks(T callbacks) {
+ mCallbacks = callbacks;
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (mCallbacks == null) {
+ return;
+ }
+ int id = view.getId();
+ if (id == R.id.action_share) {
+ mCallbacks.onShare();
+ } else if (id == R.id.action_screenshot) {
+ mCallbacks.onScreenshot();
+ }
+ }
+
+ @Override
+ protected void onAttachedToWindow() {
+ super.onAttachedToWindow();
+ updateHiddenFlags(HIDDEN_DISABLED_FEATURE, !ENABLE_OVERVIEW_ACTIONS.get());
+ updateHiddenFlags(HIDDEN_UNSUPPORTED_NAVIGATION, !removeShelfFromOverview(getContext()));
+ }
+
+ public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
+ if (enable) {
+ mHiddenFlags |= visibilityFlags;
+ } else {
+ mHiddenFlags &= ~visibilityFlags;
+ }
+ boolean isHidden = mHiddenFlags != 0;
+ mMultiValueAlpha.getProperty(INDEX_HIDDEN_FLAGS_ALPHA).setValue(isHidden ? 0 : 1);
+ setVisibility(isHidden ? INVISIBLE : VISIBLE);
+ }
+
+ public AlphaProperty getContentAlpha() {
+ return mMultiValueAlpha.getProperty(INDEX_CONTENT_ALPHA);
+ }
+
+ public AlphaProperty getVisibilityAlpha() {
+ return mMultiValueAlpha.getProperty(INDEX_VISIBILITY_ALPHA);
}
}
diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
index 08a5ee9..18e8768 100644
--- a/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/views/RecentsView.java
@@ -28,7 +28,6 @@
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
import static com.android.launcher3.anim.Interpolators.LINEAR;
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_DISMISS_SWIPE_UP;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.TASK_LAUNCH_SWIPE_DOWN;
@@ -39,6 +38,10 @@
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
import static com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_GESTURE_RUNNING;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
@@ -67,7 +70,6 @@
import android.util.FloatProperty;
import android.util.Property;
import android.util.SparseBooleanArray;
-import android.view.Gravity;
import android.view.HapticFeedbackConstants;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -87,7 +89,6 @@
import com.android.launcher3.BaseActivity;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Insettable;
-import com.android.launcher3.InsettableFrameLayout;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherState;
import com.android.launcher3.PagedView;
@@ -117,7 +118,6 @@
import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.RecentsModel.TaskVisualsChangeListener;
-import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskThumbnailCache;
import com.android.quickstep.TaskUtils;
@@ -334,8 +334,7 @@
// Keeps track of the index where the first TaskView should be
private int mTaskViewStartIndex = 0;
- private View mActionsView;
- private boolean mGestureRunning = false;
+ private OverviewActionsView mActionsView;
private BaseActivity.MultiWindowModeChangedListener mMultiWindowModeChangedListener =
(inMultiWindowMode) -> {
@@ -396,11 +395,6 @@
int rotation = RecentsOrientedState.getRotationForUserDegreesRotated(i);
if (mPreviousRotation != rotation) {
animateRecentsRotationInPlace(rotation);
- if (rotation == 0) {
- showActionsView();
- } else {
- hideActionsView();
- }
mPreviousRotation = rotation;
}
}
@@ -475,6 +469,10 @@
reset();
}
+ public void init(OverviewActionsView actionsView) {
+ mActionsView = actionsView;
+ }
+
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
@@ -488,7 +486,6 @@
mIPinnedStackAnimationListener.setActivity(mActivity);
SystemUiProxy.INSTANCE.get(getContext()).setPinnedStackAnimationListener(
mIPinnedStackAnimationListener);
- setActionsView();
mOrientationState.init();
mOrientationState.addSystemRotationChangeListener(mSystemRotationChangeListener);
}
@@ -518,6 +515,7 @@
TaskView taskView = (TaskView) child;
mHasVisibleTaskData.delete(taskView.getTask().key.id);
mTaskViewPool.recycle(taskView);
+ mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, getTaskViewCount() == 0);
}
updateTaskStartIndex(child);
}
@@ -530,6 +528,7 @@
// child direction back to match system settings.
child.setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_LTR : View.LAYOUT_DIRECTION_RTL);
updateTaskStartIndex(child);
+ mActionsView.updateHiddenFlags(HIDDEN_NO_TASKS, false);
}
private void updateTaskStartIndex(View affectingView) {
@@ -699,7 +698,6 @@
if (getTaskViewCount() != requiredTaskCount) {
if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
- hideActionsView();
}
for (int i = getTaskViewCount(); i < requiredTaskCount; i++) {
addView(mTaskViewPool.getView());
@@ -709,7 +707,6 @@
}
if (requiredTaskCount > 0) {
addView(mClearAllButton);
- showActionsView();
}
}
@@ -749,7 +746,6 @@
if (indexOfChild(mClearAllButton) != -1) {
removeView(mClearAllButton);
}
- hideActionsView();
}
public int getTaskViewCount() {
@@ -1011,7 +1007,7 @@
setEnableDrawingLiveTile(false);
setRunningTaskHidden(true);
setRunningTaskIconScaledDown(true);
- mGestureRunning = true;
+ mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, true);
}
/**
@@ -1077,7 +1073,7 @@
}
setRunningTaskHidden(false);
animateUpRunningTaskIconScale();
- mGestureRunning = false;
+ mActionsView.updateHiddenFlags(HIDDEN_GESTURE_RUNNING, false);
}
/**
@@ -1094,7 +1090,6 @@
addView(taskView, mTaskViewStartIndex);
if (wasEmpty) {
addView(mClearAllButton);
- showActionsView();
}
// The temporary running task is only used for the duration between the start of the
// gesture and the task list is loaded and applied
@@ -1418,7 +1413,6 @@
if (getTaskViewCount() == 0) {
removeViewInLayout(mClearAllButton);
- hideActionsView();
startHome();
} else {
snapToPageImmediately(pageToSnapTo);
@@ -1561,14 +1555,12 @@
int alphaInt = Math.round(alpha * 255);
mEmptyMessagePaint.setAlpha(alphaInt);
mEmptyIcon.setAlpha(alphaInt);
+ mActionsView.getContentAlpha().setValue(mContentAlpha);
+
if (alpha > 0) {
setVisibility(VISIBLE);
- if (!mGestureRunning) {
- showActionsView();
- }
} else if (!mFreezeViewVisibility) {
setVisibility(GONE);
- hideActionsView();
}
}
@@ -1579,18 +1571,20 @@
public void setFreezeViewVisibility(boolean freezeViewVisibility) {
if (mFreezeViewVisibility != freezeViewVisibility) {
mFreezeViewVisibility = freezeViewVisibility;
-
if (!mFreezeViewVisibility) {
setVisibility(mContentAlpha > 0 ? VISIBLE : GONE);
- if (mContentAlpha > 0) {
- showActionsView();
- } else {
- hideActionsView();
- }
}
}
}
+ @Override
+ public void setVisibility(int visibility) {
+ super.setVisibility(visibility);
+ if (mActionsView != null) {
+ mActionsView.updateHiddenFlags(HIDDEN_NO_RECENTS, visibility != VISIBLE);
+ }
+ }
+
public void setLayoutRotation(int touchRotation, int displayRotation) {
int launcherRotation = mOrientationState.getLauncherRotation();
setLayoutInternal(touchRotation, displayRotation, launcherRotation);
@@ -1603,6 +1597,7 @@
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
mClearAllButton.setRotation(mOrientationHandler.getDegreesRotated());
mActivity.getDragLayer().recreateControllers();
+ mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, touchRotation != 0);
requestLayout();
}
}
@@ -2161,36 +2156,4 @@
mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
}
}
-
- private void showActionsView() {
- if (mActionsView != null && getTaskViewCount() > 0) {
- mActionsView.setVisibility(VISIBLE);
- }
- }
-
- private void hideActionsView() {
- if (mActionsView != null) {
- mActionsView.setVisibility(GONE);
- }
- }
-
- private void setActionsView() {
- if (mActionsView == null && ENABLE_OVERVIEW_ACTIONS.get()
- && SysUINavigationMode.removeShelfFromOverview(mActivity)) {
- mActionsView = ((ViewGroup) getParent()).findViewById(R.id.overview_actions_view);
- if (mActionsView != null) {
- InsettableFrameLayout.LayoutParams layoutParams =
- new InsettableFrameLayout.LayoutParams(LayoutParams.MATCH_PARENT,
- getResources().getDimensionPixelSize(
- R.dimen.overview_actions_height));
- layoutParams.gravity = Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL;
- int margin = getResources().getDimensionPixelSize(
- R.dimen.overview_actions_horizontal_margin);
- layoutParams.setMarginStart(margin);
- layoutParams.setMarginEnd(margin);
- mActionsView.setLayoutParams(layoutParams);
- showActionsView();
- }
- }
- }
}
diff --git a/quickstep/res/layout/overview_actions.xml b/quickstep/res/layout/overview_actions.xml
deleted file mode 100644
index ad5efb6..0000000
--- a/quickstep/res/layout/overview_actions.xml
+++ /dev/null
@@ -1,41 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayout
- android:id="@+id/action_buttons"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:orientation="horizontal">
- <Space
- android:layout_width="0dp"
- android:layout_height="1dp"
- android:layout_weight="1" >
- </Space>
- <Button
- android:id="@+id/action_screenshot"
- style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableTop="@drawable/ic_screenshot"
- android:text="@string/action_screenshot" />
- <Space
- android:layout_width="0dp"
- android:layout_height="1dp"
- android:layout_weight="1" >
- </Space>
-
- <Button
- android:id="@+id/action_share"
- style="@style/OverviewActionButton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:drawableTop="@drawable/ic_share"
- android:text="@string/action_share" />
- <Space
- android:layout_width="0dp"
- android:layout_height="1dp"
- android:layout_weight="1" >
- </Space>
- </LinearLayout>
-
-</merge>
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 328c20b..e163991 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -16,8 +16,48 @@
-->
<com.android.quickstep.views.OverviewActionsView
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:visibility="gone">
+ android:layout_width="match_parent"
+ android:layout_height="@dimen/overview_actions_height"
+ android:layout_gravity="center_horizontal|bottom"
+ android:layout_marginLeft="@dimen/overview_actions_horizontal_margin"
+ android:layout_marginRight="@dimen/overview_actions_horizontal_margin" >
+
+ <LinearLayout
+ android:id="@+id/action_buttons"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center"
+ android:orientation="horizontal">
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1" >
+ </Space>
+ <Button
+ android:id="@+id/action_screenshot"
+ style="@style/OverviewActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableTop="@drawable/ic_screenshot"
+ android:text="@string/action_screenshot" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1" >
+ </Space>
+
+ <Button
+ android:id="@+id/action_share"
+ style="@style/OverviewActionButton"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:drawableTop="@drawable/ic_share"
+ android:text="@string/action_share" />
+ <Space
+ android:layout_width="0dp"
+ android:layout_height="1dp"
+ android:layout_weight="1" >
+ </Space>
+ </LinearLayout>
</com.android.quickstep.views.OverviewActionsView>
\ No newline at end of file
diff --git a/quickstep/res/values/config.xml b/quickstep/res/values/config.xml
index a688f9a..2b11ca0 100644
--- a/quickstep/res/values/config.xml
+++ b/quickstep/res/values/config.xml
@@ -13,13 +13,11 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-<resources xmlns:tools="http://schemas.android.com/tools">
+<resources>
<string name="task_overlay_factory_class" translatable="false"/>
<!-- Activities which block home gesture -->
- <string-array name="gesture_blocking_activities" tools:ignore="InconsistentArrays">
- <item>com.android.launcher3/com.android.quickstep.interaction.GestureSandboxActivity</item>
- </string-array>
+ <string-array name="gesture_blocking_activities" translatable="false"/>
<string name="stats_log_manager_class" translatable="false">com.android.quickstep.logging.StatsLogCompatManager</string>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 48e25bd..b7abd61 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -28,7 +28,6 @@
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.CancellationSignal;
-import android.view.View;
import com.android.launcher3.LauncherState.ScaleAndTranslation;
import com.android.launcher3.LauncherStateManager.StateHandler;
@@ -52,6 +51,7 @@
import com.android.quickstep.util.RemoteAnimationProvider;
import com.android.quickstep.util.RemoteFadeOutAnimationListener;
import com.android.quickstep.util.ShelfPeekAnim;
+import com.android.quickstep.views.OverviewActionsView;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
@@ -75,7 +75,7 @@
private final ShelfPeekAnim mShelfPeekAnim = new ShelfPeekAnim(this);
- private View mActionsView;
+ private OverviewActionsView mActionsView;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -164,19 +164,17 @@
protected void setupViews() {
super.setupViews();
mActionsView = findViewById(R.id.overview_actions_view);
-
+ ((RecentsView) getOverviewPanel()).init(mActionsView);
if (FeatureFlags.ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(this)) {
// Overview is above all other launcher elements, including qsb, so move it to the top.
getOverviewPanel().bringToFront();
- if (mActionsView != null) {
- mActionsView.bringToFront();
- }
+ mActionsView.bringToFront();
}
}
- public View getActionsView() {
- return mActionsView;
+ public <T extends OverviewActionsView> T getActionsView() {
+ return (T) mActionsView;
}
@Override
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index f83737e..5f5d6dc 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -177,7 +177,14 @@
}
private void setDepth(float depth) {
- mDepth = depth;
+ // Round out the depth to dedupe frequent, non-perceptable updates
+ int depthI = (int) (depth * 256);
+ float depthF = depthI / 256f;
+ if (Float.compare(mDepth, depthF) == 0) {
+ return;
+ }
+
+ mDepth = depthF;
if (mSurface == null || !mSurface.isValid()) {
return;
}
diff --git a/quickstep/src/com/android/quickstep/SysUINavigationMode.java b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
index 375e589..6a10b37 100644
--- a/quickstep/src/com/android/quickstep/SysUINavigationMode.java
+++ b/quickstep/src/com/android/quickstep/SysUINavigationMode.java
@@ -26,6 +26,7 @@
import com.android.launcher3.util.MainThreadInitializedObject;
+import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@@ -128,6 +129,11 @@
return getMode(context) != Mode.TWO_BUTTONS;
}
+ public void dump(PrintWriter pw) {
+ pw.println("SysUINavigationMode:");
+ pw.println(" mode=" + mMode.name());
+ }
+
public interface NavigationModeChangeListener {
void onNavigationModeChanged(Mode newMode);
diff --git a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
index ab2484d..a678cb5 100644
--- a/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
+++ b/quickstep/src/com/android/quickstep/util/QuickstepOnboardingPrefs.java
@@ -18,6 +18,8 @@
import static com.android.launcher3.LauncherState.ALL_APPS;
import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
+import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
import android.content.SharedPreferences;
@@ -58,7 +60,14 @@
});
}
- if (!getBoolean(SHELF_BOUNCE_SEEN)) {
+ boolean shelfBounceSeen = getBoolean(SHELF_BOUNCE_SEEN);
+ if (!shelfBounceSeen && ENABLE_OVERVIEW_ACTIONS.get()
+ && removeShelfFromOverview(launcher)) {
+ // There's no shelf in overview, so don't bounce it (can't get to all apps anyway).
+ shelfBounceSeen = true;
+ mSharedPrefs.edit().putBoolean(SHELF_BOUNCE_SEEN, shelfBounceSeen).apply();
+ }
+ if (!shelfBounceSeen) {
mStateManager.addStateListener(new StateListener() {
@Override
public void onStateTransitionStart(LauncherState toState) { }
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index de13277..a137908 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -45,12 +45,8 @@
<include
android:id="@+id/overview_panel"
- layout="@layout/overview_panel"
- android:visibility="gone" />
+ layout="@layout/overview_panel" />
- <include
- android:id="@+id/overview_actions_view"
- layout="@layout/overview_actions_container" />
<!-- Keep these behind the workspace so that they are not visible when
we go into AllApps -->
diff --git a/res/layout/overview_panel.xml b/res/layout/overview_panel.xml
index 2637f03..f513688 100644
--- a/res/layout/overview_panel.xml
+++ b/res/layout/overview_panel.xml
@@ -17,4 +17,5 @@
<Space
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
- android:layout_height="0dp" />
\ No newline at end of file
+ android:layout_height="0dp"
+ android:visibility="gone" />
\ No newline at end of file
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index f69c8ed..e4f201c 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -181,7 +181,9 @@
sourceContainer);
}
getUserEventDispatcher().logAppLaunch(v, intent, user);
- getStatsLogManager().log(APP_LAUNCH_TAP, item.buildProto(null, null));
+
+ getStatsLogManager().log(APP_LAUNCH_TAP, item == null ? null
+ : item.buildProto(null, null));
return true;
} catch (NullPointerException|ActivityNotFoundException|SecurityException e) {
Toast.makeText(this, R.string.activity_not_found, Toast.LENGTH_SHORT).show();
diff --git a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
index 3ee1293..f97eb28 100644
--- a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
+++ b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java
@@ -15,206 +15,90 @@
*/
package com.android.launcher3.allapps;
-import com.android.launcher3.util.Thunk;
+import androidx.recyclerview.widget.LinearSmoothScroller;
+import androidx.recyclerview.widget.RecyclerView.ViewHolder;
-import java.util.HashSet;
-import java.util.List;
+import com.android.launcher3.allapps.AlphabeticalAppsList.FastScrollSectionInfo;
-import androidx.recyclerview.widget.RecyclerView;
+public class AllAppsFastScrollHelper {
-public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallback {
+ private static final int NO_POSITION = -1;
- private static final int INITIAL_TOUCH_SETTLING_DURATION = 100;
- private static final int REPEAT_TOUCH_SETTLING_DURATION = 200;
+ private int mTargetFastScrollPosition = NO_POSITION;
private AllAppsRecyclerView mRv;
- private AlphabeticalAppsList mApps;
+ private ViewHolder mLastSelectedViewHolder;
- // Keeps track of the current and targeted fast scroll section (the section to scroll to after
- // the initial delay)
- int mTargetFastScrollPosition = -1;
- @Thunk String mCurrentFastScrollSection;
- @Thunk String mTargetFastScrollSection;
-
- // The settled states affect the delay before the fast scroll animation is applied
- private boolean mHasFastScrollTouchSettled;
- private boolean mHasFastScrollTouchSettledAtLeastOnce;
-
- // Set of all views animated during fast scroll. We keep track of these ourselves since there
- // is no way to reset a view once it gets scrapped or recycled without other hacks
- private HashSet<RecyclerView.ViewHolder> mTrackedFastScrollViews = new HashSet<>();
-
- // Smooth fast-scroll animation frames
- @Thunk int mFastScrollFrameIndex;
- @Thunk final int[] mFastScrollFrames = new int[10];
-
- /**
- * This runnable runs a single frame of the smooth scroll animation and posts the next frame
- * if necessary.
- */
- @Thunk Runnable mSmoothSnapNextFrameRunnable = new Runnable() {
- @Override
- public void run() {
- if (mFastScrollFrameIndex < mFastScrollFrames.length) {
- mRv.scrollBy(0, mFastScrollFrames[mFastScrollFrameIndex]);
- mFastScrollFrameIndex++;
- mRv.postOnAnimation(mSmoothSnapNextFrameRunnable);
- }
- }
- };
-
- /**
- * This runnable updates the current fast scroll section to the target fastscroll section.
- */
- Runnable mFastScrollToTargetSectionRunnable = new Runnable() {
- @Override
- public void run() {
- // Update to the target section
- mCurrentFastScrollSection = mTargetFastScrollSection;
- mHasFastScrollTouchSettled = true;
- mHasFastScrollTouchSettledAtLeastOnce = true;
- updateTrackedViewsFastScrollFocusState();
- }
- };
-
- public AllAppsFastScrollHelper(AllAppsRecyclerView rv, AlphabeticalAppsList apps) {
+ public AllAppsFastScrollHelper(AllAppsRecyclerView rv) {
mRv = rv;
- mApps = apps;
- }
-
- public void onSetAdapter(AllAppsGridAdapter adapter) {
- adapter.setBindViewCallback(this);
}
/**
* Smooth scrolls the recycler view to the given section.
- *
- * @return whether the fastscroller can scroll to the new section.
*/
- public boolean smoothScrollToSection(int scrollY, int availableScrollHeight,
- AlphabeticalAppsList.FastScrollSectionInfo info) {
- if (mTargetFastScrollPosition != info.fastScrollToItem.position) {
- mTargetFastScrollPosition = info.fastScrollToItem.position;
- smoothSnapToPosition(scrollY, availableScrollHeight, info);
- return true;
+ public void smoothScrollToSection(FastScrollSectionInfo info) {
+ if (mTargetFastScrollPosition == info.fastScrollToItem.position) {
+ return;
}
- return false;
- }
-
- /**
- * Smoothly snaps to a given position. We do this manually by calculating the keyframes
- * ourselves and animating the scroll on the recycler view.
- */
- private void smoothSnapToPosition(int scrollY, int availableScrollHeight,
- AlphabeticalAppsList.FastScrollSectionInfo info) {
- mRv.removeCallbacks(mSmoothSnapNextFrameRunnable);
- mRv.removeCallbacks(mFastScrollToTargetSectionRunnable);
-
- trackAllChildViews();
- if (mHasFastScrollTouchSettled) {
- // In this case, the user has already settled once (and the fast scroll state has
- // animated) and they are just fine-tuning their section from the last section, so
- // we should make it feel fast and update immediately.
- mCurrentFastScrollSection = info.sectionName;
- mTargetFastScrollSection = null;
- updateTrackedViewsFastScrollFocusState();
- } else {
- // Otherwise, the user has scrubbed really far, and we don't want to distract the user
- // with the flashing fast scroll state change animation in addition to the fast scroll
- // section popup, so reset the views to normal, and wait for the touch to settle again
- // before animating the fast scroll state.
- mCurrentFastScrollSection = null;
- mTargetFastScrollSection = info.sectionName;
- mHasFastScrollTouchSettled = false;
- updateTrackedViewsFastScrollFocusState();
-
- // Delay scrolling to a new section until after some duration. If the user has been
- // scrubbing a while and makes multiple big jumps, then reduce the time needed for the
- // fast scroll to settle so it doesn't feel so long.
- mRv.postDelayed(mFastScrollToTargetSectionRunnable,
- mHasFastScrollTouchSettledAtLeastOnce ?
- REPEAT_TOUCH_SETTLING_DURATION :
- INITIAL_TOUCH_SETTLING_DURATION);
- }
-
- // Calculate the full animation from the current scroll position to the final scroll
- // position, and then run the animation for the duration. If we are scrolling to the
- // first fast scroll section, then just scroll to the top of the list itself.
- List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
- mApps.getFastScrollerSections();
- int newPosition = info.fastScrollToItem.position;
- int newScrollY = fastScrollSections.size() > 0 && fastScrollSections.get(0) == info
- ? 0
- : Math.min(availableScrollHeight, mRv.getCurrentScrollY(newPosition, 0));
- int numFrames = mFastScrollFrames.length;
- int deltaY = newScrollY - scrollY;
- float ySign = Math.signum(deltaY);
- int step = (int) (ySign * Math.ceil((float) Math.abs(deltaY) / numFrames));
- for (int i = 0; i < numFrames; i++) {
- // TODO(winsonc): We can interpolate this as well.
- mFastScrollFrames[i] = (int) (ySign * Math.min(Math.abs(step), Math.abs(deltaY)));
- deltaY -= step;
- }
- mFastScrollFrameIndex = 0;
- mRv.postOnAnimation(mSmoothSnapNextFrameRunnable);
+ mTargetFastScrollPosition = info.fastScrollToItem.position;
+ mRv.getLayoutManager().startSmoothScroll(new MyScroller(mTargetFastScrollPosition));
}
public void onFastScrollCompleted() {
- // TODO(winsonc): Handle the case when the user scrolls and releases before the animation
- // runs
-
- // Stop animating the fast scroll position and state
- mRv.removeCallbacks(mSmoothSnapNextFrameRunnable);
- mRv.removeCallbacks(mFastScrollToTargetSectionRunnable);
-
- // Reset the tracking variables
- mHasFastScrollTouchSettled = false;
- mHasFastScrollTouchSettledAtLeastOnce = false;
- mCurrentFastScrollSection = null;
- mTargetFastScrollSection = null;
- mTargetFastScrollPosition = -1;
-
- updateTrackedViewsFastScrollFocusState();
- mTrackedFastScrollViews.clear();
+ mTargetFastScrollPosition = NO_POSITION;
+ setLastHolderSelected(false);
+ mLastSelectedViewHolder = null;
}
- @Override
- public void onBindView(AllAppsGridAdapter.ViewHolder holder) {
- // Update newly bound views to the current fast scroll state if we are fast scrolling
- if (mCurrentFastScrollSection != null || mTargetFastScrollSection != null) {
- mTrackedFastScrollViews.add(holder);
+
+ private void setLastHolderSelected(boolean isSelected) {
+ if (mLastSelectedViewHolder != null) {
+ mLastSelectedViewHolder.itemView.setActivated(isSelected);
+ mLastSelectedViewHolder.setIsRecyclable(!isSelected);
}
}
- /**
- * Starts tracking all the recycler view's children which are FastScrollFocusableViews.
- */
- private void trackAllChildViews() {
- int childCount = mRv.getChildCount();
- for (int i = 0; i < childCount; i++) {
- RecyclerView.ViewHolder viewHolder = mRv.getChildViewHolder(mRv.getChildAt(i));
- if (viewHolder != null) {
- mTrackedFastScrollViews.add(viewHolder);
- }
- }
- }
+ private class MyScroller extends LinearSmoothScroller {
- /**
- * Updates the fast scroll focus on all the children.
- */
- private void updateTrackedViewsFastScrollFocusState() {
- for (RecyclerView.ViewHolder viewHolder : mTrackedFastScrollViews) {
- int pos = viewHolder.getAdapterPosition();
- boolean isActive = false;
- if (mCurrentFastScrollSection != null
- && pos > RecyclerView.NO_POSITION
- && pos < mApps.getAdapterItems().size()) {
- AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(pos);
- isActive = item != null &&
- mCurrentFastScrollSection.equals(item.sectionName) &&
- item.position == mTargetFastScrollPosition;
+ private final int mTargetPosition;
+
+ public MyScroller(int targetPosition) {
+ super(mRv.getContext());
+
+ mTargetPosition = targetPosition;
+ setTargetPosition(targetPosition);
+ }
+
+ @Override
+ protected int getVerticalSnapPreference() {
+ return SNAP_TO_START;
+ }
+
+ @Override
+ protected void onStop() {
+ super.onStop();
+ if (mTargetPosition != mTargetFastScrollPosition) {
+ // Target changed, before the last scroll can finish
+ return;
}
- viewHolder.itemView.setActivated(isActive);
+
+ ViewHolder currentHolder = mRv.findViewHolderForAdapterPosition(mTargetPosition);
+ if (currentHolder == mLastSelectedViewHolder) {
+ return;
+ }
+
+ setLastHolderSelected(false);
+ mLastSelectedViewHolder = currentHolder;
+ setLastHolderSelected(true);
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (mTargetPosition != mTargetFastScrollPosition) {
+ setLastHolderSelected(false);
+ mLastSelectedViewHolder = null;
+ }
}
}
}
diff --git a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
index 4aebec0..3afa756 100644
--- a/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
+++ b/src/com/android/launcher3/allapps/AllAppsGridAdapter.java
@@ -71,11 +71,6 @@
public static final int VIEW_TYPE_MASK_DIVIDER = VIEW_TYPE_ALL_APPS_DIVIDER;
public static final int VIEW_TYPE_MASK_ICON = VIEW_TYPE_ICON;
-
- public interface BindViewCallback {
- void onBindView(ViewHolder holder);
- }
-
/**
* ViewHolder for each icon.
*/
@@ -186,7 +181,6 @@
private int mAppsPerRow;
- private BindViewCallback mBindViewCallback;
private OnFocusChangeListener mIconFocusListener;
// The text to show when there are no search results and no market search handler.
@@ -248,13 +242,6 @@
}
/**
- * Sets the callback for when views are bound.
- */
- public void setBindViewCallback(BindViewCallback cb) {
- mBindViewCallback = cb;
- }
-
- /**
* Returns the grid layout manager.
*/
public GridLayoutManager getLayoutManager() {
@@ -319,9 +306,6 @@
// nothing to do
break;
}
- if (mBindViewCallback != null) {
- mBindViewCallback.onBindView(holder);
- }
}
@Override
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index 069472f..cbf02b7 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -53,12 +53,12 @@
public class AllAppsRecyclerView extends BaseRecyclerView implements LogContainerProvider {
private AlphabeticalAppsList mApps;
- private AllAppsFastScrollHelper mFastScrollHelper;
private final int mNumAppsPerRow;
// The specific view heights that we use to calculate scroll
- private SparseIntArray mViewHeights = new SparseIntArray();
- private SparseIntArray mCachedScrollPositions = new SparseIntArray();
+ private final SparseIntArray mViewHeights = new SparseIntArray();
+ private final SparseIntArray mCachedScrollPositions = new SparseIntArray();
+ private final AllAppsFastScrollHelper mFastScrollHelper;
// The empty-search result background
private AllAppsBackgroundDrawable mEmptySearchBackground;
@@ -85,6 +85,7 @@
mEmptySearchBackgroundTopOffset = res.getDimensionPixelSize(
R.dimen.all_apps_empty_search_bg_top_offset);
mNumAppsPerRow = LauncherAppState.getIDP(context).numColumns;
+ mFastScrollHelper = new AllAppsFastScrollHelper(this);
}
/**
@@ -92,7 +93,6 @@
*/
public void setApps(AlphabeticalAppsList apps) {
mApps = apps;
- mFastScrollHelper = new AllAppsFastScrollHelper(this, apps);
}
public AlphabeticalAppsList getApps() {
@@ -221,9 +221,6 @@
return "";
}
- // Stop the scroller if it is scrolling
- stopScroll();
-
// Find the fastscroll section that maps to this touch fraction
List<AlphabeticalAppsList.FastScrollSectionInfo> fastScrollSections =
mApps.getFastScrollerSections();
@@ -236,10 +233,7 @@
lastInfo = info;
}
- // Update the fast scroll
- int scrollY = getCurrentScrollY();
- int availableScrollHeight = getAvailableScrollHeight();
- mFastScrollHelper.smoothScrollToSection(scrollY, availableScrollHeight, lastInfo);
+ mFastScrollHelper.smoothScrollToSection(lastInfo);
return lastInfo.sectionName;
}
@@ -257,7 +251,6 @@
mCachedScrollPositions.clear();
}
});
- mFastScrollHelper.onSetAdapter((AllAppsGridAdapter) adapter);
}
@Override
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index bcd91da..2b91cb1 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -168,6 +168,7 @@
for (DebugFlag flag : sDebugFlags) {
flag.initialize(context);
}
+ sDebugFlags.sort((f1, f2) -> f1.key.compareToIgnoreCase(f2.key));
}
}
@@ -178,10 +179,20 @@
}
public static void dump(PrintWriter pw) {
- pw.println("FeatureFlags:");
+ pw.println("DeviceFlags:");
synchronized (sDebugFlags) {
for (DebugFlag flag : sDebugFlags) {
- pw.println(" " + flag.key + "=" + flag.get());
+ if (flag instanceof DeviceFlag) {
+ pw.println(" " + flag.toString());
+ }
+ }
+ }
+ pw.println("DebugFlags:");
+ synchronized (sDebugFlags) {
+ for (DebugFlag flag : sDebugFlags) {
+ if (!(flag instanceof DeviceFlag)) {
+ pw.println(" " + flag.toString());
+ }
}
}
}
@@ -202,13 +213,11 @@
@Override
public String toString() {
- return appendProps(new StringBuilder()
- .append(getClass().getSimpleName()).append('{'))
- .append('}').toString();
+ return appendProps(new StringBuilder()).toString();
}
protected StringBuilder appendProps(StringBuilder src) {
- return src.append("key=").append(key).append(", defaultValue=").append(defaultValue);
+ return src.append(key).append(", defaultValue=").append(defaultValue);
}
public void addChangeListener(Context context, Runnable r) { }
@@ -240,8 +249,7 @@
@Override
protected StringBuilder appendProps(StringBuilder src) {
- return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue)
- .append(", description=").append(description);
+ return super.appendProps(src).append(", mCurrentValue=").append(mCurrentValue);
}
}
diff --git a/src/com/android/launcher3/folder/FolderNameInfo.java b/src/com/android/launcher3/folder/FolderNameInfo.java
index 1287219..1841cd9 100644
--- a/src/com/android/launcher3/folder/FolderNameInfo.java
+++ b/src/com/android/launcher3/folder/FolderNameInfo.java
@@ -50,6 +50,10 @@
return mLabel;
}
+ public double getScore() {
+ return mScore;
+ }
+
/**
* Used to package this object into a {@link Parcel}.
*
diff --git a/src/com/android/launcher3/util/MultiValueAlpha.java b/src/com/android/launcher3/util/MultiValueAlpha.java
index 07f835d..a8642b0 100644
--- a/src/com/android/launcher3/util/MultiValueAlpha.java
+++ b/src/com/android/launcher3/util/MultiValueAlpha.java
@@ -16,7 +16,7 @@
package com.android.launcher3.util;
-import android.util.Property;
+import android.util.FloatProperty;
import android.view.View;
import java.util.Arrays;
@@ -26,8 +26,8 @@
*/
public class MultiValueAlpha {
- public static final Property<AlphaProperty, Float> VALUE =
- new Property<AlphaProperty, Float>(Float.TYPE, "value") {
+ public static final FloatProperty<AlphaProperty> VALUE =
+ new FloatProperty<AlphaProperty>("value") {
@Override
public Float get(AlphaProperty alphaProperty) {
@@ -35,7 +35,7 @@
}
@Override
- public void set(AlphaProperty object, Float value) {
+ public void setValue(AlphaProperty object, float value) {
object.setValue(value);
}
};
diff --git a/src/com/android/launcher3/views/RecyclerViewFastScroller.java b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
index 5653801..6a83332 100644
--- a/src/com/android/launcher3/views/RecyclerViewFastScroller.java
+++ b/src/com/android/launcher3/views/RecyclerViewFastScroller.java
@@ -67,7 +67,6 @@
private final static int MAX_TRACK_ALPHA = 30;
private final static int SCROLL_BAR_VIS_DURATION = 150;
- private static final float FAST_SCROLL_OVERLAY_Y_OFFSET_FACTOR = 0.75f;
private static final List<Rect> SYSTEM_GESTURE_EXCLUSION_RECT =
Collections.singletonList(new Rect());
@@ -184,7 +183,7 @@
if (mThumbOffsetY == y) {
return;
}
- updatePopupY((int) y);
+ updatePopupY(y);
mThumbOffsetY = y;
invalidate();
}
@@ -237,7 +236,7 @@
} else if (mRv.supportsFastScrolling()
&& isNearScrollBar(mDownX)) {
calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY);
- updateFastScrollSectionNameAndThumbOffset(mLastY, y);
+ updateFastScrollSectionNameAndThumbOffset(y);
}
break;
case MotionEvent.ACTION_MOVE:
@@ -252,7 +251,7 @@
calcTouchOffsetAndPrepToFastScroll(mDownY, mLastY);
}
if (mIsDragging) {
- updateFastScrollSectionNameAndThumbOffset(mLastY, y);
+ updateFastScrollSectionNameAndThumbOffset(y);
}
break;
case MotionEvent.ACTION_UP:
@@ -281,7 +280,7 @@
showActiveScrollbar(true);
}
- private void updateFastScrollSectionNameAndThumbOffset(int lastY, int y) {
+ private void updateFastScrollSectionNameAndThumbOffset(int y) {
// Update the fastscroller section name at this touch position
int bottom = mRv.getScrollbarTrackHeight() - mThumbHeight;
float boundedY = (float) Math.max(0, Math.min(bottom, y - mTouchOffsetY));