diff --git a/quickstep/res/layout/activity_allset.xml b/quickstep/res/layout/activity_allset.xml index f08cabe13e..7ea92b59d1 100644 --- a/quickstep/res/layout/activity_allset.xml +++ b/quickstep/res/layout/activity_allset.xml @@ -38,6 +38,7 @@ app:lottie_loop="true" /> { + TextView settings = findViewById(R.id.navigation_settings); + settings.setTextColor(accentColor); + settings.setOnClickListener(v -> { try { startActivityForResult( Intent.parseUri(URI_SYSTEM_NAVIGATION_SETTING, 0), 0); @@ -142,12 +146,41 @@ public class AllSetActivity extends Activity { } }); - TextView hintTextView = findViewById(R.id.hint); + TextView hint = findViewById(R.id.hint); DeviceProfile dp = InvariantDeviceProfile.INSTANCE.get(this).getDeviceProfile(this); if (!dp.isGestureMode) { - hintTextView.setText(R.string.allset_button_hint); + hint.setText(R.string.allset_button_hint); } - hintTextView.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate()); + hint.setAccessibilityDelegate(new SkipButtonAccessibilityDelegate()); + + View textContent = findViewById(R.id.text_content_view); + textContent.addOnLayoutChangeListener( + (v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { + mTempSettingsBounds.set( + settings.getLeft(), + settings.getTop(), + settings.getRight(), + settings.getBottom()); + mTempInclusionBounds.set( + 0, + // Do not allow overlapping with the subtitle text + subtitle.getBottom(), + textContent.getWidth(), + textContent.getHeight()); + mTempExclusionBounds.set( + hint.getLeft(), + hint.getTop(), + hint.getRight(), + hint.getBottom()); + + Utilities.translateOverlappingView( + settings, + mTempSettingsBounds, + mTempInclusionBounds, + mTempExclusionBounds, + Utilities.TRANSLATE_UP); + }); + mTISBindHelper = new TISBindHelper(this, this::onTISConnected); mVibrator = getSystemService(Vibrator.class); diff --git a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java index bd0ce34182..b5084843b8 100644 --- a/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java +++ b/quickstep/src/com/android/quickstep/interaction/RootSandboxLayout.java @@ -19,6 +19,7 @@ import static com.android.launcher3.config.FeatureFlags.ENABLE_NEW_GESTURE_NAV_T import android.content.Context; import android.graphics.Insets; +import android.graphics.Rect; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; @@ -34,6 +35,10 @@ import com.android.launcher3.Utilities; /** Root layout that TutorialFragment uses to intercept motion events. */ public class RootSandboxLayout extends RelativeLayout { + private final Rect mTempStepIndicatorBounds = new Rect(); + private final Rect mTempInclusionBounds = new Rect(); + private final Rect mTempExclusionBounds = new Rect(); + private View mFeedbackView; private View mTutorialStepView; private View mSkipButton; @@ -98,18 +103,23 @@ public class RootSandboxLayout extends RelativeLayout { private void updateTutorialStepViewTranslation( @NonNull View anchorView, boolean translateToRight) { - mTutorialStepView.setTranslationX(translateToRight - ? Math.min( - // Translate to the right if the views are overlapping on large fonts and - // display sizes. - Math.max(0, anchorView.getRight() - mTutorialStepView.getLeft()), - // Do not translate beyond the bounds of the container view. - mFeedbackView.getWidth() - mTutorialStepView.getRight()) - : Math.max( - // Translate to the left if the views are overlapping on large fonts and - // display sizes. - Math.min(0, anchorView.getLeft() - mTutorialStepView.getRight()), - // Do not translate beyond the bounds of the container view. - -mTutorialStepView.getLeft())); + mTempStepIndicatorBounds.set( + mTutorialStepView.getLeft(), + mTutorialStepView.getTop(), + mTutorialStepView.getRight(), + mTutorialStepView.getBottom()); + mTempInclusionBounds.set(0, 0, mFeedbackView.getWidth(), mFeedbackView.getHeight()); + mTempExclusionBounds.set( + anchorView.getLeft(), + anchorView.getTop(), + anchorView.getRight(), + anchorView.getBottom()); + + Utilities.translateOverlappingView( + mTutorialStepView, + mTempStepIndicatorBounds, + mTempInclusionBounds, + mTempExclusionBounds, + translateToRight ? Utilities.TRANSLATE_RIGHT : Utilities.TRANSLATE_LEFT); } } diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java index 59327dc936..0fbaecbe7e 100644 --- a/src/com/android/launcher3/Utilities.java +++ b/src/com/android/launcher3/Utilities.java @@ -65,6 +65,7 @@ import android.view.ViewConfiguration; import android.view.animation.Interpolator; import androidx.annotation.ChecksSdkIntAtLeast; +import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.core.graphics.ColorUtils; @@ -136,6 +137,14 @@ public final class Utilities { @Deprecated public static final boolean IS_DEBUG_DEVICE = BuildConfig.IS_DEBUG_DEVICE; + public static final int TRANSLATE_UP = 0; + public static final int TRANSLATE_DOWN = 1; + public static final int TRANSLATE_LEFT = 2; + public static final int TRANSLATE_RIGHT = 3; + + @IntDef({TRANSLATE_UP, TRANSLATE_DOWN, TRANSLATE_LEFT, TRANSLATE_RIGHT}) + public @interface AdjustmentDirection{} + /** * Returns true if theme is dark. */ @@ -731,4 +740,63 @@ public final class Utilities { matrixValues[Matrix.MTRANS_X], matrixValues[Matrix.MTRANS_Y] )); } + + /** + * Translates the {@code targetView} so that it overlaps with {@code exclusionBounds} as little + * as possible, while remaining within {@code inclusionBounds}. + *

+ * {@code inclusionBounds} will always take precedence over {@code exclusionBounds}, so if + * {@code targetView} needs to be translated outside of {@code inclusionBounds} to fully fix an + * overlap with {@code exclusionBounds}, then {@code targetView} will only be translated up to + * the border of {@code inclusionBounds}. + *

+ * Note: {@code targetViewBounds}, {@code inclusionBounds} and {@code exclusionBounds} must all + * be in relation to the same reference point on screen. + *

+ * @param targetView the view being translated + * @param targetViewBounds the bounds of the {@code targetView} + * @param inclusionBounds the bounds the {@code targetView} absolutely must stay within + * @param exclusionBounds the bounds to try to move the {@code targetView} away from + * @param adjustmentDirection the translation direction that should be attempted to fix an + * overlap + */ + public static void translateOverlappingView( + @NonNull View targetView, + @NonNull Rect targetViewBounds, + @NonNull Rect inclusionBounds, + @NonNull Rect exclusionBounds, + @AdjustmentDirection int adjustmentDirection) { + switch (adjustmentDirection) { + case TRANSLATE_RIGHT: + targetView.setTranslationX(Math.min( + // Translate to the right if the view is overlapping on the left. + Math.max(0, exclusionBounds.right - targetViewBounds.left), + // Do not translate beyond the inclusion bounds. + inclusionBounds.right - targetViewBounds.right)); + break; + case TRANSLATE_LEFT: + targetView.setTranslationX(Math.max( + // Translate to the left if the view is overlapping on the right. + Math.min(0, exclusionBounds.left - targetViewBounds.right), + // Do not translate beyond the inclusion bounds. + inclusionBounds.left - targetViewBounds.left)); + break; + case TRANSLATE_DOWN: + targetView.setTranslationY(Math.min( + // Translate downwards if the view is overlapping on the top. + Math.max(0, exclusionBounds.bottom - targetViewBounds.top), + // Do not translate beyond the inclusion bounds. + inclusionBounds.bottom - targetViewBounds.bottom)); + break; + case TRANSLATE_UP: + targetView.setTranslationY(Math.max( + // Translate upwards if the view is overlapping on the bottom. + Math.min(0, exclusionBounds.top - targetViewBounds.bottom), + // Do not translate beyond the inclusion bounds. + inclusionBounds.top - targetViewBounds.top)); + break; + default: + // No-Op + } + } }