Snap for 7236705 from 0a74a35a41 to sc-v2-release
Change-Id: Ic8607f7b47f5e8c84474793cecf2fd31b83b569b
This commit is contained in:
@@ -10,5 +10,5 @@
|
||||
<!-- Label for a button that translates a screenshot of the current app. [CHAR_LIMIT=40] -->
|
||||
<string name="action_translate">Translate</string>
|
||||
<!-- Label for a button that triggers Search on a screenshot of the current app. [CHAR_LIMIT=40] -->
|
||||
<string name="action_search">Search</string>
|
||||
<string name="action_search">Lens</string>
|
||||
</resources>
|
||||
|
||||
@@ -36,6 +36,8 @@ import android.os.SystemClock;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.TaskThumbnailView;
|
||||
@@ -51,6 +53,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
public static final String ACTION_SEARCH = "com.android.quickstep.ACTION_SEARCH";
|
||||
public static final String ELAPSED_NANOS = "niu_actions_elapsed_realtime_nanos";
|
||||
public static final String ACTIONS_URL = "niu_actions_app_url";
|
||||
private static final String ASSIST_KEY_CONTENT = "content";
|
||||
private static final String TAG = "TaskOverlayFactoryGo";
|
||||
|
||||
// Empty constructor required for ResourceBasedOverride
|
||||
@@ -68,8 +71,6 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
* @param <T> The type of View in which the overlay will be placed
|
||||
*/
|
||||
public static final class TaskOverlayGo<T extends OverviewActionsView> extends TaskOverlay {
|
||||
private static final String ASSIST_KEY_CONTENT = "content";
|
||||
|
||||
private String mNIUPackageName;
|
||||
private int mTaskId;
|
||||
private Bundle mAssistData;
|
||||
@@ -95,7 +96,7 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
}
|
||||
|
||||
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
|
||||
boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
|
||||
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
|
||||
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
|
||||
|
||||
mTaskId = task.key.id;
|
||||
@@ -122,7 +123,11 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
});
|
||||
}
|
||||
|
||||
private void sendNIUIntent(String actionType) {
|
||||
/**
|
||||
* Creates and sends an Intent corresponding to the button that was clicked
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void sendNIUIntent(String actionType) {
|
||||
Intent intent = createNIUIntent(actionType);
|
||||
mImageApi.shareAsDataWithExplicitIntent(/* crop */ null, intent);
|
||||
}
|
||||
@@ -178,6 +183,11 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
public void setImageActionsAPI(ImageActionsApi imageActionsApi) {
|
||||
mImageApi = imageActionsApi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -22,5 +22,4 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/recents_clear_all"
|
||||
android:textColor="?attr/workspaceTextColor"
|
||||
android:textSize="14sp"
|
||||
android:translationY="@dimen/task_thumbnail_half_top_margin" />
|
||||
android:textSize="14sp" />
|
||||
@@ -13,6 +13,8 @@
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
<!-- NOTE! don't add dimensions for margins / paddings / sizes that change per orientation to this
|
||||
file, they need to be loaded at runtime. -->
|
||||
<com.android.quickstep.views.TaskView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
@@ -24,8 +26,7 @@
|
||||
<com.android.quickstep.views.TaskThumbnailView
|
||||
android:id="@+id/snapshot"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="@dimen/task_thumbnail_top_margin"/>
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<com.android.quickstep.views.IconView
|
||||
android:id="@+id/icon"
|
||||
|
||||
@@ -16,4 +16,6 @@
|
||||
-->
|
||||
<resources>
|
||||
<dimen name="task_card_menu_horizontal_padding">24dp</dimen>
|
||||
|
||||
<dimen name="overview_task_margin">8dp</dimen>
|
||||
</resources>
|
||||
@@ -15,11 +15,8 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
|
||||
<dimen name="task_thumbnail_top_margin">80dp</dimen>
|
||||
<dimen name="task_thumbnail_half_top_margin">40dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_size">48dp</dimen>
|
||||
<dimen name="task_icon_top_margin">16dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_size_grid">32dp</dimen>
|
||||
<!-- For screens without rounded corners -->
|
||||
<dimen name="task_corner_radius_small">2dp</dimen>
|
||||
|
||||
|
||||
@@ -335,13 +335,17 @@ public abstract class BaseQuickstepLauncher extends Launcher
|
||||
? new float[] {1, 1} : new float[] {1.1f, 0};
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getNormalTaskbarScale() {
|
||||
if (mTaskbarController != null) {
|
||||
return mTaskbarController.getTaskbarScaleOnHome();
|
||||
}
|
||||
return super.getNormalTaskbarScale();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragLayerHierarchyChanged() {
|
||||
onLauncherStateOrFocusChanged();
|
||||
|
||||
if (mTaskbarController != null) {
|
||||
mTaskbarController.onLauncherDragLayerHierarchyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,14 +35,13 @@ public class TaskbarActivityContext extends ContextWrapper implements ActivityCo
|
||||
private final DeviceProfile mDeviceProfile;
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final TaskbarContainerView mTaskbarContainerView;
|
||||
private final float mIconScale;
|
||||
|
||||
public TaskbarActivityContext(BaseQuickstepLauncher launcher) {
|
||||
super(launcher);
|
||||
mDeviceProfile = launcher.getDeviceProfile().copy(this);
|
||||
float taskbarIconSize = getResources().getDimension(R.dimen.taskbar_icon_size);
|
||||
mIconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
|
||||
mDeviceProfile.updateIconSize(mIconScale, getResources());
|
||||
float iconScale = taskbarIconSize / mDeviceProfile.iconSizePx;
|
||||
mDeviceProfile.updateIconSize(iconScale, getResources());
|
||||
|
||||
mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
|
||||
|
||||
@@ -73,11 +72,4 @@ public class TaskbarActivityContext extends ContextWrapper implements ActivityCo
|
||||
public Rect getFolderBoundingBox() {
|
||||
return mTaskbarContainerView.getFolderBoundingBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The ratio of taskbar icon size vs normal workspace/hotseat icon size.
|
||||
*/
|
||||
public float getTaskbarIconScale() {
|
||||
return mIconScale;
|
||||
}
|
||||
}
|
||||
|
||||
+29
-20
@@ -20,36 +20,38 @@ import static com.android.launcher3.LauncherState.TASKBAR;
|
||||
import android.animation.Animator;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
|
||||
/**
|
||||
* Works with TaskbarController to update the TaskbarView's alpha based on LauncherState, whether
|
||||
* Launcher is in the foreground, etc.
|
||||
* Works with TaskbarController to update the TaskbarView's visual properties based on factors such
|
||||
* as LauncherState, whether Launcher is in the foreground, etc.
|
||||
*/
|
||||
public class TaskbarVisibilityController {
|
||||
public class TaskbarAnimationController {
|
||||
|
||||
private static final long IME_VISIBILITY_ALPHA_DURATION = 120;
|
||||
private static final long FLOATING_VIEW_VISIBILITY_ALPHA_DURATION = 120;
|
||||
|
||||
private final BaseQuickstepLauncher mLauncher;
|
||||
private final TaskbarController.TaskbarVisibilityControllerCallbacks mTaskbarCallbacks;
|
||||
private final TaskbarController.TaskbarAnimationControllerCallbacks mTaskbarCallbacks;
|
||||
|
||||
// Background alpha.
|
||||
private AnimatedFloat mTaskbarBackgroundAlpha = new AnimatedFloat(
|
||||
private final AnimatedFloat mTaskbarBackgroundAlpha = new AnimatedFloat(
|
||||
this::onTaskbarBackgroundAlphaChanged);
|
||||
|
||||
// Overall visibility.
|
||||
private AnimatedFloat mTaskbarVisibilityAlphaForLauncherState = new AnimatedFloat(
|
||||
private final AnimatedFloat mTaskbarVisibilityAlphaForLauncherState = new AnimatedFloat(
|
||||
this::updateVisibilityAlpha);
|
||||
private AnimatedFloat mTaskbarVisibilityAlphaForIme = new AnimatedFloat(
|
||||
this::updateVisibilityAlpha);
|
||||
private AnimatedFloat mTaskbarVisibilityAlphaForFloatingView = new AnimatedFloat(
|
||||
private final AnimatedFloat mTaskbarVisibilityAlphaForIme = new AnimatedFloat(
|
||||
this::updateVisibilityAlpha);
|
||||
|
||||
public TaskbarVisibilityController(BaseQuickstepLauncher launcher,
|
||||
TaskbarController.TaskbarVisibilityControllerCallbacks taskbarCallbacks) {
|
||||
// Scale.
|
||||
private final AnimatedFloat mTaskbarScaleForLauncherState = new AnimatedFloat(
|
||||
this::updateScale);
|
||||
|
||||
public TaskbarAnimationController(BaseQuickstepLauncher launcher,
|
||||
TaskbarController.TaskbarAnimationControllerCallbacks taskbarCallbacks) {
|
||||
mLauncher = launcher;
|
||||
mTaskbarCallbacks = taskbarCallbacks;
|
||||
}
|
||||
@@ -62,7 +64,6 @@ public class TaskbarVisibilityController {
|
||||
boolean isImeVisible = (SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags()
|
||||
& QuickStepContract.SYSUI_STATE_IME_SHOWING) != 0;
|
||||
mTaskbarVisibilityAlphaForIme.updateValue(isImeVisible ? 0f : 1f);
|
||||
mTaskbarVisibilityAlphaForFloatingView.updateValue(1f);
|
||||
|
||||
onTaskbarBackgroundAlphaChanged();
|
||||
updateVisibilityAlpha();
|
||||
@@ -76,6 +77,10 @@ public class TaskbarVisibilityController {
|
||||
return mTaskbarVisibilityAlphaForLauncherState;
|
||||
}
|
||||
|
||||
protected AnimatedFloat getTaskbarScaleForLauncherState() {
|
||||
return mTaskbarScaleForLauncherState;
|
||||
}
|
||||
|
||||
protected Animator createAnimToBackgroundAlpha(float toAlpha, long duration) {
|
||||
return mTaskbarBackgroundAlpha.animateToValue(mTaskbarBackgroundAlpha.value, toAlpha)
|
||||
.setDuration(duration);
|
||||
@@ -86,14 +91,10 @@ public class TaskbarVisibilityController {
|
||||
.setDuration(IME_VISIBILITY_ALPHA_DURATION).start();
|
||||
}
|
||||
|
||||
protected void animateToVisibilityForFloatingView(float toAlpha) {
|
||||
mTaskbarVisibilityAlphaForIme.animateToValue(mTaskbarVisibilityAlphaForFloatingView.value,
|
||||
toAlpha).setDuration(FLOATING_VIEW_VISIBILITY_ALPHA_DURATION).start();
|
||||
}
|
||||
|
||||
private void onTaskbarBackgroundAlphaChanged() {
|
||||
mTaskbarCallbacks.updateTaskbarBackgroundAlpha(mTaskbarBackgroundAlpha.value);
|
||||
updateVisibilityAlpha();
|
||||
updateScale();
|
||||
}
|
||||
|
||||
private void updateVisibilityAlpha() {
|
||||
@@ -102,8 +103,7 @@ public class TaskbarVisibilityController {
|
||||
// LauncherState if Launcher is paused.
|
||||
float alphaDueToLauncher = Math.max(mTaskbarBackgroundAlpha.value,
|
||||
mTaskbarVisibilityAlphaForLauncherState.value);
|
||||
float alphaDueToOther = mTaskbarVisibilityAlphaForIme.value
|
||||
* mTaskbarVisibilityAlphaForFloatingView.value;
|
||||
float alphaDueToOther = mTaskbarVisibilityAlphaForIme.value;
|
||||
float taskbarAlpha = alphaDueToLauncher * alphaDueToOther;
|
||||
mTaskbarCallbacks.updateTaskbarVisibilityAlpha(taskbarAlpha);
|
||||
|
||||
@@ -111,6 +111,15 @@ public class TaskbarVisibilityController {
|
||||
setNavBarButtonAlpha(1f - taskbarAlpha);
|
||||
}
|
||||
|
||||
private void updateScale() {
|
||||
// We use mTaskbarBackgroundAlpha as a proxy for whether Launcher is resumed/paused, the
|
||||
// assumption being that Taskbar should always be at scale 1f regardless of the current
|
||||
// LauncherState if Launcher is paused.
|
||||
float scale = mTaskbarScaleForLauncherState.value;
|
||||
scale = Utilities.mapRange(mTaskbarBackgroundAlpha.value, scale, 1f);
|
||||
mTaskbarCallbacks.updateTaskbarScale(scale);
|
||||
}
|
||||
|
||||
private void setNavBarButtonAlpha(float navBarAlpha) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setNavBarButtonAlpha(navBarAlpha, false);
|
||||
}
|
||||
@@ -19,8 +19,6 @@ import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
|
||||
import static com.android.systemui.shared.system.WindowManagerWrapper.ITYPE_EXTRA_NAVIGATION_BAR;
|
||||
|
||||
@@ -75,7 +73,7 @@ public class TaskbarController {
|
||||
// Layout width and height of the Taskbar in the default state.
|
||||
private final Point mTaskbarSize;
|
||||
private final TaskbarStateHandler mTaskbarStateHandler;
|
||||
private final TaskbarVisibilityController mTaskbarVisibilityController;
|
||||
private final TaskbarAnimationController mTaskbarAnimationController;
|
||||
private final TaskbarHotseatController mHotseatController;
|
||||
private final TaskbarRecentsController mRecentsController;
|
||||
private final TaskbarDragController mDragController;
|
||||
@@ -104,8 +102,8 @@ public class TaskbarController {
|
||||
mWindowManager = mLauncher.getWindowManager();
|
||||
mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize);
|
||||
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
|
||||
mTaskbarVisibilityController = new TaskbarVisibilityController(mLauncher,
|
||||
createTaskbarVisibilityControllerCallbacks());
|
||||
mTaskbarAnimationController = new TaskbarAnimationController(mLauncher,
|
||||
createTaskbarAnimationControllerCallbacks());
|
||||
mHotseatController = new TaskbarHotseatController(mLauncher,
|
||||
createTaskbarHotseatControllerCallbacks());
|
||||
mRecentsController = new TaskbarRecentsController(mLauncher,
|
||||
@@ -113,8 +111,8 @@ public class TaskbarController {
|
||||
mDragController = new TaskbarDragController(mLauncher);
|
||||
}
|
||||
|
||||
private TaskbarVisibilityControllerCallbacks createTaskbarVisibilityControllerCallbacks() {
|
||||
return new TaskbarVisibilityControllerCallbacks() {
|
||||
private TaskbarAnimationControllerCallbacks createTaskbarAnimationControllerCallbacks() {
|
||||
return new TaskbarAnimationControllerCallbacks() {
|
||||
@Override
|
||||
public void updateTaskbarBackgroundAlpha(float alpha) {
|
||||
mTaskbarViewInApp.setBackgroundAlpha(alpha);
|
||||
@@ -125,6 +123,12 @@ public class TaskbarController {
|
||||
mTaskbarContainerView.setAlpha(alpha);
|
||||
mTaskbarViewOnHome.setAlpha(alpha);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTaskbarScale(float scale) {
|
||||
mTaskbarViewInApp.setScaleX(scale);
|
||||
mTaskbarViewInApp.setScaleY(scale);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -151,13 +155,22 @@ public class TaskbarController {
|
||||
ActivityManagerWrapper.getInstance().startActivityFromRecents(task.key,
|
||||
ActivityOptions.makeBasic());
|
||||
} else if (tag instanceof FolderInfo) {
|
||||
if (mLauncher.hasBeenResumed()) {
|
||||
FolderInfo folderInfo = (FolderInfo) tag;
|
||||
onClickedOnFolderFromHome(folderInfo);
|
||||
} else {
|
||||
FolderIcon folderIcon = (FolderIcon) view;
|
||||
onClickedOnFolderInApp(folderIcon);
|
||||
}
|
||||
FolderIcon folderIcon = (FolderIcon) view;
|
||||
Folder folder = folderIcon.getFolder();
|
||||
|
||||
setTaskbarWindowFullscreen(true);
|
||||
|
||||
mTaskbarContainerView.post(() -> {
|
||||
folder.animateOpen();
|
||||
|
||||
folder.iterateOverItems((itemInfo, itemView) -> {
|
||||
itemView.setOnClickListener(getItemOnClickListener());
|
||||
itemView.setOnLongClickListener(getItemOnLongClickListener());
|
||||
// To play haptic when dragging, like other Taskbar items do.
|
||||
itemView.setHapticFeedbackEnabled(true);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
} else {
|
||||
ItemClickHandler.INSTANCE.onClick(view);
|
||||
}
|
||||
@@ -167,44 +180,9 @@ public class TaskbarController {
|
||||
};
|
||||
}
|
||||
|
||||
// Open the real folder in Launcher.
|
||||
private void onClickedOnFolderFromHome(FolderInfo folderInfo) {
|
||||
alignRealHotseatWithTaskbar();
|
||||
|
||||
FolderIcon folderIcon = (FolderIcon) mLauncher.getHotseat()
|
||||
.getFirstItemMatch((info, v) -> info == folderInfo);
|
||||
folderIcon.post(folderIcon::performClick);
|
||||
}
|
||||
|
||||
// Open the Taskbar folder, and handle clicks on folder items.
|
||||
private void onClickedOnFolderInApp(FolderIcon folderIcon) {
|
||||
Folder folder = folderIcon.getFolder();
|
||||
|
||||
setTaskbarWindowFullscreen(true);
|
||||
|
||||
mTaskbarContainerView.post(() -> {
|
||||
folder.animateOpen();
|
||||
|
||||
folder.iterateOverItems((itemInfo, itemView) -> {
|
||||
itemView.setOnClickListener(getItemOnClickListener());
|
||||
itemView.setOnLongClickListener(getItemOnLongClickListener());
|
||||
// To play haptic when dragging, like other Taskbar items do.
|
||||
itemView.setHapticFeedbackEnabled(true);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public View.OnLongClickListener getItemOnLongClickListener() {
|
||||
return view -> {
|
||||
if (mLauncher.hasBeenResumed() && view.getTag() instanceof ItemInfo) {
|
||||
// TODO: remove this path
|
||||
return mDragController.startWorkspaceDragOnLongClick(view);
|
||||
} else {
|
||||
return mDragController.startSystemDragOnLongClick(view);
|
||||
}
|
||||
};
|
||||
return mDragController::startSystemDragOnLongClick;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,12 +246,10 @@ public class TaskbarController {
|
||||
mTaskbarContainerView.init(mTaskbarViewInApp);
|
||||
addToWindowManager();
|
||||
mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks());
|
||||
mTaskbarVisibilityController.init();
|
||||
mTaskbarAnimationController.init();
|
||||
mHotseatController.init();
|
||||
mRecentsController.init();
|
||||
|
||||
SCALE_PROPERTY.set(mTaskbarViewInApp, mLauncher.hasBeenResumed()
|
||||
? getTaskbarScaleOnHome() : 1f);
|
||||
updateWhichTaskbarViewIsVisible();
|
||||
}
|
||||
|
||||
@@ -281,7 +257,12 @@ public class TaskbarController {
|
||||
return new TaskbarStateHandlerCallbacks() {
|
||||
@Override
|
||||
public AnimatedFloat getAlphaTarget() {
|
||||
return mTaskbarVisibilityController.getTaskbarVisibilityForLauncherState();
|
||||
return mTaskbarAnimationController.getTaskbarVisibilityForLauncherState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AnimatedFloat getScaleTarget() {
|
||||
return mTaskbarAnimationController.getTaskbarScaleForLauncherState();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -300,7 +281,7 @@ public class TaskbarController {
|
||||
mTaskbarContainerView.cleanup();
|
||||
removeFromWindowManager();
|
||||
mTaskbarStateHandler.setTaskbarCallbacks(null);
|
||||
mTaskbarVisibilityController.cleanup();
|
||||
mTaskbarAnimationController.cleanup();
|
||||
mHotseatController.cleanup();
|
||||
mRecentsController.cleanup();
|
||||
}
|
||||
@@ -368,12 +349,10 @@ public class TaskbarController {
|
||||
*/
|
||||
public Animator createAnimToLauncher(@Nullable LauncherState toState, long duration) {
|
||||
PendingAnimation anim = new PendingAnimation(duration);
|
||||
anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(0, duration));
|
||||
anim.add(mTaskbarAnimationController.createAnimToBackgroundAlpha(0, duration));
|
||||
if (toState != null) {
|
||||
mTaskbarStateHandler.setStateWithAnimation(toState, new StateAnimationConfig(), anim);
|
||||
}
|
||||
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(),
|
||||
getTaskbarScaleOnHome(), LINEAR);
|
||||
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
@@ -394,8 +373,7 @@ public class TaskbarController {
|
||||
|
||||
private Animator createAnimToApp(long duration) {
|
||||
PendingAnimation anim = new PendingAnimation(duration);
|
||||
anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(1, duration));
|
||||
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(), 1f, LINEAR);
|
||||
anim.add(mTaskbarAnimationController.createAnimToBackgroundAlpha(1, duration));
|
||||
anim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
@@ -416,7 +394,7 @@ public class TaskbarController {
|
||||
* Should be called when the IME visibility changes, so we can hide/show Taskbar accordingly.
|
||||
*/
|
||||
public void setIsImeVisible(boolean isImeVisible) {
|
||||
mTaskbarVisibilityController.animateToVisibilityForIme(isImeVisible ? 0 : 1);
|
||||
mTaskbarAnimationController.animateToVisibilityForIme(isImeVisible ? 0 : 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,14 +487,6 @@ public class TaskbarController {
|
||||
mTaskbarViewOnHome.getHeight() - hotseatBounds.bottom);
|
||||
}
|
||||
|
||||
/**
|
||||
* A view was added or removed from DragLayer, check if we need to hide our hotseat copy and
|
||||
* show the real one instead.
|
||||
*/
|
||||
public void onLauncherDragLayerHierarchyChanged() {
|
||||
// TODO: remove, as this is a no-op now
|
||||
}
|
||||
|
||||
private void updateWhichTaskbarViewIsVisible() {
|
||||
boolean isInApp = !mLauncher.hasBeenResumed() || mIsAnimatingToLauncher
|
||||
|| mIsAnimatingToApp;
|
||||
@@ -561,15 +531,17 @@ public class TaskbarController {
|
||||
*/
|
||||
protected interface TaskbarStateHandlerCallbacks {
|
||||
AnimatedFloat getAlphaTarget();
|
||||
AnimatedFloat getScaleTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains methods that TaskbarVisibilityController can call to interface with
|
||||
* Contains methods that TaskbarAnimationController can call to interface with
|
||||
* TaskbarController.
|
||||
*/
|
||||
protected interface TaskbarVisibilityControllerCallbacks {
|
||||
protected interface TaskbarAnimationControllerCallbacks {
|
||||
void updateTaskbarBackgroundAlpha(float alpha);
|
||||
void updateTaskbarVisibilityAlpha(float alpha);
|
||||
void updateTaskbarScale(float scale);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.LauncherSettings;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.model.data.WorkspaceItemInfo;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.system.ClipDescriptionCompat;
|
||||
@@ -125,38 +124,6 @@ public class TaskbarDragController {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a drag and drop operation that controls a real Workspace (Hotseat) view.
|
||||
* @param view The Taskbar item that was long clicked.
|
||||
* @return Whether {@link View#startDragAndDrop} started successfully.
|
||||
*/
|
||||
protected boolean startWorkspaceDragOnLongClick(View view) {
|
||||
View.DragShadowBuilder transparentShadowBuilder = new View.DragShadowBuilder(view) {
|
||||
private static final int ARBITRARY_SHADOW_SIZE = 10;
|
||||
|
||||
@Override
|
||||
public void onDrawShadow(Canvas canvas) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {
|
||||
outShadowSize.set(ARBITRARY_SHADOW_SIZE, ARBITRARY_SHADOW_SIZE);
|
||||
outShadowTouchPoint.set(ARBITRARY_SHADOW_SIZE / 2, ARBITRARY_SHADOW_SIZE / 2);
|
||||
}
|
||||
};
|
||||
|
||||
TaskbarDragListener taskbarDragListener = new TaskbarDragListener(mLauncher,
|
||||
(ItemInfo) view.getTag());
|
||||
if (view.startDragAndDrop(new ClipData("", new String[] {taskbarDragListener.getMimeType()},
|
||||
new ClipData.Item("")),
|
||||
transparentShadowBuilder, null /* localState */, View.DRAG_FLAG_GLOBAL)) {
|
||||
view.setOnDragListener(getDraggedViewDragListener());
|
||||
taskbarDragListener.init(mLauncher.getDragLayer());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the original Taskbar item while it is being dragged.
|
||||
*/
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import android.content.ClipDescription;
|
||||
import android.graphics.Point;
|
||||
import android.view.DragEvent;
|
||||
import android.view.View;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.dragndrop.DragLayer;
|
||||
import com.android.launcher3.dragndrop.DragOptions;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Listens to system drag and drop events initated by the Taskbar, and forwards them to Launcher's
|
||||
* internal DragController to move Hotseat items.
|
||||
*/
|
||||
public class TaskbarDragListener implements View.OnDragListener {
|
||||
|
||||
private static final String MIME_TYPE_PREFIX = "com.android.launcher3.taskbar.drag_and_drop/";
|
||||
|
||||
private final BaseQuickstepLauncher mLauncher;
|
||||
private final ItemInfo mDraggedItem;
|
||||
// Randomly generated id used to verify the drag event.
|
||||
private final String mId;
|
||||
|
||||
// Initialized in init().
|
||||
DragLayer mDragLayer;
|
||||
|
||||
/**
|
||||
* @param draggedItem The info of the item that was long clicked, which we will use to find
|
||||
* the equivalent match on Hotseat to drag internally.
|
||||
*/
|
||||
public TaskbarDragListener(BaseQuickstepLauncher launcher, ItemInfo draggedItem) {
|
||||
mLauncher = launcher;
|
||||
mDraggedItem = draggedItem;
|
||||
mId = UUID.randomUUID().toString();
|
||||
}
|
||||
|
||||
protected void init(DragLayer dragLayer) {
|
||||
mDragLayer = dragLayer;
|
||||
mDragLayer.setOnDragListener(this);
|
||||
// Temporarily disable haptics, as system will already play one when drag and drop starts.
|
||||
mDragLayer.setHapticFeedbackEnabled(false);
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
mDragLayer.setOnDragListener(null);
|
||||
mLauncher.setNextWorkspaceDragOptions(null);
|
||||
mDragLayer.setHapticFeedbackEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a randomly generated id used to verify the drag event.
|
||||
*/
|
||||
protected String getMimeType() {
|
||||
return MIME_TYPE_PREFIX + mId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(View dragLayer, DragEvent dragEvent) {
|
||||
ClipDescription clipDescription = dragEvent.getClipDescription();
|
||||
if (dragEvent.getAction() == DragEvent.ACTION_DRAG_STARTED) {
|
||||
if (clipDescription == null || !clipDescription.hasMimeType(getMimeType())) {
|
||||
// We didn't initiate this drag, ignore.
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
View hotseatView = mLauncher.getHotseat().getFirstItemMatch(
|
||||
(info, view) -> info == mDraggedItem);
|
||||
if (hotseatView == null) {
|
||||
cleanup();
|
||||
return false;
|
||||
}
|
||||
DragOptions dragOptions = new DragOptions();
|
||||
dragOptions.simulatedDndStartPoint = new Point((int) dragEvent.getX(),
|
||||
(int) dragEvent.getY());
|
||||
mLauncher.setNextWorkspaceDragOptions(dragOptions);
|
||||
hotseatView.performLongClick();
|
||||
} else if (dragEvent.getAction() == DragEvent.ACTION_DRAG_ENDED) {
|
||||
cleanup();
|
||||
}
|
||||
return mLauncher.getDragController().onDragEvent(dragEvent);
|
||||
}
|
||||
}
|
||||
@@ -16,14 +16,12 @@
|
||||
package com.android.launcher3.taskbar;
|
||||
|
||||
import static com.android.launcher3.LauncherState.TASKBAR;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_TASKBAR_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_TASKBAR;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
@@ -55,8 +53,10 @@ public class TaskbarStateHandler implements StateManager.StateHandler<LauncherSt
|
||||
}
|
||||
|
||||
AnimatedFloat alphaTarget = mTaskbarCallbacks.getAlphaTarget();
|
||||
AnimatedFloat scaleTarget = mTaskbarCallbacks.getScaleTarget();
|
||||
boolean isTaskbarVisible = (state.getVisibleElements(mLauncher) & TASKBAR) != 0;
|
||||
alphaTarget.updateValue(isTaskbarVisible ? 1f : 0f);
|
||||
scaleTarget.updateValue(state.getTaskbarScale(mLauncher));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,13 +65,12 @@ public class TaskbarStateHandler implements StateManager.StateHandler<LauncherSt
|
||||
if (mTaskbarCallbacks == null) {
|
||||
return;
|
||||
}
|
||||
if (config.hasAnimationFlag(SKIP_TASKBAR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
AnimatedFloat alphaTarget = mTaskbarCallbacks.getAlphaTarget();
|
||||
AnimatedFloat scaleTarget = mTaskbarCallbacks.getScaleTarget();
|
||||
boolean isTaskbarVisible = (toState.getVisibleElements(mLauncher) & TASKBAR) != 0;
|
||||
animation.setFloat(alphaTarget, AnimatedFloat.VALUE, isTaskbarVisible ? 1f : 0f,
|
||||
config.getInterpolator(ANIM_TASKBAR_FADE, Interpolators.LINEAR));
|
||||
animation.setFloat(alphaTarget, AnimatedFloat.VALUE, isTaskbarVisible ? 1f : 0f, LINEAR);
|
||||
animation.setFloat(scaleTarget, AnimatedFloat.VALUE, toState.getTaskbarScale(mLauncher),
|
||||
LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,11 +120,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
}
|
||||
|
||||
protected void init(int numHotseatIcons, int numRecentIcons) {
|
||||
mLayoutTransition = new LayoutTransition();
|
||||
addUpdateListenerForAllLayoutTransitions(
|
||||
() -> mControllerCallbacks.onItemPositionsChanged(this));
|
||||
setLayoutTransition(mLayoutTransition);
|
||||
|
||||
mHotseatStartIndex = 0;
|
||||
mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1;
|
||||
updateHotseatItems(new ItemInfo[numHotseatIcons]);
|
||||
@@ -135,6 +130,14 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
mRecentsStartIndex = dividerIndex + 1;
|
||||
mRecentsEndIndex = mRecentsStartIndex + numRecentIcons - 1;
|
||||
updateRecentTasks(new Task[numRecentIcons]);
|
||||
|
||||
mLayoutTransition = new LayoutTransition();
|
||||
addUpdateListenerForAllLayoutTransitions(() -> {
|
||||
if (getLayoutTransition() == mLayoutTransition) {
|
||||
mControllerCallbacks.onItemPositionsChanged(this);
|
||||
}
|
||||
});
|
||||
setLayoutTransition(mLayoutTransition);
|
||||
}
|
||||
|
||||
private void addUpdateListenerForAllLayoutTransitions(Runnable onUpdate) {
|
||||
@@ -159,10 +162,20 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
|
||||
}
|
||||
|
||||
protected void cleanup() {
|
||||
endAllLayoutTransitionAnimators();
|
||||
setLayoutTransition(null);
|
||||
removeAllViews();
|
||||
mHotseatRecentsDivider = null;
|
||||
}
|
||||
|
||||
private void endAllLayoutTransitionAnimators() {
|
||||
mLayoutTransition.getAnimator(LayoutTransition.CHANGE_APPEARING).end();
|
||||
mLayoutTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING).end();
|
||||
mLayoutTransition.getAnimator(LayoutTransition.CHANGING).end();
|
||||
mLayoutTransition.getAnimator(LayoutTransition.APPEARING).end();
|
||||
mLayoutTransition.getAnimator(LayoutTransition.DISAPPEARING).end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the alpha of the background color behind all the Taskbar contents.
|
||||
* @param alpha 0 is fully transparent, 1 is fully opaque.
|
||||
|
||||
@@ -82,6 +82,11 @@ public class OverviewState extends LauncherState {
|
||||
return new float[] {NO_SCALE, NO_OFFSET};
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getTaskbarScale(Launcher launcher) {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
|
||||
return new PageAlphaProvider(DEACCEL_2) {
|
||||
|
||||
-16
@@ -18,7 +18,6 @@ package com.android.launcher3.uioverrides.states;
|
||||
import static android.view.View.VISIBLE;
|
||||
|
||||
import static com.android.launcher3.LauncherState.HINT_STATE;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator;
|
||||
@@ -33,12 +32,10 @@ import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_DEPTH;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_TASKBAR_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
@@ -82,7 +79,6 @@ public class QuickstepAtomicAnimationFactory extends
|
||||
if (toState == NORMAL && fromState == OVERVIEW) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
|
||||
config.setInterpolator(ANIM_TASKBAR_FADE, ACCEL);
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL_DEACCEL);
|
||||
@@ -141,7 +137,6 @@ public class QuickstepAtomicAnimationFactory extends
|
||||
config.setInterpolator(ANIM_DEPTH, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_TASKBAR_FADE, OVERSHOOT_1_2);
|
||||
} else if (fromState == HINT_STATE && toState == NORMAL) {
|
||||
config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
|
||||
if (mHintToNormalDuration == -1) {
|
||||
@@ -150,17 +145,6 @@ public class QuickstepAtomicAnimationFactory extends
|
||||
mHintToNormalDuration = (int) va.getDuration();
|
||||
}
|
||||
config.duration = Math.max(config.duration, mHintToNormalDuration);
|
||||
} else if (mActivity.getTaskbarController() != null) {
|
||||
boolean wasHotseatVisible = fromState.areElementsVisible(mActivity, HOTSEAT_ICONS);
|
||||
boolean isHotseatVisible = toState.areElementsVisible(mActivity, HOTSEAT_ICONS);
|
||||
if (wasHotseatVisible || isHotseatVisible) {
|
||||
config.setInterpolator(ANIM_TASKBAR_FADE, INSTANT);
|
||||
config.setInterpolator(ANIM_HOTSEAT_FADE, INSTANT);
|
||||
|
||||
if (isHotseatVisible) {
|
||||
mActivity.getTaskbarController().alignRealHotseatWithTaskbar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import static android.widget.Toast.LENGTH_SHORT;
|
||||
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
@@ -97,11 +96,12 @@ import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AnimatorControllerWithResistance;
|
||||
import com.android.quickstep.util.InputConsumerProxy;
|
||||
import com.android.quickstep.util.InputProxyHandlerFactory;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
import com.android.quickstep.util.ProtoTracer;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
import com.android.quickstep.util.SwipePipToHomeAnimator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
@@ -113,12 +113,10 @@ import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
|
||||
import com.android.systemui.shared.system.LatencyTrackerCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.TaskInfoCompat;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -200,7 +198,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
||||
|
||||
public static final long MAX_SWIPE_DURATION = 350;
|
||||
public static final long MIN_OVERSHOOT_DURATION = 120;
|
||||
public static final long HOME_DURATION = StaggeredWorkspaceAnim.DURATION_MS;
|
||||
|
||||
public static final float MIN_PROGRESS_FOR_OVERVIEW = 0.7f;
|
||||
private static final float SWIPE_DURATION_MULTIPLIER =
|
||||
@@ -255,7 +253,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mActivityInterface = gestureState.getActivityInterface();
|
||||
mActivityInitListener = mActivityInterface.createActivityInitListener(this::onActivityInit);
|
||||
mInputConsumerProxy =
|
||||
new InputConsumerProxy(inputConsumer, this::createNewInputProxyHandler);
|
||||
new InputConsumerProxy(inputConsumer, () -> {
|
||||
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
}, new InputProxyHandlerFactory(mActivityInterface, mGestureState));
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
@@ -783,19 +784,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
handleNormalGestureEnd(endVelocity, isFling, velocity, false /* isCancel */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to create a input proxy for the running task
|
||||
*/
|
||||
@UiThread
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
|
||||
StatefulActivity activity = mActivityInterface.getCreatedActivity();
|
||||
return activity == null ? InputConsumer.NO_OP
|
||||
: new OverviewInputConsumer(mGestureState, activity, null, true);
|
||||
}
|
||||
|
||||
private void endRunningWindowAnim(boolean cancel) {
|
||||
if (mRunningWindowAnim != null) {
|
||||
if (cancel) {
|
||||
@@ -923,6 +911,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
float currentShift = mCurrentShift.value;
|
||||
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
|
||||
isFling, isCancel);
|
||||
// Set the state, but don't notify until the animation completes
|
||||
mGestureState.setEndTarget(endTarget, false /* isAtomic */);
|
||||
|
||||
float endShift = endTarget.isLauncher ? 1 : 0;
|
||||
final float startShift;
|
||||
if (!isFling) {
|
||||
@@ -945,7 +936,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
}
|
||||
Interpolator interpolator;
|
||||
S state = mActivityInterface.stateFromGestureEndTarget(endTarget);
|
||||
if (state.displayOverviewTasksAsGrid(mActivity.getDeviceProfile())) {
|
||||
if (state.displayOverviewTasksAsGrid(mDp)) {
|
||||
interpolator = ACCEL_DEACCEL;
|
||||
} else if (endTarget == RECENTS) {
|
||||
interpolator = OVERSHOOT_1_2;
|
||||
@@ -957,7 +948,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mInputConsumerProxy.enable();
|
||||
}
|
||||
if (endTarget == HOME) {
|
||||
duration = Math.max(MIN_OVERSHOOT_DURATION, duration);
|
||||
duration = HOME_DURATION;
|
||||
} else if (endTarget == RECENTS) {
|
||||
if (mRecentsView != null) {
|
||||
int nearestPage = mRecentsView.getDestinationPage();
|
||||
@@ -1055,8 +1046,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
@UiThread
|
||||
private void animateToProgressInternal(float start, float end, long duration,
|
||||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
||||
// Set the state, but don't notify until the animation completes
|
||||
mGestureState.setEndTarget(target, false /* isAtomic */);
|
||||
maybeUpdateRecentsAttachedState();
|
||||
|
||||
// If we are transitioning to launcher, then listen for the activity to be restarted while
|
||||
@@ -1147,10 +1136,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
});
|
||||
animatorSet.play(windowAnim);
|
||||
S state = mActivityInterface.stateFromGestureEndTarget(mGestureState.getEndTarget());
|
||||
if (mRecentsView != null && state.displayOverviewTasksAsGrid(
|
||||
mActivity.getDeviceProfile())) {
|
||||
if (mRecentsView != null && state.displayOverviewTasksAsGrid(mDp)) {
|
||||
animatorSet.play(ObjectAnimator.ofFloat(mRecentsView, RECENTS_GRID_PROGRESS, 1));
|
||||
animatorSet.play(mTaskViewSimulator.gridProgress.animateToValue(0, 1));
|
||||
}
|
||||
animatorSet.setDuration(duration).setInterpolator(interpolator);
|
||||
animatorSet.start();
|
||||
@@ -1339,6 +1326,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
mInputConsumerProxy.destroy();
|
||||
mTaskAnimationManager.setLiveTileCleanUpHandler(null);
|
||||
}
|
||||
mInputConsumerProxy.unregisterCallback();
|
||||
endRunningWindowAnim(false /* cancel */);
|
||||
|
||||
if (mGestureEndCallback != null) {
|
||||
@@ -1503,36 +1491,13 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
protected abstract void finishRecentsControllerToHome(Runnable callback);
|
||||
|
||||
private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() {
|
||||
@Override
|
||||
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
|
||||
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
|
||||
if (mRecentsView.getRunningTaskIndex() != -1
|
||||
&& mRecentsView.getRunningTaskId() == task.taskId
|
||||
&& mRecentsAnimationTargets.hasTask(task.taskId)) {
|
||||
launchOtherTaskInLiveTileMode(task.taskId, mRecentsAnimationTargets.apps);
|
||||
}
|
||||
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
|
||||
mLiveTileRestartListener);
|
||||
}
|
||||
};
|
||||
|
||||
private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
|
||||
endLauncherTransitionController();
|
||||
mActivityInterface.onSwipeUpToRecentsComplete();
|
||||
mRecentsView.onSwipeUpAnimationSuccess();
|
||||
if (LIVE_TILE.get()) {
|
||||
mTaskAnimationManager.setLaunchOtherTaskInLiveTileModeHandler(
|
||||
appearedTaskTarget -> {
|
||||
RemoteAnimationTargetCompat[] apps = Arrays.copyOf(
|
||||
mRecentsAnimationTargets.apps,
|
||||
mRecentsAnimationTargets.apps.length + 1);
|
||||
apps[apps.length - 1] = appearedTaskTarget;
|
||||
launchOtherTaskInLiveTileMode(appearedTaskTarget.taskId, apps);
|
||||
});
|
||||
mTaskAnimationManager.setLiveTileCleanUpHandler(mInputConsumerProxy::destroy);
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(
|
||||
mLiveTileRestartListener);
|
||||
mTaskAnimationManager.enableLiveTileRestartListener();
|
||||
}
|
||||
|
||||
SystemUiProxy.INSTANCE.get(mContext).onOverviewShown(false, TAG);
|
||||
@@ -1540,65 +1505,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
reset();
|
||||
}
|
||||
|
||||
private void launchOtherTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
TaskView taskView = mRecentsView.getTaskView(taskId);
|
||||
if (taskView == null || !mRecentsView.isTaskViewVisible(taskView)) {
|
||||
// TODO: Refine this animation.
|
||||
SurfaceTransactionApplier surfaceApplier =
|
||||
new SurfaceTransactionApplier(mActivity.getDragLayer());
|
||||
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
appAnimator.setInterpolator(ACCEL_DEACCEL);
|
||||
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
|
||||
@Override
|
||||
public void onUpdate(float percent) {
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(
|
||||
apps[apps.length - 1].leash);
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(percent, percent);
|
||||
matrix.postTranslate(mDp.widthPx * (1 - percent) / 2,
|
||||
mDp.heightPx * (1 - percent) / 2);
|
||||
builder.withAlpha(percent).withMatrix(matrix);
|
||||
surfaceApplier.scheduleApply(builder.build());
|
||||
}
|
||||
});
|
||||
anim.play(appAnimator);
|
||||
} else {
|
||||
TaskViewUtils.composeRecentsLaunchAnimator(
|
||||
anim, taskView, apps,
|
||||
mRecentsAnimationTargets.wallpapers, true /* launcherClosing */,
|
||||
mActivity.getStateManager(), mRecentsView,
|
||||
mActivityInterface.getDepthController());
|
||||
}
|
||||
anim.addListener(new AnimatorListenerAdapter(){
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
cleanUp(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
cleanUp(true);
|
||||
}
|
||||
|
||||
private void cleanUp(boolean canceled) {
|
||||
if (mRecentsAnimationController != null) {
|
||||
mRecentsAnimationController.finish(false /* toRecents */,
|
||||
null /* onFinishComplete */);
|
||||
if (canceled) {
|
||||
mRecentsAnimationController = null;
|
||||
} else {
|
||||
mActivityInterface.onLaunchTaskSuccess();
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
|
||||
}
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
private static boolean isNotInRecents(RemoteAnimationTargetCompat app) {
|
||||
return app.isNotInRecents
|
||||
|| app.activityType == ACTIVITY_TYPE_HOME;
|
||||
|
||||
@@ -31,6 +31,7 @@ import android.animation.Animator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.Gravity;
|
||||
@@ -43,6 +44,7 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
@@ -195,41 +197,53 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the taskView size for the provided device configuration
|
||||
* Calculates the taskView size for the provided device configuration.
|
||||
*/
|
||||
public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect,
|
||||
PagedOrientationHandler orientedState) {
|
||||
Resources res = context.getResources();
|
||||
if (dp.isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
|
||||
Rect gridRect = new Rect();
|
||||
calculateGridSize(context, dp, gridRect);
|
||||
|
||||
int taskMargin = res.getDimensionPixelSize(R.dimen.overview_task_margin);
|
||||
int taskIconAndMargin = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size)
|
||||
+ res.getDimensionPixelSize(R.dimen.task_icon_top_margin);
|
||||
int proactiveRowAndMargin = res.getDimensionPixelSize(R.dimen.overview_proactive_row_height)
|
||||
+ res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin);
|
||||
int rowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
|
||||
float rowHeight = (gridRect.height() - rowSpacing) / 2f;
|
||||
|
||||
calculateTaskSizeInternal(context, dp,
|
||||
taskIconAndMargin + taskMargin,
|
||||
proactiveRowAndMargin + getOverviewActionsHeight(context) + taskMargin,
|
||||
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
|
||||
outRect);
|
||||
PointF taskDimension = getTaskDimension(context, dp);
|
||||
float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / Math.max(
|
||||
taskDimension.x, taskDimension.y);
|
||||
int outWidth = Math.round(scale * taskDimension.x);
|
||||
int outHeight = Math.round(scale * taskDimension.y);
|
||||
|
||||
int gravity = Gravity.TOP;
|
||||
gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
|
||||
gridRect.inset(0, dp.overviewTaskThumbnailTopMarginPx, 0, 0);
|
||||
Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
|
||||
} else {
|
||||
int taskMargin = dp.overviewTaskMarginPx;
|
||||
int proactiveRowAndMargin;
|
||||
if (dp.isVerticalBarLayout()) {
|
||||
// In Vertical Bar Layout the proactive row doesn't have its own space, it's inside
|
||||
// the actions row.
|
||||
proactiveRowAndMargin = 0;
|
||||
} else {
|
||||
proactiveRowAndMargin = res.getDimensionPixelSize(
|
||||
R.dimen.overview_proactive_row_height)
|
||||
+ res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin);
|
||||
}
|
||||
calculateTaskSizeInternal(context, dp,
|
||||
dp.overviewTaskThumbnailTopMarginPx,
|
||||
proactiveRowAndMargin + getOverviewActionsHeight(context) + taskMargin,
|
||||
res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
|
||||
outRect);
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
|
||||
int claimedSpaceAbove, int claimedSpaceBelow, int minimumHorizontalPadding,
|
||||
Rect outRect) {
|
||||
float taskWidth, taskHeight;
|
||||
PointF taskDimension = getTaskDimension(context, dp);
|
||||
Rect insets = dp.getInsets();
|
||||
if (dp.isMultiWindowMode) {
|
||||
WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context);
|
||||
taskWidth = bounds.availableSize.x;
|
||||
taskHeight = bounds.availableSize.y;
|
||||
} else if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
|
||||
taskWidth = dp.availableWidthPx;
|
||||
taskHeight = dp.availableHeightPx;
|
||||
} else {
|
||||
taskWidth = dp.widthPx;
|
||||
taskHeight = dp.heightPx;
|
||||
}
|
||||
|
||||
Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
|
||||
potentialTaskRect.inset(insets.left, insets.top, insets.right, insets.bottom);
|
||||
@@ -240,14 +254,30 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
claimedSpaceBelow);
|
||||
|
||||
float scale = Math.min(
|
||||
potentialTaskRect.width() / taskWidth,
|
||||
potentialTaskRect.height() / taskHeight);
|
||||
int outWidth = Math.round(scale * taskWidth);
|
||||
int outHeight = Math.round(scale * taskHeight);
|
||||
potentialTaskRect.width() / taskDimension.x,
|
||||
potentialTaskRect.height() / taskDimension.y);
|
||||
int outWidth = Math.round(scale * taskDimension.x);
|
||||
int outHeight = Math.round(scale * taskDimension.y);
|
||||
|
||||
Gravity.apply(Gravity.CENTER, outWidth, outHeight, potentialTaskRect, outRect);
|
||||
}
|
||||
|
||||
private PointF getTaskDimension(Context context, DeviceProfile dp) {
|
||||
PointF dimension = new PointF();
|
||||
if (dp.isMultiWindowMode) {
|
||||
WindowBounds bounds = SplitScreenBounds.INSTANCE.getSecondaryWindowBounds(context);
|
||||
dimension.x = bounds.availableSize.x;
|
||||
dimension.y = bounds.availableSize.y;
|
||||
} else if (TaskView.CLIP_STATUS_AND_NAV_BARS) {
|
||||
dimension.x = dp.availableWidthPx;
|
||||
dimension.y = dp.availableHeightPx;
|
||||
} else {
|
||||
dimension.x = dp.widthPx;
|
||||
dimension.y = dp.heightPx;
|
||||
}
|
||||
return dimension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the overview grid size for the provided device configuration.
|
||||
*/
|
||||
@@ -267,13 +297,11 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
* Calculates the modal taskView size for the provided device configuration
|
||||
*/
|
||||
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
Resources res = context.getResources();
|
||||
calculateTaskSizeInternal(
|
||||
context, dp,
|
||||
res.getDimensionPixelSize(R.dimen.overview_task_margin),
|
||||
getOverviewActionsHeight(context)
|
||||
+ res.getDimensionPixelSize(R.dimen.overview_task_margin),
|
||||
res.getDimensionPixelSize(R.dimen.overview_task_margin),
|
||||
dp.overviewTaskMarginPx,
|
||||
getOverviewActionsHeight(context) + dp.overviewTaskMarginPx,
|
||||
dp.overviewTaskMarginPx,
|
||||
outRect);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,13 +41,4 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets {
|
||||
public boolean hasTargets() {
|
||||
return unfilteredApps.length != 0;
|
||||
}
|
||||
|
||||
public boolean hasTask(int taskId) {
|
||||
for (RemoteAnimationTargetCompat target : unfilteredApps) {
|
||||
if (target.taskId == taskId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,10 +17,11 @@ package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_STARTED;
|
||||
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
@@ -31,13 +32,13 @@ import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.RemoteTransitionCompat;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
|
||||
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
public static final boolean ENABLE_SHELL_TRANSITIONS =
|
||||
@@ -49,10 +50,24 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
// Temporary until we can hook into gesture state events
|
||||
private GestureState mLastGestureState;
|
||||
private RemoteAnimationTargetCompat mLastAppearedTaskTarget;
|
||||
private Consumer<RemoteAnimationTargetCompat> mLaunchOtherTaskHandler;
|
||||
private Runnable mLiveTileCleanUpHandler;
|
||||
private Context mCtx;
|
||||
|
||||
private final TaskStackChangeListener mLiveTileRestartListener = new TaskStackChangeListener() {
|
||||
@Override
|
||||
public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task,
|
||||
boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) {
|
||||
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
|
||||
if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
|
||||
&& activityInterface.getCreatedActivity() != null) {
|
||||
RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
|
||||
recentsView.launchSideTaskInLiveTileModeForRestartedApp(task.taskId);
|
||||
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(
|
||||
mLiveTileRestartListener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TaskAnimationManager(Context ctx) {
|
||||
mCtx = ctx;
|
||||
}
|
||||
@@ -114,9 +129,14 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
|
||||
@Override
|
||||
public void onTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
if (mLaunchOtherTaskHandler != null
|
||||
&& mLastGestureState.getEndTarget() == RECENTS) {
|
||||
mLaunchOtherTaskHandler.accept(appearedTaskTarget);
|
||||
BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
|
||||
if (LIVE_TILE.get() && activityInterface.isInLiveTileMode()
|
||||
&& activityInterface.getCreatedActivity() != null) {
|
||||
RecentsView recentsView =
|
||||
activityInterface.getCreatedActivity().getOverviewPanel();
|
||||
RemoteAnimationTargetCompat[] apps = new RemoteAnimationTargetCompat[1];
|
||||
apps[0] = appearedTaskTarget;
|
||||
recentsView.launchSideTaskInLiveTileMode(appearedTaskTarget.taskId, apps);
|
||||
return;
|
||||
}
|
||||
if (mController != null) {
|
||||
@@ -161,17 +181,12 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* The passed-in handler is used to render side task launch animation in recents in live tile
|
||||
* mode.
|
||||
*/
|
||||
public void setLaunchOtherTaskInLiveTileModeHandler(
|
||||
Consumer<RemoteAnimationTargetCompat> handler) {
|
||||
mLaunchOtherTaskHandler = handler;
|
||||
public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
|
||||
mLiveTileCleanUpHandler = cleanUpHandler;
|
||||
}
|
||||
|
||||
public void setLiveTileCleanUpHandler(Runnable runnable) {
|
||||
mLiveTileCleanUpHandler = runnable;
|
||||
public void enableLiveTileRestartListener() {
|
||||
ActivityManagerWrapper.getInstance().registerTaskStackListener(mLiveTileRestartListener);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -215,6 +230,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
mLiveTileCleanUpHandler.run();
|
||||
mLiveTileCleanUpHandler = null;
|
||||
}
|
||||
ActivityManagerWrapper.getInstance().unregisterTaskStackListener(mLiveTileRestartListener);
|
||||
|
||||
// Release all the target leashes
|
||||
if (mTargets != null) {
|
||||
@@ -231,7 +247,6 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||
mTargets = null;
|
||||
mLastGestureState = null;
|
||||
mLastAppearedTaskTarget = null;
|
||||
mLaunchOtherTaskHandler = null;
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
|
||||
@@ -176,7 +176,7 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
|
||||
if (thumbnail != null) {
|
||||
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
|
||||
boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
|
||||
boolean isAllowedByPolicy = mThumbnailView.isRealSnapshot();
|
||||
getActionsView().setCallbacks(new OverlayUICallbacksImpl(isAllowedByPolicy, task));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DU
|
||||
import static com.android.launcher3.Utilities.getDescendantCoordRelativeToAncestor;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR;
|
||||
import static com.android.launcher3.anim.Interpolators.TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.clampToProgress;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.launcher3.statehandlers.DepthController.DEPTH;
|
||||
@@ -200,8 +201,7 @@ public final class TaskViewUtils {
|
||||
tsv.setPreview(targets.apps[targets.apps.length - 1]);
|
||||
tsv.fullScreenProgress.value = 0;
|
||||
tsv.recentsViewScale.value = 1;
|
||||
tsv.gridProgress.value = gridProgress;
|
||||
tsv.gridTranslationSecondary.value = gridTranslationSecondary;
|
||||
tsv.taskSecondaryTranslation.value = gridTranslationSecondary;
|
||||
tsv.setScroll(startScroll);
|
||||
|
||||
// Fade in the task during the initial 20% of the animation
|
||||
@@ -214,7 +214,8 @@ public final class TaskViewUtils {
|
||||
AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
|
||||
out.setFloat(tsv.recentsViewScale,
|
||||
AnimatedFloat.VALUE, tsv.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
|
||||
out.setFloat(tsv.gridProgress, AnimatedFloat.VALUE, 0, TOUCH_RESPONSE_INTERPOLATOR);
|
||||
out.setFloat(tsv.taskSecondaryTranslation, AnimatedFloat.VALUE, 0,
|
||||
TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL);
|
||||
out.setInt(tsv, TaskViewSimulator.SCROLL, 0, TOUCH_RESPONSE_INTERPOLATOR);
|
||||
|
||||
TaskViewSimulator finalTsv = tsv;
|
||||
|
||||
@@ -38,7 +38,8 @@ public class InputConsumerProxy {
|
||||
private static final String TAG = "InputConsumerProxy";
|
||||
|
||||
private final InputConsumerController mInputConsumerController;
|
||||
private final Supplier<InputConsumer> mConsumerSupplier;
|
||||
private Runnable mCallback;
|
||||
private Supplier<InputConsumer> mConsumerSupplier;
|
||||
|
||||
// The consumer is created lazily on demand.
|
||||
private InputConsumer mInputConsumer;
|
||||
@@ -48,8 +49,9 @@ public class InputConsumerProxy {
|
||||
private boolean mDestroyPending = false;
|
||||
|
||||
public InputConsumerProxy(InputConsumerController inputConsumerController,
|
||||
Supplier<InputConsumer> consumerSupplier) {
|
||||
Runnable callback, Supplier<InputConsumer> consumerSupplier) {
|
||||
mInputConsumerController = inputConsumerController;
|
||||
mCallback = callback;
|
||||
mConsumerSupplier = consumerSupplier;
|
||||
}
|
||||
|
||||
@@ -64,9 +66,7 @@ public class InputConsumerProxy {
|
||||
if (ev instanceof MotionEvent) {
|
||||
onInputConsumerMotionEvent((MotionEvent) ev);
|
||||
} else if (ev instanceof KeyEvent) {
|
||||
if (mInputConsumer == null) {
|
||||
mInputConsumer = mConsumerSupplier.get();
|
||||
}
|
||||
initInputConsumerIfNeeded();
|
||||
mInputConsumer.onKeyEvent((KeyEvent) ev);
|
||||
return true;
|
||||
}
|
||||
@@ -89,9 +89,7 @@ public class InputConsumerProxy {
|
||||
|
||||
if (action == ACTION_DOWN) {
|
||||
mTouchInProgress = true;
|
||||
if (mInputConsumer == null) {
|
||||
mInputConsumer = mConsumerSupplier.get();
|
||||
}
|
||||
initInputConsumerIfNeeded();
|
||||
} else if (action == ACTION_CANCEL || action == ACTION_UP) {
|
||||
// Finish any pending actions
|
||||
mTouchInProgress = false;
|
||||
@@ -115,4 +113,18 @@ public class InputConsumerProxy {
|
||||
mDestroyed = true;
|
||||
mInputConsumerController.setInputListener(null);
|
||||
}
|
||||
|
||||
public void unregisterCallback() {
|
||||
mCallback = null;
|
||||
}
|
||||
|
||||
private void initInputConsumerIfNeeded() {
|
||||
if (mInputConsumer == null) {
|
||||
if (mCallback != null) {
|
||||
mCallback.run();
|
||||
}
|
||||
mInputConsumer = mConsumerSupplier.get();
|
||||
mConsumerSupplier = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.quickstep.BaseActivityInterface;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A factory that creates a input consumer for
|
||||
* {@link com.android.quickstep.util.InputConsumerProxy}.
|
||||
*/
|
||||
public class InputProxyHandlerFactory implements Supplier<InputConsumer> {
|
||||
|
||||
private final BaseActivityInterface mActivityInterface;
|
||||
private final GestureState mGestureState;
|
||||
|
||||
@UiThread
|
||||
public InputProxyHandlerFactory(BaseActivityInterface activityInterface,
|
||||
GestureState gestureState) {
|
||||
mActivityInterface = activityInterface;
|
||||
mGestureState = gestureState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to create a input proxy for the running task
|
||||
*/
|
||||
@Override
|
||||
public InputConsumer get() {
|
||||
StatefulActivity activity = mActivityInterface.getCreatedActivity();
|
||||
return activity == null ? InputConsumer.NO_OP
|
||||
: new OverviewInputConsumer(mGestureState, activity, null, true);
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_DEPTH_CONTROLLER;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.SKIP_TASKBAR;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
@@ -61,7 +60,10 @@ import com.android.systemui.plugins.ResourceProvider;
|
||||
public class StaggeredWorkspaceAnim {
|
||||
|
||||
private static final int APP_CLOSE_ROW_START_DELAY_MS = 10;
|
||||
// How long it takes to fade in each staggered row.
|
||||
private static final int ALPHA_DURATION_MS = 250;
|
||||
// Should be used for animations running alongside this StaggeredWorkspaceAnim.
|
||||
public static final int DURATION_MS = 250;
|
||||
|
||||
private static final float MAX_VELOCITY_PX_PER_S = 22f;
|
||||
|
||||
@@ -132,15 +134,15 @@ public class StaggeredWorkspaceAnim {
|
||||
}
|
||||
|
||||
if (animateOverviewScrim) {
|
||||
PendingAnimation pendingAnimation = new PendingAnimation(ALPHA_DURATION_MS);
|
||||
PendingAnimation pendingAnimation = new PendingAnimation(DURATION_MS);
|
||||
addScrimAnimationForState(launcher, NORMAL, pendingAnimation);
|
||||
mAnimators.play(pendingAnimation.buildAnim());
|
||||
}
|
||||
|
||||
addDepthAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
|
||||
addDepthAnimationForState(launcher, NORMAL, DURATION_MS);
|
||||
|
||||
mAnimators.play(launcher.getDragLayer().getSysUiScrim().createSysuiMultiplierAnim(0f, 1f)
|
||||
.setDuration(ALPHA_DURATION_MS));
|
||||
.setDuration(DURATION_MS));
|
||||
mAnimators.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
@@ -182,8 +184,7 @@ public class StaggeredWorkspaceAnim {
|
||||
*/
|
||||
private void prepareToAnimate(Launcher launcher, boolean animateOverviewScrim) {
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
config.animFlags = ANIM_ALL_COMPONENTS | SKIP_OVERVIEW | SKIP_DEPTH_CONTROLLER
|
||||
| SKIP_TASKBAR;
|
||||
config.animFlags = ANIM_ALL_COMPONENTS | SKIP_OVERVIEW | SKIP_DEPTH_CONTROLLER;
|
||||
config.duration = 0;
|
||||
// setRecentsAttachedToAppWindow() will animate recents out.
|
||||
launcher.getStateManager().createAtomicAnimation(BACKGROUND_APP, NORMAL, config).start();
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.android.quickstep.util;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.states.RotationHelper.deltaRotation;
|
||||
import static com.android.launcher3.touch.PagedOrientationHandler.MATRIX_POST_TRANSLATE;
|
||||
import static com.android.quickstep.util.NavigationModeFeatureFlag.LIVE_TILE;
|
||||
@@ -36,7 +35,6 @@ import android.util.IntProperty;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
@@ -79,7 +77,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
private final boolean mIsRecentsRtl;
|
||||
|
||||
private final Rect mTaskRect = new Rect();
|
||||
private final Rect mGridRect = new Rect();
|
||||
private boolean mDrawsBelowRecents;
|
||||
private final PointF mPivot = new PointF();
|
||||
private DeviceProfile mDp;
|
||||
@@ -98,22 +95,18 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
private final FullscreenDrawParams mCurrentFullscreenParams;
|
||||
public final AnimatedFloat taskPrimaryTranslation = new AnimatedFloat();
|
||||
public final AnimatedFloat taskSecondaryTranslation = new AnimatedFloat();
|
||||
public final AnimatedFloat gridTranslationSecondary = new AnimatedFloat();
|
||||
|
||||
// RecentsView properties
|
||||
public final AnimatedFloat recentsViewScale = new AnimatedFloat();
|
||||
public final AnimatedFloat fullScreenProgress = new AnimatedFloat();
|
||||
public final AnimatedFloat recentsViewSecondaryTranslation = new AnimatedFloat();
|
||||
public final AnimatedFloat recentsViewPrimaryTranslation = new AnimatedFloat();
|
||||
public final AnimatedFloat gridProgress = new AnimatedFloat();
|
||||
private final ScrollState mScrollState = new ScrollState();
|
||||
|
||||
// Cached calculations
|
||||
private boolean mLayoutValid = false;
|
||||
private boolean mScrollValid = false;
|
||||
private int mOrientationStateId;
|
||||
private final int mTaskThumbnailPadding;
|
||||
private final int mRowSpacing;
|
||||
|
||||
public TaskViewSimulator(Context context, BaseActivityInterface sizeStrategy) {
|
||||
mContext = context;
|
||||
@@ -125,8 +118,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
mOrientationStateId = mOrientationState.getStateId();
|
||||
Resources resources = context.getResources();
|
||||
mIsRecentsRtl = mOrientationState.getOrientationHandler().getRecentsRtlSetting(resources);
|
||||
mTaskThumbnailPadding = (int) resources.getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
mRowSpacing = (int) resources.getDimension(R.dimen.overview_grid_row_spacing);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -268,7 +259,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
mOrientationStateId = mOrientationState.getStateId();
|
||||
|
||||
getFullScreenScale();
|
||||
mSizeStrategy.calculateGridSize(mContext, mDp, mGridRect);
|
||||
mThumbnailData.rotation = mOrientationState.getDisplayRotation();
|
||||
|
||||
// mIsRecentsRtl is the inverse of TaskView RTL.
|
||||
@@ -309,34 +299,6 @@ public class TaskViewSimulator implements TransformParams.BuilderProxy {
|
||||
mMatrix.postTranslate(insets.left, insets.top);
|
||||
mMatrix.postScale(scale, scale);
|
||||
|
||||
// Apply TaskView matrix: gridProgress related properties
|
||||
float interpolatedGridProgress = ACCEL_DEACCEL.getInterpolation(gridProgress.value);
|
||||
final int boxLength = (int) Math.max(taskWidth, taskHeight);
|
||||
float availableHeight = mGridRect.height();
|
||||
float rowHeight = (availableHeight - mRowSpacing) / 2;
|
||||
float gridScale = rowHeight / (boxLength + mTaskThumbnailPadding);
|
||||
scale = Utilities.mapRange(interpolatedGridProgress, 1f, gridScale);
|
||||
mMatrix.postScale(scale, scale, mIsRecentsRtl ? 0 : taskWidth, 0);
|
||||
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
|
||||
Utilities.mapRange(interpolatedGridProgress, 0, gridTranslationSecondary.value));
|
||||
|
||||
// Apply TaskView matrix: task rect and grid rect difference
|
||||
float scaledWidth = taskWidth * gridScale;
|
||||
float taskGridHorizontalDiff;
|
||||
if (mIsRecentsRtl) {
|
||||
float taskRight = mTaskRect.left + scaledWidth;
|
||||
taskGridHorizontalDiff = mGridRect.right - taskRight;
|
||||
} else {
|
||||
float taskLeft = mTaskRect.right - scaledWidth;
|
||||
taskGridHorizontalDiff = mGridRect.left - taskLeft;
|
||||
}
|
||||
float taskGridVerticalDiff =
|
||||
mGridRect.top + mTaskThumbnailPadding * gridScale - mTaskRect.top;
|
||||
mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
|
||||
Utilities.mapRange(interpolatedGridProgress, 0, taskGridHorizontalDiff));
|
||||
mOrientationState.getOrientationHandler().setSecondary(mMatrix, MATRIX_POST_TRANSLATE,
|
||||
Utilities.mapRange(interpolatedGridProgress, 0, taskGridVerticalDiff));
|
||||
|
||||
// Apply TaskView matrix: translate, scroll
|
||||
mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
|
||||
mOrientationState.getOrientationHandler().set(mMatrix, MATRIX_POST_TRANSLATE,
|
||||
|
||||
@@ -21,6 +21,7 @@ import android.util.AttributeSet;
|
||||
import android.util.FloatProperty;
|
||||
import android.widget.Button;
|
||||
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.quickstep.views.RecentsView.PageCallbacks;
|
||||
import com.android.quickstep.views.RecentsView.ScrollState;
|
||||
@@ -40,30 +41,32 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
}
|
||||
};
|
||||
|
||||
private final StatefulActivity mActivity;
|
||||
private float mScrollAlpha = 1;
|
||||
private float mContentAlpha = 1;
|
||||
private float mVisibilityAlpha = 1;
|
||||
private float mGridProgress = 1;
|
||||
|
||||
private boolean mIsRtl;
|
||||
private final float mOriginalTranslationX, mOriginalTranslationY;
|
||||
private float mNormalTranslationPrimary;
|
||||
private float mGridTranslationPrimary;
|
||||
private float mGridTranslationSecondary;
|
||||
private float mGridScrollOffset;
|
||||
private float mOffsetTranslationPrimary;
|
||||
|
||||
private int mScrollOffset;
|
||||
private int mSidePadding;
|
||||
|
||||
public ClearAllButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
mOriginalTranslationX = getTranslationX();
|
||||
mOriginalTranslationY = getTranslationY();
|
||||
mActivity = StatefulActivity.fromContext(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
|
||||
mScrollOffset = orientationHandler.getClearAllScrollOffset(getRecentsView(), mIsRtl);
|
||||
mSidePadding = orientationHandler.getClearAllSidePadding(getRecentsView(), mIsRtl);
|
||||
}
|
||||
|
||||
private RecentsView getRecentsView() {
|
||||
@@ -96,25 +99,27 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScroll(ScrollState scrollState) {
|
||||
PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
|
||||
public void onPageScroll(ScrollState scrollState, boolean gridEnabled) {
|
||||
RecentsView recentsView = getRecentsView();
|
||||
if (recentsView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
|
||||
float orientationSize = orientationHandler.getPrimaryValue(getWidth(), getHeight());
|
||||
if (orientationSize == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float shift;
|
||||
if (mIsRtl) {
|
||||
shift = Math.min(scrollState.scrollFromEdge, orientationSize);
|
||||
} else {
|
||||
shift = Math.min(scrollState.scrollFromEdge,
|
||||
orientationSize + getGridTrans(mGridTranslationPrimary))
|
||||
- getGridTrans(mGridTranslationPrimary);
|
||||
int leftEdgeScroll = recentsView.getLeftMostChildScroll();
|
||||
float adjustedScrollFromEdge = scrollState.scrollFromEdge - leftEdgeScroll;
|
||||
float shift = Math.min(adjustedScrollFromEdge, orientationSize);
|
||||
mNormalTranslationPrimary = mIsRtl ? -shift : shift;
|
||||
if (!gridEnabled) {
|
||||
mNormalTranslationPrimary += mSidePadding;
|
||||
}
|
||||
mNormalTranslationPrimary = mIsRtl ? (mScrollOffset - shift) : (mScrollOffset + shift);
|
||||
applyPrimaryTranslation();
|
||||
orientationHandler.getSecondaryViewTranslate().set(this,
|
||||
orientationHandler.getSecondaryValue(mOriginalTranslationX, mOriginalTranslationY));
|
||||
applySecondaryTranslation();
|
||||
mScrollAlpha = 1 - shift / orientationSize;
|
||||
updateAlpha();
|
||||
}
|
||||
@@ -130,11 +135,26 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
applyPrimaryTranslation();
|
||||
}
|
||||
|
||||
public void setGridTranslationSecondary(float gridTranslationSecondary) {
|
||||
mGridTranslationSecondary = gridTranslationSecondary;
|
||||
applyPrimaryTranslation();
|
||||
}
|
||||
|
||||
public void setGridScrollOffset(float gridScrollOffset) {
|
||||
mGridScrollOffset = gridScrollOffset;
|
||||
}
|
||||
|
||||
public void setOffsetTranslationPrimary(float offsetTranslationPrimary) {
|
||||
mOffsetTranslationPrimary = offsetTranslationPrimary;
|
||||
applyPrimaryTranslation();
|
||||
}
|
||||
|
||||
public float getScrollAdjustment(boolean gridEnabled) {
|
||||
float scrollAdjustment = 0;
|
||||
if (gridEnabled) {
|
||||
scrollAdjustment += mGridTranslationPrimary;
|
||||
scrollAdjustment += mGridTranslationPrimary + mGridScrollOffset;
|
||||
}
|
||||
scrollAdjustment += mOffsetTranslationPrimary;
|
||||
return scrollAdjustment;
|
||||
}
|
||||
|
||||
@@ -160,10 +180,31 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
|
||||
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
|
||||
orientationHandler.getPrimaryViewTranslate().set(this,
|
||||
mNormalTranslationPrimary + getGridTrans(mGridTranslationPrimary));
|
||||
orientationHandler.getPrimaryValue(0f, getOriginalTranslationY())
|
||||
+ mNormalTranslationPrimary + mOffsetTranslationPrimary + getGridTrans(
|
||||
mGridTranslationPrimary));
|
||||
}
|
||||
|
||||
private void applySecondaryTranslation() {
|
||||
RecentsView recentsView = getRecentsView();
|
||||
if (recentsView == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
|
||||
orientationHandler.getSecondaryViewTranslate().set(this,
|
||||
orientationHandler.getSecondaryValue(0f, getOriginalTranslationY())
|
||||
+ getGridTrans(mGridTranslationSecondary));
|
||||
}
|
||||
|
||||
private float getGridTrans(float endTranslation) {
|
||||
return mGridProgress > 0 ? endTranslation : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Y translation that is set in the original layout position, before scrolling.
|
||||
*/
|
||||
private float getOriginalTranslationY() {
|
||||
return mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx / 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.widget.FrameLayout;
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Insettable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.util.MultiValueAlpha;
|
||||
@@ -144,6 +145,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
updateVerticalMargin(SysUINavigationMode.getMode(getContext()));
|
||||
updateHorizontalPadding();
|
||||
}
|
||||
|
||||
public void updateHiddenFlags(@ActionsHiddenFlags int visibilityFlags, boolean enable) {
|
||||
@@ -187,6 +189,10 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
return mMultiValueAlpha.getProperty(INDEX_FULLSCREEN_ALPHA);
|
||||
}
|
||||
|
||||
private void updateHorizontalPadding() {
|
||||
setPadding(mInsets.left, 0, mInsets.right, 0);
|
||||
}
|
||||
|
||||
/** Updates vertical margins for different navigation mode or configuration changes. */
|
||||
public void updateVerticalMargin(Mode mode) {
|
||||
LayoutParams actionParams = (LayoutParams) findViewById(
|
||||
@@ -196,6 +202,13 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
getBottomVerticalMargin(mode));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the device profile for this view to draw with.
|
||||
*/
|
||||
public void setDp(DeviceProfile dp) {
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
protected int getBottomVerticalMargin(Mode mode) {
|
||||
int bottomMargin;
|
||||
int orientation = getResources().getConfiguration().orientation;
|
||||
|
||||
@@ -27,6 +27,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_MODAL_TASK;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT;
|
||||
import static com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION;
|
||||
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
||||
import static com.android.launcher3.Utilities.mapToRange;
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
@@ -34,6 +35,7 @@ import static com.android.launcher3.Utilities.squaredTouchSlop;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL;
|
||||
@@ -50,6 +52,7 @@ import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
|
||||
import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.LayoutTransition;
|
||||
import android.animation.LayoutTransition.TransitionListener;
|
||||
@@ -61,6 +64,7 @@ import android.app.ActivityManager.RunningTaskInfo;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
@@ -129,8 +133,11 @@ import com.android.quickstep.RecentsModel.TaskVisualsChangeListener;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.TaskOverlayFactory;
|
||||
import com.android.quickstep.TaskThumbnailCache;
|
||||
import com.android.quickstep.TaskViewUtils;
|
||||
import com.android.quickstep.ViewUtils;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.MultiValueUpdateListener;
|
||||
import com.android.quickstep.util.RecentsOrientedState;
|
||||
import com.android.quickstep.util.SplitScreenBounds;
|
||||
import com.android.quickstep.util.SurfaceTransactionApplier;
|
||||
@@ -142,6 +149,8 @@ import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.PackageManagerWrapper;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams;
|
||||
import com.android.systemui.shared.system.TaskStackChangeListener;
|
||||
import com.android.wm.shell.pip.IPipAnimationListener;
|
||||
|
||||
@@ -301,6 +310,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
protected final Rect mTempRect = new Rect();
|
||||
protected final RectF mTempRectF = new RectF();
|
||||
private final PointF mTempPointF = new PointF();
|
||||
private float mFullscreenScale;
|
||||
|
||||
private static final int DISMISS_TASK_DURATION = 300;
|
||||
private static final int ADDITION_TASK_DURATION = 200;
|
||||
@@ -310,7 +320,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
protected final T mActivity;
|
||||
private final float mFastFlingVelocity;
|
||||
private final RecentsModel mModel;
|
||||
private final int mTaskTopMargin;
|
||||
private final int mRowSpacing;
|
||||
private final ClearAllButton mClearAllButton;
|
||||
private final Rect mClearAllButtonDeadZoneRect = new Rect();
|
||||
@@ -529,8 +538,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
|
||||
mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
|
||||
setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
|
||||
mTaskTopMargin = getResources()
|
||||
.getDimensionPixelSize(R.dimen.task_thumbnail_top_margin);
|
||||
mRowSpacing = getResources().getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
|
||||
mSquaredTouchSlop = squaredTouchSlop(context);
|
||||
|
||||
@@ -717,6 +724,72 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
super.draw(canvas);
|
||||
}
|
||||
|
||||
public void launchSideTaskInLiveTileModeForRestartedApp(int taskId) {
|
||||
if (mRunningTaskId != -1 && mRunningTaskId == taskId &&
|
||||
getLiveTileParams().getTargetSet().findTask(taskId) != null) {
|
||||
launchSideTaskInLiveTileMode(taskId, getLiveTileParams().getTargetSet().apps);
|
||||
}
|
||||
}
|
||||
|
||||
public void launchSideTaskInLiveTileMode(int taskId, RemoteAnimationTargetCompat[] apps) {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
TaskView taskView = getTaskView(taskId);
|
||||
if (taskView == null || !isTaskViewVisible(taskView)) {
|
||||
// TODO: Refine this animation.
|
||||
SurfaceTransactionApplier surfaceApplier =
|
||||
new SurfaceTransactionApplier(mActivity.getDragLayer());
|
||||
ValueAnimator appAnimator = ValueAnimator.ofFloat(0, 1);
|
||||
appAnimator.setDuration(RECENTS_LAUNCH_DURATION);
|
||||
appAnimator.setInterpolator(ACCEL_DEACCEL);
|
||||
appAnimator.addUpdateListener(new MultiValueUpdateListener() {
|
||||
@Override
|
||||
public void onUpdate(float percent) {
|
||||
SurfaceParams.Builder builder = new SurfaceParams.Builder(
|
||||
apps[apps.length - 1].leash);
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postScale(percent, percent);
|
||||
matrix.postTranslate(mActivity.getDeviceProfile().widthPx * (1 - percent) / 2,
|
||||
mActivity.getDeviceProfile().heightPx * (1 - percent) / 2);
|
||||
builder.withAlpha(percent).withMatrix(matrix);
|
||||
surfaceApplier.scheduleApply(builder.build());
|
||||
}
|
||||
});
|
||||
anim.play(appAnimator);
|
||||
} else {
|
||||
TaskViewUtils.composeRecentsLaunchAnimator(
|
||||
anim, taskView, apps,
|
||||
mLiveTileParams.getTargetSet().wallpapers, true /* launcherClosing */,
|
||||
mActivity.getStateManager(), this,
|
||||
getDepthController());
|
||||
}
|
||||
anim.addListener(new AnimatorListenerAdapter(){
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animator) {
|
||||
cleanUp(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationCancel(Animator animator) {
|
||||
cleanUp(true);
|
||||
}
|
||||
|
||||
private void cleanUp(boolean canceled) {
|
||||
if (mRecentsAnimationController != null) {
|
||||
mRecentsAnimationController.finish(false /* toRecents */,
|
||||
null /* onFinishComplete */);
|
||||
if (canceled) {
|
||||
mRecentsAnimationController = null;
|
||||
} else {
|
||||
mSizeStrategy.onLaunchTaskSuccess();
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", false);
|
||||
}
|
||||
}
|
||||
});
|
||||
anim.start();
|
||||
}
|
||||
|
||||
private void updateTaskStartIndex(View affectingView) {
|
||||
if (!(affectingView instanceof TaskView) && !(affectingView instanceof ClearAllButton)) {
|
||||
int childCount = getChildCount();
|
||||
@@ -744,7 +817,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
int taskStart = mOrientationHandler.getChildStart(tv) + (int) tv.getOffsetAdjustment(
|
||||
mOverviewFullscreenEnabled, showAsGrid());
|
||||
int taskSize = (int) (mOrientationHandler.getMeasuredSize(tv) * tv.getSizeAdjustment(
|
||||
mOverviewFullscreenEnabled, showAsGrid()));
|
||||
mOverviewFullscreenEnabled));
|
||||
int taskEnd = taskStart + taskSize;
|
||||
return (taskStart >= start && taskStart <= end) || (taskEnd >= start
|
||||
&& taskEnd <= end);
|
||||
@@ -1022,7 +1095,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
mLiveTileTaskViewSimulator.taskSecondaryTranslation.value = 0;
|
||||
mLiveTileTaskViewSimulator.fullScreenProgress.value = 0;
|
||||
mLiveTileTaskViewSimulator.recentsViewScale.value = 1;
|
||||
mLiveTileTaskViewSimulator.gridProgress.value = 0;
|
||||
}
|
||||
if (mRunningTaskTileHidden) {
|
||||
setRunningTaskHidden(mRunningTaskTileHidden);
|
||||
@@ -1066,7 +1138,9 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
public void setInsets(Rect insets) {
|
||||
mInsets.set(insets);
|
||||
resetPaddingFromTaskSize();
|
||||
mLiveTileTaskViewSimulator.setDp(mActivity.getDeviceProfile());
|
||||
DeviceProfile dp = mActivity.getDeviceProfile();
|
||||
mLiveTileTaskViewSimulator.setDp(dp);
|
||||
mActionsView.setDp(dp);
|
||||
}
|
||||
|
||||
private void resetPaddingFromTaskSize() {
|
||||
@@ -1075,7 +1149,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
mTaskWidth = mTempRect.width();
|
||||
mTaskHeight = mTempRect.height();
|
||||
|
||||
mTempRect.top -= mTaskTopMargin;
|
||||
mTempRect.top -= dp.overviewTaskThumbnailTopMarginPx;
|
||||
setPadding(mTempRect.left - mInsets.left, mTempRect.top - mInsets.top,
|
||||
dp.widthPx - mInsets.right - mTempRect.right,
|
||||
dp.heightPx - mInsets.bottom - mTempRect.bottom);
|
||||
@@ -1092,6 +1166,10 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
*/
|
||||
private void updateTaskSize() {
|
||||
final int taskCount = getTaskViewCount();
|
||||
if (taskCount == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
float accumulatedTranslationX = 0;
|
||||
float[] fullscreenTranslations = new float[taskCount];
|
||||
int firstNonHomeTaskIndex = 0;
|
||||
@@ -1106,8 +1184,11 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
|
||||
taskView.updateTaskSize();
|
||||
fullscreenTranslations[i] += accumulatedTranslationX;
|
||||
// Compensate space caused by TaskView scaling.
|
||||
float widthDiff =
|
||||
taskView.getLayoutParams().width * (1 - taskView.getFullscreenScale());
|
||||
// Compensate page spacing widening caused by RecentsView scaling.
|
||||
widthDiff += mPageSpacing * (1 - 1 / mFullscreenScale);
|
||||
float fullscreenTranslationX = mIsRtl ? widthDiff : -widthDiff;
|
||||
fullscreenTranslations[i] += fullscreenTranslationX;
|
||||
accumulatedTranslationX += fullscreenTranslationX;
|
||||
@@ -1181,13 +1262,13 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
View page = getPageAt(i);
|
||||
mScrollState.updateInterpolation(mActivity.getDeviceProfile(),
|
||||
mOrientationHandler.getChildStartWithTranslation(page));
|
||||
((PageCallbacks) page).onPageScroll(mScrollState);
|
||||
((PageCallbacks) page).onPageScroll(mScrollState, mOverviewGridEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getDestinationPage(int scaledScroll) {
|
||||
if (mGridProgress == 0) {
|
||||
if (!showAsGrid()) {
|
||||
return super.getDestinationPage(scaledScroll);
|
||||
}
|
||||
|
||||
@@ -1600,10 +1681,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
}
|
||||
|
||||
final int boxLength = Math.max(mTaskWidth, mTaskHeight);
|
||||
float availableHeight = mLastComputedGridSize.height();
|
||||
float rowHeight = (availableHeight - mRowSpacing) / 2;
|
||||
float gridScale = rowHeight / (boxLength + mTaskTopMargin);
|
||||
|
||||
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
int topRowWidth = 0;
|
||||
int bottomRowWidth = 0;
|
||||
float topAccumulatedTranslationX = 0;
|
||||
@@ -1621,43 +1699,17 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
continue;
|
||||
}
|
||||
|
||||
taskView.setGridScale(gridScale);
|
||||
|
||||
float scaledWidth = taskView.getLayoutParams().width * gridScale;
|
||||
float taskGridHorizontalDiff;
|
||||
if (mIsRtl) {
|
||||
float taskRight = mLastComputedTaskSize.left + scaledWidth;
|
||||
taskGridHorizontalDiff = mLastComputedGridSize.right - taskRight;
|
||||
} else {
|
||||
float taskLeft = mLastComputedTaskSize.right - scaledWidth;
|
||||
taskGridHorizontalDiff = mLastComputedGridSize.left - taskLeft;
|
||||
}
|
||||
gridTranslations[i] -= taskGridHorizontalDiff;
|
||||
taskView.setGridOffsetTranslationX(taskGridHorizontalDiff);
|
||||
|
||||
float taskGridVerticalDiff = mLastComputedGridSize.top + mTaskTopMargin * gridScale
|
||||
- mLastComputedTaskSize.top;
|
||||
|
||||
// Off-set gap due to task scaling.
|
||||
float widthDiff = taskView.getLayoutParams().width * (1 - gridScale);
|
||||
float gridScaleTranslationX = mIsRtl ? widthDiff : -widthDiff;
|
||||
gridTranslations[i] += gridScaleTranslationX;
|
||||
|
||||
// Visible offset caused by having scaling pivot on top-right.
|
||||
taskView.setNonRtlVisibleOffset(mIsRtl ? 0 : widthDiff);
|
||||
|
||||
if (topRowWidth <= bottomRowWidth) {
|
||||
gridTranslations[i] += topAccumulatedTranslationX;
|
||||
topRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing;
|
||||
topRowWidth += taskView.getLayoutParams().width + mPageSpacing;
|
||||
topSet.add(i);
|
||||
|
||||
taskView.setGridTranslationY(taskGridVerticalDiff);
|
||||
taskView.setGridTranslationY(0);
|
||||
|
||||
// Move horizontally into empty space.
|
||||
float widthOffset = 0;
|
||||
for (int j = i - 1; bottomSet.contains(j); j--) {
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale
|
||||
+ mPageSpacing;
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
|
||||
}
|
||||
|
||||
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
@@ -1665,26 +1717,39 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
topAccumulatedTranslationX += gridTranslationX;
|
||||
} else {
|
||||
gridTranslations[i] += bottomAccumulatedTranslationX;
|
||||
bottomRowWidth += taskView.getLayoutParams().width * gridScale + mPageSpacing;
|
||||
bottomRowWidth += taskView.getLayoutParams().width + mPageSpacing;
|
||||
bottomSet.add(i);
|
||||
|
||||
// Move into bottom row.
|
||||
float heightOffset = (boxLength + mTaskTopMargin) * gridScale + mRowSpacing;
|
||||
taskView.setGridTranslationY(heightOffset + taskGridVerticalDiff);
|
||||
float heightOffset = (boxLength + taskTopMargin) + mRowSpacing;
|
||||
taskView.setGridTranslationY(heightOffset);
|
||||
|
||||
// Move horizontally into empty space.
|
||||
float widthOffset = 0;
|
||||
for (int j = i - 1; topSet.contains(j); j--) {
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width * gridScale
|
||||
+ mPageSpacing;
|
||||
widthOffset += getTaskViewAt(j).getLayoutParams().width + mPageSpacing;
|
||||
}
|
||||
|
||||
float gridTranslationX = mIsRtl ? widthOffset : -widthOffset;
|
||||
gridTranslations[i] += gridTranslationX;
|
||||
bottomAccumulatedTranslationX += gridTranslationX;
|
||||
}
|
||||
topAccumulatedTranslationX += gridScaleTranslationX;
|
||||
bottomAccumulatedTranslationX += gridScaleTranslationX;
|
||||
}
|
||||
|
||||
// If the first non-home task does not take full width of task Rect, shift all tasks
|
||||
// accordingly without affecting scrolls.
|
||||
int firstTaskWidth = getTaskViewAt(firstNonHomeTaskIndex).getLayoutParams().width;
|
||||
float firstNonHomeTaskOffset = firstTaskWidth == ViewGroup.LayoutParams.MATCH_PARENT ? 0
|
||||
: mTaskWidth - firstTaskWidth;
|
||||
float offsetTranslation = mIsRtl ? firstNonHomeTaskOffset : -firstNonHomeTaskOffset;
|
||||
|
||||
// We need to maintain first non-home task's grid translation at 0, now shift translation
|
||||
// of all the TaskViews to achieve that.
|
||||
for (int i = firstNonHomeTaskIndex; i < taskCount; i++) {
|
||||
TaskView taskView = getTaskViewAt(i);
|
||||
taskView.setGridTranslationX(
|
||||
gridTranslations[i] - gridTranslations[firstNonHomeTaskIndex]);
|
||||
taskView.setGridOffsetTranslationX(offsetTranslation);
|
||||
}
|
||||
|
||||
// Use the accumulated translation of the longer row.
|
||||
@@ -1700,7 +1765,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
shorterRowCompensation = bottomRowWidth - topRowWidth;
|
||||
}
|
||||
} else {
|
||||
if (!topSet.contains(taskCount - 1)) {
|
||||
if (bottomSet.contains(taskCount - 1)) {
|
||||
shorterRowCompensation = topRowWidth - bottomRowWidth;
|
||||
}
|
||||
}
|
||||
@@ -1721,14 +1786,14 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
clearAllAccumulatedTranslation + clearAllShorterRowCompensation
|
||||
+ clearAllShortTotalCompensation;
|
||||
|
||||
// We need to maintain first non-home task's grid translation at 0, now shift translation
|
||||
// of all the TaskViews to achieve that.
|
||||
for (int i = firstNonHomeTaskIndex; i < taskCount; i++) {
|
||||
getTaskViewAt(i).setGridTranslationX(
|
||||
gridTranslations[i] - gridTranslations[firstNonHomeTaskIndex]);
|
||||
}
|
||||
mClearAllButton.setGridTranslationPrimary(
|
||||
clearAllTotalTranslationX - gridTranslations[firstNonHomeTaskIndex]);
|
||||
mClearAllButton.setGridTranslationSecondary(
|
||||
boxLength - mTaskHeight / 2f + mRowSpacing / 2f);
|
||||
mClearAllButton.setGridScrollOffset(
|
||||
mIsRtl ? mLastComputedTaskSize.left - mLastComputedGridSize.left
|
||||
: mLastComputedTaskSize.right - mLastComputedGridSize.right);
|
||||
mClearAllButton.setOffsetTranslationPrimary(offsetTranslation);
|
||||
|
||||
setGridProgress(mGridProgress);
|
||||
}
|
||||
@@ -1753,7 +1818,6 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
for (int i = 0; i < taskCount; i++) {
|
||||
getTaskViewAt(i).setGridProgress(gridProgress);
|
||||
}
|
||||
mLiveTileTaskViewSimulator.gridProgress.value = gridProgress;
|
||||
mClearAllButton.setGridProgress(gridProgress);
|
||||
}
|
||||
|
||||
@@ -1801,8 +1865,10 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
|
||||
/**
|
||||
* Updates the page UI based on scroll params.
|
||||
*
|
||||
* @param gridEnabled whether Overveiw is currently showing as 2 rows grid
|
||||
*/
|
||||
default void onPageScroll(ScrollState scrollState) {}
|
||||
default void onPageScroll(ScrollState scrollState, boolean gridEnabled) {}
|
||||
}
|
||||
|
||||
public static class ScrollState extends CurveProperties {
|
||||
@@ -2297,7 +2363,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
|
||||
// Update the pivots such that when the task is scaled, it fills the full page
|
||||
getTaskSize(mTempRect);
|
||||
getPagedViewOrientedState().getFullScreenScaleAndPivot(
|
||||
mFullscreenScale = getPagedViewOrientedState().getFullScreenScaleAndPivot(
|
||||
mTempRect, mActivity.getDeviceProfile(), mTempPointF);
|
||||
setPivotX(mTempPointF.x);
|
||||
setPivotY(mTempPointF.y);
|
||||
@@ -2485,7 +2551,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
if (child == mSplitHiddenTaskView) {
|
||||
|
||||
int left = newScroll[i] + getPaddingStart();
|
||||
int topMargin = mSplitHiddenTaskView.getThumbnailTopMargin();
|
||||
int topMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
int top = -mSplitHiddenTaskView.getHeight() - locationOnScreen[1];
|
||||
mSplitHiddenTaskView.layout(left, top,
|
||||
left + mSplitHiddenTaskView.getWidth(),
|
||||
@@ -2858,22 +2924,42 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
@Override
|
||||
protected int computeMinScroll() {
|
||||
if (getTaskViewCount() > 0) {
|
||||
if (mDisallowScrollToClearAll) {
|
||||
if (mIsRtl && mDisallowScrollToClearAll) {
|
||||
// We aren't showing the clear all button,
|
||||
// so use the leftmost task as the min scroll.
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
|
||||
}
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
|
||||
}
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
|
||||
}
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
return getLeftMostChildScroll();
|
||||
}
|
||||
return super.computeMinScroll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns page scroll of the left most child.
|
||||
*/
|
||||
public int getLeftMostChildScroll() {
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
|
||||
}
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int computeMaxScroll() {
|
||||
if (getTaskViewCount() > 0) {
|
||||
if (!mIsRtl && mDisallowScrollToClearAll) {
|
||||
// We aren't showing the clear all button,
|
||||
// so use the rightmost task as the min scroll.
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
|
||||
}
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
}
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
|
||||
}
|
||||
return super.computeMaxScroll();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean getPageScrolls(int[] outPageScrolls, boolean layoutChildren,
|
||||
ComputePageScrollsLogic scrollLogic) {
|
||||
@@ -2919,26 +3005,7 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
return super.getChildVisibleSize(index);
|
||||
}
|
||||
return (int) (super.getChildVisibleSize(index) * taskView.getSizeAdjustment(
|
||||
mOverviewFullscreenEnabled, showAsGrid()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int computeMaxScroll() {
|
||||
if (getTaskViewCount() > 0) {
|
||||
if (mDisallowScrollToClearAll) {
|
||||
// We aren't showing the clear all button,
|
||||
// so use the rightmost task as the min scroll.
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
}
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)));
|
||||
}
|
||||
if (mIsRtl) {
|
||||
return getScrollForPage(mTaskViewStartIndex);
|
||||
}
|
||||
return getScrollForPage(indexOfChild(getTaskViewAt(getTaskViewCount() - 1)) + 1);
|
||||
}
|
||||
return super.computeMaxScroll();
|
||||
mOverviewFullscreenEnabled));
|
||||
}
|
||||
|
||||
public ClearAllButton getClearAllButton() {
|
||||
@@ -3160,7 +3227,9 @@ public abstract class RecentsView<T extends StatefulActivity> extends PagedView
|
||||
MAIN_EXECUTOR.execute(() -> {
|
||||
// Needed for activities that auto-enter PiP, which will not trigger a remote
|
||||
// animation to be created
|
||||
mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
|
||||
if (mActivity != null) {
|
||||
mActivity.clearForceInvisibleFlag(STATE_HANDLER_INVISIBILITY_FLAGS);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,6 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
private static final int REVEAL_OPEN_DURATION = 150;
|
||||
private static final int REVEAL_CLOSE_DURATION = 100;
|
||||
|
||||
private final float mThumbnailTopMargin;
|
||||
private BaseDraggingActivity mActivity;
|
||||
private TextView mTaskName;
|
||||
private AnimatorSet mOpenCloseAnimator;
|
||||
@@ -73,7 +72,6 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mActivity = BaseDraggingActivity.fromContext(context);
|
||||
mThumbnailTopMargin = getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
setClipToOutline(true);
|
||||
}
|
||||
|
||||
@@ -123,14 +121,15 @@ public class TaskMenuView extends AbstractFloatingView {
|
||||
}
|
||||
|
||||
public void setPosition(float x, float y, PagedOrientationHandler pagedOrientationHandler) {
|
||||
float adjustedY = y + mThumbnailTopMargin;
|
||||
int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
float adjustedY = y + taskTopMargin;
|
||||
// Changing pivot to make computations easier
|
||||
// NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
|
||||
// which would render the X and Y position set here incorrect
|
||||
setPivotX(0);
|
||||
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
|
||||
// In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
|
||||
setPivotY(-mThumbnailTopMargin);
|
||||
setPivotY(-taskTopMargin);
|
||||
} else {
|
||||
setPivotY(0);
|
||||
}
|
||||
|
||||
@@ -440,13 +440,14 @@ public class TaskThumbnailView extends View implements PluginListener<OverviewSc
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the snapshot is real.
|
||||
* Returns whether the snapshot is real. If the device is locked for the user of the task,
|
||||
* the snapshot used will be an app-theme generated snapshot instead of a real snapshot.
|
||||
*/
|
||||
public boolean isRealSnapshot() {
|
||||
if (mThumbnailData == null) {
|
||||
return false;
|
||||
}
|
||||
return mThumbnailData.isRealSnapshot;
|
||||
return mThumbnailData.isRealSnapshot && !mTask.isLocked;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -279,7 +279,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
private float mFullscreenProgress;
|
||||
private float mGridProgress;
|
||||
private float mFullscreenScale = 1;
|
||||
private float mGridScale = 1;
|
||||
private final FullscreenDrawParams mCurrentFullscreenParams;
|
||||
private final StatefulActivity mActivity;
|
||||
|
||||
@@ -298,7 +297,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
private float mGridTranslationY;
|
||||
// Offset translation does not affect scroll calculation.
|
||||
private float mGridOffsetTranslationX;
|
||||
private float mNonRtlVisibleOffset;
|
||||
|
||||
private ObjectAnimator mIconAndDimAnimator;
|
||||
private float mIconScaleAnimStartProgress = 0;
|
||||
@@ -376,7 +374,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
mCurrentFullscreenParams = new FullscreenDrawParams(context);
|
||||
mDigitalWellBeingToast = new DigitalWellBeingToast(mActivity, this);
|
||||
|
||||
mOutlineProvider = new TaskOutlineProvider(getContext(), mCurrentFullscreenParams);
|
||||
mOutlineProvider = new TaskOutlineProvider(getContext(), mCurrentFullscreenParams,
|
||||
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx);
|
||||
setOutlineProvider(mOutlineProvider);
|
||||
}
|
||||
|
||||
@@ -673,17 +672,14 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
}
|
||||
}
|
||||
|
||||
public int getThumbnailTopMargin() {
|
||||
return (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
}
|
||||
|
||||
public void setOrientationState(RecentsOrientedState orientationState) {
|
||||
PagedOrientationHandler orientationHandler = orientationState.getOrientationHandler();
|
||||
boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
LayoutParams snapshotParams = (LayoutParams) mSnapshotView.getLayoutParams();
|
||||
int thumbnailPadding = (int) getResources().getDimension(R.dimen.task_thumbnail_top_margin);
|
||||
int taskIconMargin = (int) getResources().getDimension(R.dimen.task_icon_top_margin);
|
||||
int taskIconHeight = (int) getResources().getDimension(R.dimen.task_thumbnail_icon_size);
|
||||
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
|
||||
snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
|
||||
int taskIconMargin = deviceProfile.overviewTaskMarginPx;
|
||||
int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
|
||||
LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
|
||||
switch (orientationHandler.getRotation()) {
|
||||
case ROTATION_90:
|
||||
@@ -694,7 +690,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
break;
|
||||
case ROTATION_180:
|
||||
iconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
|
||||
iconParams.bottomMargin = -thumbnailPadding;
|
||||
iconParams.bottomMargin = -snapshotParams.topMargin;
|
||||
iconParams.leftMargin = iconParams.rightMargin = 0;
|
||||
iconParams.topMargin = taskIconMargin;
|
||||
break;
|
||||
@@ -711,8 +707,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
iconParams.topMargin = taskIconMargin;
|
||||
break;
|
||||
}
|
||||
mSnapshotView.setLayoutParams(snapshotParams);
|
||||
iconParams.width = iconParams.height = taskIconHeight;
|
||||
mIconView.setLayoutParams(iconParams);
|
||||
mIconView.setRotation(orientationHandler.getDegreesRotated());
|
||||
snapshotParams.topMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
|
||||
mSnapshotView.setLayoutParams(snapshotParams);
|
||||
|
||||
if (mMenuView != null) {
|
||||
mMenuView.onRotationChanged();
|
||||
@@ -792,8 +792,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
|
||||
@Override
|
||||
public void onRecycle() {
|
||||
mFullscreenTranslationX = mGridTranslationX = mGridTranslationY =
|
||||
mGridOffsetTranslationX = mBoxTranslationY = mNonRtlVisibleOffset = 0f;
|
||||
mFullscreenTranslationX = mGridTranslationX =
|
||||
mGridTranslationY = mGridOffsetTranslationX = mBoxTranslationY = 0f;
|
||||
resetViewTransforms();
|
||||
// Clear any references to the thumbnail (it will be re-read either from the cache or the
|
||||
// system on next bind)
|
||||
@@ -803,7 +803,7 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScroll(ScrollState scrollState) {
|
||||
public void onPageScroll(ScrollState scrollState, boolean gridEnabled) {
|
||||
// Don't do anything if it's modal.
|
||||
if (mModalness > 0) {
|
||||
return;
|
||||
@@ -906,11 +906,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
return mFullscreenScale;
|
||||
}
|
||||
|
||||
public void setGridScale(float gridScale) {
|
||||
mGridScale = gridScale;
|
||||
applyScale();
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves TaskView between carousel and 2 row grid.
|
||||
*
|
||||
@@ -927,8 +922,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
float scale = 1;
|
||||
float fullScreenProgress = EXAGGERATED_EASE.getInterpolation(mFullscreenProgress);
|
||||
scale *= Utilities.mapRange(fullScreenProgress, 1f, mFullscreenScale);
|
||||
float gridProgress = ACCEL_DEACCEL.getInterpolation(mGridProgress);
|
||||
scale *= Utilities.mapRange(gridProgress, 1f, mGridScale);
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
}
|
||||
@@ -991,10 +984,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
applyTranslationX();
|
||||
}
|
||||
|
||||
public void setNonRtlVisibleOffset(float nonRtlVisibleOffset) {
|
||||
mNonRtlVisibleOffset = nonRtlVisibleOffset;
|
||||
}
|
||||
|
||||
public float getScrollAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
|
||||
float scrollAdjustment = 0;
|
||||
if (fullscreenEnabled) {
|
||||
@@ -1006,22 +995,19 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
return scrollAdjustment;
|
||||
}
|
||||
|
||||
public float getOffsetAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
|
||||
public float getOffsetAdjustment(boolean fullscreenEnabled,boolean gridEnabled) {
|
||||
float offsetAdjustment = getScrollAdjustment(fullscreenEnabled, gridEnabled);
|
||||
if (gridEnabled) {
|
||||
offsetAdjustment += mGridOffsetTranslationX + mNonRtlVisibleOffset;
|
||||
offsetAdjustment += mGridOffsetTranslationX;
|
||||
}
|
||||
return offsetAdjustment;
|
||||
}
|
||||
|
||||
public float getSizeAdjustment(boolean fullscreenEnabled, boolean gridEnabled) {
|
||||
public float getSizeAdjustment(boolean fullscreenEnabled) {
|
||||
float sizeAdjustment = 1;
|
||||
if (fullscreenEnabled) {
|
||||
sizeAdjustment *= mFullscreenScale;
|
||||
}
|
||||
if (gridEnabled) {
|
||||
sizeAdjustment *= mGridScale;
|
||||
}
|
||||
return sizeAdjustment;
|
||||
}
|
||||
|
||||
@@ -1083,17 +1069,17 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
|
||||
private static final class TaskOutlineProvider extends ViewOutlineProvider {
|
||||
|
||||
private final int mMarginTop;
|
||||
private int mMarginTop;
|
||||
private FullscreenDrawParams mFullscreenParams;
|
||||
|
||||
TaskOutlineProvider(Context context, FullscreenDrawParams fullscreenParams) {
|
||||
mMarginTop = context.getResources().getDimensionPixelSize(
|
||||
R.dimen.task_thumbnail_top_margin);
|
||||
TaskOutlineProvider(Context context, FullscreenDrawParams fullscreenParams, int topMargin) {
|
||||
mMarginTop = topMargin;
|
||||
mFullscreenParams = fullscreenParams;
|
||||
}
|
||||
|
||||
public void setFullscreenParams(FullscreenDrawParams params) {
|
||||
public void updateParams(FullscreenDrawParams params, int topMargin) {
|
||||
mFullscreenParams = params;
|
||||
mMarginTop = topMargin;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1216,7 +1202,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
}
|
||||
|
||||
thumbnail.setFullscreenParams(mCurrentFullscreenParams);
|
||||
mOutlineProvider.setFullscreenParams(mCurrentFullscreenParams);
|
||||
mOutlineProvider.updateParams(
|
||||
mCurrentFullscreenParams,
|
||||
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx);
|
||||
invalidateOutline();
|
||||
}
|
||||
|
||||
@@ -1238,8 +1226,8 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
|
||||
void updateTaskSize() {
|
||||
ViewGroup.LayoutParams params = getLayoutParams();
|
||||
if (mActivity.getDeviceProfile().isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get()) {
|
||||
final int thumbnailPadding = (int) getResources().getDimension(
|
||||
R.dimen.task_thumbnail_top_margin);
|
||||
final int thumbnailPadding =
|
||||
mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
|
||||
|
||||
Rect lastComputedTaskSize = getRecentsView().getLastComputedTaskSize();
|
||||
int taskWidth = lastComputedTaskSize.width();
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorControlNormal">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20.41,4.94l-1.35,-1.35c-0.78,-0.78 -2.05,-0.78 -2.83,0L3,16.82L3,21h4.18L20.41,7.77c0.79,-0.78 0.79,-2.05 0,-2.83zM6.41,19.06L5,19v-1.36l9.82,-9.82 1.41,1.41 -9.82,9.83z"/>
|
||||
</vector>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright (C) 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.
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item
|
||||
android:width="@dimen/widget_reconfigure_button_size"
|
||||
android:height="@dimen/widget_reconfigure_button_size">
|
||||
<shape
|
||||
android:shape="rectangle">
|
||||
<solid android:color="?android:attr/colorAccent" />
|
||||
<corners android:radius="@dimen/widget_reconfigure_button_corner_radius" />
|
||||
</shape>
|
||||
</item>
|
||||
<item
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/widget_reconfigure_button_padding"
|
||||
android:drawable="@drawable/gm_edit_24"
|
||||
android:color="?android:attr/colorPrimary" />
|
||||
</layer-list>
|
||||
@@ -26,6 +26,7 @@
|
||||
android:clipChildren="true"
|
||||
android:clipToPadding="false"
|
||||
android:descendantFocusability="afterDescendants"
|
||||
android:paddingTop="@dimen/all_apps_header_top_padding"
|
||||
launcher:pageIndicator="@+id/tabs" >
|
||||
|
||||
<include layout="@layout/all_apps_rv_layout" />
|
||||
|
||||
@@ -73,5 +73,17 @@
|
||||
android:src="@drawable/ic_widget_resize_handle"
|
||||
android:tint="?android:attr/colorAccent" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/widget_reconfigure_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="@dimen/widget_reconfigure_button_padding"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_marginBottom="@dimen/widget_reconfigure_button_margin"
|
||||
android:layout_marginEnd="@dimen/widget_reconfigure_button_margin"
|
||||
android:src="@drawable/widget_reconfigure_button_frame"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
||||
</com.android.launcher3.AppWidgetResizeFrame>
|
||||
@@ -129,11 +129,10 @@
|
||||
<!-- numHotseatIcons defaults to numColumns, if not specified -->
|
||||
<attr name="numHotseatIcons" format="integer" />
|
||||
<attr name="dbFile" format="string" />
|
||||
<!-- numAllAppsColumns defaults to numColumns, if not specified -->
|
||||
<attr name="numAllAppsColumns" format="integer" />
|
||||
<attr name="defaultLayoutId" format="reference" />
|
||||
<attr name="demoModeLayoutId" format="reference" />
|
||||
<attr name="isScalable" format="boolean" />
|
||||
<attr name="devicePaddingId" format="reference" />
|
||||
|
||||
</declare-styleable>
|
||||
|
||||
@@ -170,6 +169,9 @@
|
||||
<attr name="allAppsIconSize" format="float" />
|
||||
<!-- allAppsIconTextSize defaults to iconTextSize, if not specified -->
|
||||
<attr name="allAppsIconTextSize" format="float" />
|
||||
|
||||
<!-- numAllAppsColumns defaults to GridDisplayOption.numColumns, if not specified -->
|
||||
<attr name="numAllAppsColumns" format="integer" />
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="CellLayout">
|
||||
|
||||
@@ -56,6 +56,12 @@
|
||||
<dimen name="resize_frame_background_padding">24dp</dimen>
|
||||
<dimen name="resize_frame_margin">22dp</dimen>
|
||||
|
||||
<!-- App widget reconfigure button -->
|
||||
<dimen name="widget_reconfigure_button_corner_radius">14dp</dimen>
|
||||
<dimen name="widget_reconfigure_button_padding">6dp</dimen>
|
||||
<dimen name="widget_reconfigure_button_margin">32dp</dimen>
|
||||
<dimen name="widget_reconfigure_button_size">36dp</dimen>
|
||||
|
||||
<!-- Fast scroll -->
|
||||
<dimen name="fastscroll_track_min_width">6dp</dimen>
|
||||
<dimen name="fastscroll_track_max_width">8dp</dimen>
|
||||
@@ -286,4 +292,9 @@
|
||||
<!-- Size of the maximum radius for the enforced rounded rectangles. -->
|
||||
<dimen name="enforced_rounded_corner_max_radius">16dp</dimen>
|
||||
|
||||
<!-- Overview placeholder to compile in Launcer3 without Quickstep -->
|
||||
<dimen name="task_thumbnail_icon_size">0dp</dimen>
|
||||
<dimen name="task_thumbnail_icon_size_grid">0dp</dimen>
|
||||
<dimen name="overview_task_margin">0dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
||||
+11
-2
@@ -380,9 +380,18 @@
|
||||
<!--- heading shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_title">Work profile is paused</string>
|
||||
<!--- body shown when user opens work apps tab while work apps are paused -->
|
||||
<string name="work_apps_paused_body">Work apps can\'t send you notifications, use your battery, or access your location</string>
|
||||
<string name="work_apps_paused_body">Work apps can’t send you notifications, use your battery, or access your location</string>
|
||||
<!-- content description for paused work apps list -->
|
||||
<string name="work_apps_paused_content_description">Work profile is paused. Work apps can\’t send you notifications, use your battery, or access your location</string>
|
||||
<string name="work_apps_paused_content_description">Work profile is paused. Work apps can’t send you notifications, use your battery, or access your location</string>
|
||||
<!-- string shown in educational banner about work profile -->
|
||||
<string name="work_apps_paused_edu_banner">Work apps are badged and visible to your IT admin</string>
|
||||
<!-- button string shown to dismiss work tab education -->
|
||||
<string name="work_apps_paused_edu_accept">Got it</string>
|
||||
|
||||
<!-- button string shown pause work profile -->
|
||||
<string name="work_apps_pause_btn_text">Pause work apps</string>
|
||||
<!-- button string shown enable work profile -->
|
||||
<string name="work_apps_enable_btn_text">Turn on</string>
|
||||
|
||||
<!-- A hint shown in launcher settings develop options filter box -->
|
||||
<string name="developer_options_filter_hint">Filter</string>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<workspaceBottomPadding
|
||||
launcher:a="0.50"
|
||||
launcher:b="0"
|
||||
launcher:c="-16dp"/>
|
||||
launcher:c="16dp"/>
|
||||
<hotseatBottomPadding
|
||||
launcher:a="0.50"
|
||||
launcher:b="0"
|
||||
+1
-1
@@ -82,7 +82,7 @@ public final class WidgetsListAdapterTest {
|
||||
mTestProfile.numColumns = 5;
|
||||
mUserHandle = Process.myUserHandle();
|
||||
mAdapter = new WidgetsListAdapter(mContext, mMockLayoutInflater, mMockWidgetCache,
|
||||
mIconCache, null, null);
|
||||
mIconCache, null, null, null);
|
||||
mAdapter.registerAdapterDataObserver(mListener);
|
||||
|
||||
doAnswer(invocation -> ((ComponentWithLabel) invocation.getArgument(0))
|
||||
|
||||
+2
-1
@@ -105,7 +105,8 @@ public final class WidgetsListHeaderViewHolderBinderTest {
|
||||
mWidgetPreviewLoader,
|
||||
mIconCache,
|
||||
/* iconClickListener= */ view -> {},
|
||||
/* iconLongClickListener= */ view -> false);
|
||||
/* iconLongClickListener= */ view -> false,
|
||||
/* searchBarUIHelper= */ null);
|
||||
mViewHolderBinder = new WidgetsListHeaderViewHolderBinder(
|
||||
LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
|
||||
}
|
||||
|
||||
+2
-1
@@ -105,7 +105,8 @@ public final class WidgetsListSearchHeaderViewHolderBinderTest {
|
||||
mWidgetPreviewLoader,
|
||||
mIconCache,
|
||||
/* iconClickListener= */ view -> {},
|
||||
/* iconLongClickListener= */ view -> false);
|
||||
/* iconLongClickListener= */ view -> false,
|
||||
/* searchBarUIHelper= */ null);
|
||||
mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
|
||||
LayoutInflater.from(mTestActivity), mOnHeaderClickListener, widgetsListAdapter);
|
||||
}
|
||||
|
||||
+2
-1
@@ -111,7 +111,8 @@ public final class WidgetsListTableViewHolderBinderTest {
|
||||
mWidgetPreviewLoader,
|
||||
mIconCache,
|
||||
/* iconClickListener= */ view -> {},
|
||||
/* iconLongClickListener= */ view -> false);
|
||||
/* iconLongClickListener= */ view -> false,
|
||||
/* searchBarUIHelper= */ null);
|
||||
mViewHolderBinder = new WidgetsListTableViewHolderBinder(
|
||||
mContext,
|
||||
LayoutInflater.from(mTestActivity),
|
||||
|
||||
@@ -98,13 +98,6 @@ public abstract class AbstractFloatingView extends LinearLayout implements Touch
|
||||
public static final int TYPE_HIDE_BACK_BUTTON = TYPE_ON_BOARD_POPUP | TYPE_DISCOVERY_BOUNCE
|
||||
| TYPE_SNACKBAR | TYPE_WIDGET_RESIZE_FRAME | TYPE_LISTENER;
|
||||
|
||||
// When these types of floating views are open, hide the taskbar hotseat and show the real one.
|
||||
public static final int TYPE_REPLACE_TASKBAR_WITH_HOTSEAT = TYPE_FOLDER | TYPE_ACTION_POPUP;
|
||||
|
||||
// Hide the taskbar when these types of floating views are open.
|
||||
public static final int TYPE_HIDE_TASKBAR = TYPE_WIDGETS_BOTTOM_SHEET | TYPE_WIDGETS_FULL_SHEET
|
||||
| TYPE_ON_BOARD_POPUP;
|
||||
|
||||
public static final int TYPE_ACCESSIBLE = TYPE_ALL & ~TYPE_DISCOVERY_BOUNCE & ~TYPE_LISTENER
|
||||
& ~TYPE_ALL_APPS_EDU;
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.util.SizeF;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -74,6 +75,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
private LauncherAppWidgetHostView mWidgetView;
|
||||
private CellLayout mCellLayout;
|
||||
private DragLayer mDragLayer;
|
||||
private ImageButton mReconfigureButton;
|
||||
|
||||
private Rect mWidgetPadding;
|
||||
|
||||
@@ -211,6 +213,17 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
mDragHandles[INDEX_RIGHT].setVisibility(GONE);
|
||||
}
|
||||
|
||||
mReconfigureButton = (ImageButton) findViewById(R.id.widget_reconfigure_button);
|
||||
if (info.isReconfigurable()) {
|
||||
mReconfigureButton.setVisibility(VISIBLE);
|
||||
mReconfigureButton.setOnClickListener(view -> mLauncher
|
||||
.getAppWidgetHost()
|
||||
.startConfigActivity(
|
||||
mLauncher,
|
||||
mWidgetView.getAppWidgetId(),
|
||||
Launcher.REQUEST_RECONFIGURE_APPWIDGET));
|
||||
}
|
||||
|
||||
// When we create the resize frame, we first mark all cells as unoccupied. The appropriate
|
||||
// cells (same if not resized, or different) will be marked as occupied when the resize
|
||||
// frame is dismissed.
|
||||
@@ -582,6 +595,13 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isTouchOnReconfigureButton(MotionEvent ev) {
|
||||
int xFrame = (int) ev.getX() - getLeft();
|
||||
int yFrame = (int) ev.getY() - getTop();
|
||||
mReconfigureButton.getHitRect(sTmpRect);
|
||||
return sTmpRect.contains(xFrame, yFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
int action = ev.getAction();
|
||||
@@ -609,6 +629,11 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN && handleTouchDown(ev)) {
|
||||
return true;
|
||||
}
|
||||
// Keep the resize frame open but let a click on the reconfigure button fall through to the
|
||||
// button's OnClickListener.
|
||||
if (isTouchOnReconfigureButton(ev)) {
|
||||
return false;
|
||||
}
|
||||
close(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -52,8 +52,8 @@ public class DevicePaddings {
|
||||
|
||||
ArrayList<DevicePadding> mDevicePaddings = new ArrayList<>();
|
||||
|
||||
public DevicePaddings(Context context) {
|
||||
try (XmlResourceParser parser = context.getResources().getXml(R.xml.size_limits)) {
|
||||
public DevicePaddings(Context context, int devicePaddingId) {
|
||||
try (XmlResourceParser parser = context.getResources().getXml(devicePaddingId)) {
|
||||
final int depth = parser.getDepth();
|
||||
int type;
|
||||
while (((type = parser.next()) != XmlPullParser.END_TAG ||
|
||||
@@ -94,16 +94,27 @@ public class DevicePaddings {
|
||||
if (workspaceTopPadding == null
|
||||
|| workspaceBottomPadding == null
|
||||
|| hotseatBottomPadding == null) {
|
||||
throw new RuntimeException("DevicePadding missing padding.");
|
||||
if (Utilities.IS_DEBUG_DEVICE) {
|
||||
throw new RuntimeException("DevicePadding missing padding.");
|
||||
}
|
||||
}
|
||||
|
||||
mDevicePaddings.add(new DevicePadding(maxWidthPx, workspaceTopPadding,
|
||||
workspaceBottomPadding, hotseatBottomPadding));
|
||||
DevicePadding dp = new DevicePadding(maxWidthPx, workspaceTopPadding,
|
||||
workspaceBottomPadding, hotseatBottomPadding);
|
||||
if (dp.isValid()) {
|
||||
mDevicePaddings.add(dp);
|
||||
} else {
|
||||
Log.e(TAG, "Invalid device padding found.");
|
||||
if (Utilities.IS_DEBUG_DEVICE) {
|
||||
throw new RuntimeException("DevicePadding is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException | XmlPullParserException e) {
|
||||
Log.e(TAG, "Failure parsing device padding layout.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
@@ -128,6 +139,9 @@ public class DevicePaddings {
|
||||
*/
|
||||
public static final class DevicePadding {
|
||||
|
||||
// One for each padding since they can each be off by 1 due to rounding errors.
|
||||
private static final int ROUNDING_THRESHOLD_PX = 3;
|
||||
|
||||
private final int maxEmptySpacePx;
|
||||
private final PaddingFormula workspaceTopPadding;
|
||||
private final PaddingFormula workspaceBottomPadding;
|
||||
@@ -143,6 +157,10 @@ public class DevicePaddings {
|
||||
this.hotseatBottomPadding = hotseatBottomPadding;
|
||||
}
|
||||
|
||||
public int getMaxEmptySpacePx() {
|
||||
return maxEmptySpacePx;
|
||||
}
|
||||
|
||||
public int getWorkspaceTopPadding(int extraSpacePx) {
|
||||
return workspaceTopPadding.calculate(extraSpacePx);
|
||||
}
|
||||
@@ -154,6 +172,22 @@ public class DevicePaddings {
|
||||
public int getHotseatBottomPadding(int extraSpacePx) {
|
||||
return hotseatBottomPadding.calculate(extraSpacePx);
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
int workspaceTopPadding = getWorkspaceTopPadding(maxEmptySpacePx);
|
||||
int workspaceBottomPadding = getWorkspaceBottomPadding(maxEmptySpacePx);
|
||||
int hotseatBottomPadding = getHotseatBottomPadding(maxEmptySpacePx);
|
||||
int sum = workspaceTopPadding + workspaceBottomPadding + hotseatBottomPadding;
|
||||
int diff = Math.abs(sum - maxEmptySpacePx);
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "isValid: workspaceTopPadding=" + workspaceTopPadding
|
||||
+ ", workspaceBottomPadding=" + workspaceBottomPadding
|
||||
+ ", hotseatBottomPadding=" + hotseatBottomPadding
|
||||
+ ", sum=" + sum
|
||||
+ ", diff=" + diff);
|
||||
}
|
||||
return diff <= ROUNDING_THRESHOLD_PX;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -104,6 +104,7 @@ public class DeviceProfile {
|
||||
private final int mWorkspacePageIndicatorOverlapWorkspace;
|
||||
|
||||
// Workspace icons
|
||||
public float iconScale;
|
||||
public int iconSizePx;
|
||||
public int iconTextSizePx;
|
||||
public int iconDrawablePaddingPx;
|
||||
@@ -151,6 +152,11 @@ public class DeviceProfile {
|
||||
public int allAppsIconDrawablePaddingPx;
|
||||
public float allAppsIconTextSizePx;
|
||||
|
||||
// Overview
|
||||
public int overviewTaskMarginPx;
|
||||
public int overviewTaskIconSizePx;
|
||||
public int overviewTaskThumbnailTopMarginPx;
|
||||
|
||||
// Widgets
|
||||
public final PointF appWidgetScale = new PointF(1.0f, 1.0f);
|
||||
|
||||
@@ -297,15 +303,29 @@ public class DeviceProfile {
|
||||
: (hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx
|
||||
+ (isScalableGrid ? 0 : hotseatExtraVerticalSize)));
|
||||
|
||||
overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
|
||||
overviewTaskIconSizePx =
|
||||
isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get() ? res.getDimensionPixelSize(
|
||||
R.dimen.task_thumbnail_icon_size_grid) : res.getDimensionPixelSize(
|
||||
R.dimen.task_thumbnail_icon_size);
|
||||
overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx * 2;
|
||||
|
||||
// Calculate all of the remaining variables.
|
||||
extraSpace = updateAvailableDimensions(res);
|
||||
// Now that we have all of the variables calculated, we can tune certain sizes.
|
||||
if (isScalableGrid) {
|
||||
DevicePadding padding = inv.devicePaddings.getDevicePadding(extraSpace);
|
||||
workspaceTopPadding = padding.getWorkspaceTopPadding(extraSpace);
|
||||
workspaceBottomPadding = padding.getWorkspaceBottomPadding(extraSpace);
|
||||
if (isScalableGrid && inv.devicePaddings != null) {
|
||||
// Paddings were created assuming no scaling, so we first unscale the extra space.
|
||||
int unscaledExtraSpace = (int) (extraSpace / iconScale);
|
||||
DevicePadding padding = inv.devicePaddings.getDevicePadding(unscaledExtraSpace);
|
||||
|
||||
int paddingWorkspaceTop = padding.getWorkspaceTopPadding(unscaledExtraSpace);
|
||||
int paddingWorkspaceBottom = padding.getWorkspaceBottomPadding(unscaledExtraSpace);
|
||||
int paddingHotseatBottom = padding.getHotseatBottomPadding(unscaledExtraSpace);
|
||||
|
||||
workspaceTopPadding = Math.round(paddingWorkspaceTop * iconScale);
|
||||
workspaceBottomPadding = Math.round(paddingWorkspaceBottom * iconScale);
|
||||
extraHotseatBottomPadding = Math.round(paddingHotseatBottom * iconScale);
|
||||
|
||||
extraHotseatBottomPadding = padding.getHotseatBottomPadding(extraSpace);
|
||||
hotseatBarSizePx += extraHotseatBottomPadding;
|
||||
hotseatBarBottomPaddingPx += extraHotseatBottomPadding;
|
||||
} else if (!isVerticalBarLayout() && isPhone && isTallDevice) {
|
||||
@@ -478,6 +498,8 @@ public class DeviceProfile {
|
||||
* hotseat sizes, workspaceSpringLoadedShrinkFactor, folderIconSizePx, and folderIconOffsetYPx.
|
||||
*/
|
||||
public void updateIconSize(float scale, Resources res) {
|
||||
iconScale = scale;
|
||||
|
||||
// Workspace
|
||||
final boolean isVerticalLayout = isVerticalBarLayout();
|
||||
float invIconSizeDp = isVerticalLayout ? inv.landscapeIconSize : inv.iconSize;
|
||||
@@ -878,7 +900,14 @@ public class DeviceProfile {
|
||||
writer.println(prefix + pxToDpStr("workspacePadding.right", workspacePadding.right));
|
||||
writer.println(prefix + pxToDpStr("workspacePadding.bottom", workspacePadding.bottom));
|
||||
|
||||
writer.println(prefix + pxToDpStr("scaleToFit", iconScale));
|
||||
writer.println(prefix + pxToDpStr("extraSpace", extraSpace));
|
||||
|
||||
if (inv.devicePaddings != null) {
|
||||
int unscaledExtraSpace = (int) (extraSpace / iconScale);
|
||||
writer.println(prefix + pxToDpStr("maxEmptySpace",
|
||||
inv.devicePaddings.getDevicePadding(unscaledExtraSpace).getMaxEmptySpacePx()));
|
||||
}
|
||||
writer.println(prefix + pxToDpStr("workspaceTopPadding", workspaceTopPadding));
|
||||
writer.println(prefix + pxToDpStr("workspaceBottomPadding", workspaceBottomPadding));
|
||||
writer.println(prefix + pxToDpStr("extraHotseatBottomPadding", extraHotseatBottomPadding));
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.graphics.ColorFilter;
|
||||
import android.graphics.ColorMatrix;
|
||||
import android.graphics.ColorMatrixColorFilter;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -61,6 +62,8 @@ public class FastBitmapDrawable extends Drawable {
|
||||
private boolean mIsPressed;
|
||||
private boolean mIsDisabled;
|
||||
private float mDisabledAlpha = 1f;
|
||||
private float mRoundedCornersRadius = 0f;
|
||||
private final Path mClipPath = new Path();
|
||||
|
||||
// Animator and properties for the fast bitmap drawable's scale
|
||||
private static final Property<FastBitmapDrawable, Float> SCALE
|
||||
@@ -102,6 +105,13 @@ public class FastBitmapDrawable extends Drawable {
|
||||
|
||||
@Override
|
||||
public final void draw(Canvas canvas) {
|
||||
if (mRoundedCornersRadius > 0) {
|
||||
float radius = mRoundedCornersRadius * mScale;
|
||||
mClipPath.reset();
|
||||
mClipPath.addRoundRect(0, 0, getIntrinsicWidth(), getIntrinsicHeight(),
|
||||
radius, radius, Path.Direction.CCW);
|
||||
canvas.clipPath(mClipPath);
|
||||
}
|
||||
if (mScale != 1f) {
|
||||
int count = canvas.save();
|
||||
Rect bounds = getBounds();
|
||||
@@ -164,6 +174,14 @@ public class FastBitmapDrawable extends Drawable {
|
||||
return mScale;
|
||||
}
|
||||
|
||||
public void setRoundedCornersRadius(float radius) {
|
||||
mRoundedCornersRadius = radius;
|
||||
}
|
||||
|
||||
public float getRoundedCornersRadius() {
|
||||
return mRoundedCornersRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIntrinsicWidth() {
|
||||
return mBitmap.getWidth();
|
||||
|
||||
@@ -132,6 +132,7 @@ public class InvariantDeviceProfile {
|
||||
* Do not query directly. see {@link DeviceProfile#isScalableGrid}.
|
||||
*/
|
||||
protected boolean isScalable;
|
||||
public int devicePaddingId;
|
||||
|
||||
public String dbFile;
|
||||
public int defaultLayoutId;
|
||||
@@ -140,7 +141,7 @@ public class InvariantDeviceProfile {
|
||||
public DeviceProfile landscapeProfile;
|
||||
public DeviceProfile portraitProfile;
|
||||
|
||||
public DevicePaddings devicePaddings;
|
||||
@Nullable public DevicePaddings devicePaddings;
|
||||
|
||||
public Point defaultWallpaperSize;
|
||||
public Rect defaultWidgetPadding;
|
||||
@@ -165,6 +166,7 @@ public class InvariantDeviceProfile {
|
||||
numHotseatIcons = p.numHotseatIcons;
|
||||
numAllAppsColumns = p.numAllAppsColumns;
|
||||
isScalable = p.isScalable;
|
||||
devicePaddingId = p.devicePaddingId;
|
||||
minCellHeight = p.minCellHeight;
|
||||
minCellWidth = p.minCellWidth;
|
||||
borderSpacing = p.borderSpacing;
|
||||
@@ -225,13 +227,17 @@ public class InvariantDeviceProfile {
|
||||
.add(myDisplayOption);
|
||||
result.iconSize = defaultDisplayOption.iconSize;
|
||||
result.landscapeIconSize = defaultDisplayOption.landscapeIconSize;
|
||||
result.allAppsIconSize = Math.min(
|
||||
defaultDisplayOption.allAppsIconSize, myDisplayOption.allAppsIconSize);
|
||||
if (defaultDisplayOption.allAppsIconSize < myDisplayOption.allAppsIconSize) {
|
||||
result.allAppsIconSize = defaultDisplayOption.allAppsIconSize;
|
||||
result.numAllAppsColumns = defaultDisplayOption.numAllAppsColumns;
|
||||
} else {
|
||||
result.allAppsIconSize = myDisplayOption.allAppsIconSize;
|
||||
result.numAllAppsColumns = myDisplayOption.numAllAppsColumns;
|
||||
}
|
||||
result.minCellHeight = defaultDisplayOption.minCellHeight;
|
||||
result.minCellWidth = defaultDisplayOption.minCellWidth;
|
||||
result.borderSpacing = defaultDisplayOption.borderSpacing;
|
||||
|
||||
devicePaddings = new DevicePaddings(context);
|
||||
initGrid(context, myInfo, result);
|
||||
}
|
||||
|
||||
@@ -262,7 +268,6 @@ public class InvariantDeviceProfile {
|
||||
ArrayList<DisplayOption> allOptions = getPredefinedDeviceProfiles(context, gridName);
|
||||
|
||||
DisplayOption displayOption = invDistWeightedInterpolate(displayInfo, allOptions);
|
||||
devicePaddings = new DevicePaddings(context);
|
||||
initGrid(context, displayInfo, displayOption);
|
||||
return displayOption.grid.name;
|
||||
}
|
||||
@@ -278,8 +283,8 @@ public class InvariantDeviceProfile {
|
||||
demoModeLayoutId = closestProfile.demoModeLayoutId;
|
||||
numFolderRows = closestProfile.numFolderRows;
|
||||
numFolderColumns = closestProfile.numFolderColumns;
|
||||
numAllAppsColumns = closestProfile.numAllAppsColumns;
|
||||
isScalable = closestProfile.isScalable;
|
||||
devicePaddingId = closestProfile.devicePaddingId;
|
||||
|
||||
mExtraAttrs = closestProfile.extraAttrs;
|
||||
|
||||
@@ -293,6 +298,7 @@ public class InvariantDeviceProfile {
|
||||
minCellHeight = displayOption.minCellHeight;
|
||||
minCellWidth = displayOption.minCellWidth;
|
||||
borderSpacing = displayOption.borderSpacing;
|
||||
numAllAppsColumns = Math.round(displayOption.numAllAppsColumns);
|
||||
|
||||
if (Utilities.isGridOptionsEnabled(context)) {
|
||||
allAppsIconSize = displayOption.allAppsIconSize;
|
||||
@@ -302,6 +308,10 @@ public class InvariantDeviceProfile {
|
||||
allAppsIconTextSize = iconTextSize;
|
||||
}
|
||||
|
||||
if (devicePaddingId != 0) {
|
||||
devicePaddings = new DevicePaddings(context, devicePaddingId);
|
||||
}
|
||||
|
||||
// If the partner customization apk contains any grid overrides, apply them
|
||||
// Supported overrides: numRows, numColumns, iconSize
|
||||
applyPartnerDeviceProfileOverrides(context, displayInfo.metrics);
|
||||
@@ -609,12 +619,12 @@ public class InvariantDeviceProfile {
|
||||
private final int numHotseatIcons;
|
||||
|
||||
private final String dbFile;
|
||||
private final int numAllAppsColumns;
|
||||
|
||||
private final int defaultLayoutId;
|
||||
private final int demoModeLayoutId;
|
||||
|
||||
private final boolean isScalable;
|
||||
private final int devicePaddingId;
|
||||
|
||||
private final SparseArray<TypedValue> extraAttrs;
|
||||
|
||||
@@ -636,11 +646,11 @@ public class InvariantDeviceProfile {
|
||||
R.styleable.GridDisplayOption_numFolderRows, numRows);
|
||||
numFolderColumns = a.getInt(
|
||||
R.styleable.GridDisplayOption_numFolderColumns, numColumns);
|
||||
numAllAppsColumns = a.getInt(
|
||||
R.styleable.GridDisplayOption_numAllAppsColumns, numColumns);
|
||||
|
||||
isScalable = a.getBoolean(
|
||||
R.styleable.GridDisplayOption_isScalable, false);
|
||||
devicePaddingId = a.getResourceId(
|
||||
R.styleable.GridDisplayOption_devicePaddingId, 0);
|
||||
|
||||
a.recycle();
|
||||
|
||||
@@ -656,6 +666,7 @@ public class InvariantDeviceProfile {
|
||||
private final float minHeightDps;
|
||||
private final boolean canBeDefault;
|
||||
|
||||
private float numAllAppsColumns;
|
||||
private float minCellHeight;
|
||||
private float minCellWidth;
|
||||
private float borderSpacing;
|
||||
@@ -676,6 +687,8 @@ public class InvariantDeviceProfile {
|
||||
minHeightDps = a.getFloat(R.styleable.ProfileDisplayOption_minHeightDps, 0);
|
||||
canBeDefault = a.getBoolean(
|
||||
R.styleable.ProfileDisplayOption_canBeDefault, false);
|
||||
numAllAppsColumns = a.getInt(R.styleable.ProfileDisplayOption_numAllAppsColumns,
|
||||
grid.numColumns);
|
||||
|
||||
minCellHeight = a.getFloat(R.styleable.ProfileDisplayOption_minCellHeightDps, 0);
|
||||
minCellWidth = a.getFloat(R.styleable.ProfileDisplayOption_minCellWidthDps, 0);
|
||||
@@ -702,12 +715,14 @@ public class InvariantDeviceProfile {
|
||||
minWidthDps = 0;
|
||||
minHeightDps = 0;
|
||||
canBeDefault = false;
|
||||
numAllAppsColumns = 0;
|
||||
minCellHeight = 0;
|
||||
minCellWidth = 0;
|
||||
borderSpacing = 0;
|
||||
}
|
||||
|
||||
private DisplayOption multiply(float w) {
|
||||
numAllAppsColumns *= w;
|
||||
iconSize *= w;
|
||||
landscapeIconSize *= w;
|
||||
allAppsIconSize *= w;
|
||||
@@ -720,6 +735,7 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
|
||||
private DisplayOption add(DisplayOption p) {
|
||||
numAllAppsColumns += p.numAllAppsColumns;
|
||||
iconSize += p.iconSize;
|
||||
landscapeIconSize += p.landscapeIconSize;
|
||||
allAppsIconSize += p.allAppsIconSize;
|
||||
|
||||
@@ -2763,6 +2763,13 @@ public class Launcher extends StatefulActivity<LauncherState> implements Launche
|
||||
return new float[] {NO_SCALE, NO_OFFSET};
|
||||
}
|
||||
|
||||
/**
|
||||
* @see LauncherState#getTaskbarScale(Launcher)
|
||||
*/
|
||||
public float getNormalTaskbarScale() {
|
||||
return 1f;
|
||||
}
|
||||
|
||||
public static Launcher getLauncher(Context context) {
|
||||
return fromContext(context);
|
||||
}
|
||||
|
||||
@@ -176,6 +176,10 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
||||
return launcher.getNormalOverviewScaleAndOffset();
|
||||
}
|
||||
|
||||
public float getTaskbarScale(Launcher launcher) {
|
||||
return launcher.getNormalTaskbarScale();
|
||||
}
|
||||
|
||||
public float getOverviewFullscreenProgress() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1512,17 +1512,16 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
return getDestinationPage(mOrientationHandler.getPrimaryScroll(this));
|
||||
}
|
||||
|
||||
protected int getDestinationPage(int scaledScroll) {
|
||||
return getPageNearestToCenterOfScreen(scaledScroll);
|
||||
protected int getDestinationPage(int primaryScroll) {
|
||||
return getPageNearestToCenterOfScreen(primaryScroll);
|
||||
}
|
||||
|
||||
public int getPageNearestToCenterOfScreen() {
|
||||
return getPageNearestToCenterOfScreen(mOrientationHandler.getPrimaryScroll(this));
|
||||
}
|
||||
|
||||
private int getPageNearestToCenterOfScreen(int scaledScroll) {
|
||||
int pageOrientationSize = mOrientationHandler.getMeasuredSize(this);
|
||||
int screenCenter = scaledScroll + (pageOrientationSize / 2);
|
||||
private int getPageNearestToCenterOfScreen(int primaryScroll) {
|
||||
int screenCenter = getScreenCenter(primaryScroll);
|
||||
int minDistanceFromScreenCenter = Integer.MAX_VALUE;
|
||||
int minDistanceFromScreenCenterIndex = -1;
|
||||
final int childCount = getChildCount();
|
||||
@@ -1538,18 +1537,26 @@ public abstract class PagedView<T extends View & PageIndicator> extends ViewGrou
|
||||
}
|
||||
|
||||
private int getDisplacementFromScreenCenter(int childIndex, int screenCenter) {
|
||||
int childSize = getChildVisibleSize(childIndex);
|
||||
int childSize = Math.round(getChildVisibleSize(childIndex));
|
||||
int halfChildSize = (childSize / 2);
|
||||
int childCenter = getChildOffset(childIndex) + halfChildSize;
|
||||
return childCenter - screenCenter;
|
||||
}
|
||||
|
||||
protected int getDisplacementFromScreenCenter(int childIndex) {
|
||||
int pageOrientationSize = mOrientationHandler.getMeasuredSize(this);
|
||||
int screenCenter = mOrientationHandler.getPrimaryScroll(this) + (pageOrientationSize / 2);
|
||||
int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
|
||||
int screenCenter = getScreenCenter(primaryScroll);
|
||||
return getDisplacementFromScreenCenter(childIndex, screenCenter);
|
||||
}
|
||||
|
||||
private int getScreenCenter(int primaryScroll) {
|
||||
float primaryScale = mOrientationHandler.getPrimaryScale(this);
|
||||
float primaryPivot = mOrientationHandler.getPrimaryValue(getPivotX(), getPivotY());
|
||||
int pageOrientationSize = mOrientationHandler.getMeasuredSize(this);
|
||||
return Math.round(primaryScroll + (pageOrientationSize / 2f - primaryPivot) / primaryScale
|
||||
+ primaryPivot);
|
||||
}
|
||||
|
||||
protected void snapToDestination() {
|
||||
snapToPage(getDestinationPage(), getPageSnapDuration());
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import static com.android.launcher3.anim.Interpolators.ZOOM_OUT;
|
||||
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
|
||||
import static com.android.launcher3.graphics.Scrim.SCRIM_PROGRESS;
|
||||
import static com.android.launcher3.graphics.SysUiScrim.SYSUI_PROGRESS;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_FADE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE;
|
||||
@@ -133,8 +132,7 @@ public class WorkspaceStateTransitionAnimation {
|
||||
}
|
||||
|
||||
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
|
||||
propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha,
|
||||
config.getInterpolator(ANIM_HOTSEAT_FADE, fadeInterpolator));
|
||||
propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha, fadeInterpolator);
|
||||
float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
|
||||
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
|
||||
workspacePageIndicatorAlpha, fadeInterpolator);
|
||||
|
||||
@@ -583,10 +583,6 @@ public class AllAppsContainerView extends SpringRelativeLayout implements DragSo
|
||||
int padding = mHeader.getMaxTranslation();
|
||||
for (int i = 0; i < mAH.length; i++) {
|
||||
mAH[i].padding.top = padding;
|
||||
if (FeatureFlags.ENABLE_DEVICE_SEARCH.get() && mUsingTabs) {
|
||||
//add extra space between tabs and recycler view
|
||||
mAH[i].padding.top += mLauncher.getDeviceProfile().edgeMarginPx;
|
||||
}
|
||||
mAH[i].applyPadding();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,8 +23,6 @@ import android.util.AttributeSet;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.PagedView;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.workprofile.PersonalWorkPagedView;
|
||||
|
||||
/**
|
||||
@@ -43,10 +41,6 @@ public class AllAppsPagedView extends PersonalWorkPagedView {
|
||||
|
||||
public AllAppsPagedView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
int topPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0
|
||||
: context.getResources().getDimensionPixelOffset(
|
||||
R.dimen.all_apps_header_top_padding);
|
||||
setPadding(0, topPadding, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -106,8 +106,8 @@ public class FloatingHeaderView extends LinearLayout implements
|
||||
|
||||
public FloatingHeaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mHeaderTopPadding = FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 :
|
||||
context.getResources().getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
|
||||
mHeaderTopPadding = context.getResources()
|
||||
.getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -125,7 +125,6 @@ public class FloatingHeaderView extends LinearLayout implements
|
||||
}
|
||||
}
|
||||
mFixedRows = rows.toArray(new FloatingHeaderRow[rows.size()]);
|
||||
setPadding(0, mHeaderTopPadding, 0, 0);
|
||||
mAllRows = mFixedRows;
|
||||
}
|
||||
|
||||
@@ -243,9 +242,7 @@ public class FloatingHeaderView extends LinearLayout implements
|
||||
|
||||
public int getMaxTranslation() {
|
||||
if (mMaxTranslation == 0 && mTabsHidden) {
|
||||
int paddingOffset = getResources().getDimensionPixelSize(
|
||||
R.dimen.all_apps_search_bar_bottom_padding);
|
||||
return FeatureFlags.ENABLE_DEVICE_SEARCH.get() ? 0 : paddingOffset;
|
||||
return getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_bottom_padding);
|
||||
} else if (mMaxTranslation > 0 && mTabsHidden) {
|
||||
return mMaxTranslation + getPaddingTop();
|
||||
} else {
|
||||
|
||||
@@ -77,6 +77,9 @@ public class Interpolators {
|
||||
|
||||
public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR =
|
||||
new PathInterpolator(0.3f, 0f, 0.1f, 1f);
|
||||
public static final Interpolator TOUCH_RESPONSE_INTERPOLATOR_ACCEL_DEACCEL =
|
||||
v -> ACCEL_DEACCEL.getInterpolation(TOUCH_RESPONSE_INTERPOLATOR.getInterpolation(v));
|
||||
|
||||
|
||||
/**
|
||||
* Inversion of ZOOM_OUT, compounded with an ease-out.
|
||||
|
||||
@@ -38,7 +38,6 @@ public class StateAnimationConfig {
|
||||
PLAY_ATOMIC_OVERVIEW_PEEK,
|
||||
SKIP_OVERVIEW,
|
||||
SKIP_DEPTH_CONTROLLER,
|
||||
SKIP_TASKBAR,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AnimationFlags {}
|
||||
@@ -47,7 +46,6 @@ public class StateAnimationConfig {
|
||||
public static final int PLAY_ATOMIC_OVERVIEW_PEEK = 1 << 2;
|
||||
public static final int SKIP_OVERVIEW = 1 << 3;
|
||||
public static final int SKIP_DEPTH_CONTROLLER = 1 << 4;
|
||||
public static final int SKIP_TASKBAR = 1 << 5;
|
||||
|
||||
public long duration;
|
||||
public boolean userControlled;
|
||||
@@ -74,8 +72,6 @@ public class StateAnimationConfig {
|
||||
ANIM_OVERVIEW_MODAL,
|
||||
ANIM_DEPTH,
|
||||
ANIM_OVERVIEW_ACTIONS_FADE,
|
||||
ANIM_TASKBAR_FADE,
|
||||
ANIM_HOTSEAT_FADE,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface AnimType {}
|
||||
@@ -95,10 +91,8 @@ public class StateAnimationConfig {
|
||||
public static final int ANIM_OVERVIEW_MODAL = 13;
|
||||
public static final int ANIM_DEPTH = 14;
|
||||
public static final int ANIM_OVERVIEW_ACTIONS_FADE = 15;
|
||||
public static final int ANIM_TASKBAR_FADE = 16;
|
||||
public static final int ANIM_HOTSEAT_FADE = 17; // if not set, falls back to ANIM_WORKSPACE_FADE
|
||||
|
||||
private static final int ANIM_TYPES_COUNT = 18;
|
||||
private static final int ANIM_TYPES_COUNT = 16;
|
||||
|
||||
protected final Interpolator[] mInterpolators = new Interpolator[ANIM_TYPES_COUNT];
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClearAllScrollOffset(View view, boolean isRtl) {
|
||||
public int getClearAllSidePadding(View view, boolean isRtl) {
|
||||
return (isRtl ? view.getPaddingBottom() : - view.getPaddingTop()) / 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public interface PagedOrientationHandler {
|
||||
float getPrimaryVelocity(VelocityTracker velocityTracker, int pointerId);
|
||||
int getMeasuredSize(View view);
|
||||
float getPrimarySize(RectF rect);
|
||||
int getClearAllScrollOffset(View view, boolean isRtl);
|
||||
int getClearAllSidePadding(View view, boolean isRtl);
|
||||
int getSecondaryDimension(View view);
|
||||
FloatProperty<View> getPrimaryViewTranslate();
|
||||
FloatProperty<View> getSecondaryViewTranslate();
|
||||
|
||||
@@ -132,7 +132,7 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getClearAllScrollOffset(View view, boolean isRtl) {
|
||||
public int getClearAllSidePadding(View view, boolean isRtl) {
|
||||
return (isRtl ? view.getPaddingRight() : - view.getPaddingLeft()) / 2;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,43 +42,16 @@ public class MultiValueAlpha {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Determines how each alpha should factor into the final alpha.
|
||||
*/
|
||||
public enum Mode {
|
||||
BLEND() {
|
||||
@Override
|
||||
public float calculateNewAlpha(float currentAlpha, float otherAlpha) {
|
||||
return currentAlpha * otherAlpha;
|
||||
}
|
||||
},
|
||||
|
||||
MAX() {
|
||||
@Override
|
||||
public float calculateNewAlpha(float currentAlpha, float otherAlpha) {
|
||||
return Math.max(currentAlpha, otherAlpha);
|
||||
}
|
||||
};
|
||||
|
||||
protected abstract float calculateNewAlpha(float currentAlpha, float otherAlpha);
|
||||
}
|
||||
|
||||
private final View mView;
|
||||
private final AlphaProperty[] mMyProperties;
|
||||
private final Mode mMode;
|
||||
|
||||
private int mValidMask;
|
||||
// Whether we should change from INVISIBLE to VISIBLE and vice versa at low alpha values.
|
||||
private boolean mUpdateVisibility;
|
||||
|
||||
public MultiValueAlpha(View view, int size) {
|
||||
this(view, size, Mode.BLEND);
|
||||
}
|
||||
|
||||
public MultiValueAlpha(View view, int size, Mode mode) {
|
||||
mView = view;
|
||||
mMyProperties = new AlphaProperty[size];
|
||||
mMode = mode;
|
||||
|
||||
mValidMask = 0;
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -124,7 +97,7 @@ public class MultiValueAlpha {
|
||||
mOthers = 1;
|
||||
for (AlphaProperty prop : mMyProperties) {
|
||||
if (prop != this) {
|
||||
mOthers = mMode.calculateNewAlpha(mOthers, prop.mValue);
|
||||
mOthers *= prop.mValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +107,7 @@ public class MultiValueAlpha {
|
||||
mValidMask = mMyMask;
|
||||
mValue = value;
|
||||
|
||||
mView.setAlpha(mMode.calculateNewAlpha(mOthers, mValue));
|
||||
mView.setAlpha(mOthers * mValue);
|
||||
if (mUpdateVisibility) {
|
||||
AlphaUpdateListener.updateVisibility(mView);
|
||||
}
|
||||
|
||||
@@ -497,12 +497,13 @@ public class LauncherAppWidgetHostView extends NavigableAppWidgetHostView
|
||||
|
||||
@UiThread
|
||||
private void enforceRoundedCorners() {
|
||||
if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled(this)) {
|
||||
if (mEnforcedCornerRadius <= 0 || !RoundedCornerEnforcement.isRoundedCornerEnabled()) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
View background = RoundedCornerEnforcement.findBackground(this);
|
||||
if (RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
|
||||
if (background == null
|
||||
|| RoundedCornerEnforcement.hasAppWidgetOptedOut(this, background)) {
|
||||
resetRoundedCorners();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -139,6 +139,10 @@ public class LauncherAppWidgetProviderInfo extends AppWidgetProviderInfo
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isReconfigurable() {
|
||||
return configure != null && (getWidgetFeatures() & WIDGET_FEATURE_RECONFIGURABLE) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ComponentName getComponent() {
|
||||
return provider;
|
||||
|
||||
@@ -54,10 +54,13 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
||||
|
||||
@Nullable private RemoteViews mRemoteViewsPreview;
|
||||
@Nullable private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
|
||||
private final float mEnforcedRoundedCornersForWidget;
|
||||
|
||||
public PendingItemDragHelper(View view) {
|
||||
super(view);
|
||||
mAddInfo = (PendingAddItemInfo) view.getTag();
|
||||
mEnforcedRoundedCornersForWidget = RoundedCornerEnforcement.computeEnforcedRadius(
|
||||
view.getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -115,10 +118,14 @@ public class PendingItemDragHelper extends DragPreviewProvider {
|
||||
.addDragListener(new AppWidgetHostViewDragListener(launcher));
|
||||
}
|
||||
if (preview == null) {
|
||||
preview = new FastBitmapDrawable(
|
||||
FastBitmapDrawable p = new FastBitmapDrawable(
|
||||
app.getWidgetCache().generateWidgetPreview(launcher,
|
||||
createWidgetInfo.info, maxWidth, null,
|
||||
previewSizeBeforeScale).first);
|
||||
if (RoundedCornerEnforcement.isRoundedCornerEnabled()) {
|
||||
p.setRoundedCornersRadius(mEnforcedRoundedCornersForWidget);
|
||||
}
|
||||
preview = p;
|
||||
}
|
||||
|
||||
if (previewSizeBeforeScale[0] < previewBitmapWidth) {
|
||||
|
||||
@@ -72,12 +72,8 @@ public class RoundedCornerEnforcement {
|
||||
}
|
||||
|
||||
/** Check if the app widget is in the deny list. */
|
||||
public static boolean isRoundedCornerEnabled(@NonNull View view) {
|
||||
if (!Utilities.ATLEAST_S || !FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get()) {
|
||||
return false;
|
||||
}
|
||||
// Here we need to test if the view's component is in the (to be created) deny list.
|
||||
return true;
|
||||
public static boolean isRoundedCornerEnabled() {
|
||||
return Utilities.ATLEAST_S && FeatureFlags.ENABLE_ENFORCED_ROUNDED_CORNERS.get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,6 +94,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
protected final BaseActivity mActivity;
|
||||
protected final DeviceProfile mDeviceProfile;
|
||||
private final CheckLongPressHelper mLongPressHelper;
|
||||
private final float mEnforcedCornerRadius;
|
||||
|
||||
private RemoteViews mPreview;
|
||||
private LauncherAppWidgetHostView mAppWidgetHostViewPreview;
|
||||
@@ -118,6 +119,7 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
setWillNotDraw(false);
|
||||
setClipToPadding(false);
|
||||
setAccessibilityDelegate(mActivity.getAccessibilityDelegate());
|
||||
mEnforcedCornerRadius = RoundedCornerEnforcement.computeEnforcedRadius(context);
|
||||
}
|
||||
|
||||
private void setContainerWidth() {
|
||||
@@ -245,7 +247,9 @@ public class WidgetCell extends LinearLayout implements OnLayoutChangeListener {
|
||||
}
|
||||
|
||||
public void applyPreview(Bitmap bitmap) {
|
||||
applyPreview(new FastBitmapDrawable(bitmap));
|
||||
FastBitmapDrawable drawable = new FastBitmapDrawable(bitmap);
|
||||
drawable.setRoundedCornersRadius(mEnforcedCornerRadius);
|
||||
applyPreview(drawable);
|
||||
}
|
||||
|
||||
private void applyPreview(Drawable drawable) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import android.util.IntProperty;
|
||||
import android.util.Pair;
|
||||
import android.view.Gravity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.animation.Interpolator;
|
||||
@@ -152,6 +153,19 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
mNoIntercept = false;
|
||||
ScrollView scrollView = findViewById(R.id.widgets_table_scroll_view);
|
||||
if (getPopupContainer().isEventOverView(scrollView, ev)
|
||||
&& scrollView.getScrollY() > 0) {
|
||||
mNoIntercept = true;
|
||||
}
|
||||
}
|
||||
return super.onControllerInterceptTouchEvent(ev);
|
||||
}
|
||||
|
||||
protected WidgetCell addItemCell(ViewGroup parent) {
|
||||
WidgetCell widget = (WidgetCell) LayoutInflater.from(getContext())
|
||||
.inflate(R.layout.widget_cell, parent, false);
|
||||
|
||||
@@ -58,6 +58,7 @@ import com.android.launcher3.widget.LauncherAppWidgetHost.ProviderChangedListene
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.picker.search.SearchModeListener;
|
||||
import com.android.launcher3.widget.picker.search.WidgetsSearchBar;
|
||||
import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper;
|
||||
import com.android.launcher3.widget.util.WidgetsTableUtils;
|
||||
import com.android.launcher3.workprofile.PersonalWorkPagedView;
|
||||
import com.android.launcher3.workprofile.PersonalWorkSlidingTabStrip.OnActivePageChangedListener;
|
||||
@@ -71,7 +72,8 @@ import java.util.function.Predicate;
|
||||
*/
|
||||
public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
implements Insettable, ProviderChangedListener, OnActivePageChangedListener,
|
||||
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener {
|
||||
WidgetsRecyclerView.HeaderViewDimensionsProvider, SearchModeListener,
|
||||
WidgetsSearchBarUIHelper {
|
||||
private static final String TAG = WidgetsFullSheet.class.getSimpleName();
|
||||
|
||||
private static final long DEFAULT_OPEN_DURATION = 267;
|
||||
@@ -561,6 +563,11 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
getWindowInsetsController().hide(WindowInsets.Type.ime());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSearchBarFocus() {
|
||||
mSearchAndRecommendationViewHolder.mSearchBar.clearSearchBarFocus();
|
||||
}
|
||||
|
||||
/** A holder class for holding adapters & their corresponding recycler view. */
|
||||
private final class AdapterHolder {
|
||||
static final int PRIMARY = 0;
|
||||
@@ -583,7 +590,9 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
apps.getWidgetCache(),
|
||||
apps.getIconCache(),
|
||||
/* iconClickListener= */ WidgetsFullSheet.this,
|
||||
/* iconLongClickListener= */ WidgetsFullSheet.this);
|
||||
/* iconLongClickListener= */ WidgetsFullSheet.this,
|
||||
/* WidgetsSearchBarUIHelper= */
|
||||
mAdapterType == SEARCH ? WidgetsFullSheet.this : null);
|
||||
mWidgetsListAdapter.setHasStableIds(true);
|
||||
switch (mAdapterType) {
|
||||
case PRIMARY:
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
import com.android.launcher3.widget.picker.search.WidgetsSearchBarUIHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -69,6 +70,7 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
private static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
|
||||
private static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header;
|
||||
|
||||
@Nullable private final WidgetsSearchBarUIHelper mSearchBarUIHelper;
|
||||
private final WidgetsDiffReporter mDiffReporter;
|
||||
private final SparseArray<ViewHolderBinder> mViewHolderBinders = new SparseArray<>();
|
||||
private final WidgetsListTableViewHolderBinder mWidgetsListTableViewHolderBinder;
|
||||
@@ -88,7 +90,9 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
|
||||
public WidgetsListAdapter(Context context, LayoutInflater layoutInflater,
|
||||
WidgetPreviewLoader widgetPreviewLoader, IconCache iconCache,
|
||||
OnClickListener iconClickListener, OnLongClickListener iconLongClickListener) {
|
||||
OnClickListener iconClickListener, OnLongClickListener iconLongClickListener,
|
||||
@Nullable WidgetsSearchBarUIHelper searchBarUIHelper) {
|
||||
mSearchBarUIHelper = searchBarUIHelper;
|
||||
mDiffReporter = new WidgetsDiffReporter(iconCache, this);
|
||||
mWidgetsListTableViewHolderBinder = new WidgetsListTableViewHolderBinder(context,
|
||||
layoutInflater, iconClickListener, iconLongClickListener,
|
||||
@@ -237,6 +241,9 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
|
||||
@Override
|
||||
public void onHeaderClicked(boolean showWidgets, PackageUserKey packageUserKey) {
|
||||
if (mSearchBarUIHelper != null) {
|
||||
mSearchBarUIHelper.clearSearchBarFocus();
|
||||
}
|
||||
if (showWidgets) {
|
||||
mWidgetsContentVisiblePackageUserKey = packageUserKey;
|
||||
updateVisibleEntries();
|
||||
|
||||
@@ -79,4 +79,9 @@ public class LauncherWidgetsSearchBar extends LinearLayout implements WidgetsSea
|
||||
super.onDetachedFromWindow();
|
||||
mController.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSearchBarFocus() {
|
||||
mController.clearFocus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,11 @@ public interface WidgetsSearchBar {
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Clears focus from search bar.
|
||||
*/
|
||||
void clearSearchBarFocus();
|
||||
|
||||
/**
|
||||
* Sets the vertical location, in pixels, of this search bar relative to its top position.
|
||||
*/
|
||||
|
||||
@@ -103,8 +103,7 @@ public class WidgetsSearchBarController implements TextWatcher,
|
||||
public void clearSearchResult() {
|
||||
mSearchAlgorithm.cancel(/* interruptActiveRequests= */ true);
|
||||
mInput.getText().clear();
|
||||
mInput.clearFocus();
|
||||
mInput.hideKeyboard();
|
||||
clearFocus();
|
||||
mSearchModeListener.exitSearchMode();
|
||||
}
|
||||
|
||||
@@ -117,18 +116,24 @@ public class WidgetsSearchBarController implements TextWatcher,
|
||||
|
||||
@Override
|
||||
public boolean onBackKey() {
|
||||
mInput.clearFocus();
|
||||
mInput.hideKeyboard();
|
||||
clearFocus();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKey(View view, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
mInput.clearFocus();
|
||||
mInput.hideKeyboard();
|
||||
clearFocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears focus from edit text.
|
||||
*/
|
||||
public void clearFocus() {
|
||||
mInput.clearFocus();
|
||||
mInput.hideKeyboard();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (C) 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.
|
||||
*/
|
||||
|
||||
package com.android.launcher3.widget.picker.search;
|
||||
|
||||
/**
|
||||
* UI helper for {@link WidgetsSearchBar}.
|
||||
*/
|
||||
public interface WidgetsSearchBarUIHelper {
|
||||
/**
|
||||
* Clears focus from the search bar.
|
||||
*/
|
||||
void clearSearchBarFocus();
|
||||
}
|
||||
Reference in New Issue
Block a user