Snap for 9032824 from 2ae4420a12 to tm-qpr1-release

Change-Id: I96f55323cd7279874f8a95e63918880df6086317
This commit is contained in:
Android Build Coastguard Worker
2022-09-06 23:24:57 +00:00
17 changed files with 255 additions and 63 deletions
@@ -35,6 +35,7 @@ import androidx.core.content.ContextCompat;
import com.android.launcher3.R;
import com.android.launcher3.allapps.FloatingHeaderRow;
import com.android.launcher3.allapps.FloatingHeaderView;
import com.android.launcher3.util.OnboardingPrefs;
import com.android.launcher3.util.Themes;
import com.android.launcher3.views.ActivityContext;
@@ -92,8 +93,10 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
? R.color.all_apps_label_text_dark
: R.color.all_apps_label_text);
mShowAllAppsLabel = !ActivityContext.lookupContext(
getContext()).getOnboardingPrefs().hasReachedMaxCount(ALL_APPS_VISITED_COUNT);
OnboardingPrefs<?> onboardingPrefs = ActivityContext.lookupContext(
getContext()).getOnboardingPrefs();
mShowAllAppsLabel = onboardingPrefs == null || !onboardingPrefs.hasReachedMaxCount(
ALL_APPS_VISITED_COUNT);
}
public void setup(FloatingHeaderView parent, FloatingHeaderRow[] rows, boolean tabsHidden) {
@@ -216,8 +219,8 @@ public class AppsDividerView extends View implements FloatingHeaderRow {
CharSequence allAppsLabelText = getResources().getText(R.string.all_apps_label);
mAllAppsLabelLayout = StaticLayout.Builder.obtain(
allAppsLabelText, 0, allAppsLabelText.length(), mPaint,
Math.round(mPaint.measureText(allAppsLabelText.toString())))
allAppsLabelText, 0, allAppsLabelText.length(), mPaint,
Math.round(mPaint.measureText(allAppsLabelText.toString())))
.setAlignment(Layout.Alignment.ALIGN_CENTER)
.setMaxLines(1)
.setIncludePad(true)
@@ -334,6 +334,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
return ActiveGestureErrorDetector.GestureEvent.STATE_GESTURE_COMPLETED;
} else if (stateFlag == STATE_GESTURE_CANCELLED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_GESTURE_CANCELLED;
} else if (stateFlag == STATE_SCREENSHOT_CAPTURED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_SCREENSHOT_CAPTURED;
} else if (stateFlag == STATE_CAPTURE_SCREENSHOT) {
return ActiveGestureErrorDetector.GestureEvent.STATE_CAPTURE_SCREENSHOT;
} else if (stateFlag == STATE_HANDLER_INVALIDATED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_HANDLER_INVALIDATED;
}
return null;
}
@@ -1222,6 +1228,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
// Let RecentsView handle the scrolling to the task, which we launch in startNewTask()
// or resumeLastTask().
if (mRecentsView != null) {
ActiveGestureLog.INSTANCE.trackEvent(ActiveGestureErrorDetector.GestureEvent
.SET_ON_PAGE_TRANSITION_END_CALLBACK);
mRecentsView.setOnPageTransitionEndCallback(
() -> mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED));
} else {
@@ -1535,7 +1543,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
Rect keepClearArea;
if (!ENABLE_PIP_KEEP_CLEAR_ALGORITHM) {
// make the height equal to hotseatBarSizePx only
keepClearArea = new Rect(0, 0, mDp.hotseatBarSizePx, 0);
keepClearArea = new Rect(0, 0, 0, mDp.hotseatBarSizePx);
return keepClearArea;
}
// the keep clear area in global screen coordinates, in pixels
@@ -1699,6 +1707,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
* handler (in case of quick switch).
*/
private void cancelCurrentAnimation() {
ActiveGestureLog.INSTANCE.addLog(
"AbsSwipeUpHandler.cancelCurrentAnimation",
ActiveGestureErrorDetector.GestureEvent.CANCEL_CURRENT_ANIMATION);
mCanceled = true;
mCurrentShift.cancelAnimation();
@@ -189,6 +189,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL
return ActiveGestureErrorDetector.GestureEvent.STATE_END_TARGET_ANIMATION_FINISHED;
} else if (stateFlag == STATE_RECENTS_SCROLLING_FINISHED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_RECENTS_SCROLLING_FINISHED;
} else if (stateFlag == STATE_RECENTS_ANIMATION_CANCELED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_RECENTS_ANIMATION_CANCELED;
}
return null;
}
@@ -32,6 +32,8 @@ import androidx.annotation.UiThread;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RunnableList;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
import com.android.systemui.shared.system.RecentsAnimationControllerCompat;
@@ -172,7 +174,12 @@ public class RecentsAnimationController {
*/
@UiThread
public void cleanupScreenshot() {
UI_HELPER_EXECUTOR.execute(() -> mController.cleanupScreenshot());
UI_HELPER_EXECUTOR.execute(() -> {
ActiveGestureLog.INSTANCE.addLog(
"cleanupScreenshot",
ActiveGestureErrorDetector.GestureEvent.CLEANUP_SCREENSHOT);
mController.cleanupScreenshot();
});
}
/**
@@ -36,6 +36,8 @@ import androidx.annotation.UiThread;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.quickstep.TopTaskTracker.CachedTaskInfo;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.quickstep.util.ActiveGestureLog;
import com.android.quickstep.views.RecentsView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
@@ -136,6 +138,8 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
// handling this call entirely
return;
}
ActiveGestureLog.INSTANCE.addLog("TaskAnimationManager.startRecentsAnimation",
ActiveGestureErrorDetector.GestureEvent.START_RECENTS_ANIMATION);
mController = controller;
mTargets = targets;
mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId());
@@ -43,7 +43,6 @@ import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.MOD
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.annotation.TargetApi;
import android.app.PendingIntent;
@@ -198,8 +197,7 @@ public final class TaskViewUtils {
BaseActivity baseActivity = BaseActivity.fromContext(context);
DeviceProfile dp = baseActivity.getDeviceProfile();
boolean showAsGrid = dp.isTablet;
boolean parallaxCenterAndAdjacentTask =
taskIndex != recentsView.getCurrentPage() && !showAsGrid;
boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage();
int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex);
int taskRectTranslationSecondary = showAsGrid ? (int) v.getGridTranslationY() : 0;
@@ -603,11 +601,7 @@ public final class TaskViewUtils {
if (raController != null) {
raController.setWillFinishToHome(false);
}
Context context = v.getContext();
DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
launcherAnim = dp.isTablet
? ObjectAnimator.ofFloat(recentsView, RecentsView.CONTENT_ALPHA, 0)
: recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
launcherAnim = recentsView.createAdjacentPageAnimForTaskLaunch(taskView);
launcherAnim.setInterpolator(Interpolators.TOUCH_RESPONSE_INTERPOLATOR);
launcherAnim.setDuration(RECENTS_LAUNCH_DURATION);
@@ -721,8 +721,10 @@ public class TouchInteractionService extends Service
gestureState.updateRunningTask(taskInfo);
}
// Log initial state for the gesture.
ActiveGestureLog.INSTANCE.addLog(
"Current SystemUi state flags= " + mDeviceState.getSystemUiStateString());
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current running task package name=")
.append(taskInfo == null ? "no running task" : taskInfo.getPackageName()));
ActiveGestureLog.INSTANCE.addLog(new CompoundString("Current SystemUi state flags=")
.append(mDeviceState.getSystemUiStateString()));
return gestureState;
}
@@ -1024,12 +1026,27 @@ public class TouchInteractionService extends Service
.append("activity == null, trying to use default input consumer"));
}
if (activity.getRootView().hasWindowFocus()
|| previousGestureState.isRunningAnimationToLauncher()
|| (ASSISTANT_GIVES_LAUNCHER_FOCUS.get()
&& forceOverviewInputConsumer)
|| (ENABLE_QUICKSTEP_LIVE_TILE.get()
&& gestureState.getActivityInterface().isInLiveTileMode())) {
boolean hasWindowFocus = activity.getRootView().hasWindowFocus();
boolean isPreviousGestureAnimatingToLauncher =
previousGestureState.isRunningAnimationToLauncher();
boolean forcingOverviewInputConsumer =
ASSISTANT_GIVES_LAUNCHER_FOCUS.get() && forceOverviewInputConsumer;
boolean isInLiveTileMode = ENABLE_QUICKSTEP_LIVE_TILE.get()
&& gestureState.getActivityInterface().isInLiveTileMode();
reasonString.append(SUBSTRING_PREFIX)
.append(hasWindowFocus
? "activity has window focus"
: (isPreviousGestureAnimatingToLauncher
? "previous gesture is still animating to launcher"
: (forcingOverviewInputConsumer
? "assistant gives launcher focus and forcing focus"
: (isInLiveTileMode
? "device is in live mode"
: "all overview focus conditions failed"))));
if (hasWindowFocus
|| isPreviousGestureAnimatingToLauncher
|| forcingOverviewInputConsumer
|| isInLiveTileMode) {
reasonString.append(SUBSTRING_PREFIX)
.append("overview should have focus, using OverviewInputConsumer");
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
@@ -28,6 +28,8 @@ import android.content.Intent;
import android.graphics.Point;
import android.view.MotionEvent;
import androidx.annotation.Nullable;
import com.android.launcher3.anim.AnimatorListeners;
import com.android.launcher3.testing.TestLogging;
import com.android.launcher3.testing.shared.TestProtocol;
@@ -41,6 +43,7 @@ import com.android.quickstep.RecentsAnimationCallbacks;
import com.android.quickstep.RecentsAnimationController;
import com.android.quickstep.RecentsAnimationTargets;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.util.ActiveGestureErrorDetector;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputMonitorCompat;
@@ -99,7 +102,8 @@ public class ProgressDelegateInputConsumer implements InputConsumer,
mDisplaySize = DisplayController.INSTANCE.get(context).getInfo().currentSize;
// Init states
mStateCallback = new MultiStateCallback(STATE_NAMES);
mStateCallback = new MultiStateCallback(
STATE_NAMES, ProgressDelegateInputConsumer::getTrackedEventForState);
mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_HANDLER_INVALIDATED,
this::endRemoteAnimation);
mStateCallback.runOnceAtState(STATE_TARGET_RECEIVED | STATE_FLING_FINISHED,
@@ -109,6 +113,14 @@ public class ProgressDelegateInputConsumer implements InputConsumer,
mSwipeDetector.setDetectableScrollConditions(DIRECTION_POSITIVE, false);
}
@Nullable
private static ActiveGestureErrorDetector.GestureEvent getTrackedEventForState(int stateFlag) {
if (stateFlag == STATE_HANDLER_INVALIDATED) {
return ActiveGestureErrorDetector.GestureEvent.STATE_HANDLER_INVALIDATED;
}
return null;
}
@Override
public int getType() {
return TYPE_PROGRESS_DELEGATE;
@@ -29,11 +29,24 @@ import java.util.Set;
*/
public class ActiveGestureErrorDetector {
/**
* Enums associated to gesture navigation events.
*/
public enum GestureEvent {
MOTION_DOWN, MOTION_UP, SET_END_TARGET, ON_SETTLED_ON_END_TARGET, START_RECENTS_ANIMATION,
FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION, STATE_GESTURE_STARTED,
STATE_GESTURE_COMPLETED, STATE_GESTURE_CANCELLED, STATE_END_TARGET_ANIMATION_FINISHED,
STATE_RECENTS_SCROLLING_FINISHED
FINISH_RECENTS_ANIMATION, CANCEL_RECENTS_ANIMATION, SET_ON_PAGE_TRANSITION_END_CALLBACK,
CANCEL_CURRENT_ANIMATION, CLEANUP_SCREENSHOT,
/**
* These GestureEvents are specifically associated to state flags that get set in
* {@link com.android.quickstep.MultiStateCallback}. If a state flag needs to be tracked
* for error detection, an enum should be added here and that state flag-enum pair should
* be added to the state flag's container class' {@code getTrackedEventForState} method.
*/
STATE_GESTURE_STARTED, STATE_GESTURE_COMPLETED, STATE_GESTURE_CANCELLED,
STATE_END_TARGET_ANIMATION_FINISHED, STATE_RECENTS_SCROLLING_FINISHED,
STATE_CAPTURE_SCREENSHOT, STATE_SCREENSHOT_CAPTURED, STATE_HANDLER_INVALIDATED,
STATE_RECENTS_ANIMATION_CANCELED
}
private ActiveGestureErrorDetector() {}
@@ -90,6 +103,14 @@ public class ActiveGestureErrorDetector {
+ "before/without startRecentsAnimation.",
writer);
break;
case CLEANUP_SCREENSHOT:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(GestureEvent.STATE_SCREENSHOT_CAPTURED),
/* errorMessage= */ prefix + "\t\trecents activity screenshot was "
+ "cleaned up before/without STATE_SCREENSHOT_CAPTURED "
+ "being set.",
writer);
break;
case STATE_GESTURE_COMPLETED:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(GestureEvent.MOTION_UP),
@@ -114,12 +135,39 @@ public class ActiveGestureErrorDetector {
+ "before/without STATE_GESTURE_STARTED.",
writer);
break;
case STATE_SCREENSHOT_CAPTURED:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(GestureEvent.STATE_CAPTURE_SCREENSHOT),
/* errorMessage= */ prefix + "\t\tSTATE_SCREENSHOT_CAPTURED set "
+ "before/without STATE_CAPTURE_SCREENSHOT.",
writer);
break;
case STATE_RECENTS_SCROLLING_FINISHED:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(
GestureEvent.SET_ON_PAGE_TRANSITION_END_CALLBACK),
/* errorMessage= */ prefix + "\t\tSTATE_RECENTS_SCROLLING_FINISHED "
+ "set before/without calling "
+ "setOnPageTransitionEndCallback.",
writer);
break;
case STATE_RECENTS_ANIMATION_CANCELED:
errorDetected |= printErrorIfTrue(
!encounteredEvents.contains(
GestureEvent.START_RECENTS_ANIMATION),
/* errorMessage= */ prefix + "\t\tSTATE_RECENTS_ANIMATION_CANCELED "
+ "set before/without startRecentsAnimation.",
writer);
break;
case MOTION_DOWN:
case SET_END_TARGET:
case START_RECENTS_ANIMATION:
case SET_ON_PAGE_TRANSITION_END_CALLBACK:
case CANCEL_CURRENT_ANIMATION:
case STATE_GESTURE_STARTED:
case STATE_END_TARGET_ANIMATION_FINISHED:
case STATE_RECENTS_SCROLLING_FINISHED:
case STATE_CAPTURE_SCREENSHOT:
case STATE_HANDLER_INVALIDATED:
default:
// No-Op
}
@@ -183,6 +231,39 @@ public class ActiveGestureErrorDetector {
+ "STATE_GESTURE_COMPLETED and STATE_GESTURE_CANCELLED weren't.",
writer);
errorDetected |= printErrorIfTrue(
/* condition= */ encounteredEvents.contains(
GestureEvent.STATE_CAPTURE_SCREENSHOT)
&& !encounteredEvents.contains(GestureEvent.STATE_SCREENSHOT_CAPTURED),
/* errorMessage= */ prefix + "\t\tSTATE_CAPTURE_SCREENSHOT was set, but "
+ "STATE_SCREENSHOT_CAPTURED wasn't.",
writer);
errorDetected |= printErrorIfTrue(
/* condition= */ encounteredEvents.contains(
GestureEvent.SET_ON_PAGE_TRANSITION_END_CALLBACK)
&& !encounteredEvents.contains(
GestureEvent.STATE_RECENTS_SCROLLING_FINISHED),
/* errorMessage= */ prefix + "\t\tsetOnPageTransitionEndCallback called, but "
+ "STATE_RECENTS_SCROLLING_FINISHED wasn't set.",
writer);
errorDetected |= printErrorIfTrue(
/* condition= */ !encounteredEvents.contains(
GestureEvent.CANCEL_CURRENT_ANIMATION)
&& !encounteredEvents.contains(GestureEvent.STATE_HANDLER_INVALIDATED),
/* errorMessage= */ prefix + "\t\tAbsSwipeUpHandler.cancelCurrentAnimation "
+ "wasn't called and STATE_HANDLER_INVALIDATED wasn't set.",
writer);
errorDetected |= printErrorIfTrue(
/* condition= */ encounteredEvents.contains(
GestureEvent.STATE_RECENTS_ANIMATION_CANCELED)
&& !encounteredEvents.contains(GestureEvent.CLEANUP_SCREENSHOT),
/* errorMessage= */ prefix + "\t\tSTATE_RECENTS_ANIMATION_CANCELED was set but "
+ "the task screenshot wasn't cleaned up.",
writer);
if (!errorDetected) {
writer.println(prefix + "\t\tNo errors detected.");
}
@@ -138,14 +138,10 @@ public class ActiveGestureLog {
List<EventEntry> lastEventEntries = lastEventLog.eventEntries;
EventEntry lastEntry = lastEventEntries.size() > 0
? lastEventEntries.get(lastEventEntries.size() - 1) : null;
EventEntry secondLastEntry = lastEventEntries.size() > 1
? lastEventEntries.get(lastEventEntries.size() - 2) : null;
// Update the last EventEntry if it's a duplicate
if (isEntrySame(lastEntry, type, event, compoundString, gestureEvent)
&& isEntrySame(secondLastEntry, type, event, compoundString, gestureEvent)) {
lastEntry.update(type, event, extras, compoundString, gestureEvent);
secondLastEntry.duplicateCount++;
if (isEntrySame(lastEntry, type, event, extras, compoundString, gestureEvent)) {
lastEntry.duplicateCount++;
return;
}
EventEntry eventEntry = new EventEntry();
@@ -223,11 +219,13 @@ public class ActiveGestureLog {
EventEntry entry,
int type,
String event,
float extras,
CompoundString compoundString,
ActiveGestureErrorDetector.GestureEvent gestureEvent) {
return entry != null
&& entry.type == type
&& entry.event.equals(event)
&& Float.compare(entry.extras, extras) == 0
&& entry.mCompoundString.equals(compoundString)
&& entry.gestureEvent == gestureEvent;
}
@@ -342,7 +340,7 @@ public class ActiveGestureLog {
return false;
}
CompoundString other = (CompoundString) obj;
return mIsNoOp && other.mIsNoOp && Objects.equals(mSubstrings, other.mSubstrings);
return (mIsNoOp == other.mIsNoOp) && Objects.equals(mSubstrings, other.mSubstrings);
}
}
}
@@ -4317,25 +4317,27 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
int taskIndex = indexOfChild(tv);
int centerTaskIndex = getCurrentPage();
boolean launchingCenterTask = taskIndex == centerTaskIndex;
float toScale = getMaxScaleForFullScreen();
RecentsView recentsView = tv.getRecentsView();
boolean showAsGrid = showAsGrid();
boolean launchingCenterTask = showAsGrid
? tv.isFocusedTask() && isTaskViewFullyVisible(tv)
: taskIndex == centerTaskIndex;
if (launchingCenterTask) {
anim.play(ObjectAnimator.ofFloat(recentsView, RECENTS_SCALE_PROPERTY, toScale));
anim.play(ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS, 1));
} else {
anim.play(ObjectAnimator.ofFloat(this, RECENTS_SCALE_PROPERTY, toScale));
anim.play(ObjectAnimator.ofFloat(this, FULLSCREEN_PROGRESS, 1));
} else if (!showAsGrid) {
// We are launching an adjacent task, so parallax the center and other adjacent task.
float displacementX = tv.getWidth() * (toScale - 1f);
float primaryTranslation = mIsRtl ? -displacementX : displacementX;
anim.play(ObjectAnimator.ofFloat(getPageAt(centerTaskIndex),
mOrientationHandler.getPrimaryViewTranslate(), primaryTranslation));
int runningTaskIndex = recentsView.getRunningTaskIndex();
int runningTaskIndex = getRunningTaskIndex();
if (ENABLE_QUICKSTEP_LIVE_TILE.get()
&& runningTaskIndex != -1
&& runningTaskIndex != taskIndex
&& recentsView.getRemoteTargetHandles() != null) {
for (RemoteTargetHandle remoteHandle : recentsView.getRemoteTargetHandles()) {
&& getRemoteTargetHandles() != null) {
for (RemoteTargetHandle remoteHandle : getRemoteTargetHandles()) {
anim.play(ObjectAnimator.ofFloat(
remoteHandle.getTaskViewSimulator().taskPrimaryTranslation,
AnimatedFloat.VALUE,
@@ -4355,7 +4357,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
properties));
}
}
anim.play(ObjectAnimator.ofFloat(recentsView, TASK_THUMBNAIL_SPLASH_ALPHA, 0, 1));
anim.play(ObjectAnimator.ofFloat(this, TASK_THUMBNAIL_SPLASH_ALPHA, 0, 1));
return anim;
}
+1
View File
@@ -226,6 +226,7 @@
<dimen name="drop_target_text_size">16sp</dimen>
<dimen name="drop_target_shadow_elevation">2dp</dimen>
<dimen name="drop_target_bar_margin_horizontal">4dp</dimen>
<dimen name="drop_target_button_drawable_size">20dp</dimen>
<dimen name="drop_target_button_drawable_padding">8dp</dimen>
<dimen name="drop_target_button_drawable_horizontal_padding">16dp</dimen>
<dimen name="drop_target_button_drawable_vertical_padding">8dp</dimen>
@@ -91,7 +91,7 @@ public abstract class ButtonDropTarget extends TextView
Resources resources = getResources();
mDragDistanceThreshold = resources.getDimensionPixelSize(R.dimen.drag_distanceThreshold);
mDrawableSize = resources.getDimensionPixelSize(R.dimen.drop_target_text_size);
mDrawableSize = resources.getDimensionPixelSize(R.dimen.drop_target_button_drawable_size);
mDrawablePadding = resources.getDimensionPixelSize(
R.dimen.drop_target_button_drawable_padding);
}
@@ -374,11 +374,63 @@ public abstract class ButtonDropTarget extends TextView
hideTooltip();
}
/**
* Returns if the text will be truncated within the provided availableWidth.
*/
public boolean isTextTruncated(int availableWidth) {
availableWidth -= (getPaddingLeft() + getPaddingRight() + mDrawable.getIntrinsicWidth()
+ getCompoundDrawablePadding());
CharSequence displayedText = TextUtils.ellipsize(mText, getPaint(), availableWidth,
availableWidth -= getPaddingLeft() + getPaddingRight();
if (mIconVisible) {
availableWidth -= mDrawable.getIntrinsicWidth() + getCompoundDrawablePadding();
}
if (availableWidth <= 0) {
return true;
}
CharSequence firstLine = TextUtils.ellipsize(mText, getPaint(), availableWidth,
TextUtils.TruncateAt.END);
return !mText.equals(displayedText);
if (!mTextMultiLine) {
return !TextUtils.equals(mText, firstLine);
}
if (TextUtils.equals(mText, firstLine)) {
// When multi-line is active, if it can display as one line, then text is not truncated.
return false;
}
CharSequence secondLine =
TextUtils.ellipsize(mText.subSequence(firstLine.length(), mText.length()),
getPaint(), availableWidth, TextUtils.TruncateAt.END);
return !(TextUtils.equals(mText.subSequence(0, firstLine.length()), firstLine)
&& TextUtils.equals(mText.subSequence(firstLine.length(), secondLine.length()),
secondLine));
}
/**
* Reduce the size of the text until it fits the measured width or reaches a minimum.
*
* The minimum size is defined by {@code R.dimen.button_drop_target_min_text_size} and
* it diminishes by intervals defined by
* {@code R.dimen.button_drop_target_resize_text_increment}
* This functionality is very similar to the option
* {@link TextView#setAutoSizeTextTypeWithDefaults(int)} but can't be used in this view because
* the layout width is {@code WRAP_CONTENT}.
*
* @return The biggest text size in SP that makes the text fit or if the text can't fit returns
* the min available value
*/
public float resizeTextToFit() {
float minSize = Utilities.pxToSp(getResources()
.getDimensionPixelSize(R.dimen.button_drop_target_min_text_size));
float step = Utilities.pxToSp(getResources()
.getDimensionPixelSize(R.dimen.button_drop_target_resize_text_increment));
float textSize = Utilities.pxToSp(getTextSize());
int availableWidth = getMeasuredWidth();
while (textSize > minSize) {
if (isTextTruncated(availableWidth)) {
textSize -= step;
setTextSize(textSize);
} else {
return textSize;
}
}
return minSize;
}
}
+1 -1
View File
@@ -1037,7 +1037,7 @@ public class DeviceProfile {
/ getCellLayoutHeight();
scale = Math.min(scale, 1f);
// Reduce scale if next pages would not be visible after scaling the workspace
// Reduce scale if next pages would not be visible after scaling the workspace.
int workspaceWidth = availableWidthPx;
float scaledWorkspaceWidth = workspaceWidth * scale;
float maxAvailableWidth = workspaceWidth - (2 * workspaceSpringLoadedMinNextPageVisiblePx);
+19 -12
View File
@@ -151,6 +151,8 @@ public class DropTargetBar extends FrameLayout
int widthSpec = MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST);
ButtonDropTarget firstButton = mTempTargets[0];
firstButton.setTextSize(TypedValue.COMPLEX_UNIT_PX,
mLauncher.getDeviceProfile().dropTargetTextSizePx);
firstButton.setTextVisible(true);
firstButton.setIconVisible(true);
firstButton.measure(widthSpec, heightSpec);
@@ -160,14 +162,16 @@ public class DropTargetBar extends FrameLayout
int horizontalPadding = dp.dropTargetHorizontalPaddingPx;
ButtonDropTarget firstButton = mTempTargets[0];
firstButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.dropTargetTextSizePx);
firstButton.setTextVisible(true);
firstButton.setIconVisible(true);
firstButton.setTextMultiLine(false);
// Reset second button padding in case it was previously changed to multi-line text.
// Reset first button padding in case it was previously changed to multi-line text.
firstButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
verticalPadding);
ButtonDropTarget secondButton = mTempTargets[1];
secondButton.setTextSize(TypedValue.COMPLEX_UNIT_PX, dp.dropTargetTextSizePx);
secondButton.setTextVisible(true);
secondButton.setIconVisible(true);
secondButton.setTextMultiLine(false);
@@ -175,20 +179,14 @@ public class DropTargetBar extends FrameLayout
secondButton.setPadding(horizontalPadding, verticalPadding, horizontalPadding,
verticalPadding);
float scale = dp.getWorkspaceSpringLoadScale(mLauncher);
int scaledPanelWidth = (int) (dp.getCellLayoutWidth() * scale);
int availableWidth;
if (dp.isTwoPanels) {
// Both buttons for two panel fit to the width of one Cell Layout (less
// half of the center gap between the buttons).
int halfButtonGap = dp.dropTargetGapPx / 2;
availableWidth = scaledPanelWidth - halfButtonGap / 2;
// Each button for two panel fits to half the width of the screen excluding the
// center gap between the buttons.
availableWidth = (dp.availableWidthPx - dp.dropTargetGapPx) / 2;
} else {
// Both buttons plus the button gap do not display past the edge of the scaled
// workspace, less a pre-defined gap from the edge of the workspace.
availableWidth = scaledPanelWidth - dp.dropTargetGapPx
- 2 * dp.dropTargetButtonWorkspaceEdgeGapPx;
// Both buttons plus the button gap do not display past the edge of the screen.
availableWidth = dp.availableWidthPx - dp.dropTargetGapPx;
}
int widthSpec = MeasureSpec.makeMeasureSpec(availableWidth, MeasureSpec.AT_MOST);
@@ -219,6 +217,15 @@ public class DropTargetBar extends FrameLayout
horizontalPadding, verticalPadding / 2);
}
}
// If text is still truncated, shrink to fit in measured width and resize both targets.
float minTextSize =
Math.min(firstButton.resizeTextToFit(), secondButton.resizeTextToFit());
if (firstButton.getTextSize() != minTextSize
|| secondButton.getTextSize() != minTextSize) {
firstButton.setTextSize(minTextSize);
secondButton.setTextSize(minTextSize);
}
}
setMeasuredDimension(width, height);
}
@@ -73,11 +73,11 @@ public class SecondaryDisplayLauncher extends BaseDraggingActivity
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mModel = LauncherAppState.getInstance(this).getModel();
mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
mSecondaryDisplayPredictions = SecondaryDisplayPredictions.newInstance(this);
if (getWindow().getDecorView().isAttachedToWindow()) {
initUi();
}
mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
mSecondaryDisplayPredictions = SecondaryDisplayPredictions.newInstance(this);
}
@Override
@@ -141,6 +141,7 @@ public interface ActivityContext {
default void applyOverwritesToLogItem(LauncherAtom.ItemInfo.Builder itemInfoBuilder) { }
/** Onboarding preferences for any onboarding data within this context. */
@Nullable
default OnboardingPrefs<?> getOnboardingPrefs() {
return null;
}