Snap for 7230642 from 0fa5225d57 to sc-release
Change-Id: I801b2f39fae07352380b4283337654d67a8e9385
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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" />
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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" />
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user