Merge "Add TaskbarView as a child of Hotseat" into sc-dev
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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" />
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user