Snap for 7230642 from 0fa5225d57 to sc-v2-release

Change-Id: I1553d97bf20900334bd5ec95d6557fcccfc2760c
This commit is contained in:
android-build-team Robot
2021-03-24 01:08:24 +00:00
30 changed files with 438 additions and 231 deletions
+2
View File
@@ -24,6 +24,8 @@
<uses-sdk android:targetSdkVersion="29" android:minSdkVersion="25"/>
<uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO" />
<application
android:backupAgent="com.android.launcher3.LauncherBackupAgent"
android:fullBackupOnly="true"
@@ -20,11 +20,21 @@ import static com.android.quickstep.views.OverviewActionsView.DISABLED_NO_THUMBN
import static com.android.quickstep.views.OverviewActionsView.DISABLED_ROTATED;
import android.annotation.SuppressLint;
import android.app.ActivityTaskManager;
import android.app.IAssistDataReceiver;
import android.app.assist.AssistContent;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.RemoteException;
import android.os.SystemClock;
import android.text.TextUtils;
import android.util.Log;
import com.android.launcher3.R;
import com.android.quickstep.views.OverviewActionsView;
@@ -40,6 +50,8 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
public static final String ACTION_TRANSLATE = "com.android.quickstep.ACTION_TRANSLATE";
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 TAG = "TaskOverlayFactoryGo";
// Empty constructor required for ResourceBasedOverride
public TaskOverlayFactoryGo(Context context) {}
@@ -56,11 +68,16 @@ 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 mPackageName;
private String mNIUPackageName;
private int mTaskId;
private Bundle mAssistData;
private final Handler mMainThreadHandler;
private TaskOverlayGo(TaskThumbnailView taskThumbnailView) {
super(taskThumbnailView);
mMainThreadHandler = new Handler(Looper.getMainLooper());
}
/**
@@ -70,16 +87,39 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
public void initOverlay(Task task, ThumbnailData thumbnail, Matrix matrix,
boolean rotated) {
getActionsView().updateDisabledFlags(DISABLED_NO_THUMBNAIL, thumbnail == null);
mPackageName =
mNIUPackageName =
mApplicationContext.getResources().getString(R.string.niu_actions_package);
if (thumbnail == null || TextUtils.isEmpty(mPackageName)) {
if (thumbnail == null || TextUtils.isEmpty(mNIUPackageName)) {
return;
}
getActionsView().updateDisabledFlags(DISABLED_ROTATED, rotated);
boolean isAllowedByPolicy = thumbnail.isRealSnapshot;
getActionsView().setCallbacks(new OverlayUICallbacksGoImpl(isAllowedByPolicy, task));
mTaskId = task.key.id;
AssistDataReceiverImpl receiver = new AssistDataReceiverImpl();
receiver.setOverlay(this);
try {
ActivityTaskManager.getService().requestAssistDataForTask(receiver, mTaskId,
mApplicationContext.getPackageName());
} catch (RemoteException e) {
Log.e(TAG, "Unable to request AssistData");
}
}
/**
* Called when AssistDataReceiverImpl receives data from ActivityTaskManagerService's
* AssistDataRequester
*/
public void onAssistDataReceived(Bundle data) {
mMainThreadHandler.post(() -> {
if (data != null) {
mAssistData = data;
}
});
}
private void sendNIUIntent(String actionType) {
@@ -88,11 +128,21 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
}
private Intent createNIUIntent(String actionType) {
return new Intent(actionType)
Intent intent = new Intent(actionType)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
.setPackage(mPackageName)
.setPackage(mNIUPackageName)
.putExtra(ELAPSED_NANOS, SystemClock.elapsedRealtimeNanos());
if (mAssistData != null) {
final AssistContent content = mAssistData.getParcelable(ASSIST_KEY_CONTENT);
Uri webUri = (content == null) ? null : content.getWebUri();
if (webUri != null) {
intent.putExtra(ACTIONS_URL, webUri.toString());
}
}
return intent;
}
protected class OverlayUICallbacksGoImpl extends OverlayUICallbacksImpl
@@ -130,6 +180,26 @@ public final class TaskOverlayFactoryGo extends TaskOverlayFactory {
}
}
/**
* Basic AssistDataReceiver. This is passed to ActivityTaskManagerService, which then requests
* the data.
*/
private static final class AssistDataReceiverImpl extends IAssistDataReceiver.Stub {
private TaskOverlayGo mOverlay;
public void setOverlay(TaskOverlayGo overlay) {
mOverlay = overlay;
}
@Override
public void onHandleAssistData(Bundle data) {
mOverlay.onAssistDataReceived(data);
}
@Override
public void onHandleAssistScreenshot(Bitmap screenshot) {}
}
/**
* Callbacks the Ui can generate. This is the only way for a Ui to call methods on the
* controller.
-2
View File
@@ -18,6 +18,4 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/taskbar_divider_thickness"
android:layout_height="@dimen/taskbar_divider_height"
android:layout_marginStart="@dimen/taskbar_icon_spacing"
android:layout_marginEnd="@dimen/taskbar_icon_spacing"
android:background="@color/taskbar_divider" />
+26
View File
@@ -0,0 +1,26 @@
<?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.
-->
<com.android.launcher3.taskbar.TaskbarView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/taskbar_view"
android:layout_width="match_parent"
android:layout_height="@dimen/taskbar_size"
android:background="@android:color/transparent"
android:layout_gravity="bottom"
android:gravity="center"
android:visibility="gone" />
@@ -46,6 +46,7 @@ import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.taskbar.TaskbarActivityContext;
import com.android.launcher3.taskbar.TaskbarController;
import com.android.launcher3.taskbar.TaskbarStateHandler;
import com.android.launcher3.taskbar.TaskbarView;
import com.android.launcher3.uioverrides.RecentsViewStateController;
import com.android.launcher3.util.ActivityOptionsWrapper;
import com.android.launcher3.util.DisplayController;
@@ -243,9 +244,10 @@ public abstract class BaseQuickstepLauncher extends Launcher
mTaskbarController = null;
}
if (mDeviceProfile.isTaskbarPresent) {
TaskbarView taskbarViewOnHome = (TaskbarView) mHotseat.getTaskbarView();
TaskbarActivityContext taskbarActivityContext = new TaskbarActivityContext(this);
mTaskbarController = new TaskbarController(this,
taskbarActivityContext.getTaskbarContainerView());
taskbarActivityContext.getTaskbarContainerView(), taskbarViewOnHome);
mTaskbarController.init();
}
}
@@ -73,6 +73,7 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange
public static final String LAST_PREDICTION_ENABLED_STATE = "last_prediction_enabled_state";
private static final String LAST_SNAPSHOT_TIME_MILLIS = "LAST_SNAPSHOT_TIME_MILLIS";
private static final int NUM_OF_RECOMMENDED_WIDGETS_PREDICATION = 20;
private static final boolean IS_DEBUG = false;
private static final String TAG = "QuickstepModelDelegate";
@@ -217,7 +218,7 @@ public class QuickstepModelDelegate extends ModelDelegate implements OnIDPChange
registerWidgetsPredictor(apm.createAppPredictionSession(
new AppPredictionContext.Builder(context)
.setUiSurface("widgets")
.setPredictedTargetCount(mIDP.numColumns)
.setPredictedTargetCount(NUM_OF_RECOMMENDED_WIDGETS_PREDICATION)
.build()));
}
@@ -54,10 +54,7 @@ public class TaskbarActivityContext extends ContextWrapper implements ActivityCo
return mTaskbarContainerView;
}
/**
* @return A LayoutInflater to use in this Context. Views inflated with this LayoutInflater will
* be able to access this TaskbarActivityContext via ActivityContext.lookupContext().
*/
@Override
public LayoutInflater getLayoutInflater() {
return mLayoutInflater;
}
@@ -84,7 +84,7 @@ public class TaskbarContainerView extends BaseDragLayer<TaskbarActivityContext>
private ViewTreeObserverWrapper.OnComputeInsetsListener createTaskbarInsetsComputer() {
return insetsInfo -> {
if (getAlpha() < AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD
|| mTaskbarView.isDraggingItem()) {
|| mTaskbarView.getVisibility() != VISIBLE || mTaskbarView.isDraggingItem()) {
// We're invisible or dragging out of taskbar, let touches pass through us.
insetsInfo.touchableRegion.setEmpty();
insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
@@ -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.AbstractFloatingView.TYPE_HIDE_TASKBAR;
import static com.android.launcher3.AbstractFloatingView.TYPE_REPLACE_TASKBAR_WITH_HOTSEAT;
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;
@@ -43,7 +41,6 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.Hotseat;
import com.android.launcher3.LauncherState;
import com.android.launcher3.QuickstepTransitionManager;
import com.android.launcher3.R;
@@ -54,6 +51,7 @@ import com.android.launcher3.model.data.FolderInfo;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.touch.ItemClickHandler;
import com.android.launcher3.views.ActivityContext;
import com.android.quickstep.AnimatedFloat;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -70,7 +68,8 @@ public class TaskbarController {
private static final String WINDOW_TITLE = "Taskbar";
private final TaskbarContainerView mTaskbarContainerView;
private final TaskbarView mTaskbarView;
private final TaskbarView mTaskbarViewInApp;
private final TaskbarView mTaskbarViewOnHome;
private final BaseQuickstepLauncher mLauncher;
private final WindowManager mWindowManager;
// Layout width and height of the Taskbar in the default state.
@@ -91,14 +90,17 @@ public class TaskbarController {
private @Nullable Animator mAnimator;
private boolean mIsAnimatingToLauncher;
private boolean mIsAnimatingToApp;
public TaskbarController(BaseQuickstepLauncher launcher,
TaskbarContainerView taskbarContainerView) {
TaskbarContainerView taskbarContainerView, TaskbarView taskbarViewOnHome) {
mLauncher = launcher;
mTaskbarContainerView = taskbarContainerView;
mTaskbarContainerView.construct(createTaskbarContainerViewCallbacks());
mTaskbarView = mTaskbarContainerView.findViewById(R.id.taskbar_view);
mTaskbarView.construct(createTaskbarViewCallbacks());
mTaskbarViewInApp = mTaskbarContainerView.findViewById(R.id.taskbar_view);
mTaskbarViewInApp.construct(createTaskbarViewCallbacks());
mTaskbarViewOnHome = taskbarViewOnHome;
mTaskbarViewOnHome.construct(createTaskbarViewCallbacks());
mWindowManager = mLauncher.getWindowManager();
mTaskbarSize = new Point(MATCH_PARENT, mLauncher.getDeviceProfile().taskbarSize);
mTaskbarStateHandler = mLauncher.getTaskbarStateHandler();
@@ -115,12 +117,13 @@ public class TaskbarController {
return new TaskbarVisibilityControllerCallbacks() {
@Override
public void updateTaskbarBackgroundAlpha(float alpha) {
mTaskbarView.setBackgroundAlpha(alpha);
mTaskbarViewInApp.setBackgroundAlpha(alpha);
}
@Override
public void updateTaskbarVisibilityAlpha(float alpha) {
mTaskbarContainerView.setAlpha(alpha);
mTaskbarViewOnHome.setAlpha(alpha);
}
};
}
@@ -196,7 +199,7 @@ public class TaskbarController {
public View.OnLongClickListener getItemOnLongClickListener() {
return view -> {
if (mLauncher.hasBeenResumed() && view.getTag() instanceof ItemInfo) {
alignRealHotseatWithTaskbar();
// TODO: remove this path
return mDragController.startWorkspaceDragOnLongClick(view);
} else {
return mDragController.startSystemDragOnLongClick(view);
@@ -205,11 +208,24 @@ public class TaskbarController {
}
@Override
public int getEmptyHotseatViewVisibility() {
public int getEmptyHotseatViewVisibility(TaskbarView taskbarView) {
// When on the home screen, we want the empty hotseat views to take up their full
// space so that the others line up with the home screen hotseat.
return mLauncher.hasBeenResumed() || mIsAnimatingToLauncher
? View.INVISIBLE : View.GONE;
boolean isOnHomeScreen = taskbarView == mTaskbarViewOnHome
|| mLauncher.hasBeenResumed() || mIsAnimatingToLauncher;
return isOnHomeScreen ? View.INVISIBLE : View.GONE;
}
@Override
public float getNonIconScale(TaskbarView taskbarView) {
return taskbarView == mTaskbarViewOnHome ? getTaskbarScaleOnHome() : 1f;
}
@Override
public void onItemPositionsChanged(TaskbarView taskbarView) {
if (taskbarView == mTaskbarViewOnHome) {
alignRealHotseatWithTaskbar();
}
}
};
}
@@ -218,7 +234,7 @@ public class TaskbarController {
return new TaskbarHotseatControllerCallbacks() {
@Override
public void updateHotseatItems(ItemInfo[] hotseatItemInfos) {
mTaskbarView.updateHotseatItems(hotseatItemInfos);
mTaskbarViewInApp.updateHotseatItems(hotseatItemInfos);
mLatestLoadedHotseatItems = hotseatItemInfos;
dedupeAndUpdateRecentItems();
}
@@ -235,7 +251,8 @@ public class TaskbarController {
@Override
public void updateRecentTaskAtIndex(int taskIndex, Task task) {
mTaskbarView.updateRecentTaskAtIndex(taskIndex, task);
mTaskbarViewInApp.updateRecentTaskAtIndex(taskIndex, task);
mTaskbarViewOnHome.updateRecentTaskAtIndex(taskIndex, task);
}
};
}
@@ -244,16 +261,20 @@ public class TaskbarController {
* Initializes the Taskbar, including adding it to the screen.
*/
public void init() {
mTaskbarView.init(mHotseatController.getNumHotseatIcons(),
mTaskbarViewInApp.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarContainerView.init(mTaskbarView);
mTaskbarViewOnHome.init(mHotseatController.getNumHotseatIcons(),
mRecentsController.getNumRecentIcons());
mTaskbarContainerView.init(mTaskbarViewInApp);
addToWindowManager();
mTaskbarStateHandler.setTaskbarCallbacks(createTaskbarStateHandlerCallbacks());
mTaskbarVisibilityController.init();
mHotseatController.init();
mRecentsController.init();
SCALE_PROPERTY.set(mTaskbarView, mLauncher.hasBeenResumed() ? getTaskbarScaleOnHome() : 1f);
SCALE_PROPERTY.set(mTaskbarViewInApp, mLauncher.hasBeenResumed()
? getTaskbarScaleOnHome() : 1f);
updateWhichTaskbarViewIsVisible();
}
private TaskbarStateHandlerCallbacks createTaskbarStateHandlerCallbacks() {
@@ -274,7 +295,8 @@ public class TaskbarController {
mAnimator.end();
}
mTaskbarView.cleanup();
mTaskbarViewInApp.cleanup();
mTaskbarViewOnHome.cleanup();
mTaskbarContainerView.cleanup();
removeFromWindowManager();
mTaskbarStateHandler.setTaskbarCallbacks(null);
@@ -313,7 +335,7 @@ public class TaskbarController {
TaskbarContainerView.LayoutParams taskbarLayoutParams =
new TaskbarContainerView.LayoutParams(mTaskbarSize.x, mTaskbarSize.y);
taskbarLayoutParams.gravity = gravity;
mTaskbarView.setLayoutParams(taskbarLayoutParams);
mTaskbarViewInApp.setLayoutParams(taskbarLayoutParams);
mWindowManager.addView(mTaskbarContainerView, mWindowLayoutParams);
}
@@ -330,7 +352,6 @@ public class TaskbarController {
mAnimator = createAnimToLauncher(null, duration);
} else {
mAnimator = createAnimToApp(duration);
replaceTaskbarWithHotseatOrViceVersa();
}
mAnimator.addListener(new AnimatorListenerAdapter() {
@Override
@@ -351,36 +372,41 @@ public class TaskbarController {
if (toState != null) {
mTaskbarStateHandler.setStateWithAnimation(toState, new StateAnimationConfig(), anim);
}
anim.addFloat(mTaskbarView, SCALE_PROPERTY, mTaskbarView.getScaleX(),
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(),
getTaskbarScaleOnHome(), LINEAR);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mIsAnimatingToLauncher = true;
mTaskbarView.updateHotseatItemsVisibility();
mTaskbarViewInApp.updateHotseatItemsVisibility();
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatingToLauncher = false;
updateWhichTaskbarViewIsVisible();
}
});
anim.addOnFrameCallback(this::alignRealHotseatWithTaskbar);
return anim.buildAnim();
}
private Animator createAnimToApp(long duration) {
PendingAnimation anim = new PendingAnimation(duration);
anim.add(mTaskbarVisibilityController.createAnimToBackgroundAlpha(1, duration));
anim.addFloat(mTaskbarView, SCALE_PROPERTY, mTaskbarView.getScaleX(), 1f, LINEAR);
anim.addFloat(mTaskbarViewInApp, SCALE_PROPERTY, mTaskbarViewInApp.getScaleX(), 1f, LINEAR);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
mTaskbarView.updateHotseatItemsVisibility();
setReplaceTaskbarWithHotseat(false);
mIsAnimatingToApp = true;
mTaskbarViewInApp.updateHotseatItemsVisibility();
updateWhichTaskbarViewIsVisible();
}
@Override
public void onAnimationEnd(Animator animation) {
mIsAnimatingToApp = false;
}
});
return anim.buildAnim();
@@ -405,11 +431,11 @@ public class TaskbarController {
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
*/
public boolean isEventOverAnyTaskbarItem(MotionEvent ev) {
return mTaskbarView.isEventOverAnyItem(ev);
return mTaskbarViewInApp.isEventOverAnyItem(ev);
}
public boolean isDraggingItem() {
return mTaskbarView.isDraggingItem();
return mTaskbarViewInApp.isDraggingItem() || mTaskbarViewOnHome.isDraggingItem();
}
private void dedupeAndUpdateRecentItems() {
@@ -454,7 +480,8 @@ public class TaskbarController {
tasksArray[tasksArray.length - 1 - i] = task;
}
mTaskbarView.updateRecentTasks(tasksArray);
mTaskbarViewInApp.updateRecentTasks(tasksArray);
mTaskbarViewOnHome.updateRecentTasks(tasksArray);
mRecentsController.loadIconsForTasks(tasksArray);
}
@@ -475,10 +502,11 @@ public class TaskbarController {
int hotseatHeight = grid.workspacePadding.bottom + grid.taskbarSize;
int hotseatTopDiff = hotseatHeight - grid.taskbarSize;
mTaskbarView.getHotseatBoundsAtScale(getTaskbarScaleOnHome()).roundOut(hotseatBounds);
mLauncher.getHotseat().setPadding(hotseatBounds.left, hotseatBounds.top + hotseatTopDiff,
mTaskbarView.getWidth() - hotseatBounds.right,
mTaskbarView.getHeight() - hotseatBounds.bottom);
mTaskbarViewOnHome.getHotseatBounds().roundOut(hotseatBounds);
mLauncher.getHotseat().setPadding(hotseatBounds.left,
hotseatBounds.top + hotseatTopDiff,
mTaskbarViewOnHome.getWidth() - hotseatBounds.right,
mTaskbarViewOnHome.getHeight() - hotseatBounds.bottom);
}
/**
@@ -486,36 +514,32 @@ public class TaskbarController {
* show the real one instead.
*/
public void onLauncherDragLayerHierarchyChanged() {
replaceTaskbarWithHotseatOrViceVersa();
// TODO: remove, as this is a no-op now
}
private void replaceTaskbarWithHotseatOrViceVersa() {
boolean replaceTaskbarWithHotseat = AbstractFloatingView.getTopOpenViewWithType(mLauncher,
TYPE_REPLACE_TASKBAR_WITH_HOTSEAT) != null;
if (!mLauncher.hasBeenResumed()) {
replaceTaskbarWithHotseat = false;
}
setReplaceTaskbarWithHotseat(replaceTaskbarWithHotseat);
boolean hideTaskbar = AbstractFloatingView.getTopOpenViewWithType(mLauncher,
TYPE_HIDE_TASKBAR) != null;
mTaskbarVisibilityController.animateToVisibilityForFloatingView(hideTaskbar ? 0f : 1f);
}
private void setReplaceTaskbarWithHotseat(boolean replaceTaskbarWithHotseat) {
Hotseat hotseat = mLauncher.getHotseat();
if (replaceTaskbarWithHotseat) {
alignRealHotseatWithTaskbar();
hotseat.getReplaceTaskbarAlpha().setValue(1f);
mTaskbarView.setHotseatViewsHidden(true);
private void updateWhichTaskbarViewIsVisible() {
boolean isInApp = !mLauncher.hasBeenResumed() || mIsAnimatingToLauncher
|| mIsAnimatingToApp;
if (isInApp) {
mTaskbarViewInApp.setVisibility(View.VISIBLE);
mTaskbarViewOnHome.setVisibility(View.INVISIBLE);
mLauncher.getHotseat().setIconsAlpha(0);
} else {
hotseat.getReplaceTaskbarAlpha().setValue(0f);
mTaskbarView.setHotseatViewsHidden(false);
mTaskbarViewInApp.setVisibility(View.INVISIBLE);
mTaskbarViewOnHome.setVisibility(View.VISIBLE);
mLauncher.getHotseat().setIconsAlpha(1);
}
}
private float getTaskbarScaleOnHome() {
return 1f / mTaskbarContainerView.getTaskbarActivityContext().getTaskbarIconScale();
/**
* Returns the ratio of the taskbar icon size on home vs in an app.
*/
public float getTaskbarScaleOnHome() {
DeviceProfile inAppDp = mTaskbarContainerView.getTaskbarActivityContext()
.getDeviceProfile();
DeviceProfile onHomeDp = ActivityContext.lookupContext(mTaskbarViewOnHome.getContext())
.getDeviceProfile();
return (float) onHomeDp.cellWidthPx / inAppDp.cellWidthPx;
}
/**
@@ -561,7 +585,10 @@ public class TaskbarController {
protected interface TaskbarViewCallbacks {
View.OnClickListener getItemOnClickListener();
View.OnLongClickListener getItemOnLongClickListener();
int getEmptyHotseatViewVisibility();
int getEmptyHotseatViewVisibility(TaskbarView taskbarView);
/** Returns how much to scale non-icon elements such as spacing and dividers. */
float getNonIconScale(TaskbarView taskbarView);
void onItemPositionsChanged(TaskbarView taskbarView);
}
/**
@@ -15,11 +15,14 @@
*/
package com.android.launcher3.taskbar;
import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.LayoutTransition;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
@@ -36,6 +39,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BubbleTextView;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.folder.FolderIcon;
@@ -48,20 +52,23 @@ import com.android.systemui.shared.recents.model.Task;
/**
* Hosts the Taskbar content such as Hotseat and Recent Apps. Drawn on top of other apps.
*/
public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconParent {
public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconParent, Insettable {
private final ColorDrawable mBackgroundDrawable;
private final int mItemMarginLeftRight;
private final int mDividerWidth;
private final int mDividerHeight;
private final int mIconTouchSize;
private final boolean mIsRtl;
private final int mTouchSlop;
private final RectF mTempDelegateBounds = new RectF();
private final RectF mDelegateSlopBounds = new RectF();
private final int[] mTempOutLocation = new int[2];
private final Matrix mTempMatrix = new Matrix();
// Initialized in TaskbarController constructor.
private TaskbarController.TaskbarViewCallbacks mControllerCallbacks;
// Scale on elements that aren't icons.
private float mNonIconScale;
private int mItemMarginLeftRight;
// Initialized in init().
private LayoutTransition mLayoutTransition;
@@ -78,7 +85,6 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
private boolean mIsDraggingItem;
// Only non-null when the corresponding Folder is open.
private @Nullable FolderIcon mLeaveBehindFolderIcon;
private boolean mIsHotseatHidden;
public TaskbarView(@NonNull Context context) {
this(context, null);
@@ -99,7 +105,8 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
Resources resources = getResources();
mBackgroundDrawable = (ColorDrawable) getBackground();
mItemMarginLeftRight = resources.getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
mDividerWidth = resources.getDimensionPixelSize(R.dimen.taskbar_divider_thickness);
mDividerHeight = resources.getDimensionPixelSize(R.dimen.taskbar_divider_height);
mIconTouchSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_touch_size);
mIsRtl = Utilities.isRtl(resources);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -107,11 +114,16 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
protected void construct(TaskbarController.TaskbarViewCallbacks taskbarViewCallbacks) {
mControllerCallbacks = taskbarViewCallbacks;
mNonIconScale = mControllerCallbacks.getNonIconScale(this);
mItemMarginLeftRight = getResources().getDimensionPixelSize(R.dimen.taskbar_icon_spacing);
mItemMarginLeftRight = Math.round(mItemMarginLeftRight * mNonIconScale);
}
protected void init(int numHotseatIcons, int numRecentIcons) {
mLayoutTransition = new LayoutTransition();
setLayoutTransitionsEnabled(true);
addUpdateListenerForAllLayoutTransitions(
() -> mControllerCallbacks.onItemPositionsChanged(this));
setLayoutTransition(mLayoutTransition);
mHotseatStartIndex = 0;
mHotseatEndIndex = mHotseatStartIndex + numHotseatIcons - 1;
@@ -125,12 +137,30 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
updateRecentTasks(new Task[numRecentIcons]);
}
private void setLayoutTransitionsEnabled(boolean enabled) {
setLayoutTransition(enabled ? mLayoutTransition : null);
private void addUpdateListenerForAllLayoutTransitions(Runnable onUpdate) {
addUpdateListenerForLayoutTransition(LayoutTransition.CHANGE_APPEARING, onUpdate);
addUpdateListenerForLayoutTransition(LayoutTransition.CHANGE_DISAPPEARING, onUpdate);
addUpdateListenerForLayoutTransition(LayoutTransition.CHANGING, onUpdate);
addUpdateListenerForLayoutTransition(LayoutTransition.APPEARING, onUpdate);
addUpdateListenerForLayoutTransition(LayoutTransition.DISAPPEARING, onUpdate);
}
private void addUpdateListenerForLayoutTransition(int transitionType, Runnable onUpdate) {
Animator anim = mLayoutTransition.getAnimator(transitionType);
if (anim instanceof ValueAnimator) {
((ValueAnimator) anim).addUpdateListener(valueAnimator -> onUpdate.run());
} else {
AnimatorSet animSet = new AnimatorSet();
ValueAnimator updateAnim = ValueAnimator.ofFloat(0, 1);
updateAnim.addUpdateListener(valueAnimator -> onUpdate.run());
animSet.playTogether(anim, updateAnim);
mLayoutTransition.setAnimator(transitionType, animSet);
}
}
protected void cleanup() {
removeAllViews();
mHotseatRecentsDivider = null;
}
/**
@@ -170,12 +200,11 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
if (hotseatView == null || hotseatView.getSourceLayoutResId() != expectedLayoutResId
|| needsReinflate) {
removeView(hotseatView);
TaskbarActivityContext activityContext =
ActivityContext.lookupContext(getContext());
ActivityContext activityContext = ActivityContext.lookupContext(getContext());
if (isFolder) {
FolderInfo folderInfo = (FolderInfo) hotseatItemInfo;
FolderIcon folderIcon = FolderIcon.inflateFolderAndIcon(expectedLayoutResId,
activityContext, this, folderInfo);
ActivityContext.lookupContext(getContext()), this, folderInfo);
folderIcon.setTextVisible(false);
hotseatView = folderIcon;
} else {
@@ -216,22 +245,12 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
}
/**
* Hides or shows the hotseat items immediately (without layout transitions).
*/
protected void setHotseatViewsHidden(boolean hidden) {
mIsHotseatHidden = hidden;
setLayoutTransitionsEnabled(false);
updateHotseatItemsVisibility();
setLayoutTransitionsEnabled(true);
}
private void updateHotseatItemVisibility(View hotseatView) {
if (hotseatView.getTag() != null) {
hotseatView.setVisibility(mIsHotseatHidden ? INVISIBLE : VISIBLE);
hotseatView.setVisibility(VISIBLE);
} else {
int oldVisibility = hotseatView.getVisibility();
int newVisibility = mControllerCallbacks.getEmptyHotseatViewVisibility();
int newVisibility = mControllerCallbacks.getEmptyHotseatViewVisibility(this);
hotseatView.setVisibility(newVisibility);
if (oldVisibility == GONE && newVisibility != GONE) {
// By default, the layout transition only runs when going to VISIBLE,
@@ -243,7 +262,11 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
private View addDivider(int dividerIndex) {
View divider = inflate(R.layout.taskbar_divider);
addView(divider, dividerIndex);
LayoutParams lp = new LayoutParams(mDividerWidth, mDividerHeight);
lp.setMargins(mItemMarginLeftRight, 0, mItemMarginLeftRight, 0);
divider.setScaleX(mNonIconScale);
divider.setScaleY(mNonIconScale);
addView(divider, dividerIndex, lp);
return divider;
}
@@ -437,9 +460,9 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
/**
* @return The bounding box of where the hotseat elements will be when we reach the given scale.
* @return The bounding box of where the hotseat elements are relative to this TaskbarView.
*/
protected RectF getHotseatBoundsAtScale(float taskbarViewScale) {
protected RectF getHotseatBounds() {
View firstHotseatView = null, lastHotseatView = null;
for (int i = mHotseatStartIndex; i <= mHotseatEndIndex; i++) {
View child = getChildAt(i);
@@ -455,14 +478,11 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
View leftmostHotseatView = !mIsRtl ? firstHotseatView : lastHotseatView;
View rightmostHotseatView = !mIsRtl ? lastHotseatView : firstHotseatView;
RectF hotseatBounds = new RectF(
return new RectF(
leftmostHotseatView.getLeft() - mItemMarginLeftRight,
leftmostHotseatView.getTop(),
rightmostHotseatView.getRight() + mItemMarginLeftRight,
rightmostHotseatView.getBottom());
mTempMatrix.setScale(taskbarViewScale, taskbarViewScale, getPivotX(), getPivotY());
mTempMatrix.mapRect(hotseatBounds);
return hotseatBounds;
}
// FolderIconParent implemented methods.
@@ -493,7 +513,12 @@ public class TaskbarView extends LinearLayout implements FolderIcon.FolderIconPa
}
private View inflate(@LayoutRes int layoutResId) {
TaskbarActivityContext taskbarActivityContext = ActivityContext.lookupContext(getContext());
return taskbarActivityContext.getLayoutInflater().inflate(layoutResId, this, false);
return ActivityContext.lookupContext(getContext()).getLayoutInflater()
.inflate(layoutResId, this, false);
}
@Override
public void setInsets(Rect insets) {
// Ignore, we just implement Insettable to draw behind system insets.
}
}
@@ -617,7 +617,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
final boolean passed = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW;
if (passed != mPassedOverviewThreshold) {
mPassedOverviewThreshold = passed;
if (!mDeviceState.isTwoButtonNavMode()) {
if (mDeviceState.isTwoButtonNavMode()) {
performHapticFeedback();
}
}
@@ -112,20 +112,32 @@ public class StaggeredWorkspaceAnim {
}
// Set up springs for the hotseat and qsb.
ViewGroup hotseatChild = (ViewGroup) hotseat.getChildAt(0);
ViewGroup hotseatIcons = hotseat.getShortcutsAndWidgets();
if (grid.isVerticalBarLayout()) {
for (int i = hotseatChild.getChildCount() - 1; i >= 0; i--) {
View child = hotseatChild.getChildAt(i);
for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
View child = hotseatIcons.getChildAt(i);
CellLayout.LayoutParams lp = ((CellLayout.LayoutParams) child.getLayoutParams());
addStaggeredAnimationForView(child, lp.cellY + 1, totalRows);
}
} else {
for (int i = hotseatChild.getChildCount() - 1; i >= 0; i--) {
View child = hotseatChild.getChildAt(i);
addStaggeredAnimationForView(child, grid.inv.numRows + 1, totalRows);
final int hotseatRow, qsbRow, taskbarRow;
if (grid.isTaskbarPresent) {
qsbRow = grid.inv.numRows + 1;
hotseatRow = grid.inv.numRows + 2;
} else {
hotseatRow = grid.inv.numRows + 1;
qsbRow = grid.inv.numRows + 2;
}
// Taskbar and hotseat overlap.
taskbarRow = hotseatRow;
for (int i = hotseatIcons.getChildCount() - 1; i >= 0; i--) {
View child = hotseatIcons.getChildAt(i);
addStaggeredAnimationForView(child, hotseatRow, totalRows);
}
addStaggeredAnimationForView(hotseat.getQsb(), grid.inv.numRows + 2, totalRows);
addStaggeredAnimationForView(hotseat.getQsb(), qsbRow, totalRows);
addStaggeredAnimationForView(hotseat.getTaskbarView(), taskbarRow, totalRows);
}
if (animateOverviewScrim) {
@@ -298,7 +298,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
private boolean mEndQuickswitchCuj;
private View mContextualChipWrapper;
private View mContextualChip;
private final float[] mIconCenterCoords = new float[2];
private final float[] mChipCenterCoords = new float[2];
@@ -447,9 +446,9 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
mModalness = modalness;
mIconView.setAlpha(comp(modalness));
if (mContextualChip != null) {
mContextualChip.setScaleX(comp(modalness));
mContextualChip.setScaleY(comp(modalness));
if (mContextualChipWrapper != null) {
mContextualChipWrapper.setScaleX(comp(modalness));
mContextualChipWrapper.setScaleY(comp(modalness));
}
mDigitalWellBeingToast.updateBannerOffset(modalness,
mCurrentFullscreenParams.mCurrentDrawnInsets.top
@@ -689,10 +688,10 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
.getInterpolation(progress);
mIconView.setScaleX(scale);
mIconView.setScaleY(scale);
if (mContextualChip != null && mContextualChipWrapper != null) {
if (mContextualChipWrapper != null && mContextualChipWrapper != null) {
mContextualChipWrapper.setAlpha(scale);
mContextualChip.setScaleX(scale);
mContextualChip.setScaleY(scale);
mContextualChipWrapper.setScaleX(Math.min(scale, comp(mModalness)));
mContextualChipWrapper.setScaleY(Math.min(scale, comp(mModalness)));
}
mDigitalWellBeingToast.updateBannerOffset(1f - scale,
mCurrentFullscreenParams.mCurrentDrawnInsets.top
@@ -797,14 +796,12 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
int expectedChipHeight = getExpectedViewHeight(view);
float chipOffset = getResources().getDimension(R.dimen.chip_hint_vertical_offset);
layoutParams.bottomMargin = -expectedChipHeight - (int) chipOffset;
mContextualChip = ((FrameLayout) mContextualChipWrapper).getChildAt(0);
mContextualChip.setScaleX(0f);
mContextualChip.setScaleY(0f);
mContextualChipWrapper.setScaleX(0f);
mContextualChipWrapper.setScaleY(0f);
addView(view, getChildCount(), layoutParams);
if (mContextualChip != null) {
mContextualChip.animate().scaleX(1f).scaleY(1f).setDuration(50);
}
if (mContextualChipWrapper != null) {
float scale = comp(mModalness);
mContextualChipWrapper.animate().scaleX(scale).scaleY(scale).setDuration(50);
mChipTouchDelegate = new TransformingTouchDelegate(mContextualChipWrapper);
}
}
@@ -825,7 +822,6 @@ public class TaskView extends FrameLayout implements PageCallbacks, Reusable {
}
View oldContextualChipWrapper = mContextualChipWrapper;
mContextualChipWrapper = null;
mContextualChip = null;
mChipTouchDelegate = null;
return oldContextualChipWrapper;
}
+1 -1
View File
@@ -16,5 +16,5 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="?attr/popupColorPrimary"/>
<corners android:radius="@dimen/popup_middle_item_radius" />
<corners android:radius="@dimen/popup_smaller_radius" />
</shape>
+2
View File
@@ -32,6 +32,8 @@
android:paddingEnd="@dimen/popup_padding_end"
android:drawableEnd="@drawable/ic_drag_handle"
android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
android:singleLine="true"
android:ellipsize="end"
android:textSize="14sp"
android:textColor="?android:attr/textColorPrimary"
launcher:layoutHorizontal="true"
+2 -1
View File
@@ -31,7 +31,8 @@
android:paddingStart="@dimen/deep_shortcuts_text_padding_start"
android:paddingEnd="@dimen/popup_padding_end"
android:textSize="14sp"
android:maxLines="1"
android:singleLine="true"
android:ellipsize="end"
android:textColor="?android:attr/textColorPrimary"
launcher:iconDisplay="shortcut_popup"
launcher:layoutHorizontal="true"
+21
View File
@@ -0,0 +1,21 @@
<?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.
-->
<Space
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="0dp"
android:layout_height="0dp"
android:visibility="gone" />
+1 -35
View File
@@ -24,41 +24,7 @@
android:elevation="@dimen/deep_shortcuts_elevation"
android:layout_gravity="bottom"
android:theme="?attr/widgetsTheme">
<View
android:layout_width="48dp"
android:layout_height="2dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"
android:background="?android:attr/textColorSecondary"/>
<TextView
style="@style/TextHeadline"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:paddingTop="4dp"
android:fontFamily="sans-serif"
android:textColor="?android:attr/textColorTertiary"
android:textSize="14sp"
android:text="@string/long_press_widget_to_add"/>
<ScrollView
android:id="@+id/widgets_table_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
android:layout_marginVertical="16dp">
<include layout="@layout/widgets_table_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</ScrollView>
<include layout="@layout/widgets_bottom_sheet_content" />
</com.android.launcher3.widget.WidgetsBottomSheet>
@@ -0,0 +1,43 @@
<?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.
-->
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<View
android:layout_width="48dp"
android:layout_height="2dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="16dp"
android:background="?android:attr/textColorSecondary"/>
<TextView
style="@style/TextHeadline"
android:id="@+id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:textColor="?android:attr/textColorPrimary"
android:textSize="24sp"/>
<ScrollView
android:id="@+id/widgets_table_scroll_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fadeScrollbars="false"
android:layout_marginVertical="16dp">
<include layout="@layout/widgets_table_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal" />
</ScrollView>
</merge>
+2 -2
View File
@@ -185,7 +185,7 @@
<!-- Deep shortcuts -->
<dimen name="deep_shortcuts_elevation">0dp</dimen>
<dimen name="bg_popup_item_width">234dp</dimen>
<dimen name="bg_popup_item_width">216dp</dimen>
<dimen name="bg_popup_item_height">56dp</dimen>
<dimen name="pre_drag_view_scale">6dp</dimen>
<!-- an icon with shortcuts must be dragged this far before the container is removed. -->
@@ -193,7 +193,7 @@
<dimen name="deep_shortcut_icon_size">32dp</dimen>
<dimen name="popup_margin">2dp</dimen>
<dimen name="popup_single_item_radius">100dp</dimen>
<dimen name="popup_middle_item_radius">4dp</dimen>
<dimen name="popup_smaller_radius">4dp</dimen>
<dimen name="deep_shortcut_drawable_padding">12dp</dimen>
<dimen name="deep_shortcut_drag_handle_size">16dp</dimen>
<dimen name="popup_padding_start">10dp</dimen>
-2
View File
@@ -269,8 +269,6 @@
<string name="app_waiting_download_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> waiting to install</string>
<!-- Strings for widgets & more in the popup container/bottom sheet -->
<!-- Title for a bottom sheet that shows widgets for a particular app -->
<string name="widgets_bottom_sheet_title"><xliff:g id="name" example="Messenger">%1$s</xliff:g> widgets</string>
<!-- Accessibility title for the popup containing a list of widgets. [CHAR_LIMIT=50] -->
<string name="widgets_list">Widgets list</string>
@@ -100,6 +100,8 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
private int mRunningVInc;
private int mMinHSpan;
private int mMinVSpan;
private int mMaxHSpan;
private int mMaxVSpan;
private int mDeltaX;
private int mDeltaY;
private int mDeltaXAddOn;
@@ -183,6 +185,8 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
mMinHSpan = info.minSpanX;
mMinVSpan = info.minSpanY;
mMaxHSpan = info.maxSpanX;
mMaxVSpan = info.maxSpanY;
mWidgetPadding = AppWidgetHostView.getDefaultPaddingForWidget(getContext(),
widgetView.getAppWidgetInfo().provider, null);
@@ -314,7 +318,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
// expandability.
mTempRange1.set(cellX, spanX + cellX);
int hSpanDelta = mTempRange1.applyDeltaAndBound(mLeftBorderActive, mRightBorderActive,
hSpanInc, mMinHSpan, mCellLayout.getCountX(), mTempRange2);
hSpanInc, mMinHSpan, mMaxHSpan, mCellLayout.getCountX(), mTempRange2);
cellX = mTempRange2.start;
spanX = mTempRange2.size();
if (hSpanDelta != 0) {
@@ -323,7 +327,7 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
mTempRange1.set(cellY, spanY + cellY);
int vSpanDelta = mTempRange1.applyDeltaAndBound(mTopBorderActive, mBottomBorderActive,
vSpanInc, mMinVSpan, mCellLayout.getCountY(), mTempRange2);
vSpanInc, mMinVSpan, mMaxVSpan, mCellLayout.getCountY(), mTempRange2);
cellY = mTempRange2.start;
spanY = mTempRange2.size();
if (vSpanDelta != 0) {
@@ -642,12 +646,15 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
* @param minSize minimum size after with the moving edge should not be shifted any further.
* For eg, if delta = -3 when moving the endEdge brings the size to less than
* minSize, only delta = -2 will applied
* @param maxSize maximum size after with the moving edge should not be shifted any further.
* For eg, if delta = -3 when moving the endEdge brings the size to greater
* than maxSize, only delta = -2 will applied
* @param maxEnd The maximum value to the end edge (start edge is always restricted to 0)
* @return the amount of increase when endEdge was moves and the amount of decrease when
* the start edge was moved.
*/
public int applyDeltaAndBound(boolean moveStart, boolean moveEnd, int delta,
int minSize, int maxEnd, IntRange out) {
int minSize, int maxSize, int maxEnd, IntRange out) {
applyDelta(moveStart, moveEnd, delta, out);
if (out.start < 0) {
out.start = 0;
@@ -662,6 +669,13 @@ public class AppWidgetResizeFrame extends AbstractFloatingView implements View.O
out.end = out.start + minSize;
}
}
if (out.size() > maxSize) {
if (moveStart) {
out.start = out.end - maxSize;
} else if (moveEnd) {
out.end = out.start + maxSize;
}
}
return moveEnd ? out.size() - size() : size() - out.size();
}
}
+29 -15
View File
@@ -29,8 +29,6 @@ import android.widget.FrameLayout;
import androidx.annotation.Nullable;
import com.android.launcher3.util.MultiValueAlpha;
import java.util.function.Consumer;
/**
@@ -38,10 +36,6 @@ import java.util.function.Consumer;
*/
public class Hotseat extends CellLayout implements Insettable {
private static final int ALPHA_INDEX_STATE = 0;
private static final int ALPHA_INDEX_REPLACE_TASKBAR = 1;
private static final int NUM_ALPHA_CHANNELS = 2;
// Ratio of empty space, qsb should take up to appear visually centered.
public static final float QSB_CENTER_FACTOR = .325f;
@@ -52,10 +46,12 @@ public class Hotseat extends CellLayout implements Insettable {
@Nullable
private Consumer<Boolean> mOnVisibilityAggregatedCallback;
private final MultiValueAlpha mMultiValueAlpha;
private final View mQsb;
private final int mQsbHeight;
private final View mTaskbarView;
private final int mTaskbarViewHeight;
public Hotseat(Context context) {
this(context, null);
}
@@ -66,12 +62,15 @@ public class Hotseat extends CellLayout implements Insettable {
public Hotseat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mMultiValueAlpha = new MultiValueAlpha(this, NUM_ALPHA_CHANNELS, MultiValueAlpha.Mode.MAX);
mMultiValueAlpha.setUpdateVisibility(true);
mQsb = LayoutInflater.from(context).inflate(R.layout.search_container_hotseat, this, false);
mQsbHeight = mQsb.getLayoutParams().height;
addView(mQsb);
mTaskbarView = LayoutInflater.from(context).inflate(R.layout.taskbar_view, this, false);
mTaskbarViewHeight = mTaskbarView.getLayoutParams().height;
// We want taskbar in the back so its background applies to Hotseat as well.
addView(mTaskbarView, 0);
}
/**
@@ -193,6 +192,8 @@ public class Hotseat extends CellLayout implements Insettable {
int width = getShortcutsAndWidgets().getMeasuredWidth();
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
mTaskbarView.measure(MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(mTaskbarViewHeight, MeasureSpec.EXACTLY));
}
@Override
@@ -212,6 +213,13 @@ public class Hotseat extends CellLayout implements Insettable {
- (dp.isTaskbarPresent ? dp.taskbarSize : dp.getInsets().bottom);
int top = bottom - mQsbHeight;
mQsb.layout(left, top, right, bottom);
int taskbarWidth = mTaskbarView.getMeasuredWidth();
left = (r - l - taskbarWidth) / 2;
right = left + taskbarWidth;
bottom = b - t;
top = bottom - mTaskbarViewHeight;
mTaskbarView.layout(left, top, right, bottom);
}
/**
@@ -221,12 +229,11 @@ public class Hotseat extends CellLayout implements Insettable {
return mWorkspace.getFirstMatch(new CellLayout[] { this }, itemOperator);
}
public MultiValueAlpha.AlphaProperty getStateAlpha() {
return mMultiValueAlpha.getProperty(ALPHA_INDEX_STATE);
}
public MultiValueAlpha.AlphaProperty getReplaceTaskbarAlpha() {
return mMultiValueAlpha.getProperty(ALPHA_INDEX_REPLACE_TASKBAR);
/**
* Sets the alpha value of just our ShortcutAndWidgetContainer.
*/
public void setIconsAlpha(float alpha) {
getShortcutsAndWidgets().setAlpha(alpha);
}
/**
@@ -235,4 +242,11 @@ public class Hotseat extends CellLayout implements Insettable {
public View getQsb() {
return mQsb;
}
/**
* Returns the Taskbar inside hotseat
*/
public View getTaskbarView() {
return mTaskbarView;
}
}
+1 -6
View File
@@ -185,12 +185,7 @@ public abstract class LauncherState implements BaseState<LauncherState> {
}
public int getVisibleElements(Launcher launcher) {
DeviceProfile deviceProfile = launcher.getDeviceProfile();
int flags = WORKSPACE_PAGE_INDICATOR | VERTICAL_SWIPE_INDICATOR | TASKBAR;
if (!deviceProfile.isTaskbarPresent) {
flags |= HOTSEAT_ICONS;
}
return flags;
return HOTSEAT_ICONS | WORKSPACE_PAGE_INDICATOR | VERTICAL_SWIPE_INDICATOR | TASKBAR;
}
/**
@@ -54,7 +54,6 @@ import com.android.launcher3.graphics.SysUiScrim;
import com.android.launcher3.graphics.WorkspaceDragScrim;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.util.DynamicResource;
import com.android.launcher3.util.MultiValueAlpha;
import com.android.systemui.plugins.ResourceProvider;
/**
@@ -135,8 +134,8 @@ public class WorkspaceStateTransitionAnimation {
}
float hotseatIconsAlpha = (elements & HOTSEAT_ICONS) != 0 ? 1 : 0;
propertySetter.setFloat(hotseat.getStateAlpha(), MultiValueAlpha.VALUE,
hotseatIconsAlpha, config.getInterpolator(ANIM_HOTSEAT_FADE, fadeInterpolator));
propertySetter.setViewAlpha(hotseat, hotseatIconsAlpha,
config.getInterpolator(ANIM_HOTSEAT_FADE, fadeInterpolator));
float workspacePageIndicatorAlpha = (elements & WORKSPACE_PAGE_INDICATOR) != 0 ? 1 : 0;
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
workspacePageIndicatorAlpha, fadeInterpolator);
@@ -189,6 +189,7 @@ public class AllAppsRecyclerView extends BaseRecyclerView {
case SCROLL_STATE_DRAGGING:
mgr.logger().sendToInteractionJankMonitor(
LAUNCHER_ALLAPPS_VERTICAL_SWIPE_BEGIN, this);
requestFocus();
getWindowInsetsController().hide(WindowInsets.Type.ime());
break;
case SCROLL_STATE_IDLE:
@@ -22,13 +22,11 @@ import android.graphics.Path;
import android.graphics.RectF;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.graphics.ColorUtils;
import androidx.recyclerview.widget.RecyclerView;
import com.android.launcher3.R;
import com.android.launcher3.allapps.AllAppsGridAdapter.AppsGridLayoutManager;
import com.android.launcher3.allapps.search.SearchAdapterProvider;
import com.android.launcher3.allapps.search.SectionDecorationInfo;
import com.android.launcher3.util.Themes;
@@ -68,28 +66,6 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
}
}
// Fallback logic in case non of the SearchTarget is labeled as focused item.
private void drawDecoration(@NonNull Canvas c,
@NonNull SectionDecorationHandler decorationHandler,
@NonNull RecyclerView parent) {
if (decorationHandler.mIsFullWidth) {
decorationHandler.mBounds.left = parent.getPaddingLeft();
decorationHandler.mBounds.right = parent.getWidth() - parent.getPaddingRight();
}
if (mAppsView.getFloatingHeaderView().getFocusedChild() == null
&& mAppsView.getApps().getFocusedChild() != null) {
int index = mAppsView.getApps().getFocusedChildIndex();
AppsGridLayoutManager layoutManager = (AppsGridLayoutManager)
mAppsView.getActiveRecyclerView().getLayoutManager();
if (layoutManager.findFirstVisibleItemPosition() <= index
&& index < parent.getChildCount()) {
RecyclerView.ViewHolder vh = parent.findViewHolderForAdapterPosition(index);
if (vh != null) decorationHandler.onFocusDraw(c, vh.itemView);
}
}
decorationHandler.reset();
}
/**
* Handles grouping and drawing of items in the same all apps sections.
*/
@@ -136,7 +112,6 @@ public class AllAppsSectionDecorator extends RecyclerView.ItemDecoration {
*/
public void onGroupDraw(Canvas canvas, View view) {
if (view == null) return;
mPaint.setColor(mFillcolor);
mBounds.set(view.getLeft(), view.getTop(), view.getRight(), view.getBottom());
onDraw(canvas);
@@ -130,13 +130,14 @@ public abstract class ArrowPopup<T extends BaseDraggingActivity> extends Abstrac
R.dimen.popup_arrow_horizontal_center_offset) - (mArrowWidth / 2);
mArrowPointRadius = resources.getDimensionPixelSize(R.dimen.popup_arrow_corner_radius);
int smallerRadius = resources.getDimensionPixelSize(R.dimen.popup_smaller_radius);
mRoundedTop = new GradientDrawable();
mRoundedTop.setCornerRadii(new float[] { mOutlineRadius, mOutlineRadius, mOutlineRadius,
mOutlineRadius, 0, 0, 0, 0});
mOutlineRadius, smallerRadius, smallerRadius, smallerRadius, smallerRadius});
mRoundedBottom = new GradientDrawable();
mRoundedBottom.setCornerRadii(new float[] { 0, 0, 0, 0, mOutlineRadius, mOutlineRadius,
mOutlineRadius, mOutlineRadius});
mRoundedBottom.setCornerRadii(new float[] { smallerRadius, smallerRadius, smallerRadius,
smallerRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius, mOutlineRadius});
int primaryColor = Themes.getAttrColor(context, R.attr.popupColorPrimary);
int secondaryColor = Themes.getAttrColor(context, R.attr.popupColorSecondary);
@@ -272,7 +273,6 @@ public abstract class ArrowPopup<T extends BaseDraggingActivity> extends Abstrac
}
onInflationComplete(reverseOrder);
assignMarginsAndBackgrounds();
orientAboutObject();
if (shouldAddArrow()) {
addArrow();
}
@@ -286,7 +286,6 @@ public abstract class ArrowPopup<T extends BaseDraggingActivity> extends Abstrac
setupForDisplay();
onInflationComplete(false);
assignMarginsAndBackgrounds();
orientAboutObject();
if (shouldAddArrow()) {
addArrow();
}
@@ -383,10 +382,18 @@ public abstract class ArrowPopup<T extends BaseDraggingActivity> extends Abstrac
private void orientAboutObject(boolean allowAlignLeft, boolean allowAlignRight) {
measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int width = getMeasuredWidth();
int extraVerticalSpace = mArrowHeight + mArrowOffsetVertical
+ getResources().getDimensionPixelSize(R.dimen.popup_vertical_padding);
int height = getMeasuredHeight() + extraVerticalSpace;
// The margins are added after we call this method, so we need to account for them here.
int numVisibleChildren = 0;
for (int i = getChildCount() - 1; i >= 0; --i) {
if (getChildAt(i).getVisibility() == VISIBLE) {
numVisibleChildren++;
}
}
int childMargins = (numVisibleChildren - 1) * mMargin;
int height = getMeasuredHeight() + extraVerticalSpace + childMargins;
int width = getMeasuredWidth();
getTargetObjectLocation(mTempRect);
InsettableFrameLayout dragLayer = getPopupContainer();
@@ -18,6 +18,7 @@ package com.android.launcher3.views;
import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Rect;
import android.view.LayoutInflater;
import android.view.View.AccessibilityDelegate;
import com.android.launcher3.DeviceProfile;
@@ -66,6 +67,18 @@ public interface ActivityContext {
default void updateOpenFolderPosition(int[] inOutPosition, Rect bounds, int width, int height) {
}
/**
* Returns a LayoutInflater that is cloned in this Context, so that Views inflated by it will
* have the same Context. (i.e. {@link #lookupContext(Context)} will find this ActivityContext.)
*/
default LayoutInflater getLayoutInflater() {
if (this instanceof Context) {
Context context = (Context) this;
return LayoutInflater.from(context).cloneInContext(context);
}
return null;
}
/**
* The root view to support drag-and-drop and popup support.
*/
@@ -73,7 +86,10 @@ public interface ActivityContext {
DeviceProfile getDeviceProfile();
static <T extends ActivityContext> T lookupContext(Context context) {
/**
* Returns the ActivityContext associated with the given Context.
*/
static <T extends Context & ActivityContext> T lookupContext(Context context) {
if (context instanceof ActivityContext) {
return (T) context;
} else if (context instanceof ContextWrapper) {
@@ -119,8 +119,7 @@ public class WidgetsBottomSheet extends BaseWidgetSheet implements Insettable {
public void populateAndShow(ItemInfo itemInfo) {
mOriginalItemInfo = itemInfo;
((TextView) findViewById(R.id.title)).setText(getContext().getString(
R.string.widgets_bottom_sheet_title, mOriginalItemInfo.title));
((TextView) findViewById(R.id.title)).setText(mOriginalItemInfo.title);
onWidgetsBound();
attachToContainer();