Snap for 7422643 from f94a93ad2c to sc-v2-release
Change-Id: I8bc74d17141a15be606e7eeec92db95775c2c3c1
This commit is contained in:
@@ -53,14 +53,17 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
public static final int ERROR_PERMISSIONS = 1;
|
||||
private static final String TAG = "TaskOverlayFactoryGo";
|
||||
|
||||
// Empty constructor required for ResourceBasedOverride
|
||||
public TaskOverlayFactoryGo(Context context) {}
|
||||
private AssistContentRequester mContentRequester;
|
||||
|
||||
public TaskOverlayFactoryGo(Context context) {
|
||||
mContentRequester = new AssistContentRequester(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new overlay instance for the given View
|
||||
*/
|
||||
public TaskOverlayGo createOverlay(TaskThumbnailView thumbnailView) {
|
||||
return new TaskOverlayGo(thumbnailView);
|
||||
return new TaskOverlayGo(thumbnailView, mContentRequester);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,9 +75,12 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
private String mTaskPackageName;
|
||||
private String mWebUrl;
|
||||
private boolean mAssistPermissionsEnabled;
|
||||
private AssistContentRequester mFactoryContentRequester;
|
||||
|
||||
private TaskOverlayGo(TaskThumbnailView taskThumbnailView) {
|
||||
private TaskOverlayGo(TaskThumbnailView taskThumbnailView,
|
||||
AssistContentRequester assistContentRequester) {
|
||||
super(taskThumbnailView);
|
||||
mFactoryContentRequester = assistContentRequester;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -105,9 +111,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
}
|
||||
|
||||
int taskId = task.key.id;
|
||||
AssistContentRequester contentRequester =
|
||||
new AssistContentRequester(mApplicationContext);
|
||||
contentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
|
||||
mFactoryContentRequester.requestAssistContent(taskId, this::onAssistContentReceived);
|
||||
}
|
||||
|
||||
/** Provide Assist Content to the overlay. */
|
||||
|
||||
@@ -45,8 +45,9 @@
|
||||
|
||||
<!-- These speeds are in dp/s -->
|
||||
<dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
|
||||
<dimen name="default_task_dismiss_drag_velocity">1.75dp</dimen>
|
||||
<dimen name="default_task_dismiss_drag_velocity_grid">0.75dp</dimen>
|
||||
<dimen name="default_task_dismiss_drag_velocity">1.5dp</dimen>
|
||||
<dimen name="default_task_dismiss_drag_velocity_grid">1dp</dimen>
|
||||
<dimen name="default_task_dismiss_drag_velocity_grid_focus_task">5dp</dimen>
|
||||
|
||||
<dimen name="recents_page_spacing">16dp</dimen>
|
||||
<dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
|
||||
|
||||
@@ -1416,14 +1416,14 @@ public class QuickstepTransitionManager implements OnDeviceProfileChangeListener
|
||||
: APP_LAUNCH_ALPHA_DOWN_DURATION;
|
||||
iconAlphaStart = hasSplashScreen && !hasDifferentAppIcon ? 0 : 1f;
|
||||
|
||||
// TOOD: Share value from shell when available.
|
||||
final float windowIconSize = Utilities.pxFromSp(108, r.getDisplayMetrics());
|
||||
final int windowIconSize = ResourceUtils.getDimenByName("starting_surface_icon_size",
|
||||
r, 108);
|
||||
|
||||
cropCenterXStart = windowTargetBounds.centerX();
|
||||
cropCenterYStart = windowTargetBounds.centerY();
|
||||
|
||||
cropWidthStart = (int) windowIconSize;
|
||||
cropHeightStart = (int) windowIconSize;
|
||||
cropWidthStart = windowIconSize;
|
||||
cropHeightStart = windowIconSize;
|
||||
|
||||
cropWidthEnd = windowTargetBounds.width();
|
||||
cropHeightEnd = windowTargetBounds.height();
|
||||
|
||||
+36
-12
@@ -21,6 +21,7 @@ import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_BOTH
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.os.SystemClock;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -72,6 +73,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
private float mProgressMultiplier;
|
||||
private float mEndDisplacement;
|
||||
private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
|
||||
private Float mOverrideVelocity = null;
|
||||
|
||||
private TaskView mTaskBeingDragged;
|
||||
|
||||
@@ -268,6 +270,7 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
mCurrentAnimation.pause();
|
||||
}
|
||||
mFlingBlockCheck.unblockFling();
|
||||
mOverrideVelocity = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -283,19 +286,36 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
mFlingBlockCheck.onEvent();
|
||||
}
|
||||
|
||||
// Once halfway through task dismissal interpolation, switch from reversible dragging-task
|
||||
// animation to playing the remaining task translation animations
|
||||
if (mCurrentAnimation.getProgressFraction() < ANIMATION_PROGRESS_FRACTION_MIDPOINT) {
|
||||
// Halve the value as we are animating the drag across the full length for only the
|
||||
// first half of the progress
|
||||
mCurrentAnimation.setPlayFraction(
|
||||
Utilities.boundToRange(totalDisplacement * mProgressMultiplier / 2, 0, 1));
|
||||
if (isGoingUp) {
|
||||
if (mCurrentAnimation.getProgressFraction() < ANIMATION_PROGRESS_FRACTION_MIDPOINT) {
|
||||
// Halve the value when dismissing, as we are animating the drag across the full
|
||||
// length for only the first half of the progress
|
||||
mCurrentAnimation.setPlayFraction(
|
||||
Utilities.boundToRange(totalDisplacement * mProgressMultiplier / 2, 0, 1));
|
||||
} else {
|
||||
// Set mOverrideVelocity to control task dismiss velocity in onDragEnd
|
||||
int velocityDimenId = R.dimen.default_task_dismiss_drag_velocity;
|
||||
if (mRecentsView.showAsGrid()) {
|
||||
if (mTaskBeingDragged.isFocusedTask()) {
|
||||
velocityDimenId =
|
||||
R.dimen.default_task_dismiss_drag_velocity_grid_focus_task;
|
||||
} else {
|
||||
velocityDimenId = R.dimen.default_task_dismiss_drag_velocity_grid;
|
||||
}
|
||||
}
|
||||
mOverrideVelocity = -mTaskBeingDragged.getResources().getDimension(velocityDimenId);
|
||||
|
||||
// Once halfway through task dismissal interpolation, switch from reversible
|
||||
// dragging-task animation to playing the remaining task translation animations
|
||||
final long now = SystemClock.uptimeMillis();
|
||||
MotionEvent upAction = MotionEvent.obtain(now, now,
|
||||
MotionEvent.ACTION_UP, 0.0f, 0.0f, 0);
|
||||
mDetector.onTouchEvent(upAction);
|
||||
upAction.recycle();
|
||||
}
|
||||
} else {
|
||||
float dragVelocity = -mTaskBeingDragged.getResources().getDimension(
|
||||
mRecentsView.showAsGrid() ? R.dimen.default_task_dismiss_drag_velocity_grid
|
||||
: R.dimen.default_task_dismiss_drag_velocity);
|
||||
onDragEnd(dragVelocity);
|
||||
return true;
|
||||
mCurrentAnimation.setPlayFraction(
|
||||
Utilities.boundToRange(totalDisplacement * mProgressMultiplier, 0, 1));
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -303,6 +323,10 @@ public abstract class TaskViewTouchController<T extends BaseDraggingActivity>
|
||||
|
||||
@Override
|
||||
public void onDragEnd(float velocity) {
|
||||
if (mOverrideVelocity != null) {
|
||||
velocity = mOverrideVelocity;
|
||||
mOverrideVelocity = null;
|
||||
}
|
||||
// Limit velocity, as very large scalar values make animations play too quickly
|
||||
float maxTaskDismissDragVelocity = mTaskBeingDragged.getResources().getDimension(
|
||||
R.dimen.max_task_dismiss_drag_velocity);
|
||||
|
||||
@@ -972,6 +972,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
}
|
||||
if (endTarget == HOME) {
|
||||
duration = HOME_DURATION;
|
||||
// Early detach the nav bar once the endTarget is determined as HOME
|
||||
if (mRecentsAnimationController != null) {
|
||||
mRecentsAnimationController.detachNavigationBarFromApp(true);
|
||||
}
|
||||
} else if (endTarget == RECENTS) {
|
||||
if (mRecentsView != null) {
|
||||
int nearestPage = mRecentsView.getDestinationPage();
|
||||
@@ -1496,7 +1500,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
if (LIVE_TILE.get()) {
|
||||
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
if (mRecentsAnimationController != null) {
|
||||
mRecentsAnimationController.getController().detachNavigationBarFromApp(true);
|
||||
mRecentsAnimationController.detachNavigationBarFromApp(true);
|
||||
}
|
||||
} else if (!hasTargets() || mRecentsAnimationController == null) {
|
||||
// If there are no targets or the animation not started, then there is nothing to finish
|
||||
|
||||
@@ -154,6 +154,14 @@ public class RecentsAnimationController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RecentsAnimationControllerCompat#detachNavigationBarFromApp
|
||||
*/
|
||||
@UiThread
|
||||
public void detachNavigationBarFromApp(boolean moveHomeToTop) {
|
||||
UI_HELPER_EXECUTOR.execute(() -> mController.detachNavigationBarFromApp(moveHomeToTop));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the final surface transaction on a Task. This is used by Launcher to notify the system
|
||||
* that animating Activity to PiP has completed and the associated task surface should be
|
||||
|
||||
@@ -54,6 +54,7 @@ public class AssistContentRequester {
|
||||
private final IActivityTaskManager mActivityTaskManager;
|
||||
private final String mPackageName;
|
||||
private final Executor mCallbackExecutor;
|
||||
private final Executor mSystemInteractionExecutor;
|
||||
|
||||
// If system loses the callback, our internal cache of original callback will also get cleared.
|
||||
private final Map<Object, Callback> mPendingCallbacks =
|
||||
@@ -63,6 +64,7 @@ public class AssistContentRequester {
|
||||
mActivityTaskManager = ActivityTaskManager.getService();
|
||||
mPackageName = context.getApplicationContext().getPackageName();
|
||||
mCallbackExecutor = Executors.MAIN_EXECUTOR;
|
||||
mSystemInteractionExecutor = Executors.UI_HELPER_EXECUTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,13 +73,16 @@ public class AssistContentRequester {
|
||||
* @param taskId to query for the content.
|
||||
* @param callback to call when the content is available, called on the main thread.
|
||||
*/
|
||||
public void requestAssistContent(int taskId, Callback callback) {
|
||||
try {
|
||||
mActivityTaskManager.requestAssistDataForTask(
|
||||
new AssistDataReceiver(callback, this), taskId, mPackageName);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Requesting assist content failed for task: " + taskId, e);
|
||||
}
|
||||
public void requestAssistContent(final int taskId, final Callback callback) {
|
||||
// ActivityTaskManager interaction here is synchronous, so call off the main thread.
|
||||
mSystemInteractionExecutor.execute(() -> {
|
||||
try {
|
||||
mActivityTaskManager.requestAssistDataForTask(
|
||||
new AssistDataReceiver(callback, this), taskId, mPackageName);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Requesting assist content failed for task: " + taskId, e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void executeOnMainExecutor(Runnable callback) {
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2021, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@android:color/system_neutral1_900" android:alpha="0.8" />
|
||||
</selector>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2021, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="@android:color/system_neutral1_200" android:alpha="0.8" />
|
||||
</selector>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
**
|
||||
** Copyright 2021, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:color="#000000" android:alpha="0.32" />
|
||||
</selector>
|
||||
@@ -31,7 +31,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@drawable/add_item_dialog_background"
|
||||
android:padding="24dp"
|
||||
android:paddingTop="24dp"
|
||||
android:theme="?attr/widgetsTheme"
|
||||
android:layout_gravity="bottom"
|
||||
android:orientation="vertical">
|
||||
@@ -42,6 +42,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:textColor="?android:attr/textColorPrimary"
|
||||
android:textSize="24sp"
|
||||
android:ellipsize="end"
|
||||
@@ -53,6 +54,7 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:paddingHorizontal="24dp"
|
||||
android:paddingTop="8dp"
|
||||
android:text="@string/add_item_request_drag_hint"
|
||||
android:textSize="14sp"
|
||||
|
||||
@@ -25,8 +25,7 @@
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="?android:attr/colorBackground"
|
||||
android:elevation="4dp">
|
||||
android:background="?android:attr/colorBackground">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/no_widgets_text"
|
||||
|
||||
@@ -36,7 +36,6 @@ import android.graphics.Rect;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.DisplayMetrics;
|
||||
import android.util.Log;
|
||||
import android.util.SparseArray;
|
||||
import android.util.TypedValue;
|
||||
import android.util.Xml;
|
||||
@@ -45,7 +44,6 @@ import android.view.Display;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.testing.TestProtocol;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.launcher3.util.DisplayController.Info;
|
||||
import com.android.launcher3.util.IntArray;
|
||||
@@ -250,17 +248,10 @@ public class InvariantDeviceProfile {
|
||||
|
||||
private String initGrid(Context context, String gridName) {
|
||||
Info displayInfo = DisplayController.INSTANCE.get(context).getInfo();
|
||||
// Determine if we have split display
|
||||
|
||||
boolean isTablet = false, isPhone = false;
|
||||
for (WindowBounds bounds : displayInfo.supportedBounds) {
|
||||
if (displayInfo.isTablet(bounds)) {
|
||||
isTablet = true;
|
||||
} else {
|
||||
isPhone = true;
|
||||
}
|
||||
}
|
||||
boolean isSplitDisplay = isPhone && isTablet && ENABLE_TWO_PANEL_HOME.get();
|
||||
// Each screen has two profiles (portrait/landscape), so devices with four or more
|
||||
// supported profiles implies two or more internal displays.
|
||||
boolean isSplitDisplay =
|
||||
displayInfo.supportedBounds.size() >= 4 && ENABLE_TWO_PANEL_HOME.get();
|
||||
|
||||
ArrayList<DisplayOption> allOptions =
|
||||
getPredefinedDeviceProfiles(context, gridName, isSplitDisplay);
|
||||
|
||||
@@ -59,6 +59,7 @@ import com.android.launcher3.pm.PinRequestHelper;
|
||||
import com.android.launcher3.util.SystemUiController;
|
||||
import com.android.launcher3.views.AbstractSlideInView;
|
||||
import com.android.launcher3.views.BaseDragLayer;
|
||||
import com.android.launcher3.widget.AddItemWidgetsBottomSheet;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetHost;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.NavigableAppWidgetHostView;
|
||||
@@ -89,6 +90,7 @@ public class AddItemActivity extends BaseActivity
|
||||
private LauncherAppState mApp;
|
||||
private InvariantDeviceProfile mIdp;
|
||||
private BaseDragLayer<AddItemActivity> mDragLayer;
|
||||
private AddItemWidgetsBottomSheet mSlideInView;
|
||||
|
||||
private WidgetCell mWidgetCell;
|
||||
|
||||
@@ -124,8 +126,6 @@ public class AddItemActivity extends BaseActivity
|
||||
mDragLayer = findViewById(R.id.add_item_drag_layer);
|
||||
mDragLayer.recreateControllers();
|
||||
mDragLayer.setInsets(mDeviceProfile.getInsets());
|
||||
AbstractSlideInView<AddItemActivity> slideInView = findViewById(R.id.add_item_bottom_sheet);
|
||||
slideInView.addOnCloseListener(this);
|
||||
mWidgetCell = findViewById(R.id.widget_cell);
|
||||
|
||||
if (mRequest.getRequestType() == PinItemRequest.REQUEST_TYPE_SHORTCUT) {
|
||||
@@ -151,6 +151,9 @@ public class AddItemActivity extends BaseActivity
|
||||
TextView widgetAppName = findViewById(R.id.widget_appName);
|
||||
widgetAppName.setText(getApplicationInfo().labelRes);
|
||||
|
||||
mSlideInView = findViewById(R.id.add_item_bottom_sheet);
|
||||
mSlideInView.addOnCloseListener(this);
|
||||
mSlideInView.show();
|
||||
setupNavBarColor();
|
||||
}
|
||||
|
||||
@@ -279,7 +282,7 @@ public class AddItemActivity extends BaseActivity
|
||||
*/
|
||||
public void onCancelClick(View v) {
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_CANCELLED);
|
||||
finish();
|
||||
mSlideInView.close(/* animate= */ true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +293,7 @@ public class AddItemActivity extends BaseActivity
|
||||
ItemInstallQueue.INSTANCE.get(this).queueItem(mRequest.getShortcutInfo());
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY);
|
||||
mRequest.accept();
|
||||
finish();
|
||||
mSlideInView.close(/* animate= */ true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -313,7 +316,7 @@ public class AddItemActivity extends BaseActivity
|
||||
mWidgetOptions.putInt(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
|
||||
mRequest.accept(mWidgetOptions);
|
||||
logCommand(LAUNCHER_ADD_EXTERNAL_ITEM_PLACED_AUTOMATICALLY);
|
||||
finish();
|
||||
mSlideInView.close(/* animate= */ true);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,8 +35,6 @@ public class WidgetsEduView extends AbstractSlideInView<Launcher> implements Ins
|
||||
|
||||
private static final int DEFAULT_CLOSE_DURATION = 200;
|
||||
|
||||
protected static final int FINAL_SCRIM_BG_COLOR = 0x88000000;
|
||||
|
||||
private Rect mInsets = new Rect();
|
||||
private View mEduView;
|
||||
|
||||
@@ -87,7 +85,7 @@ public class WidgetsEduView extends AbstractSlideInView<Launcher> implements Ins
|
||||
|
||||
@Override
|
||||
protected int getScrimColor(Context context) {
|
||||
return FINAL_SCRIM_BG_COLOR;
|
||||
return context.getResources().getColor(R.color.widgets_picker_scrim);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,8 +23,11 @@ import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Rect;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.dragndrop.AddItemActivity;
|
||||
import com.android.launcher3.views.AbstractSlideInView;
|
||||
|
||||
@@ -48,6 +51,17 @@ public class AddItemWidgetsBottomSheet extends AbstractSlideInView<AddItemActivi
|
||||
mContent = this;
|
||||
mInsets = new Rect();
|
||||
mCurrentConfiguration = new Configuration(getResources().getConfiguration());
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches to activity container and animates open the bottom sheet.
|
||||
*/
|
||||
public void show() {
|
||||
ViewParent parent = getParent();
|
||||
if (parent instanceof ViewGroup) {
|
||||
((ViewGroup) parent).removeView(this);
|
||||
}
|
||||
attachToContainer();
|
||||
animateOpen();
|
||||
}
|
||||
|
||||
@@ -95,4 +109,9 @@ public class AddItemWidgetsBottomSheet extends AbstractSlideInView<AddItemActivi
|
||||
}
|
||||
mCurrentConfiguration.updateFrom(newConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getScrimColor(Context context) {
|
||||
return context.getResources().getColor(R.color.widgets_picker_scrim);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package com.android.launcher3.widget;
|
||||
|
||||
import static com.android.launcher3.icons.GraphicsUtils.setColorAlphaBound;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.Rect;
|
||||
@@ -62,8 +60,7 @@ public abstract class BaseWidgetSheet extends AbstractSlideInView<Launcher>
|
||||
}
|
||||
|
||||
protected int getScrimColor(Context context) {
|
||||
int alpha = context.getResources().getInteger(R.integer.extracted_color_gradient_alpha);
|
||||
return setColorAlphaBound(context.getColor(R.color.wallpaper_popup_scrim), alpha);
|
||||
return context.getResources().getColor(R.color.widgets_picker_scrim);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.view.View.OnLongClickListener;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TableRow;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import androidx.recyclerview.widget.RecyclerView.Adapter;
|
||||
@@ -48,8 +49,10 @@ import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
/**
|
||||
* Recycler view adapter for the widget tray.
|
||||
@@ -87,6 +90,7 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
|| new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
|
||||
.equals(mWidgetsContentVisiblePackageUserKey);
|
||||
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
|
||||
@Nullable private RecyclerView mRecyclerView;
|
||||
|
||||
public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
|
||||
WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache,
|
||||
@@ -106,6 +110,16 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
layoutInflater, /*onHeaderClickListener=*/ this, /* listAdapter= */ this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
mRecyclerView = recyclerView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
|
||||
mRecyclerView = null;
|
||||
}
|
||||
|
||||
public void setFilter(Predicate<WidgetsListBaseEntry> filter) {
|
||||
mFilter = filter;
|
||||
}
|
||||
@@ -168,12 +182,10 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
mAllEntries.forEach(entry -> {
|
||||
if (entry instanceof WidgetsListHeaderEntry) {
|
||||
((WidgetsListHeaderEntry) entry).setIsWidgetListShown(
|
||||
new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
|
||||
.equals(mWidgetsContentVisiblePackageUserKey));
|
||||
isHeaderForVisibleContent(entry));
|
||||
} else if (entry instanceof WidgetsListSearchHeaderEntry) {
|
||||
((WidgetsListSearchHeaderEntry) entry).setIsWidgetListShown(
|
||||
new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
|
||||
.equals(mWidgetsContentVisiblePackageUserKey));
|
||||
isHeaderForVisibleContent(entry));
|
||||
}
|
||||
});
|
||||
List<WidgetsListBaseEntry> newVisibleEntries = mAllEntries.stream()
|
||||
@@ -183,6 +195,13 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
mDiffReporter.process(mVisibleEntries, newVisibleEntries, mRowComparator);
|
||||
}
|
||||
|
||||
private boolean isHeaderForVisibleContent(WidgetsListBaseEntry entry) {
|
||||
return (entry instanceof WidgetsListHeaderEntry
|
||||
|| entry instanceof WidgetsListSearchHeaderEntry)
|
||||
&& new PackageUserKey(entry.mPkgItem.packageName, entry.mPkgItem.user)
|
||||
.equals(mWidgetsContentVisiblePackageUserKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets any expanded widget header.
|
||||
*/
|
||||
@@ -247,12 +266,40 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
if (showWidgets) {
|
||||
mWidgetsContentVisiblePackageUserKey = packageUserKey;
|
||||
updateVisibleEntries();
|
||||
// Scroll the layout manager to the header position to keep it anchored to the same
|
||||
// position.
|
||||
scrollToSelectedHeaderPosition();
|
||||
} else if (packageUserKey.equals(mWidgetsContentVisiblePackageUserKey)) {
|
||||
mWidgetsContentVisiblePackageUserKey = null;
|
||||
updateVisibleEntries();
|
||||
}
|
||||
}
|
||||
|
||||
private void scrollToSelectedHeaderPosition() {
|
||||
OptionalInt selectedHeaderPosition =
|
||||
IntStream.range(0, mVisibleEntries.size())
|
||||
.filter(index -> isHeaderForVisibleContent(mVisibleEntries.get(index)))
|
||||
.findFirst();
|
||||
RecyclerView.LayoutManager layoutManager =
|
||||
mRecyclerView == null ? null : mRecyclerView.getLayoutManager();
|
||||
if (!selectedHeaderPosition.isPresent() || layoutManager == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Scroll to the selected header position. LinearLayoutManager scrolls the minimum distance
|
||||
// necessary, so this will keep the selected header in place during clicks, without
|
||||
// interrupting the animation.
|
||||
int position = selectedHeaderPosition.getAsInt();
|
||||
if (position == mVisibleEntries.size() - 2) {
|
||||
// If the selected header is in the last position (-1 for the content), then scroll to
|
||||
// the final position so the last list of widgets will show.
|
||||
layoutManager.scrollToPosition(mVisibleEntries.size() - 1);
|
||||
} else {
|
||||
// Otherwise, scroll to the position of the selected header.
|
||||
layoutManager.scrollToPosition(position);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the max horizontal spans that are allowed for grouping more than one widgets in a table
|
||||
* row.
|
||||
|
||||
@@ -154,8 +154,25 @@ public class WidgetsRecyclerView extends BaseRecyclerView implements OnItemTouch
|
||||
return -1;
|
||||
}
|
||||
|
||||
View child = getChildAt(0);
|
||||
int rowIndex = getChildPosition(child);
|
||||
int rowIndex = -1;
|
||||
View child = null;
|
||||
|
||||
LayoutManager layoutManager = getLayoutManager();
|
||||
if (layoutManager instanceof LinearLayoutManager) {
|
||||
// Use the LayoutManager as the source of truth for visible positions. During
|
||||
// animations, the view group child may not correspond to the visible views that appear
|
||||
// at the top.
|
||||
rowIndex = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
|
||||
child = layoutManager.findViewByPosition(rowIndex);
|
||||
}
|
||||
|
||||
if (child == null) {
|
||||
// If the layout manager returns null for any reason, which can happen before layout
|
||||
// has occurred for the position, then look at the child of this view as a ViewGroup.
|
||||
child = getChildAt(0);
|
||||
rowIndex = getChildPosition(child);
|
||||
}
|
||||
|
||||
for (int i = 0; i < getChildCount(); i++) {
|
||||
View view = getChildAt(i);
|
||||
if (view instanceof TableLayout) {
|
||||
|
||||
Reference in New Issue
Block a user