Snap for 8340624 from 6c7b0f7db8 to tm-release
Change-Id: Ia76757e74f6f6df7e31a7b6ea9590ea5d0d1bc86
This commit is contained in:
@@ -51,6 +51,12 @@
|
||||
<include layout="@layout/all_apps_personal_work_tabs" />
|
||||
</com.android.launcher3.allapps.FloatingHeaderView>
|
||||
|
||||
<com.android.launcher3.taskbar.allapps.TaskbarAllAppsFallbackSearchContainer
|
||||
android:id="@+id/search_container_all_apps"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<include layout="@layout/all_apps_fast_scroller" />
|
||||
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView>
|
||||
</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
|
||||
|
||||
@@ -23,14 +23,14 @@ import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
|
||||
import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.views.AppLauncher;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
// TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar.
|
||||
/** Base for common behavior between taskbar window contexts. */
|
||||
public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext,
|
||||
public abstract class BaseTaskbarContext extends ContextThemeWrapper implements AppLauncher,
|
||||
DeviceProfileListenable {
|
||||
|
||||
protected final LayoutInflater mLayoutInflater;
|
||||
|
||||
@@ -442,7 +442,8 @@ public class TaskbarActivityContext extends BaseTaskbarContext {
|
||||
mControllers.stashedHandleViewController.setIsHomeButtonDisabled(
|
||||
mControllers.navbarButtonsViewController.isHomeDisabled());
|
||||
mControllers.taskbarKeyguardController.updateStateForSysuiFlags(systemUiStateFlags);
|
||||
mControllers.taskbarStashController.updateStateForSysuiFlags(systemUiStateFlags, fromInit);
|
||||
mControllers.taskbarStashController.updateStateForSysuiFlags(
|
||||
systemUiStateFlags, fromInit || !isUserSetupComplete());
|
||||
mControllers.taskbarScrimViewController.updateStateForSysuiFlags(systemUiStateFlags,
|
||||
fromInit);
|
||||
mControllers.navButtonController.updateSysuiFlags(systemUiStateFlags);
|
||||
|
||||
@@ -54,6 +54,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
|
||||
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
|
||||
public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible.
|
||||
public static final int FLAG_IN_SETUP = 1 << 8; // In the Setup Wizard
|
||||
|
||||
// If any of these flags are enabled, isInApp should return true.
|
||||
private static final int FLAGS_IN_APP = FLAG_IN_APP | FLAG_IN_SETUP;
|
||||
|
||||
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
|
||||
private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
|
||||
@@ -141,7 +145,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
// Evaluate whether the handle should be stashed
|
||||
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
|
||||
flags -> {
|
||||
boolean inApp = hasAnyFlag(flags, FLAG_IN_APP);
|
||||
boolean inApp = hasAnyFlag(flags, FLAGS_IN_APP);
|
||||
boolean stashedInApp = hasAnyFlag(flags, FLAGS_STASHED_IN_APP);
|
||||
boolean stashedLauncherState = hasAnyFlag(flags, FLAG_IN_STASHED_LAUNCHER_STATE);
|
||||
return (inApp && stashedInApp) || (!inApp && stashedLauncherState);
|
||||
@@ -179,10 +183,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
boolean isInSetup = !mActivity.isUserSetupComplete() || sharedState.setupUIVisible;
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_MANUAL, isManuallyStashedInApp);
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, isInSetup);
|
||||
if (isInSetup) {
|
||||
// Update the in-app state to ensure isStashed() reflects right state during SUW
|
||||
updateStateForFlag(FLAG_IN_APP, true);
|
||||
}
|
||||
updateStateForFlag(FLAG_IN_SETUP, isInSetup);
|
||||
applyState();
|
||||
|
||||
notifyStashChange(/* visible */ false, /* stashed */ isStashedInApp());
|
||||
@@ -216,9 +217,10 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
* Sets the flag indicating setup UI is visible
|
||||
*/
|
||||
protected void setSetupUIVisible(boolean isVisible) {
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP,
|
||||
isVisible || !mActivity.isUserSetupComplete());
|
||||
applyState();
|
||||
boolean hideTaskbar = isVisible || !mActivity.isUserSetupComplete();
|
||||
updateStateForFlag(FLAG_IN_SETUP, hideTaskbar);
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_SETUP, hideTaskbar);
|
||||
applyState(hideTaskbar ? 0 : TASKBAR_STASH_DURATION);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,7 +261,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
}
|
||||
|
||||
private boolean isInApp() {
|
||||
return hasAnyFlag(FLAG_IN_APP);
|
||||
return hasAnyFlag(FLAGS_IN_APP);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,7 +480,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
}
|
||||
|
||||
public void applyState() {
|
||||
applyState(TASKBAR_STASH_DURATION);
|
||||
applyState(hasAnyFlag(FLAG_IN_SETUP) ? 0 : TASKBAR_STASH_DURATION);
|
||||
}
|
||||
|
||||
public void applyState(long duration) {
|
||||
@@ -568,8 +570,8 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP)) {
|
||||
mControllers.uiController.onStashedInAppChanged();
|
||||
}
|
||||
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAG_IN_APP)) {
|
||||
notifyStashChange(/* visible */ hasAnyFlag(FLAG_IN_APP),
|
||||
if (hasAnyFlag(changedFlags, FLAGS_STASHED_IN_APP | FLAGS_IN_APP)) {
|
||||
notifyStashChange(/* visible */ hasAnyFlag(FLAGS_IN_APP),
|
||||
/* stashed */ isStashedInApp());
|
||||
}
|
||||
if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_MANUAL)) {
|
||||
@@ -613,6 +615,7 @@ public class TaskbarStashController implements TaskbarControllers.LoggableTaskba
|
||||
str.add((flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0
|
||||
? "FLAG_IN_STASHED_LAUNCHER_STATE" : "");
|
||||
str.add((flags & FLAG_STASHED_IN_APP_ALL_APPS) != 0 ? "FLAG_STASHED_IN_APP_ALL_APPS" : "");
|
||||
str.add((flags & FLAG_IN_SETUP) != 0 ? "FLAG_IN_SETUP" : "");
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
|
||||
+3
-43
@@ -17,22 +17,17 @@ package com.android.launcher3.taskbar.allapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowInsets;
|
||||
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
||||
import com.android.launcher3.allapps.AlphabeticalAppsList;
|
||||
import com.android.launcher3.allapps.BaseAdapterProvider;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter;
|
||||
import com.android.launcher3.allapps.BaseAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
|
||||
/** All apps container accessible from taskbar. */
|
||||
public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<TaskbarAllAppsContext> {
|
||||
public class TaskbarAllAppsContainerView extends
|
||||
ActivityAllAppsContainerView<TaskbarAllAppsContext> {
|
||||
|
||||
public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
@@ -42,41 +37,6 @@ public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<Taskba
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SearchAdapterProvider<?> createMainAdapterProvider() {
|
||||
// Taskbar all apps does not yet support search, so this implementation is minimal.
|
||||
return new SearchAdapterProvider<TaskbarAllAppsContext>(mActivityContext) {
|
||||
@Override
|
||||
public boolean launchHighlightedItem() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getHighlightedItem() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RecyclerView.ItemDecoration getDecorator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isViewSupported(int viewType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindView(AllAppsGridAdapter.ViewHolder holder, int position) { }
|
||||
|
||||
@Override
|
||||
public AllAppsGridAdapter.ViewHolder onCreateViewHolder(LayoutInflater layoutInflater,
|
||||
ViewGroup parent, int viewType) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
|
||||
setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
|
||||
|
||||
@@ -32,6 +32,9 @@ import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.search.DefaultSearchAdapterProvider;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.popup.PopupDataProvider;
|
||||
@@ -154,6 +157,12 @@ class TaskbarAllAppsContext extends BaseTaskbarContext {
|
||||
@Override
|
||||
public void onPopupVisibilityChanged(boolean isVisible) {}
|
||||
|
||||
@Override
|
||||
public SearchAdapterProvider<?> createSearchAdapterProvider(
|
||||
ActivityAllAppsContainerView<?> appsView) {
|
||||
return new DefaultSearchAdapterProvider(this);
|
||||
}
|
||||
|
||||
/** Root drag layer for this context. */
|
||||
private static class TaskbarAllAppsDragLayer extends
|
||||
BaseDragLayer<TaskbarAllAppsContext> implements OnComputeInsetsListener {
|
||||
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (C) 2022 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.taskbar.allapps;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.SearchUiManager;
|
||||
|
||||
/** Empty search container for Taskbar All Apps used as a fallback if search is not supported. */
|
||||
public class TaskbarAllAppsFallbackSearchContainer extends View implements SearchUiManager {
|
||||
public TaskbarAllAppsFallbackSearchContainer(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TaskbarAllAppsFallbackSearchContainer(
|
||||
Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initializeSearch(ActivityAllAppsContainerView<?> containerView) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetSearch() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ExtendedEditText getEditText() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1273,8 +1273,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
HomeAnimationFactory homeAnimFactory =
|
||||
createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
|
||||
runningTaskTarget);
|
||||
mIsSwipingPipToHome = !mIsSwipeForStagedSplit
|
||||
&& homeAnimFactory.supportSwipePipToHome() && appCanEnterPip;
|
||||
mIsSwipingPipToHome = !mIsSwipeForStagedSplit && appCanEnterPip;
|
||||
final RectFSpringAnim[] windowAnim;
|
||||
if (mIsSwipingPipToHome) {
|
||||
mSwipePipToHomeAnimator = createWindowAnimationToPip(
|
||||
|
||||
@@ -50,12 +50,14 @@ import android.view.SurfaceControl;
|
||||
import android.view.SurfaceControl.Transaction;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.util.DisplayController;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
@@ -93,6 +95,8 @@ public class FallbackSwipeHandler extends
|
||||
private final Matrix mTmpMatrix = new Matrix();
|
||||
private float mMaxLauncherScale = 1;
|
||||
|
||||
private boolean mAppCanEnterPip;
|
||||
|
||||
public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
|
||||
boolean continuingLastGesture, InputConsumerController inputConsumer) {
|
||||
@@ -135,16 +139,27 @@ public class FallbackSwipeHandler extends
|
||||
protected HomeAnimationFactory createHomeAnimationFactory(ArrayList<IBinder> launchCookies,
|
||||
long duration, boolean isTargetTranslucent, boolean appCanEnterPip,
|
||||
RemoteAnimationTargetCompat runningTaskTarget) {
|
||||
mAppCanEnterPip = appCanEnterPip;
|
||||
if (appCanEnterPip) {
|
||||
return new FallbackPipToHomeAnimationFactory();
|
||||
}
|
||||
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
|
||||
startHomeIntent(mActiveAnimationFactory);
|
||||
return mActiveAnimationFactory;
|
||||
}
|
||||
|
||||
private void startHomeIntent(
|
||||
@Nullable FallbackHomeAnimationFactory gestureContractAnimationFactory) {
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
Intent intent = new Intent(mGestureState.getHomeIntent());
|
||||
mActiveAnimationFactory.addGestureContract(intent);
|
||||
if (gestureContractAnimationFactory != null) {
|
||||
gestureContractAnimationFactory.addGestureContract(intent);
|
||||
}
|
||||
try {
|
||||
mContext.startActivity(intent, options.toBundle());
|
||||
} catch (NullPointerException | ActivityNotFoundException | SecurityException e) {
|
||||
mContext.startActivity(createHomeIntent());
|
||||
}
|
||||
return mActiveAnimationFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -160,8 +175,19 @@ public class FallbackSwipeHandler extends
|
||||
|
||||
@Override
|
||||
protected void finishRecentsControllerToHome(Runnable callback) {
|
||||
final Runnable recentsCallback;
|
||||
if (mAppCanEnterPip) {
|
||||
// Make sure Launcher is resumed after auto-enter-pip transition to actually trigger
|
||||
// the PiP task appearing.
|
||||
recentsCallback = () -> {
|
||||
callback.run();
|
||||
startHomeIntent(null /* gestureContractAnimationFactory */);
|
||||
};
|
||||
} else {
|
||||
recentsCallback = callback;
|
||||
}
|
||||
mRecentsAnimationController.finish(
|
||||
false /* toRecents */, callback, true /* sendUserLeaveHint */);
|
||||
mAppCanEnterPip /* toRecents */, recentsCallback, true /* sendUserLeaveHint */);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -186,6 +212,17 @@ public class FallbackSwipeHandler extends
|
||||
}
|
||||
}
|
||||
|
||||
private class FallbackPipToHomeAnimationFactory extends HomeAnimationFactory {
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// copied from {@link LauncherSwipeHandlerV2.LauncherHomeAnimationFactory}
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
RecentsState.HOME, accuracy, StateAnimationConfig.SKIP_ALL_ANIMATIONS);
|
||||
}
|
||||
}
|
||||
|
||||
private class FallbackHomeAnimationFactory extends HomeAnimationFactory {
|
||||
private final Rect mTempRect = new Rect();
|
||||
private final TransformParams mHomeAlphaParams = new TransformParams();
|
||||
|
||||
@@ -284,10 +284,5 @@ public class LauncherSwipeHandlerV2 extends
|
||||
getViewIgnoredInWorkspaceRevealAnimation())
|
||||
.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportSwipePipToHome() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,14 +183,6 @@ public abstract class SwipeUpAnimationLogic implements
|
||||
|
||||
public void onCancel() { }
|
||||
|
||||
/**
|
||||
* @return {@code true} if this factory supports animating an Activity to PiP window on
|
||||
* swiping up to home.
|
||||
*/
|
||||
public boolean supportSwipePipToHome() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param progress The progress of the animation to the home screen.
|
||||
* @return The current alpha to set on the animating app window.
|
||||
|
||||
@@ -306,7 +306,7 @@ public final class DigitalWellBeingToast {
|
||||
|
||||
private void setBanner(@Nullable View view) {
|
||||
mBanner = view;
|
||||
if (view != null) {
|
||||
if (view != null && mTaskView.getRecentsView() != null) {
|
||||
setupAndAddBanner();
|
||||
setBannerOutline();
|
||||
}
|
||||
|
||||
@@ -271,7 +271,8 @@ public class GroupedTaskView extends TaskView {
|
||||
|
||||
getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
|
||||
taskIconHeight, mSnapshotView.getMeasuredWidth(), mSnapshotView.getMeasuredHeight(),
|
||||
isRtl, deviceProfile, mSplitBoundsConfig);
|
||||
getMeasuredHeight(), getMeasuredWidth(), isRtl, deviceProfile,
|
||||
mSplitBoundsConfig);
|
||||
}
|
||||
|
||||
private void updateSecondaryDwbPlacement() {
|
||||
|
||||
@@ -890,15 +890,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
if (confirmSecondSplitSelectApp()) {
|
||||
return;
|
||||
}
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
|
||||
RecentsView recentsView = getRecentsView();
|
||||
recentsView.switchToScreenshot(
|
||||
() -> recentsView.finishRecentsAnimation(true /* toRecents */,
|
||||
false /* shouldPip */,
|
||||
() -> showTaskMenu(iconView)));
|
||||
} else {
|
||||
showTaskMenu(iconView);
|
||||
}
|
||||
showTaskMenu(iconView);
|
||||
});
|
||||
iconView.setOnLongClickListener(v -> {
|
||||
requestDisallowInterceptTouchEvent(true);
|
||||
@@ -1008,8 +1000,11 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
// resetViewTransforms is called during Quickswitch scrolling.
|
||||
mDismissTranslationX = mTaskOffsetTranslationX =
|
||||
mTaskResistanceTranslationX = mSplitSelectTranslationX = mGridEndTranslationX = 0f;
|
||||
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY =
|
||||
mSplitSelectTranslationY = 0f;
|
||||
mDismissTranslationY = mTaskOffsetTranslationY = mTaskResistanceTranslationY = 0f;
|
||||
if (getRecentsView() == null || !getRecentsView().isSplitSelectionActive()) {
|
||||
mSplitSelectTranslationY = 0f;
|
||||
}
|
||||
|
||||
setSnapshotScale(1f);
|
||||
applyTranslationX();
|
||||
applyTranslationY();
|
||||
|
||||
@@ -16,14 +16,17 @@
|
||||
-->
|
||||
|
||||
<resources>
|
||||
<!-- Hotseat -->
|
||||
<!-- Hotseat -->
|
||||
<dimen name="spring_loaded_hotseat_top_margin">44dp</dimen>
|
||||
|
||||
<!-- Dynamic grid -->
|
||||
<!-- Dynamic grid -->
|
||||
<dimen name="dynamic_grid_edge_margin">11.33dp</dimen>
|
||||
<dimen name="cell_layout_padding">11.33dp</dimen>
|
||||
|
||||
<!-- Dragging -->
|
||||
<!-- Dragging -->
|
||||
<dimen name="drop_target_top_margin">0dp</dimen>
|
||||
<dimen name="drop_target_bottom_margin">16dp</dimen>
|
||||
|
||||
<!-- AllApps -->
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">52dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<!-- AllApps -->
|
||||
<dimen name="all_apps_search_bar_content_overlap">0dp</dimen>
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">46dp</dimen>
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">48dp</dimen>
|
||||
|
||||
<!-- Fast scroll -->
|
||||
<dimen name="fastscroll_popup_width">75dp</dimen>
|
||||
|
||||
@@ -18,13 +18,20 @@
|
||||
<!-- Dragging-->
|
||||
<dimen name="drop_target_top_margin">0dp</dimen>
|
||||
<dimen name="drop_target_bottom_margin">32dp</dimen>
|
||||
|
||||
<!-- Dynamic grid -->
|
||||
<dimen name="dynamic_grid_edge_margin">21.93dp</dimen>
|
||||
<dimen name="cell_layout_padding">29.33dp</dimen>
|
||||
|
||||
<!-- Hotseat -->
|
||||
<dimen name="spring_loaded_hotseat_top_margin">64dp</dimen>
|
||||
|
||||
<!-- AllApps -->
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">32dp</dimen>
|
||||
|
||||
<!-- Widget picker-->
|
||||
<dimen name="widget_list_horizontal_margin">49dp</dimen>
|
||||
|
||||
<!-- Bottom sheet-->
|
||||
<dimen name="bottom_sheet_extra_top_padding">0dp</dimen>
|
||||
</resources>
|
||||
|
||||
@@ -16,10 +16,12 @@
|
||||
|
||||
<resources>
|
||||
<!-- AllApps -->
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">65dp</dimen>
|
||||
<dimen name="all_apps_bottom_sheet_horizontal_padding">28dp</dimen>
|
||||
|
||||
<!-- Dynamic grid -->
|
||||
<dimen name="dynamic_grid_edge_margin">27.59dp</dimen>
|
||||
<dimen name="cell_layout_padding">36dp</dimen>
|
||||
|
||||
<!-- Dragging -->
|
||||
<dimen name="drop_target_text_size">20sp</dimen>
|
||||
<dimen name="dynamic_grid_drop_target_size">72dp</dimen>
|
||||
@@ -28,6 +30,7 @@
|
||||
<dimen name="drop_target_button_gap">32dp</dimen>
|
||||
<dimen name="drop_target_top_margin">32dp</dimen>
|
||||
<dimen name="drop_target_bottom_margin">32dp</dimen>
|
||||
|
||||
<!-- Hotseat -->
|
||||
<dimen name="spring_loaded_hotseat_top_margin">164dp</dimen>
|
||||
|
||||
|
||||
@@ -241,9 +241,28 @@
|
||||
if not specified -->
|
||||
<attr name="borderSpaceTwoPanelLandscapeVertical" format="float" />
|
||||
|
||||
<!-- These min cell values are only used if GridDisplayOption#isScalable is true -->
|
||||
<!-- defaults to minCellHeight, if not specified -->
|
||||
<attr name="allAppsCellHeight" format="float" />
|
||||
<!-- defaults to minCellWidth, if not specified -->
|
||||
<attr name="allAppsCellWidth" format="float" />
|
||||
<!-- defaults to allAppsCellHeight, if not specified -->
|
||||
<attr name="allAppsCellHeightLandscape" format="float" />
|
||||
<!-- defaults to allAppsCellWidth, if not specified -->
|
||||
<attr name="allAppsCellWidthLandscape" format="float" />
|
||||
<!-- defaults to allAppsCellHeight, if not specified -->
|
||||
<attr name="allAppsCellHeightTwoPanelPortrait" format="float" />
|
||||
<!-- defaults to allAppsCellWidth, if not specified -->
|
||||
<attr name="allAppsCellWidthTwoPanelPortrait" format="float" />
|
||||
<!-- defaults to allAppsCellHeight, if not specified -->
|
||||
<attr name="allAppsCellHeightTwoPanelLandscape" format="float" />
|
||||
<!-- defaults to allAppsCellWidth, if not specified -->
|
||||
<attr name="allAppsCellWidthTwoPanelLandscape" format="float" />
|
||||
<!-- defaults to borderSpace, if not specified -->
|
||||
<attr name="allAppsBorderSpace" format="float" />
|
||||
<!-- defaults to allAppsBorderSpace, if not specified -->
|
||||
<attr name="allAppsBorderSpaceLandscape" format="float" />
|
||||
<!-- defaults to allAppsBorderSpace, if not specified -->
|
||||
<attr name="allAppsBorderSpaceTwoPanelPortrait" format="float" />
|
||||
<!-- defaults to allAppsBorderSpace, if not specified -->
|
||||
<attr name="allAppsBorderSpaceTwoPanelLandscape" format="float" />
|
||||
|
||||
@@ -216,6 +216,7 @@ public abstract class BaseDraggingActivity extends BaseActivity
|
||||
* Creates and returns {@link SearchAdapterProvider} for build variant specific search result
|
||||
* views
|
||||
*/
|
||||
@Override
|
||||
public SearchAdapterProvider<?> createSearchAdapterProvider(
|
||||
ActivityAllAppsContainerView<?> allApps) {
|
||||
return new DefaultSearchAdapterProvider(this);
|
||||
|
||||
@@ -93,7 +93,7 @@ public class CellLayout extends ViewGroup {
|
||||
private int mFixedCellWidth;
|
||||
private int mFixedCellHeight;
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private final Point mBorderSpace;
|
||||
private Point mBorderSpace;
|
||||
|
||||
@ViewDebug.ExportedProperty(category = "launcher")
|
||||
private int mCountX;
|
||||
@@ -239,22 +239,7 @@ public class CellLayout extends ViewGroup {
|
||||
mActivity = ActivityContext.lookupContext(context);
|
||||
DeviceProfile deviceProfile = mActivity.getDeviceProfile();
|
||||
|
||||
switch (mContainerType) {
|
||||
case FOLDER:
|
||||
mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
|
||||
break;
|
||||
case HOTSEAT:
|
||||
mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
|
||||
deviceProfile.hotseatBorderSpace);
|
||||
break;
|
||||
case WORKSPACE:
|
||||
default:
|
||||
mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
|
||||
break;
|
||||
}
|
||||
|
||||
mCellWidth = mCellHeight = -1;
|
||||
mFixedCellWidth = mFixedCellHeight = -1;
|
||||
resetCellSizeInternal(deviceProfile);
|
||||
|
||||
mCountX = deviceProfile.inv.numColumns;
|
||||
mCountY = deviceProfile.inv.numRows;
|
||||
@@ -379,6 +364,12 @@ public class CellLayout extends ViewGroup {
|
||||
return mShortcutsAndWidgets.getLayerType() == LAYER_TYPE_HARDWARE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change sizes of cells
|
||||
*
|
||||
* @param width the new width of the cells
|
||||
* @param height the new height of the cells
|
||||
*/
|
||||
public void setCellDimensions(int width, int height) {
|
||||
mFixedCellWidth = mCellWidth = width;
|
||||
mFixedCellHeight = mCellHeight = height;
|
||||
@@ -386,6 +377,33 @@ public class CellLayout extends ViewGroup {
|
||||
mBorderSpace);
|
||||
}
|
||||
|
||||
private void resetCellSizeInternal(DeviceProfile deviceProfile) {
|
||||
switch (mContainerType) {
|
||||
case FOLDER:
|
||||
mBorderSpace = new Point(deviceProfile.folderCellLayoutBorderSpacePx);
|
||||
break;
|
||||
case HOTSEAT:
|
||||
mBorderSpace = new Point(deviceProfile.hotseatBorderSpace,
|
||||
deviceProfile.hotseatBorderSpace);
|
||||
break;
|
||||
case WORKSPACE:
|
||||
default:
|
||||
mBorderSpace = new Point(deviceProfile.cellLayoutBorderSpacePx);
|
||||
break;
|
||||
}
|
||||
|
||||
mCellWidth = mCellHeight = -1;
|
||||
mFixedCellWidth = mFixedCellHeight = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the cell sizes and border space
|
||||
*/
|
||||
public void resetCellSize(DeviceProfile deviceProfile) {
|
||||
resetCellSizeInternal(deviceProfile);
|
||||
requestLayout();
|
||||
}
|
||||
|
||||
public void setGridSize(int x, int y) {
|
||||
mCountX = x;
|
||||
mCountY = y;
|
||||
|
||||
@@ -624,14 +624,15 @@ public class DeviceProfile {
|
||||
+ textHeight + (topBottomPadding * 2);
|
||||
}
|
||||
|
||||
private void updateAllAppsWidth(Resources res) {
|
||||
private void updateAllAppsContainerWidth(Resources res) {
|
||||
int cellLayoutHorizontalPadding =
|
||||
(cellLayoutPaddingPx.left + cellLayoutPaddingPx.right) / 2;
|
||||
if (isTablet) {
|
||||
allAppsLeftRightPadding = res.getDimensionPixelSize(
|
||||
R.dimen.all_apps_bottom_sheet_horizontal_padding) + cellLayoutHorizontalPadding;
|
||||
allAppsLeftRightPadding =
|
||||
res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding);
|
||||
|
||||
int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
|
||||
+ (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1))
|
||||
+ (allAppsBorderSpacePx.x * (numShownAllAppsColumns - 1))
|
||||
+ allAppsLeftRightPadding * 2;
|
||||
allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
|
||||
} else {
|
||||
@@ -755,24 +756,26 @@ public class DeviceProfile {
|
||||
* Updates the iconSize for allApps* variants.
|
||||
*/
|
||||
public void updateAllAppsIconSize(float scale, Resources res) {
|
||||
if (numShownAllAppsColumns != inv.numColumns) {
|
||||
//TODO(b/218638090): remove the tablet condition once we have phone specs
|
||||
if (isScalableGrid && isTablet) {
|
||||
allAppsIconSizePx =
|
||||
pxFromDp(inv.allAppsIconSize[mTypeIndex], mMetrics);
|
||||
allAppsIconTextSizePx =
|
||||
pxFromSp(inv.allAppsIconTextSize[mTypeIndex], mMetrics);
|
||||
allAppsIconDrawablePaddingPx = iconDrawablePaddingOriginalPx;
|
||||
autoResizeAllAppsCells();
|
||||
allAppsCellWidthPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].x, mMetrics, scale);
|
||||
allAppsCellHeightPx = pxFromDp(inv.allAppsCellSize[mTypeIndex].y, mMetrics, scale);
|
||||
} else {
|
||||
float invIconSizeDp = inv.iconSize[mTypeIndex];
|
||||
float invIconTextSizeSp = inv.iconTextSize[mTypeIndex];
|
||||
allAppsIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
|
||||
allAppsIconTextSizePx = (int) (pxFromSp(invIconTextSizeSp, mMetrics) * scale);
|
||||
allAppsIconDrawablePaddingPx = (int) (iconDrawablePaddingOriginalPx * scale);
|
||||
allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
|
||||
allAppsCellHeightPx = getCellSize().y;
|
||||
}
|
||||
|
||||
allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
|
||||
updateAllAppsWidth(res);
|
||||
updateAllAppsContainerWidth(res);
|
||||
if (isVerticalBarLayout()) {
|
||||
hideWorkspaceLabelsIfNotEnoughSpace();
|
||||
}
|
||||
@@ -998,7 +1001,7 @@ public class DeviceProfile {
|
||||
additionalLeftSpace = qsbWidth + hotseatBorderSpace;
|
||||
}
|
||||
|
||||
int hotseatTopDiff = hotseatHeight - taskbarOffset;
|
||||
int hotseatTopPadding = hotseatHeight - taskbarOffset - hotseatCellHeightPx;
|
||||
|
||||
int endOffset = ApiWrapper.getHotseatEndOffset(context);
|
||||
int requiredWidth = iconSizePx * numShownHotseatIcons
|
||||
@@ -1007,7 +1010,7 @@ public class DeviceProfile {
|
||||
|
||||
int hotseatSize = Math.min(requiredWidth, availableWidthPx - endOffset);
|
||||
int sideSpacing = (availableWidthPx - hotseatSize) / 2;
|
||||
mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopDiff, sideSpacing,
|
||||
mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopPadding, sideSpacing,
|
||||
taskbarOffset);
|
||||
|
||||
if (endOffset > sideSpacing) {
|
||||
@@ -1223,6 +1226,7 @@ public class DeviceProfile {
|
||||
allAppsIconDrawablePaddingPx));
|
||||
writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx));
|
||||
writer.println(prefix + pxToDpStr("allAppsCellWidthPx", allAppsCellWidthPx));
|
||||
writer.println(prefix + pxToDpStr("allAppsBorderSpacePx", allAppsBorderSpacePx.x));
|
||||
writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns);
|
||||
writer.println(prefix + pxToDpStr("allAppsLeftRightPadding", allAppsLeftRightPadding));
|
||||
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
|
||||
|
||||
@@ -84,6 +84,7 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
removeAllViewsInLayout();
|
||||
mHasVerticalHotseat = hasVerticalHotseat;
|
||||
DeviceProfile dp = mActivity.getDeviceProfile();
|
||||
resetCellSize(dp);
|
||||
if (hasVerticalHotseat) {
|
||||
setGridSize(1, dp.numShownHotseatIcons);
|
||||
} else {
|
||||
@@ -110,10 +111,9 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
mQsb.setVisibility(View.VISIBLE);
|
||||
lp.gravity = Gravity.BOTTOM;
|
||||
lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
lp.height = (grid.isTaskbarPresent
|
||||
lp.height = grid.isTaskbarPresent
|
||||
? grid.workspacePadding.bottom
|
||||
: grid.hotseatBarSizePx)
|
||||
+ (grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom);
|
||||
: grid.hotseatBarSizePx + insets.bottom;
|
||||
}
|
||||
|
||||
Rect padding = grid.getHotseatLayoutPadding(getContext());
|
||||
|
||||
@@ -128,6 +128,7 @@ public class InvariantDeviceProfile {
|
||||
|
||||
public float[] horizontalMargin;
|
||||
|
||||
public PointF[] allAppsCellSize;
|
||||
public float[] allAppsIconSize;
|
||||
public float[] allAppsIconTextSize;
|
||||
public PointF[] allAppsBorderSpaces;
|
||||
@@ -357,6 +358,7 @@ public class InvariantDeviceProfile {
|
||||
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
|
||||
? closestProfile.numDatabaseAllAppsColumns : closestProfile.numAllAppsColumns;
|
||||
|
||||
allAppsCellSize = displayOption.allAppsCellSize;
|
||||
allAppsBorderSpaces = displayOption.allAppsBorderSpaces;
|
||||
allAppsIconSize = displayOption.allAppsIconSizes;
|
||||
allAppsIconTextSize = displayOption.allAppsIconTextSizes;
|
||||
@@ -798,6 +800,7 @@ public class InvariantDeviceProfile {
|
||||
private final float[] iconSizes = new float[COUNT_SIZES];
|
||||
private final float[] textSizes = new float[COUNT_SIZES];
|
||||
|
||||
private final PointF[] allAppsCellSize = new PointF[COUNT_SIZES];
|
||||
private final float[] allAppsIconSizes = new float[COUNT_SIZES];
|
||||
private final float[] allAppsIconTextSizes = new float[COUNT_SIZES];
|
||||
private final PointF[] allAppsBorderSpaces = new PointF[COUNT_SIZES];
|
||||
@@ -873,9 +876,35 @@ public class InvariantDeviceProfile {
|
||||
|
||||
folderBorderSpace = borderSpace;
|
||||
|
||||
x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidth,
|
||||
minCellSize[INDEX_DEFAULT].x);
|
||||
y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeight,
|
||||
minCellSize[INDEX_DEFAULT].y);
|
||||
allAppsCellSize[INDEX_DEFAULT] = new PointF(x, y);
|
||||
|
||||
x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthLandscape,
|
||||
allAppsCellSize[INDEX_DEFAULT].x);
|
||||
y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightLandscape,
|
||||
allAppsCellSize[INDEX_DEFAULT].y);
|
||||
allAppsCellSize[INDEX_LANDSCAPE] = new PointF(x, y);
|
||||
|
||||
x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelPortrait,
|
||||
allAppsCellSize[INDEX_DEFAULT].x);
|
||||
y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelPortrait,
|
||||
allAppsCellSize[INDEX_DEFAULT].y);
|
||||
allAppsCellSize[INDEX_TWO_PANEL_PORTRAIT] = new PointF(x, y);
|
||||
|
||||
x = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellWidthTwoPanelLandscape,
|
||||
allAppsCellSize[INDEX_DEFAULT].x);
|
||||
y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsCellHeightTwoPanelLandscape,
|
||||
allAppsCellSize[INDEX_DEFAULT].y);
|
||||
allAppsCellSize[INDEX_TWO_PANEL_LANDSCAPE] = new PointF(x, y);
|
||||
|
||||
x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpace,
|
||||
borderSpace);
|
||||
allAppsBorderSpaces[INDEX_DEFAULT] = new PointF(x, y);
|
||||
x = y = a.getFloat(R.styleable.ProfileDisplayOption_allAppsBorderSpaceLandscape,
|
||||
allAppsBorderSpaces[INDEX_DEFAULT].x);
|
||||
allAppsBorderSpaces[INDEX_LANDSCAPE] = new PointF(x, y);
|
||||
x = y = a.getFloat(
|
||||
R.styleable.ProfileDisplayOption_allAppsBorderSpaceTwoPanelPortrait,
|
||||
@@ -971,6 +1000,7 @@ public class InvariantDeviceProfile {
|
||||
textSizes[i] = 0;
|
||||
borderSpaces[i] = new PointF();
|
||||
minCellSize[i] = new PointF();
|
||||
allAppsCellSize[i] = new PointF();
|
||||
allAppsIconSizes[i] = 0;
|
||||
allAppsIconTextSizes[i] = 0;
|
||||
allAppsBorderSpaces[i] = new PointF();
|
||||
@@ -987,6 +1017,8 @@ public class InvariantDeviceProfile {
|
||||
minCellSize[i].y *= w;
|
||||
horizontalMargin[i] *= w;
|
||||
hotseatBorderSpaces[i] *= w;
|
||||
allAppsCellSize[i].x *= w;
|
||||
allAppsCellSize[i].y *= w;
|
||||
allAppsIconSizes[i] *= w;
|
||||
allAppsIconTextSizes[i] *= w;
|
||||
allAppsBorderSpaces[i].x *= w;
|
||||
@@ -1008,6 +1040,8 @@ public class InvariantDeviceProfile {
|
||||
minCellSize[i].y += p.minCellSize[i].y;
|
||||
horizontalMargin[i] += p.horizontalMargin[i];
|
||||
hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
|
||||
allAppsCellSize[i].x += p.allAppsCellSize[i].x;
|
||||
allAppsCellSize[i].y += p.allAppsCellSize[i].y;
|
||||
allAppsIconSizes[i] += p.allAppsIconSizes[i];
|
||||
allAppsIconTextSizes[i] += p.allAppsIconTextSizes[i];
|
||||
allAppsBorderSpaces[i].x += p.allAppsBorderSpaces[i].x;
|
||||
|
||||
@@ -26,12 +26,13 @@ import android.widget.RelativeLayout;
|
||||
import androidx.core.graphics.ColorUtils;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.PackageManagerHelper;
|
||||
import com.android.launcher3.views.AppLauncher;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -40,8 +41,8 @@ import java.util.Objects;
|
||||
*
|
||||
* @param <T> Type of context inflating all apps.
|
||||
*/
|
||||
public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extends
|
||||
BaseAllAppsContainerView<T> {
|
||||
public class ActivityAllAppsContainerView<T extends Context & AppLauncher
|
||||
& DeviceProfileListenable> extends BaseAllAppsContainerView<T> {
|
||||
|
||||
protected SearchUiManager mSearchUiManager;
|
||||
/**
|
||||
@@ -103,13 +104,8 @@ public class ActivityAllAppsContainerView<T extends BaseDraggingActivity> extend
|
||||
}
|
||||
}
|
||||
|
||||
/** Handles selection on focused view and returns {@code true} on success. */
|
||||
public boolean launchHighlightedItem() {
|
||||
return getMainAdapterProvider().launchHighlightedItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SearchAdapterProvider<?> createMainAdapterProvider() {
|
||||
protected final SearchAdapterProvider<?> createMainAdapterProvider() {
|
||||
return mActivityContext.createSearchAdapterProvider(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,13 @@ import android.view.inputmethod.EditorInfo;
|
||||
import android.widget.TextView;
|
||||
import android.widget.TextView.OnEditorActionListener;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.search.SearchAlgorithm;
|
||||
import com.android.launcher3.search.SearchCallback;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
/**
|
||||
* An interface to a search box that AllApps can command.
|
||||
@@ -45,7 +44,7 @@ public class AllAppsSearchBarController
|
||||
implements TextWatcher, OnEditorActionListener, ExtendedEditText.OnBackKeyListener,
|
||||
OnFocusChangeListener {
|
||||
|
||||
protected BaseDraggingActivity mLauncher;
|
||||
protected ActivityContext mLauncher;
|
||||
protected SearchCallback<AdapterItem> mCallback;
|
||||
protected ExtendedEditText mInput;
|
||||
protected String mQuery;
|
||||
@@ -62,7 +61,7 @@ public class AllAppsSearchBarController
|
||||
*/
|
||||
public final void initialize(
|
||||
SearchAlgorithm<AdapterItem> searchAlgorithm, ExtendedEditText input,
|
||||
BaseDraggingActivity launcher, SearchCallback<AdapterItem> callback) {
|
||||
ActivityContext launcher, SearchCallback<AdapterItem> callback) {
|
||||
mCallback = callback;
|
||||
mLauncher = launcher;
|
||||
|
||||
@@ -125,7 +124,7 @@ public class AllAppsSearchBarController
|
||||
mLauncher.getStatsLogManager().logger()
|
||||
.log(LAUNCHER_ALLAPPS_FOCUSED_ITEM_SELECTED_WITH_IME);
|
||||
// selectFocusedView should return SearchTargetEvent that is passed onto onClick
|
||||
return Launcher.getLauncher(mLauncher).getAppsView().launchHighlightedItem();
|
||||
return mLauncher.getAppsView().getMainAdapterProvider().launchHighlightedItem();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup.MarginLayoutParams;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.ExtendedEditText;
|
||||
import com.android.launcher3.Insettable;
|
||||
@@ -43,6 +42,7 @@ import com.android.launcher3.allapps.AlphabeticalAppsList;
|
||||
import com.android.launcher3.allapps.BaseAllAppsAdapter.AdapterItem;
|
||||
import com.android.launcher3.allapps.SearchUiManager;
|
||||
import com.android.launcher3.search.SearchCallback;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -53,7 +53,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText
|
||||
implements SearchUiManager, SearchCallback<AdapterItem>,
|
||||
AllAppsStore.OnUpdateListener, Insettable {
|
||||
|
||||
private final BaseDraggingActivity mLauncher;
|
||||
private final ActivityContext mLauncher;
|
||||
private final AllAppsSearchBarController mSearchBarController;
|
||||
private final SpannableStringBuilder mSearchQueryBuilder;
|
||||
|
||||
@@ -74,7 +74,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText
|
||||
public AppsSearchContainerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
|
||||
mLauncher = BaseDraggingActivity.fromContext(context);
|
||||
mLauncher = ActivityContext.lookupContext(context);
|
||||
mSearchBarController = new AllAppsSearchBarController();
|
||||
|
||||
mSearchQueryBuilder = new SpannableStringBuilder();
|
||||
@@ -134,7 +134,7 @@ public class AppsSearchContainerLayout extends ExtendedEditText
|
||||
mApps = appsView.getApps();
|
||||
mAppsView = appsView;
|
||||
mSearchBarController.initialize(
|
||||
new DefaultAppSearchAlgorithm(mLauncher),
|
||||
new DefaultAppSearchAlgorithm(getContext()),
|
||||
this, mLauncher, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,20 +23,20 @@ import android.view.ViewGroup;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.BubbleTextView;
|
||||
import com.android.launcher3.allapps.AllAppsGridAdapter;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.views.AppLauncher;
|
||||
|
||||
/**
|
||||
* Provides views for local search results
|
||||
* Provides views for local search results.
|
||||
*/
|
||||
public class DefaultSearchAdapterProvider extends SearchAdapterProvider<BaseDraggingActivity> {
|
||||
public class DefaultSearchAdapterProvider extends SearchAdapterProvider<AppLauncher> {
|
||||
|
||||
private final RecyclerView.ItemDecoration mDecoration;
|
||||
private View mHighlightedView;
|
||||
|
||||
public DefaultSearchAdapterProvider(BaseDraggingActivity launcher) {
|
||||
public DefaultSearchAdapterProvider(AppLauncher launcher) {
|
||||
super(launcher);
|
||||
mDecoration = new RecyclerView.ItemDecoration() {
|
||||
@Override
|
||||
|
||||
@@ -258,6 +258,9 @@ public final class FeatureFlags {
|
||||
"ENABLE_NEW_MIGRATION_LOGIC", true,
|
||||
"Enable the new grid migration logic, keeping pages when src < dest");
|
||||
|
||||
public static final BooleanFlag ENABLE_ONE_SEARCH_MOTION = new DeviceFlag(
|
||||
"ENABLE_ONE_SEARCH_MOTION", false, "Enables animations in OneSearch.");
|
||||
|
||||
public static void initialize(Context context) {
|
||||
synchronized (sDebugFlags) {
|
||||
for (DebugFlag flag : sDebugFlags) {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.launcher3.icons;
|
||||
|
||||
import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT;
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
|
||||
import static com.android.launcher3.widget.WidgetSections.NO_CATEGORY;
|
||||
@@ -340,14 +341,15 @@ public class IconCache extends BaseIconCache {
|
||||
Map<Pair<UserHandle, Boolean>, List<IconRequestInfo<T>>> iconLoadSubsectionsMap =
|
||||
iconRequestInfos.stream()
|
||||
.filter(iconRequest -> {
|
||||
if (iconRequest.itemInfo.getTargetComponent() != null) {
|
||||
return true;
|
||||
if (iconRequest.itemInfo.getTargetComponent() == null) {
|
||||
Log.i(TAG,
|
||||
"Skipping Item info with null component name: "
|
||||
+ iconRequest.itemInfo);
|
||||
iconRequest.itemInfo.bitmap = getDefaultIcon(
|
||||
iconRequest.itemInfo.user);
|
||||
return false;
|
||||
}
|
||||
Log.i(TAG,
|
||||
"Skipping Item info with null component name: "
|
||||
+ iconRequest.itemInfo);
|
||||
iconRequest.itemInfo.bitmap = getDefaultIcon(iconRequest.itemInfo.user);
|
||||
return false;
|
||||
return true;
|
||||
})
|
||||
.collect(groupingBy(iconRequest ->
|
||||
Pair.create(iconRequest.itemInfo.user, iconRequest.useLowResIcon)));
|
||||
@@ -356,6 +358,17 @@ public class IconCache extends BaseIconCache {
|
||||
iconLoadSubsectionsMap.forEach((sectionKey, filteredList) -> {
|
||||
Map<ComponentName, List<IconRequestInfo<T>>> duplicateIconRequestsMap =
|
||||
filteredList.stream()
|
||||
.filter(iconRequest -> {
|
||||
// Filter out icons that should not share the same bitmap and title
|
||||
if (iconRequest.itemInfo.itemType == ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
Log.e(TAG,
|
||||
"Skipping Item info for deep shortcut: "
|
||||
+ iconRequest.itemInfo,
|
||||
new IllegalStateException());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
})
|
||||
.collect(groupingBy(iconRequest ->
|
||||
iconRequest.itemInfo.getTargetComponent()));
|
||||
|
||||
|
||||
@@ -615,7 +615,13 @@ public class LoaderTask implements Runnable {
|
||||
}
|
||||
|
||||
if (info != null) {
|
||||
iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon));
|
||||
if (info.itemType
|
||||
!= LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {
|
||||
// Skip deep shortcuts; their title and icons have already been
|
||||
// loaded above.
|
||||
iconRequestInfos.add(
|
||||
c.createIconRequestInfo(info, useLowResIcon));
|
||||
}
|
||||
|
||||
c.applyCommonProperties(info);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.launcher3.touch;
|
||||
|
||||
import static android.view.Gravity.BOTTOM;
|
||||
import static android.view.Gravity.CENTER_VERTICAL;
|
||||
import static android.view.Gravity.END;
|
||||
import static android.view.Gravity.START;
|
||||
@@ -414,14 +415,17 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
@Override
|
||||
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
|
||||
StagedSplitBounds splitInfo, int desiredStagePosition) {
|
||||
float diff;
|
||||
float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
|
||||
float topLeftTaskPercent = splitInfo.appsStackedVertically
|
||||
? splitInfo.topTaskPercent
|
||||
: splitInfo.leftTaskPercent;
|
||||
float dividerBarPercent = splitInfo.appsStackedVertically
|
||||
? splitInfo.dividerHeightPercent
|
||||
: splitInfo.dividerWidthPercent;
|
||||
|
||||
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
|
||||
diff = outRect.height() * (1f - splitInfo.leftTaskPercent) + horizontalDividerDiff;
|
||||
outRect.bottom -= diff;
|
||||
outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
|
||||
} else {
|
||||
diff = outRect.height() * splitInfo.leftTaskPercent + horizontalDividerDiff;
|
||||
outRect.top += diff;
|
||||
outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -468,18 +472,42 @@ public class LandscapePagedViewHandler implements PagedOrientationHandler {
|
||||
@Override
|
||||
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
|
||||
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
|
||||
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
|
||||
DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
FrameLayout.LayoutParams primaryIconParams =
|
||||
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
|
||||
FrameLayout.LayoutParams secondaryIconParams =
|
||||
new FrameLayout.LayoutParams(primaryIconParams);
|
||||
|
||||
primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
|
||||
// We calculate the "midpoint" of the thumbnail area, and place the icons there.
|
||||
// This is the place where the thumbnail area splits by default, in a near-50/50 split.
|
||||
// It is usually not exactly 50/50, due to insets/screen cutouts.
|
||||
int fullscreenInsetThickness = deviceProfile.getInsets().top;
|
||||
int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness)
|
||||
/ 2);
|
||||
float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
|
||||
float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
|
||||
int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
|
||||
int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
|
||||
int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
|
||||
int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
|
||||
|
||||
primaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
|
||||
secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
|
||||
primaryIconView.setTranslationX(0);
|
||||
primaryIconView.setTranslationY(-(taskIconHeight / 2f));
|
||||
secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
|
||||
secondaryIconView.setTranslationX(0);
|
||||
secondaryIconView.setTranslationY(taskIconHeight / 2f);
|
||||
if (splitConfig.initiatedFromSeascape) {
|
||||
// if the split was initiated from seascape,
|
||||
// the task on the right (secondary) is slightly larger
|
||||
primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
|
||||
secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
|
||||
+ taskIconHeight);
|
||||
} else {
|
||||
// if not,
|
||||
// the task on the left (primary) is slightly larger
|
||||
primaryIconView.setTranslationY(-bottomToMidpointOffset);
|
||||
secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
|
||||
}
|
||||
|
||||
primaryIconView.setLayoutParams(primaryIconParams);
|
||||
secondaryIconView.setLayoutParams(secondaryIconParams);
|
||||
|
||||
@@ -146,7 +146,8 @@ public interface PagedOrientationHandler {
|
||||
int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
|
||||
void setSplitIconParams(View primaryIconView, View secondaryIconView,
|
||||
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
|
||||
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
|
||||
int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
|
||||
DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
|
||||
|
||||
/*
|
||||
* The following two methods try to center the TaskMenuView in landscape by finding the center
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.android.launcher3.touch;
|
||||
|
||||
import static android.view.Gravity.BOTTOM;
|
||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
import static android.view.Gravity.END;
|
||||
import static android.view.Gravity.START;
|
||||
import static android.view.Gravity.TOP;
|
||||
import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
|
||||
@@ -334,8 +335,14 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
// Set translations
|
||||
if (deviceProfile.isLandscape) {
|
||||
if (desiredTaskId == splitBounds.rightBottomTaskId) {
|
||||
translationX = ((taskViewWidth * splitBounds.leftTaskPercent)
|
||||
+ (taskViewWidth * splitBounds.dividerWidthPercent));
|
||||
float leftTopTaskPercent = splitBounds.appsStackedVertically
|
||||
? splitBounds.topTaskPercent
|
||||
: splitBounds.leftTaskPercent;
|
||||
float dividerThicknessPercent = splitBounds.appsStackedVertically
|
||||
? splitBounds.dividerHeightPercent
|
||||
: splitBounds.dividerWidthPercent;
|
||||
translationX = ((taskViewWidth * leftTopTaskPercent)
|
||||
+ (taskViewWidth * dividerThicknessPercent));
|
||||
}
|
||||
} else {
|
||||
if (desiredTaskId == splitBounds.leftTopTaskId) {
|
||||
@@ -488,19 +495,24 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
|
||||
StagedSplitBounds splitInfo, int desiredStagePosition) {
|
||||
boolean isLandscape = dp.isLandscape;
|
||||
float topLeftTaskPercent = splitInfo.appsStackedVertically
|
||||
? splitInfo.topTaskPercent
|
||||
: splitInfo.leftTaskPercent;
|
||||
float dividerBarPercent = splitInfo.appsStackedVertically
|
||||
? splitInfo.dividerHeightPercent
|
||||
: splitInfo.dividerWidthPercent;
|
||||
|
||||
if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
|
||||
if (isLandscape) {
|
||||
outRect.right = outRect.left + (int) (outRect.width() * splitInfo.leftTaskPercent);
|
||||
outRect.right = outRect.left + (int) (outRect.width() * topLeftTaskPercent);
|
||||
} else {
|
||||
outRect.bottom = outRect.top + (int) (outRect.height() * splitInfo.topTaskPercent);
|
||||
outRect.bottom = outRect.top + (int) (outRect.height() * topLeftTaskPercent);
|
||||
}
|
||||
} else {
|
||||
if (isLandscape) {
|
||||
outRect.left += (int) (outRect.width() *
|
||||
(splitInfo.leftTaskPercent + splitInfo.dividerWidthPercent));
|
||||
outRect.left += (int) (outRect.width() * (topLeftTaskPercent + dividerBarPercent));
|
||||
} else {
|
||||
outRect.top += (int) (outRect.height() *
|
||||
(splitInfo.topTaskPercent + splitInfo.dividerHeightPercent));
|
||||
outRect.top += (int) (outRect.height() * (topLeftTaskPercent + dividerBarPercent));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -559,18 +571,70 @@ public class PortraitPagedViewHandler implements PagedOrientationHandler {
|
||||
@Override
|
||||
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
|
||||
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
|
||||
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
|
||||
DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
FrameLayout.LayoutParams primaryIconParams =
|
||||
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
|
||||
FrameLayout.LayoutParams secondaryIconParams =
|
||||
new FrameLayout.LayoutParams(primaryIconParams);
|
||||
|
||||
primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
|
||||
// shifts icon half a width left (height is used conveniently here since icons are square)
|
||||
primaryIconView.setTranslationX(-(taskIconHeight / 2f));
|
||||
if (deviceProfile.isLandscape) {
|
||||
// We calculate the "midpoint" of the thumbnail area, and place the icons there.
|
||||
// This is the place where the thumbnail area splits by default, in a near-50/50 split.
|
||||
// It is usually not exactly 50/50, due to insets/screen cutouts.
|
||||
int fullscreenInsetThickness = deviceProfile.isSeascape()
|
||||
? deviceProfile.getInsets().right
|
||||
: deviceProfile.getInsets().left;
|
||||
int fullscreenMidpointFromBottom = ((deviceProfile.widthPx
|
||||
- fullscreenInsetThickness) / 2);
|
||||
float midpointFromBottomPct = (float) fullscreenMidpointFromBottom
|
||||
/ deviceProfile.widthPx;
|
||||
float insetPct = (float) fullscreenInsetThickness / deviceProfile.widthPx;
|
||||
int spaceAboveSnapshots = 0;
|
||||
int overviewThumbnailAreaThickness = groupedTaskViewWidth - spaceAboveSnapshots;
|
||||
int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness
|
||||
* midpointFromBottomPct);
|
||||
int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
|
||||
|
||||
if (deviceProfile.isSeascape()) {
|
||||
primaryIconParams.gravity = TOP | (isRtl ? END : START);
|
||||
secondaryIconParams.gravity = TOP | (isRtl ? END : START);
|
||||
if (splitConfig.initiatedFromSeascape) {
|
||||
// if the split was initiated from seascape,
|
||||
// the task on the right (secondary) is slightly larger
|
||||
primaryIconView.setTranslationX(bottomToMidpointOffset - taskIconHeight);
|
||||
secondaryIconView.setTranslationX(bottomToMidpointOffset);
|
||||
} else {
|
||||
// if not,
|
||||
// the task on the left (primary) is slightly larger
|
||||
primaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset
|
||||
- taskIconHeight);
|
||||
secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset);
|
||||
}
|
||||
} else {
|
||||
primaryIconParams.gravity = TOP | (isRtl ? START : END);
|
||||
secondaryIconParams.gravity = TOP | (isRtl ? START : END);
|
||||
if (!splitConfig.initiatedFromSeascape) {
|
||||
// if the split was initiated from landscape,
|
||||
// the task on the left (primary) is slightly larger
|
||||
primaryIconView.setTranslationX(-bottomToMidpointOffset);
|
||||
secondaryIconView.setTranslationX(-bottomToMidpointOffset + taskIconHeight);
|
||||
} else {
|
||||
// if not,
|
||||
// the task on the right (secondary) is slightly larger
|
||||
primaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset);
|
||||
secondaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset
|
||||
+ taskIconHeight);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
|
||||
// shifts icon half a width left (height is used here since icons are square)
|
||||
primaryIconView.setTranslationX(-(taskIconHeight / 2f));
|
||||
secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
|
||||
secondaryIconView.setTranslationX(taskIconHeight / 2f);
|
||||
}
|
||||
primaryIconView.setTranslationY(0);
|
||||
secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
|
||||
secondaryIconView.setTranslationX(taskIconHeight / 2f);
|
||||
secondaryIconView.setTranslationY(0);
|
||||
|
||||
primaryIconView.setLayoutParams(primaryIconParams);
|
||||
|
||||
@@ -178,16 +178,46 @@ public class SeascapePagedViewHandler extends LandscapePagedViewHandler {
|
||||
@Override
|
||||
public void setSplitIconParams(View primaryIconView, View secondaryIconView,
|
||||
int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
|
||||
boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
|
||||
DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
|
||||
super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
|
||||
primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig);
|
||||
primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight,
|
||||
groupedTaskViewWidth, isRtl, deviceProfile, splitConfig);
|
||||
FrameLayout.LayoutParams primaryIconParams =
|
||||
(FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
|
||||
FrameLayout.LayoutParams secondaryIconParams =
|
||||
(FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
|
||||
|
||||
primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
|
||||
secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
|
||||
// We calculate the "midpoint" of the thumbnail area, and place the icons there.
|
||||
// This is the place where the thumbnail area splits by default, in a near-50/50 split.
|
||||
// It is usually not exactly 50/50, due to insets/screen cutouts.
|
||||
int fullscreenInsetThickness = deviceProfile.getInsets().top;
|
||||
int fullscreenMidpointFromBottom = ((deviceProfile.heightPx
|
||||
- fullscreenInsetThickness) / 2);
|
||||
float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
|
||||
float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
|
||||
int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
|
||||
int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
|
||||
int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
|
||||
int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
|
||||
|
||||
primaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
|
||||
secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
|
||||
primaryIconView.setTranslationX(0);
|
||||
secondaryIconView.setTranslationX(0);
|
||||
if (splitConfig.initiatedFromSeascape) {
|
||||
// if the split was initiated from seascape,
|
||||
// the task on the right (secondary) is slightly larger
|
||||
primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
|
||||
secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
|
||||
+ taskIconHeight);
|
||||
} else {
|
||||
// if not,
|
||||
// the task on the left (primary) is slightly larger
|
||||
primaryIconView.setTranslationY(-bottomToMidpointOffset);
|
||||
secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
|
||||
}
|
||||
|
||||
primaryIconView.setLayoutParams(primaryIconParams);
|
||||
secondaryIconView.setLayoutParams(secondaryIconParams);
|
||||
}
|
||||
|
||||
@@ -113,6 +113,14 @@ public final class SplitConfigurationOptions {
|
||||
* the bounds were originally in
|
||||
*/
|
||||
public final boolean appsStackedVertically;
|
||||
/**
|
||||
* If {@code true}, that means at the time of creation of this object, the phone was in
|
||||
* seascape orientation. This is important on devices with insets, because they do not split
|
||||
* evenly -- one of the insets must be slightly larger to account for the inset.
|
||||
* From landscape, it is the leftTop task that expands slightly.
|
||||
* From seascape, it is the rightBottom task that expands slightly.
|
||||
*/
|
||||
public final boolean initiatedFromSeascape;
|
||||
public final int leftTopTaskId;
|
||||
public final int rightBottomTaskId;
|
||||
|
||||
@@ -128,11 +136,22 @@ public final class SplitConfigurationOptions {
|
||||
this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom,
|
||||
leftTopBounds.right, rightBottomBounds.top);
|
||||
appsStackedVertically = true;
|
||||
initiatedFromSeascape = false;
|
||||
} else {
|
||||
// horizontal apps, vertical divider
|
||||
this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top,
|
||||
rightBottomBounds.left, leftTopBounds.bottom);
|
||||
appsStackedVertically = false;
|
||||
// The following check is unreliable on devices without insets
|
||||
// (initiatedFromSeascape will always be set to false.) This happens to be OK for
|
||||
// all our current uses, but should be refactored.
|
||||
// TODO: Create a more reliable check, or refactor how splitting works on devices
|
||||
// with insets.
|
||||
if (rightBottomBounds.width() > leftTopBounds.width()) {
|
||||
initiatedFromSeascape = true;
|
||||
} else {
|
||||
initiatedFromSeascape = false;
|
||||
}
|
||||
}
|
||||
|
||||
leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right;
|
||||
|
||||
@@ -25,7 +25,8 @@ import android.view.View.AccessibilityDelegate;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.allapps.BaseAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.ActivityAllAppsContainerView;
|
||||
import com.android.launcher3.allapps.search.SearchAdapterProvider;
|
||||
import com.android.launcher3.dot.DotInfo;
|
||||
import com.android.launcher3.dragndrop.DragController;
|
||||
import com.android.launcher3.folder.FolderIcon;
|
||||
@@ -99,7 +100,7 @@ public interface ActivityContext {
|
||||
/**
|
||||
* The all apps container, if it exists in this context.
|
||||
*/
|
||||
default BaseAllAppsContainerView<?> getAppsView() {
|
||||
default ActivityAllAppsContainerView<?> getAppsView() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -190,4 +191,14 @@ public interface ActivityContext {
|
||||
default StringCache getStringCache() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns {@link SearchAdapterProvider} for build variant specific search result
|
||||
* views.
|
||||
*/
|
||||
@Nullable
|
||||
default SearchAdapterProvider<?> createSearchAdapterProvider(
|
||||
ActivityAllAppsContainerView<?> appsView) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +229,7 @@ public class OptionsPopupView extends ArrowPopup<Launcher>
|
||||
Launcher launcher = Launcher.getLauncher(view.getContext());
|
||||
launcher.startActivity(new Intent(Intent.ACTION_APPLICATION_PREFERENCES)
|
||||
.setPackage(launcher.getPackageName())
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -208,6 +208,12 @@ class DeviceProfileTest {
|
||||
PointF(64f, 83f),
|
||||
PointF(64f, 83f)
|
||||
).toTypedArray()
|
||||
allAppsCellSize = listOf(
|
||||
PointF(64f, 83f),
|
||||
PointF(64f, 83f),
|
||||
PointF(64f, 83f),
|
||||
PointF(64f, 83f)
|
||||
).toTypedArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user