Snap for 8529137 from 365fc59d74 to tm-qpr1-release
Change-Id: I90ad1d620343139be9a5da8585fee779c6375e3d
This commit is contained in:
@@ -109,6 +109,8 @@
|
||||
<string name="back_gesture_intro_title">Swipe to go back</string>
|
||||
<!-- Introduction subtitle for the Back gesture tutorial. [CHAR LIMIT=200] -->
|
||||
<string name="back_gesture_intro_subtitle">To go back to the last screen, swipe from the left or right edge to the middle of the screen.</string>
|
||||
<!-- Introduction subtitle for the Back gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=200] -->
|
||||
<string name="back_gesture_spoken_intro_subtitle">To go back to the last screen, swipe with 2 fingers from the left or right edge to the middle of the screen.</string>
|
||||
|
||||
<string name="home_gesture_feedback_swipe_too_far_from_edge">Make sure you swipe up from the bottom edge of the screen.</string>
|
||||
<!-- Feedback shown during interactive parts of Home gesture tutorial when the Overview gesture is detected. [CHAR LIMIT=100] -->
|
||||
@@ -123,6 +125,8 @@
|
||||
<string name="home_gesture_intro_title">Swipe to go home</string>
|
||||
<!-- Introduction subtitle for the Home gesture tutorial. [CHAR LIMIT=100] -->
|
||||
<string name="home_gesture_intro_subtitle">Swipe up from the bottom of your screen. This gesture always takes you to the Home screen.</string>
|
||||
<!-- Introduction subtitle for the Home gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=100] -->
|
||||
<string name="home_gesture_spoken_intro_subtitle">Swipe up with 2 fingers from the bottom of the screen. This gesture always takes you to the Home screen.</string>
|
||||
|
||||
<!-- Feedback shown during interactive parts of Overview gesture tutorial when the gesture is started too far from the edge. [CHAR LIMIT=100] -->
|
||||
<string name="overview_gesture_feedback_swipe_too_far_from_edge">Make sure you swipe up from the bottom edge of the screen.</string>
|
||||
@@ -138,6 +142,8 @@
|
||||
<string name="overview_gesture_intro_title">Swipe to switch apps</string>
|
||||
<!-- Introduction subtitle for the Overview gesture tutorial. [CHAR LIMIT=100] -->
|
||||
<string name="overview_gesture_intro_subtitle">To switch between apps, swipe up from the bottom of your screen, hold, then release.</string>
|
||||
<!-- Introduction subtitle for the Overview gesture tutorial that will be spoken by screen readers. [CHAR LIMIT=100] -->
|
||||
<string name="overview_gesture_spoken_intro_subtitle">To switch between apps, swipe up with 2 fingers from the bottom of your screen, hold, then release.</string>
|
||||
|
||||
<!-- Title shown during interactive part of Assistant gesture tutorial. [CHAR LIMIT=30] -->
|
||||
<string name="assistant_gesture_tutorial_playground_title" translatable="false">Tutorial: Assistant</string>
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* 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.search;
|
||||
|
||||
import android.app.search.SearchSession;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.model.data.ItemInfo;
|
||||
import com.android.launcher3.util.ResourceBasedOverride;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/** Manages an all apps search session. */
|
||||
public class SearchSessionManager implements ResourceBasedOverride {
|
||||
|
||||
/** Entry state for the search session (e.g. from all apps). */
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(value = {ZERO_ALLAPPS, ZERO_QSB})
|
||||
public @interface ZeroEntryState {}
|
||||
public static final int ZERO_ALLAPPS = 1;
|
||||
public static final int ZERO_QSB = 2;
|
||||
|
||||
/** Creates a {@link SearchSessionManager} instance. */
|
||||
public static SearchSessionManager newInstance(Context context) {
|
||||
return Overrides.getObject(
|
||||
SearchSessionManager.class, context, R.string.search_session_manager_class);
|
||||
}
|
||||
|
||||
/** The current {@link SearchSession}. */
|
||||
@UiThread
|
||||
public void setSearchSession(SearchSession session) {}
|
||||
|
||||
/** {@code true} if IME is shown. */
|
||||
public void setIsImeShown(boolean value) {}
|
||||
|
||||
/** Returns {@code true} if IME is enabled. */
|
||||
public boolean getIsImeEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** The current entry state for search. */
|
||||
public @ZeroEntryState int getEntryState() {
|
||||
return ZERO_ALLAPPS;
|
||||
}
|
||||
|
||||
/**
|
||||
* When user enters all apps surface via tap on home widget, set the state to
|
||||
* {@code #ZERO_QSB}. When user exits, reset to {@code #ZERO_ALLAPPS}
|
||||
*/
|
||||
public void setEntryState(@ZeroEntryState int state) {}
|
||||
|
||||
/** This will be called before opening all apps, to prepare zero state suggestions. */
|
||||
public void prepareZeroState() {}
|
||||
|
||||
/** Apply predicted items for the search zero state. */
|
||||
public void setZeroStatePredictedItems(List<ItemInfo> items) {}
|
||||
|
||||
/** Returns {@code true} if the session is valid and should be enabled. */
|
||||
public boolean isValidSession() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Called when the search session is destroyed. */
|
||||
public void onDestroy() {}
|
||||
}
|
||||
@@ -30,7 +30,8 @@ import com.android.launcher3.util.Themes;
|
||||
*/
|
||||
public class AllAppsState extends LauncherState {
|
||||
|
||||
private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
|
||||
private static final int STATE_FLAGS =
|
||||
FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS | FLAG_HOTSEAT_INACCESSIBLE;
|
||||
|
||||
public AllAppsState(int id) {
|
||||
super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
|
||||
@@ -88,7 +89,9 @@ public class AllAppsState extends LauncherState {
|
||||
|
||||
@Override
|
||||
public int getVisibleElements(Launcher launcher) {
|
||||
return ALL_APPS_CONTENT | HOTSEAT_ICONS;
|
||||
// Don't add HOTSEAT_ICONS for phones in ALL_APPS state.
|
||||
return launcher.getDeviceProfile().isPhone ? ALL_APPS_CONTENT
|
||||
: ALL_APPS_CONTENT | HOTSEAT_ICONS;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -163,7 +163,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
if (mActivity != activity) {
|
||||
return;
|
||||
}
|
||||
if (mTaskAnimationManager != null) {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true);
|
||||
}
|
||||
mRecentsView = null;
|
||||
mActivity.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
|
||||
mActivity = null;
|
||||
}
|
||||
};
|
||||
@@ -1571,9 +1575,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
|
||||
|
||||
private void reset() {
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
if (mActivity != null) {
|
||||
mActivity.unregisterActivityLifecycleCallbacks(mLifecycleCallbacks);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -45,6 +45,7 @@ import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.systemui.shared.system.QuickStepContract;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
|
||||
|
||||
/**
|
||||
* Controls the animation of swiping back and returning to launcher.
|
||||
*
|
||||
@@ -87,6 +88,7 @@ public class LauncherBackAnimationController {
|
||||
private boolean mAnimatorSetInProgress = false;
|
||||
private float mBackProgress = 0;
|
||||
private boolean mBackInProgress = false;
|
||||
private IOnBackInvokedCallback mBackCallback;
|
||||
|
||||
public LauncherBackAnimationController(
|
||||
BaseQuickstepLauncher launcher,
|
||||
@@ -112,34 +114,35 @@ public class LauncherBackAnimationController {
|
||||
* @param handler Handler to the thread to run the animations on.
|
||||
*/
|
||||
public void registerBackCallbacks(Handler handler) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(
|
||||
new IOnBackInvokedCallback.Stub() {
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
handler.post(() -> resetPositionAnimated());
|
||||
}
|
||||
mBackCallback = new IOnBackInvokedCallback.Stub() {
|
||||
@Override
|
||||
public void onBackCancelled() {
|
||||
handler.post(() -> resetPositionAnimated());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
handler.post(() -> startTransition());
|
||||
}
|
||||
@Override
|
||||
public void onBackInvoked() {
|
||||
handler.post(() -> startTransition());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackProgressed(BackEvent backEvent) {
|
||||
mBackProgress = backEvent.getProgress();
|
||||
// TODO: Update once the interpolation curve spec is finalized.
|
||||
mBackProgress =
|
||||
1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
|
||||
- mBackProgress);
|
||||
if (!mBackInProgress) {
|
||||
startBack(backEvent);
|
||||
} else {
|
||||
updateBackProgress(mBackProgress, backEvent);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void onBackProgressed(BackEvent backEvent) {
|
||||
mBackProgress = backEvent.getProgress();
|
||||
// TODO: Update once the interpolation curve spec is finalized.
|
||||
mBackProgress =
|
||||
1 - (1 - mBackProgress) * (1 - mBackProgress) * (1
|
||||
- mBackProgress);
|
||||
if (!mBackInProgress) {
|
||||
startBack(backEvent);
|
||||
} else {
|
||||
updateBackProgress(mBackProgress, backEvent);
|
||||
}
|
||||
}
|
||||
|
||||
public void onBackStarted() { }
|
||||
});
|
||||
@Override
|
||||
public void onBackStarted() { }
|
||||
};
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).setBackToLauncherCallback(mBackCallback);
|
||||
}
|
||||
|
||||
private void resetPositionAnimated() {
|
||||
@@ -162,7 +165,10 @@ public class LauncherBackAnimationController {
|
||||
|
||||
/** Unregisters the back to launcher callback in shell. */
|
||||
public void unregisterBackCallbacks() {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).clearBackToLauncherCallback();
|
||||
if (mBackCallback != null) {
|
||||
SystemUiProxy.INSTANCE.get(mLauncher).clearBackToLauncherCallback(mBackCallback);
|
||||
}
|
||||
mBackCallback = null;
|
||||
}
|
||||
|
||||
private void startBack(BackEvent backEvent) {
|
||||
|
||||
@@ -847,8 +847,14 @@ public class SystemUiProxy implements ISystemUiProxy, DisplayController.DisplayI
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears the previously registered {@link IOnBackInvokedCallback}. */
|
||||
public void clearBackToLauncherCallback() {
|
||||
/** Clears the previously registered {@link IOnBackInvokedCallback}.
|
||||
*
|
||||
* @param callback The previously registered callback instance.
|
||||
*/
|
||||
public void clearBackToLauncherCallback(IOnBackInvokedCallback callback) {
|
||||
if (mBackToLauncherCallback != callback) {
|
||||
return;
|
||||
}
|
||||
mBackToLauncherCallback = null;
|
||||
if (mBackAnimation == null) {
|
||||
return;
|
||||
|
||||
@@ -256,7 +256,7 @@ public class TaskIconCache implements DisplayInfoChangeListener {
|
||||
private BaseIconFactory getIconFactory() {
|
||||
if (mIconFactory == null) {
|
||||
mIconFactory = new BaseIconFactory(mContext,
|
||||
DisplayController.INSTANCE.get(mContext).getInfo().densityDpi,
|
||||
DisplayController.INSTANCE.get(mContext).getInfo().getDensityDpi(),
|
||||
mContext.getResources().getDimensionPixelSize(R.dimen.taskbar_icon_size));
|
||||
}
|
||||
return mIconFactory;
|
||||
|
||||
@@ -320,6 +320,10 @@ public class TaskOverlayFactory implements ResourceBasedOverride {
|
||||
Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
/** Called when the snapshot has updated its full screen drawing parameters. */
|
||||
public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
|
||||
}
|
||||
|
||||
private class ScreenshotSystemShortcut extends SystemShortcut {
|
||||
|
||||
private final BaseDraggingActivity mActivity;
|
||||
|
||||
@@ -33,17 +33,22 @@ final class BackGestureTutorialController extends TutorialController {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionTitle() {
|
||||
public int getIntroductionTitle() {
|
||||
return R.string.back_gesture_intro_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionSubtitle() {
|
||||
public int getIntroductionSubtitle() {
|
||||
return R.string.back_gesture_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSuccessFeedbackSubtitle() {
|
||||
public int getSpokenIntroductionSubtitle() {
|
||||
return R.string.back_gesture_spoken_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSuccessFeedbackSubtitle() {
|
||||
return mTutorialFragment.isAtFinalStep()
|
||||
? R.string.back_gesture_feedback_complete_without_follow_up
|
||||
: R.string.back_gesture_feedback_complete_with_overview_follow_up;
|
||||
|
||||
@@ -32,17 +32,22 @@ final class HomeGestureTutorialController extends SwipeUpGestureTutorialControll
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionTitle() {
|
||||
public int getIntroductionTitle() {
|
||||
return R.string.home_gesture_intro_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionSubtitle() {
|
||||
public int getIntroductionSubtitle() {
|
||||
return R.string.home_gesture_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSuccessFeedbackSubtitle() {
|
||||
public int getSpokenIntroductionSubtitle() {
|
||||
return R.string.home_gesture_spoken_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSuccessFeedbackSubtitle() {
|
||||
return mTutorialFragment.isAtFinalStep()
|
||||
? R.string.home_gesture_feedback_complete_without_follow_up
|
||||
: R.string.home_gesture_feedback_complete_with_follow_up;
|
||||
|
||||
+8
-3
@@ -42,17 +42,22 @@ final class OverviewGestureTutorialController extends SwipeUpGestureTutorialCont
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionTitle() {
|
||||
public int getIntroductionTitle() {
|
||||
return R.string.overview_gesture_intro_title;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getIntroductionSubtitle() {
|
||||
public int getIntroductionSubtitle() {
|
||||
return R.string.overview_gesture_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getSuccessFeedbackSubtitle() {
|
||||
public int getSpokenIntroductionSubtitle() {
|
||||
return R.string.overview_gesture_spoken_intro_subtitle;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSuccessFeedbackSubtitle() {
|
||||
return mTutorialFragment.getNumSteps() > 1 && mTutorialFragment.isAtFinalStep()
|
||||
? R.string.overview_gesture_feedback_complete_with_follow_up
|
||||
: R.string.overview_gesture_feedback_complete_without_follow_up;
|
||||
|
||||
@@ -62,7 +62,7 @@ import java.util.ArrayList;
|
||||
abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
NavBarGestureAttemptCallback {
|
||||
|
||||
private static final String TAG = "TutorialController";
|
||||
private static final String LOG_TAG = "TutorialController";
|
||||
|
||||
private static final float FINGER_DOT_VISIBLE_ALPHA = 0.7f;
|
||||
private static final float FINGER_DOT_SMALL_SCALE = 0.7f;
|
||||
@@ -217,18 +217,23 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public Integer getIntroductionTitle() {
|
||||
return null;
|
||||
public int getIntroductionTitle() {
|
||||
return NO_ID;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public Integer getIntroductionSubtitle() {
|
||||
return null;
|
||||
public int getIntroductionSubtitle() {
|
||||
return NO_ID;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public Integer getSuccessFeedbackSubtitle() {
|
||||
return null;
|
||||
public int getSpokenIntroductionSubtitle() {
|
||||
return NO_ID;
|
||||
}
|
||||
|
||||
@StringRes
|
||||
public int getSuccessFeedbackSubtitle() {
|
||||
return NO_ID;
|
||||
}
|
||||
|
||||
void showFeedback() {
|
||||
@@ -247,7 +252,16 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
* Show feedback reflecting a successful gesture attempt.
|
||||
**/
|
||||
void showSuccessFeedback() {
|
||||
showFeedback(getSuccessFeedbackSubtitle(), true);
|
||||
int successSubtitleResId = getSuccessFeedbackSubtitle();
|
||||
if (successSubtitleResId == NO_ID) {
|
||||
// Allow crash since this should never be reached with a tutorial controller used in
|
||||
// production.
|
||||
Log.e(LOG_TAG,
|
||||
"Cannot show success feedback for tutorial step: " + mTutorialType
|
||||
+ ", no success feedback subtitle",
|
||||
new IllegalStateException());
|
||||
}
|
||||
showFeedback(successSubtitleResId, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,6 +283,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
isGestureSuccessful
|
||||
? R.string.gesture_tutorial_nice : R.string.gesture_tutorial_try_again,
|
||||
subtitleResId,
|
||||
NO_ID,
|
||||
isGestureSuccessful,
|
||||
false);
|
||||
}
|
||||
@@ -276,6 +291,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
void showFeedback(
|
||||
int titleResId,
|
||||
int subtitleResId,
|
||||
int spokenSubtitleResId,
|
||||
boolean isGestureSuccessful,
|
||||
boolean useGestureAnimationDelay) {
|
||||
mFeedbackTitleView.removeCallbacks(mTitleViewCallback);
|
||||
@@ -287,7 +303,10 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
mFeedbackTitleView.setText(titleResId);
|
||||
TextView subtitle =
|
||||
mFeedbackView.findViewById(R.id.gesture_tutorial_fragment_feedback_subtitle);
|
||||
subtitle.setText(subtitleResId);
|
||||
subtitle.setText(spokenSubtitleResId == NO_ID
|
||||
? mContext.getText(subtitleResId)
|
||||
: Utilities.wrapForTts(
|
||||
mContext.getText(subtitleResId), mContext.getString(spokenSubtitleResId)));
|
||||
if (isGestureSuccessful) {
|
||||
if (mTutorialFragment.isAtFinalStep()) {
|
||||
showActionButton();
|
||||
@@ -580,7 +599,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
packageManager.getApplicationInfo(
|
||||
PIXEL_TIPS_APP_PACKAGE_NAME, PackageManager.GET_META_DATA));
|
||||
} catch (PackageManager.NameNotFoundException e) {
|
||||
Log.e(TAG,
|
||||
Log.e(LOG_TAG,
|
||||
"Could not find app label for package name: "
|
||||
+ PIXEL_TIPS_APP_PACKAGE_NAME
|
||||
+ ". Defaulting to 'Pixel Tips.'",
|
||||
@@ -593,7 +612,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
subtitleTextView.setText(
|
||||
mContext.getString(R.string.skip_tutorial_dialog_subtitle, tipsAppName));
|
||||
} else {
|
||||
Log.w(TAG, "No subtitle view in the skip tutorial dialog to update.");
|
||||
Log.w(LOG_TAG, "No subtitle view in the skip tutorial dialog to update.");
|
||||
}
|
||||
|
||||
Button cancelButton = (Button) contentView.findViewById(
|
||||
@@ -602,7 +621,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
cancelButton.setOnClickListener(
|
||||
v -> tutorialDialog.dismiss());
|
||||
} else {
|
||||
Log.w(TAG, "No cancel button in the skip tutorial dialog to update.");
|
||||
Log.w(LOG_TAG, "No cancel button in the skip tutorial dialog to update.");
|
||||
}
|
||||
|
||||
Button confirmButton = contentView.findViewById(
|
||||
@@ -613,7 +632,7 @@ abstract class TutorialController implements BackGestureAttemptCallback,
|
||||
tutorialDialog.dismiss();
|
||||
});
|
||||
} else {
|
||||
Log.w(TAG, "No confirm button in the skip tutorial dialog to update.");
|
||||
Log.w(LOG_TAG, "No confirm button in the skip tutorial dialog to update.");
|
||||
}
|
||||
|
||||
tutorialDialog.getWindow().setBackgroundDrawable(
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
*/
|
||||
package com.android.quickstep.interaction;
|
||||
|
||||
import static android.view.View.NO_ID;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.Activity;
|
||||
@@ -211,13 +213,31 @@ abstract class TutorialFragment extends Fragment implements OnTouchListener {
|
||||
if (isGestureComplete()) {
|
||||
mTutorialController.showSuccessFeedback();
|
||||
} else if (!mIntroductionShown) {
|
||||
Integer introTileStringResId = mTutorialController.getIntroductionTitle();
|
||||
Integer introSubtitleResId = mTutorialController.getIntroductionSubtitle();
|
||||
if (introTileStringResId != null && introSubtitleResId != null) {
|
||||
mTutorialController.showFeedback(
|
||||
introTileStringResId, introSubtitleResId, false, true);
|
||||
mIntroductionShown = true;
|
||||
int introTitleResId = mTutorialController.getIntroductionTitle();
|
||||
int introSubtitleResId = mTutorialController.getIntroductionSubtitle();
|
||||
if (introTitleResId == NO_ID) {
|
||||
// Allow crash since this should never be reached with a tutorial controller used in
|
||||
// production.
|
||||
Log.e(LOG_TAG,
|
||||
"Cannot show introduction feedback for tutorial step: " + mTutorialType
|
||||
+ ", no introduction feedback title",
|
||||
new IllegalStateException());
|
||||
}
|
||||
if (introTitleResId == NO_ID) {
|
||||
// Allow crash since this should never be reached with a tutorial controller used in
|
||||
// production.
|
||||
Log.e(LOG_TAG,
|
||||
"Cannot show introduction feedback for tutorial step: " + mTutorialType
|
||||
+ ", no introduction feedback subtitle",
|
||||
new IllegalStateException());
|
||||
}
|
||||
mTutorialController.showFeedback(
|
||||
introTitleResId,
|
||||
introSubtitleResId,
|
||||
mTutorialController.getSpokenIntroductionSubtitle(),
|
||||
false,
|
||||
true);
|
||||
mIntroductionShown = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,6 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
HIDDEN_NON_ZERO_ROTATION,
|
||||
HIDDEN_NO_TASKS,
|
||||
HIDDEN_NO_RECENTS,
|
||||
HIDDEN_FOCUSED_SCROLL,
|
||||
HIDDEN_SPLIT_SCREEN})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface ActionsHiddenFlags { }
|
||||
@@ -64,8 +63,7 @@ public class OverviewActionsView<T extends OverlayUICallbacks> extends FrameLayo
|
||||
public static final int HIDDEN_NON_ZERO_ROTATION = 1 << 0;
|
||||
public static final int HIDDEN_NO_TASKS = 1 << 1;
|
||||
public static final int HIDDEN_NO_RECENTS = 1 << 2;
|
||||
public static final int HIDDEN_FOCUSED_SCROLL = 1 << 3;
|
||||
public static final int HIDDEN_SPLIT_SCREEN = 1 << 4;
|
||||
public static final int HIDDEN_SPLIT_SCREEN = 1 << 3;
|
||||
|
||||
@IntDef(flag = true, value = {
|
||||
DISABLED_SCROLLING,
|
||||
|
||||
@@ -378,6 +378,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// OverScroll constants
|
||||
private static final int OVERSCROLL_PAGE_SNAP_ANIMATION_DURATION = 270;
|
||||
|
||||
private static final int DEFAULT_ACTIONS_VIEW_ALPHA_ANIMATION_DURATION = 300;
|
||||
|
||||
private static final int DISMISS_TASK_DURATION = 300;
|
||||
private static final int ADDITION_TASK_DURATION = 200;
|
||||
private static final float INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET = 0.55f;
|
||||
@@ -652,6 +654,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
private TaskView mMovingTaskView;
|
||||
|
||||
private OverviewActionsView mActionsView;
|
||||
private ObjectAnimator mActionsViewAlphaAnimator;
|
||||
private float mActionsViewAlphaAnimatorFinalValue;
|
||||
|
||||
private MultiWindowModeChangedListener mMultiWindowModeChangedListener =
|
||||
new MultiWindowModeChangedListener() {
|
||||
@@ -1145,6 +1149,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
return getScrollForPage(taskIndex) == getPagedOrientationHandler().getPrimaryScroll(this);
|
||||
}
|
||||
|
||||
private boolean isFocusedTaskInExpectedScrollPosition() {
|
||||
TaskView focusedTask = getFocusedTaskView();
|
||||
return focusedTask != null && isTaskInExpectedScrollPosition(indexOfChild(focusedTask));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link TaskView} that has taskId matching {@code taskId} or null if no match.
|
||||
*/
|
||||
@@ -1191,13 +1200,15 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
@Override
|
||||
protected void onPageBeginTransition() {
|
||||
super.onPageBeginTransition();
|
||||
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
|
||||
if (!mActivity.getDeviceProfile().isTablet) {
|
||||
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPageEndTransition() {
|
||||
super.onPageEndTransition();
|
||||
if (isClearAllHidden()) {
|
||||
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
|
||||
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
|
||||
}
|
||||
if (getNextPage() > 0) {
|
||||
@@ -1808,16 +1819,24 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
private void updateActionsViewFocusedScroll() {
|
||||
boolean hiddenFocusedScroll;
|
||||
if (showAsGrid()) {
|
||||
TaskView focusedTaskView = getFocusedTaskView();
|
||||
hiddenFocusedScroll = focusedTaskView == null
|
||||
|| !isTaskInExpectedScrollPosition(indexOfChild(focusedTaskView));
|
||||
} else {
|
||||
hiddenFocusedScroll = false;
|
||||
float actionsViewAlphaValue = isFocusedTaskInExpectedScrollPosition() ? 1 : 0;
|
||||
// If animation is already in progress towards the same end value, do not restart.
|
||||
if (mActionsViewAlphaAnimator == null || !mActionsViewAlphaAnimator.isStarted()
|
||||
|| (mActionsViewAlphaAnimator.isStarted()
|
||||
&& mActionsViewAlphaAnimatorFinalValue != actionsViewAlphaValue)) {
|
||||
animateActionsViewAlpha(actionsViewAlphaValue,
|
||||
DEFAULT_ACTIONS_VIEW_ALPHA_ANIMATION_DURATION);
|
||||
}
|
||||
}
|
||||
mActionsView.updateHiddenFlags(OverviewActionsView.HIDDEN_FOCUSED_SCROLL,
|
||||
hiddenFocusedScroll);
|
||||
}
|
||||
|
||||
private void animateActionsViewAlpha(float alphaValue, long duration) {
|
||||
mActionsViewAlphaAnimator = ObjectAnimator.ofFloat(
|
||||
mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, alphaValue);
|
||||
mActionsViewAlphaAnimatorFinalValue = alphaValue;
|
||||
mActionsViewAlphaAnimator.setDuration(duration);
|
||||
mActionsViewAlphaAnimator.start();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2346,10 +2365,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
}
|
||||
|
||||
private void animateActionsViewIn() {
|
||||
ObjectAnimator anim = ObjectAnimator.ofFloat(
|
||||
mActionsView.getVisibilityAlpha(), MultiValueAlpha.VALUE, 0, 1);
|
||||
anim.setDuration(TaskView.SCALE_ICON_DURATION);
|
||||
anim.start();
|
||||
if (!showAsGrid() || isFocusedTaskInExpectedScrollPosition()) {
|
||||
animateActionsViewAlpha(1, TaskView.SCALE_ICON_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
public void animateUpTaskIconScale() {
|
||||
@@ -3292,7 +3310,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
|
||||
// Update various scroll-dependent UI.
|
||||
dispatchScrollChanged();
|
||||
updateActionsViewFocusedScroll();
|
||||
if (isClearAllHidden()) {
|
||||
if (isClearAllHidden() && !mActivity.getDeviceProfile().isTablet) {
|
||||
mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING,
|
||||
false);
|
||||
}
|
||||
|
||||
@@ -283,6 +283,7 @@ public class TaskThumbnailView extends View {
|
||||
|
||||
public void setFullscreenParams(TaskView.FullscreenDrawParams fullscreenParams) {
|
||||
mFullscreenParams = fullscreenParams;
|
||||
getTaskOverlay().setFullscreenParams(fullscreenParams);
|
||||
invalidate();
|
||||
}
|
||||
|
||||
|
||||
@@ -1022,7 +1022,7 @@ public class TaskView extends FrameLayout implements Reusable {
|
||||
}
|
||||
|
||||
public float getTaskCornerRadius() {
|
||||
return TaskCornerRadius.get(mActivity);
|
||||
return mCurrentFullscreenParams.mCornerRadius;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -306,6 +306,17 @@
|
||||
if not specified -->
|
||||
<attr name="allAppsBorderSpaceTwoPanelLandscapeVertical" format="float" />
|
||||
|
||||
<!-- alignment of hotseat to the grid.
|
||||
Not applicable for 3 button mode when taskbar is enabled -->
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpan" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanLandscape" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanTwoPanelLandscape" format="integer" />
|
||||
<!-- defaults to numColumns, if not specified -->
|
||||
<attr name="hotseatColumnSpanTwoPanelPortrait" format="integer" />
|
||||
|
||||
<!-- defaults to borderSpaceDps, if not specified -->
|
||||
<attr name="hotseatBorderSpace" format="float" />
|
||||
<!-- defaults to hotseatBorderSpace, if not specified -->
|
||||
|
||||
@@ -176,6 +176,7 @@
|
||||
launcher:allAppsBorderSpaceHorizontal="8"
|
||||
launcher:allAppsBorderSpaceVertical="16"
|
||||
launcher:allAppsBorderSpaceLandscape="16"
|
||||
launcher:hotseatColumnSpanLandscape="4"
|
||||
launcher:hotseatBorderSpace="58"
|
||||
launcher:hotseatBorderSpaceLandscape="50.4"
|
||||
launcher:canBeDefault="true" />
|
||||
|
||||
@@ -158,6 +158,7 @@ public class DeviceProfile {
|
||||
public final int numShownHotseatIcons;
|
||||
public int hotseatCellHeightPx;
|
||||
private final int hotseatExtraVerticalSize;
|
||||
private final boolean areNavButtonsInline;
|
||||
// In portrait: size = height, in landscape: size = width
|
||||
public int hotseatBarSizePx;
|
||||
public int hotseatBarTopPaddingPx;
|
||||
@@ -358,7 +359,7 @@ public class DeviceProfile {
|
||||
|
||||
// We shrink hotseat sizes regardless of orientation, if nav buttons are inline and QSB
|
||||
// might be inline in either orientations, to keep hotseat size consistent across rotation.
|
||||
boolean areNavButtonsInline = isTaskbarPresent && !isGestureMode;
|
||||
areNavButtonsInline = isTaskbarPresent && !isGestureMode;
|
||||
if (areNavButtonsInline && canQsbInline) {
|
||||
numShownHotseatIcons = inv.numShrunkenHotseatIcons;
|
||||
} else {
|
||||
@@ -373,15 +374,14 @@ public class DeviceProfile {
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
|
||||
if (isQsbInline) {
|
||||
hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
|
||||
qsbWidth = calculateQsbWidth();
|
||||
} else {
|
||||
hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
|
||||
: res.getDimensionPixelSize(
|
||||
R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
|
||||
+ res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
|
||||
qsbWidth = 0;
|
||||
}
|
||||
|
||||
springLoadedHotseatBarTopMarginPx = res.getDimensionPixelSize(
|
||||
R.dimen.spring_loaded_hotseat_top_margin);
|
||||
hotseatBarSidePaddingEndPx =
|
||||
@@ -390,9 +390,7 @@ public class DeviceProfile {
|
||||
hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
|
||||
hotseatExtraVerticalSize =
|
||||
res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size);
|
||||
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
|
||||
updateHotseatIconSize(
|
||||
pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
|
||||
updateHotseatIconSize(pxFromDp(inv.iconSize[INDEX_DEFAULT], mMetrics));
|
||||
|
||||
qsbBottomMarginOriginalPx = isScalableGrid
|
||||
? res.getDimensionPixelSize(R.dimen.scalable_grid_qsb_bottom_margin)
|
||||
@@ -483,6 +481,10 @@ public class DeviceProfile {
|
||||
cellLayoutPadding);
|
||||
updateWorkspacePadding();
|
||||
|
||||
// Hotseat and QSB width depends on updated cellSize and workspace padding
|
||||
hotseatBorderSpace = calculateHotseatBorderSpace();
|
||||
qsbWidth = calculateQsbWidth();
|
||||
|
||||
flingToDeleteThresholdVelocity = res.getDimensionPixelSize(
|
||||
R.dimen.drag_flingToDeleteMinVelocity);
|
||||
|
||||
@@ -493,14 +495,26 @@ public class DeviceProfile {
|
||||
new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* QSB width is always calculated because when in 3 button nav the width doesn't follow the
|
||||
* width of the hotseat.
|
||||
*/
|
||||
private int calculateQsbWidth() {
|
||||
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
if (isQsbInline) {
|
||||
int columns = isTwoPanels ? inv.numColumns * 2 : inv.numColumns;
|
||||
return getIconToIconWidthForColumns(columns)
|
||||
- iconSizePx * numShownHotseatIcons
|
||||
- hotseatBorderSpace * numShownHotseatIcons;
|
||||
} else {
|
||||
int columns = inv.hotseatColumnSpan[mTypeIndex];
|
||||
return getIconToIconWidthForColumns(columns);
|
||||
}
|
||||
}
|
||||
|
||||
return cellWidthPx * columns
|
||||
+ cellLayoutBorderSpacePx.x * (columns - 1)
|
||||
- (cellWidthPx - iconSizePx) // left and right cell space
|
||||
- iconSizePx * numShownHotseatIcons
|
||||
- hotseatBorderSpace * numShownHotseatIcons;
|
||||
private int getIconToIconWidthForColumns(int columns) {
|
||||
return columns * getCellSize().x
|
||||
+ (columns - 1) * cellLayoutBorderSpacePx.x
|
||||
- (getCellSize().x - iconSizePx); // left and right cell space
|
||||
}
|
||||
|
||||
private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
|
||||
@@ -741,13 +755,6 @@ public class DeviceProfile {
|
||||
// All apps
|
||||
updateAllAppsIconSize(scale, res);
|
||||
|
||||
// Hotseat
|
||||
hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
|
||||
if (isQsbInline) {
|
||||
qsbWidth = calculateQsbWidth();
|
||||
} else {
|
||||
qsbWidth = 0;
|
||||
}
|
||||
updateHotseatIconSize(iconSizePx);
|
||||
|
||||
// Folder icon
|
||||
@@ -755,6 +762,23 @@ public class DeviceProfile {
|
||||
folderIconOffsetYPx = (iconSizePx - folderIconSizePx) / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hotseat width spans a certain number of columns on scalable grids.
|
||||
* This method calculates the space between the icons to achieve that width.
|
||||
*/
|
||||
private int calculateHotseatBorderSpace() {
|
||||
if (!isScalableGrid) return 0;
|
||||
//TODO(http://b/228998082) remove this when 3 button spaces are fixed
|
||||
if (areNavButtonsInline) {
|
||||
return pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics);
|
||||
} else {
|
||||
int columns = inv.hotseatColumnSpan[mTypeIndex];
|
||||
float hotseatWidthPx = getIconToIconWidthForColumns(columns);
|
||||
float hotseatIconsTotalPx = iconSizePx * numShownHotseatIcons;
|
||||
return (int) (hotseatWidthPx - hotseatIconsTotalPx) / (numShownHotseatIcons - 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Updates the iconSize for allApps* variants.
|
||||
@@ -1070,6 +1094,13 @@ public class DeviceProfile {
|
||||
mHotseatPadding.left -= diff;
|
||||
mHotseatPadding.right += diff;
|
||||
}
|
||||
} else if (isScalableGrid) {
|
||||
int sideSpacing = (availableWidthPx - qsbWidth) / 2;
|
||||
mHotseatPadding.set(sideSpacing,
|
||||
hotseatBarTopPaddingPx,
|
||||
sideSpacing,
|
||||
hotseatBarSizePx - hotseatCellHeightPx - hotseatBarTopPaddingPx
|
||||
+ mInsets.bottom);
|
||||
} else {
|
||||
// We want the edges of the hotseat to line up with the edges of the workspace, but the
|
||||
// icons in the hotseat are a different size, and so don't line up perfectly. To account
|
||||
@@ -1306,6 +1337,7 @@ public class DeviceProfile {
|
||||
writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
|
||||
|
||||
writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
|
||||
writer.println(prefix + "\tinv.hotseatColumnSpan: " + inv.hotseatColumnSpan[mTypeIndex]);
|
||||
writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
|
||||
writer.println(prefix + pxToDpStr("hotseatBarTopPaddingPx", hotseatBarTopPaddingPx));
|
||||
writer.println(prefix + pxToDpStr("hotseatBarBottomPaddingPx", hotseatBarBottomPaddingPx));
|
||||
@@ -1384,7 +1416,7 @@ public class DeviceProfile {
|
||||
private static Context getContext(Context c, Info info, int orientation, WindowBounds bounds) {
|
||||
Configuration config = new Configuration(c.getResources().getConfiguration());
|
||||
config.orientation = orientation;
|
||||
config.densityDpi = info.densityDpi;
|
||||
config.densityDpi = info.getDensityDpi();
|
||||
config.smallestScreenWidthDp = (int) info.smallestSizeDp(bounds);
|
||||
return c.createConfigurationContext(config);
|
||||
}
|
||||
|
||||
@@ -173,17 +173,9 @@ public class Hotseat extends CellLayout implements Insettable {
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
int width;
|
||||
if (mActivity.getDeviceProfile().isQsbInline) {
|
||||
width = mActivity.getDeviceProfile().qsbWidth;
|
||||
} else {
|
||||
MarginLayoutParams qsbParams = (MarginLayoutParams) mQsb.getLayoutParams();
|
||||
width = getShortcutsAndWidgets().getMeasuredWidth()
|
||||
- qsbParams.getMarginStart()
|
||||
- qsbParams.getMarginEnd();
|
||||
}
|
||||
int qsbWidth = mActivity.getDeviceProfile().qsbWidth;
|
||||
|
||||
mQsb.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
|
||||
mQsb.measure(MeasureSpec.makeMeasureSpec(qsbWidth, MeasureSpec.EXACTLY),
|
||||
MeasureSpec.makeMeasureSpec(mQsbHeight, MeasureSpec.EXACTLY));
|
||||
}
|
||||
|
||||
|
||||
@@ -125,6 +125,7 @@ public class InvariantDeviceProfile {
|
||||
public PointF[] borderSpaces;
|
||||
public float folderBorderSpace;
|
||||
public float[] hotseatBorderSpaces;
|
||||
public int[] hotseatColumnSpan;
|
||||
|
||||
public float[] horizontalMargin;
|
||||
|
||||
@@ -356,6 +357,7 @@ public class InvariantDeviceProfile {
|
||||
numDatabaseHotseatIcons = deviceType == TYPE_MULTI_DISPLAY
|
||||
? closestProfile.numDatabaseHotseatIcons : closestProfile.numHotseatIcons;
|
||||
hotseatBorderSpaces = displayOption.hotseatBorderSpaces;
|
||||
hotseatColumnSpan = displayOption.hotseatColumnSpan;
|
||||
|
||||
numAllAppsColumns = closestProfile.numAllAppsColumns;
|
||||
numDatabaseAllAppsColumns = deviceType == TYPE_MULTI_DISPLAY
|
||||
@@ -396,7 +398,8 @@ public class InvariantDeviceProfile {
|
||||
// We need to ensure that there is enough extra space in the wallpaper
|
||||
// for the intended parallax effects
|
||||
float parallaxFactor =
|
||||
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.densityDpi) < 720
|
||||
dpiFromPx(Math.min(displayWidth, displayHeight), displayInfo.getDensityDpi())
|
||||
< 720
|
||||
? 2
|
||||
: wallpaperTravelToScreenWidthRatio(displayWidth, displayHeight);
|
||||
defaultWallpaperSize.x =
|
||||
@@ -585,8 +588,8 @@ public class InvariantDeviceProfile {
|
||||
}
|
||||
}
|
||||
|
||||
float width = dpiFromPx(minWidthPx, displayInfo.densityDpi);
|
||||
float height = dpiFromPx(minHeightPx, displayInfo.densityDpi);
|
||||
float width = dpiFromPx(minWidthPx, displayInfo.getDensityDpi());
|
||||
float height = dpiFromPx(minHeightPx, displayInfo.getDensityDpi());
|
||||
|
||||
// Sort the profiles based on the closeness to the device size
|
||||
Collections.sort(points, (a, b) ->
|
||||
@@ -806,7 +809,9 @@ public class InvariantDeviceProfile {
|
||||
private float folderBorderSpace;
|
||||
private final PointF[] borderSpaces = new PointF[COUNT_SIZES];
|
||||
private final float[] horizontalMargin = new float[COUNT_SIZES];
|
||||
//TODO(http://b/228998082) remove this when 3 button spaces are fixed
|
||||
private final float[] hotseatBorderSpaces = new float[COUNT_SIZES];
|
||||
private final int[] hotseatColumnSpan = new int[COUNT_SIZES];
|
||||
|
||||
private final float[] iconSizes = new float[COUNT_SIZES];
|
||||
private final float[] textSizes = new float[COUNT_SIZES];
|
||||
@@ -1032,6 +1037,17 @@ public class InvariantDeviceProfile {
|
||||
R.styleable.ProfileDisplayOption_hotseatBorderSpaceTwoPanelPortrait,
|
||||
hotseatBorderSpaces[INDEX_DEFAULT]);
|
||||
|
||||
hotseatColumnSpan[INDEX_DEFAULT] = a.getInt(
|
||||
R.styleable.ProfileDisplayOption_hotseatColumnSpan, grid.numColumns);
|
||||
hotseatColumnSpan[INDEX_LANDSCAPE] = a.getInt(
|
||||
R.styleable.ProfileDisplayOption_hotseatColumnSpanLandscape, grid.numColumns);
|
||||
hotseatColumnSpan[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt(
|
||||
R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelLandscape,
|
||||
grid.numColumns);
|
||||
hotseatColumnSpan[INDEX_TWO_PANEL_PORTRAIT] = a.getInt(
|
||||
R.styleable.ProfileDisplayOption_hotseatColumnSpanTwoPanelPortrait,
|
||||
grid.numColumns);
|
||||
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
@@ -1090,6 +1106,7 @@ public class InvariantDeviceProfile {
|
||||
minCellSize[i].y += p.minCellSize[i].y;
|
||||
horizontalMargin[i] += p.horizontalMargin[i];
|
||||
hotseatBorderSpaces[i] += p.hotseatBorderSpaces[i];
|
||||
hotseatColumnSpan[i] = p.hotseatColumnSpan[i];
|
||||
allAppsCellSize[i].x += p.allAppsCellSize[i].x;
|
||||
allAppsCellSize[i].y += p.allAppsCellSize[i].y;
|
||||
allAppsIconSizes[i] += p.allAppsIconSizes[i];
|
||||
|
||||
@@ -80,6 +80,9 @@ public abstract class LauncherState implements BaseState<LauncherState> {
|
||||
public static final int FLAG_CLOSE_POPUPS = BaseState.getFlag(6);
|
||||
public static final int FLAG_OVERVIEW_UI = BaseState.getFlag(7);
|
||||
|
||||
// Flag indicating that hotseat and its contents are not accessible.
|
||||
public static final int FLAG_HOTSEAT_INACCESSIBLE = BaseState.getFlag(8);
|
||||
|
||||
|
||||
public static final float NO_OFFSET = 0;
|
||||
public static final float NO_SCALE = 1;
|
||||
|
||||
@@ -25,6 +25,7 @@ import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
|
||||
import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
|
||||
import static com.android.launcher3.LauncherState.FLAG_HOTSEAT_INACCESSIBLE;
|
||||
import static com.android.launcher3.LauncherState.HINT_STATE;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
@@ -151,6 +152,12 @@ public class WorkspaceStateTransitionAnimation {
|
||||
propertySetter.setViewAlpha(mLauncher.getWorkspace().getPageIndicator(),
|
||||
workspacePageIndicatorAlpha, fadeInterpolator);
|
||||
|
||||
// Update the accessibility flags for hotseat based on launcher state.
|
||||
hotseat.setImportantForAccessibility(
|
||||
state.hasFlag(FLAG_HOTSEAT_INACCESSIBLE)
|
||||
? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
|
||||
: View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
|
||||
|
||||
Interpolator translationInterpolator =
|
||||
config.getInterpolator(ANIM_WORKSPACE_TRANSLATE, ZOOM_OUT);
|
||||
propertySetter.setFloat(mWorkspace, VIEW_TRANSLATE_X,
|
||||
|
||||
@@ -192,27 +192,6 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean appendSearchResults(ArrayList<AdapterItem> results) {
|
||||
if (hasFilter() && results != null && results.size() > 0) {
|
||||
updateSearchAdapterItems(results, mSearchResults.size());
|
||||
refreshRecyclerView();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void updateSearchAdapterItems(ArrayList<AdapterItem> list, int offset) {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
AdapterItem adapterItem = list.get(i);
|
||||
adapterItem.position = offset + i;
|
||||
mAdapterItems.add(adapterItem);
|
||||
|
||||
if (adapterItem.isCountedForAccessibility()) {
|
||||
mAccessibilityResultsCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates internals when the set of apps are updated.
|
||||
*/
|
||||
@@ -282,7 +261,6 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
String lastSectionName = null;
|
||||
FastScrollSectionInfo lastFastScrollerSectionInfo = null;
|
||||
int position = 0;
|
||||
int appIndex = 0;
|
||||
|
||||
// Prepare to update the list of sections, filtered apps, etc.
|
||||
mAccessibilityResultsCount = 0;
|
||||
@@ -319,7 +297,16 @@ public class AlphabeticalAppsList<T extends Context & ActivityContext> implement
|
||||
mAdapterItems.add(appItem);
|
||||
}
|
||||
} else {
|
||||
updateSearchAdapterItems(mSearchResults, 0);
|
||||
int count = mSearchResults.size();
|
||||
for (int i = 0; i < count; i++) {
|
||||
AdapterItem adapterItem = mSearchResults.get(i);
|
||||
adapterItem.position = i;
|
||||
mAdapterItems.add(adapterItem);
|
||||
|
||||
if (adapterItem.isCountedForAccessibility()) {
|
||||
mAccessibilityResultsCount++;
|
||||
}
|
||||
}
|
||||
if (!FeatureFlags.ENABLE_DEVICE_SEARCH.get()) {
|
||||
// Append the search market item
|
||||
if (hasNoFilteredResults()) {
|
||||
|
||||
@@ -176,14 +176,6 @@ public class AppsSearchContainerLayout extends ExtendedEditText
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppendSearchResult(String query, ArrayList<AdapterItem> items) {
|
||||
if (items != null) {
|
||||
mApps.appendSearchResults(items);
|
||||
notifyResultChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSearchResult() {
|
||||
if (mApps.setSearchResults(null)) {
|
||||
|
||||
@@ -31,13 +31,6 @@ public interface SearchCallback<T> {
|
||||
*/
|
||||
void onSearchResult(String query, ArrayList<T> items);
|
||||
|
||||
/**
|
||||
* Called when the search from secondary source is complete.
|
||||
*
|
||||
* @param items list of search results
|
||||
*/
|
||||
void onAppendSearchResult(String query, ArrayList<T> items);
|
||||
|
||||
/**
|
||||
* Called when the search results should be cleared.
|
||||
*/
|
||||
|
||||
@@ -290,7 +290,7 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
|
||||
|
||||
// Configuration property
|
||||
public final float fontScale;
|
||||
public final int densityDpi;
|
||||
private final int densityDpi;
|
||||
public final NavigationMode navigationMode;
|
||||
|
||||
private final PortraitSize mScreenSizeDp;
|
||||
@@ -357,6 +357,10 @@ public class DisplayController implements ComponentCallbacks, SafeCloseable {
|
||||
public float smallestSizeDp(WindowBounds bounds) {
|
||||
return dpiFromPx(Math.min(bounds.bounds.width(), bounds.bounds.height()), densityDpi);
|
||||
}
|
||||
|
||||
public int getDensityDpi() {
|
||||
return densityDpi;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -94,11 +94,6 @@ public class WidgetsSearchBarController implements TextWatcher,
|
||||
mSearchModeListener.onSearchResults(items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAppendSearchResult(String query, ArrayList<WidgetsListBaseEntry> items) {
|
||||
// Not needed.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearSearchResult() {
|
||||
// Any existing search session will be cancelled by setting text to empty.
|
||||
|
||||
@@ -64,6 +64,7 @@ abstract class DeviceProfileBaseTest {
|
||||
windowBounds = WindowBounds(x, y, x, y - 100, 0)
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(false)
|
||||
whenever(info.getDensityDpi()).thenReturn(560)
|
||||
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
}
|
||||
@@ -77,6 +78,7 @@ abstract class DeviceProfileBaseTest {
|
||||
windowBounds = WindowBounds(x, y, x, y - 100, 0)
|
||||
|
||||
whenever(info.isTablet(any())).thenReturn(true)
|
||||
whenever(info.getDensityDpi()).thenReturn(320)
|
||||
|
||||
inv = newScalableInvariantDeviceProfile()
|
||||
}
|
||||
@@ -107,6 +109,7 @@ abstract class DeviceProfileBaseTest {
|
||||
PointF(16f, 16f)
|
||||
).toTypedArray()
|
||||
hotseatBorderSpaces = FloatArray(4) { 16f }
|
||||
hotseatColumnSpan = IntArray(4) { 4 }
|
||||
iconSize = FloatArray(4) { 56f }
|
||||
allAppsIconSize = FloatArray(4) { 56f }
|
||||
iconTextSize = FloatArray(4) { 14f }
|
||||
|
||||
+1
-3
@@ -23,15 +23,13 @@ import com.android.launcher3.InvariantDeviceProfile.TYPE_TABLET
|
||||
import com.google.common.truth.Truth.assertThat
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.ArgumentMatchers
|
||||
import org.mockito.Mockito.`when` as whenever
|
||||
|
||||
/**
|
||||
* Test for [DeviceProfile]
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class HotseatSizeTest : DeviceProfileBaseTest() {
|
||||
class HotseatShownIconsTest : DeviceProfileBaseTest() {
|
||||
|
||||
@Test
|
||||
fun hotseat_size_is_normal_for_handhelds() {
|
||||
@@ -29,17 +29,16 @@ import org.junit.runner.RunWith
|
||||
class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_phones() {
|
||||
fun qsb_is_not_inline_for_phones() {
|
||||
initializeVarsForPhone()
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_tablet_portrait() {
|
||||
fun qsb_is_inline_for_tablet_portrait() {
|
||||
initializeVarsForTablet()
|
||||
inv = newScalableInvariantDeviceProfile().apply {
|
||||
inlineQsb = booleanArrayOf(
|
||||
@@ -62,11 +61,10 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
)
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun qsbWidth_has_size_for_tablet_landscape() {
|
||||
fun qsb_is_inline_for_tablet_landscape() {
|
||||
initializeVarsForTablet(isLandscape = true)
|
||||
inv = newScalableInvariantDeviceProfile().apply {
|
||||
inlineQsb = booleanArrayOf(
|
||||
@@ -75,16 +73,17 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
false,
|
||||
false
|
||||
)
|
||||
numColumns = 6
|
||||
numRows = 5
|
||||
numShownHotseatIcons = 6
|
||||
}
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
if (dp.hotseatQsbHeight > 0) {
|
||||
assertThat(dp.isQsbInline).isTrue()
|
||||
assertThat(dp.qsbWidth).isGreaterThan(0)
|
||||
} else { // Launcher3 doesn't have QSB height
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,14 +91,13 @@ class InlineQsbTest : DeviceProfileBaseTest() {
|
||||
* This test is to make sure that a tablet doesn't inline the QSB if the layout doesn't support
|
||||
*/
|
||||
@Test
|
||||
fun qsbWidth_is_match_parent_for_tablet_landscape_without_inline() {
|
||||
fun qsb_is_not_inline_for_tablet_landscape_without_inline() {
|
||||
initializeVarsForTablet(isLandscape = true)
|
||||
useTwoPanels = true
|
||||
|
||||
val dp = newDP()
|
||||
|
||||
assertThat(dp.isQsbInline).isFalse()
|
||||
assertThat(dp.qsbWidth).isEqualTo(0)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -135,7 +135,7 @@ public class DeviceEmulationData {
|
||||
resourceOverrides.put(s, getDimenByName(s, context.getResources(), 0));
|
||||
}
|
||||
return new DeviceEmulationData(info.currentSize.x, info.currentSize.y,
|
||||
info.densityDpi, info.cutout, code, grids, resourceOverrides);
|
||||
info.getDensityDpi(), info.cutout, code, grids, resourceOverrides);
|
||||
}
|
||||
|
||||
public static DeviceEmulationData getDevice(String deviceCode) throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user