listener);
-
/**
* Sets a flag indicating whether to pause scroll.
* Should be set to {@code true} while the screen is binding or new data is being applied,
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
index 09f3bd43f6..c2ab115c0c 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorDots.java
@@ -27,39 +27,30 @@ import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.graphics.Canvas;
-import android.graphics.ColorFilter;
import android.graphics.Outline;
import android.graphics.Paint;
import android.graphics.Paint.Style;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffColorFilter;
import android.graphics.Rect;
import android.graphics.RectF;
-import android.graphics.drawable.VectorDrawable;
import android.os.Handler;
import android.os.Looper;
import android.util.AttributeSet;
import android.util.FloatProperty;
import android.util.IntProperty;
-import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewOutlineProvider;
import android.view.animation.Interpolator;
import android.view.animation.OvershootInterpolator;
-import androidx.annotation.DrawableRes;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import androidx.core.content.ContextCompat;
import com.android.launcher3.Insettable;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
import com.android.launcher3.util.Themes;
-import java.util.function.Consumer;
-
/**
* {@link PageIndicator} which shows dots per page. The active page is shown with the current
* accent color.
@@ -75,15 +66,12 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private static final int PAGINATION_FADE_IN_DURATION = 83;
private static final int PAGINATION_FADE_OUT_DURATION = 167;
- private static final int DISABLED_ARROW_OPACITY = 97; // 38%
-
private static final int ENTER_ANIMATION_START_DELAY = 300;
private static final int ENTER_ANIMATION_STAGGERED_DELAY = 150;
private static final int ENTER_ANIMATION_DURATION = 400;
private static final int HEIGHT_MULTIPLIER = 4;
private static final int WIDTH_MULTIPLIER = 3;
- private static final float ARROW_TOUCH_BOX_FACTOR = 2f;
private static final int PAGE_INDICATOR_ALPHA = 255;
private static final int DOT_ALPHA = 128;
@@ -92,7 +80,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private static final int VISIBLE_ALPHA = 255;
private static final int INVISIBLE_ALPHA = 0;
private Paint mPaginationPaint;
- private @Nullable Consumer mOnArrowClickListener;
// This value approximately overshoots to 1.5 times the original size.
private static final float ENTER_ANIMATION_OVERSHOOT_TENSION = 4.9f;
@@ -135,14 +122,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
private final float mGapWidth;
private final float mCircleGap;
private final boolean mIsRtl;
- private final VectorDrawable mArrowRight;
- private final VectorDrawable mArrowLeft;
- private final Rect mArrowRightBounds = new Rect();
- private final Rect mArrowLeftBounds = new Rect();
- private final int mArrowTouchBoxExtraWidth;
- private final int mArrowTouchBoxHeight;
- private final int mArrowGapWidth;
- private final int mArrowLength;
private int mNumPages;
private int mActivePage;
@@ -194,23 +173,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
: DOT_GAP_FACTOR * mDotRadius;
setOutlineProvider(new MyOutlineProver());
mIsRtl = Utilities.isRtl(getResources());
- mArrowRight = setupArrow(R.drawable.ic_chevron_right_rounded_700);
- mArrowLeft = setupArrow(R.drawable.ic_chevron_left_rounded_700);
- /* the width of the arrows themselves plus extra folder / touch padding. x2 for 2 arrows. */
- mArrowTouchBoxExtraWidth = 2 * ((int) ((5.5f) * mGapWidth)
- + getResources().getDimensionPixelSize(R.dimen.folder_footer_horiz_padding));
- mArrowTouchBoxHeight =
- getResources().getDimensionPixelSize(R.dimen.folder_footer_height_default);
- mArrowLength = getResources().getDimensionPixelSize(R.dimen.folder_arrow_icon_length);
- mArrowGapWidth = getResources().getDimensionPixelSize(R.dimen.folder_arrow_gap_width);
- }
-
- private VectorDrawable setupArrow(@DrawableRes int resId) {
- VectorDrawable icon = (VectorDrawable) ContextCompat.getDrawable(getContext(), resId);
- ColorFilter arrowColorFilter = new PorterDuffColorFilter(mPaginationPaint.getColor(),
- PorterDuff.Mode.SRC_ATOP);
- icon.setColorFilter(arrowColorFilter);
- return icon;
}
@Override
@@ -448,11 +410,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
requestLayout();
}
- @Override
- public void setArrowClickListener(@Nullable Consumer listener) {
- mOnArrowClickListener = listener;
- }
-
@Override
public void setPauseScroll(boolean pause, boolean isTwoPanels) {
mIsTwoPanels = isTwoPanels;
@@ -467,20 +424,13 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // TODO(b/394355070): Verify Folder Entry Animation works correctly with visual updates
// Add extra spacing of mDotRadius on all sides so than entry animation could be run
- // and so the hitboxes of arrows can be clicked easier.
int width = MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY ?
MeasureSpec.getSize(widthMeasureSpec)
: (int) ((mNumPages * WIDTH_MULTIPLIER + 2) * mDotRadius);
int height = MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY
? MeasureSpec.getSize(heightMeasureSpec)
: (int) (HEIGHT_MULTIPLIER * mDotRadius);
- if (enableLauncherVisualRefresh() && mOnArrowClickListener != null) {
- // Extra height and width and gaps for accessibility arrows.
- width += mArrowTouchBoxExtraWidth;
- height = mArrowTouchBoxHeight;
- }
setMeasuredDimension(width, height);
}
@@ -573,17 +523,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
float bounceProgress = (posDif > 1) ? posDif - 1 : 0;
float bounceAdjustment = Math.abs(currentPosition - boundedPosition) * diameter;
- if (mOnArrowClickListener != null) {
- // Here we draw the Left Arrow
- mArrowLeft.setAlpha(boundedPosition == 0 ? DISABLED_ARROW_OPACITY : alpha);
- mArrowLeftBounds.left = (int) (sTempRect.left - mArrowGapWidth - mArrowLength);
- mArrowLeftBounds.top = (int) (y - (float) mArrowLength / 2);
- mArrowLeftBounds.right = mArrowLeftBounds.left + mArrowLength;
- mArrowLeftBounds.bottom = mArrowLeftBounds.top + mArrowLength;
- mArrowLeft.setBounds(mArrowLeftBounds);
- mArrowLeft.draw(canvas);
- }
-
// Here we draw the dots, one at a time from the left-most dot to the right-most dot
// 1.0 => 000000 000000111111 000000
// 1.3 => 000000 0000001111 11000000
@@ -640,17 +579,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
sTempRect.left = sTempRect.right + mGapWidth;
}
- if (mOnArrowClickListener != null) {
- // Here we draw the Right Arrow
- mArrowRight.setAlpha(boundedPosition == (mNumPages - 1)
- ? DISABLED_ARROW_OPACITY : alpha);
- mArrowRightBounds.left = (int) (sTempRect.left - mGapWidth + mArrowGapWidth);
- mArrowRightBounds.top = (int) (y - (float) mArrowLength / 2);
- mArrowRightBounds.right = mArrowRightBounds.left + mArrowLength;
- mArrowRightBounds.bottom = mArrowRightBounds.top + mArrowLength;
- mArrowRight.setBounds(mArrowRightBounds);
- mArrowRight.draw(canvas);
- }
} else {
// Here we draw the dots
mPaginationPaint.setAlpha((int) (alpha * DOT_ALPHA_FRACTION));
@@ -668,27 +596,6 @@ public class PageIndicatorDots extends View implements Insettable, PageIndicator
mPaginationPaint.setAlpha(alpha);
}
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mOnArrowClickListener == null) {
- // No - Op. Don't care about touch events
- } else if ((mIsRtl && withinExpandedBounds(mArrowRightBounds, ev))
- || (!mIsRtl && withinExpandedBounds(mArrowLeftBounds, ev))) {
- mOnArrowClickListener.accept(Direction.START);
- } else if ((mIsRtl && withinExpandedBounds(mArrowLeftBounds, ev))
- || (!mIsRtl && withinExpandedBounds(mArrowRightBounds, ev))) {
- mOnArrowClickListener.accept(Direction.END);
- }
- return super.onTouchEvent(ev);
- }
-
- // For larger Touch box
- private boolean withinExpandedBounds(Rect rect, MotionEvent ev) {
- RectF scaledRect = new RectF(rect);
- scale(scaledRect, ARROW_TOUCH_BOX_FACTOR);
- return scaledRect.contains(ev.getX(), ev.getY());
- }
-
private static void scale(RectF rect, float factor) {
float horizontalAdjustment = rect.width() * (factor - 1) / 2;
float verticalAdjustment = rect.height() * (factor - 1) / 2;
diff --git a/src/com/android/launcher3/pageindicators/PaginationArrow.kt b/src/com/android/launcher3/pageindicators/PaginationArrow.kt
new file mode 100644
index 0000000000..77a9e3c232
--- /dev/null
+++ b/src/com/android/launcher3/pageindicators/PaginationArrow.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2025 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.pageindicators
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.widget.ImageView
+import androidx.core.content.ContextCompat
+import com.android.launcher3.R
+
+/**
+ * Handles logic for the pagination arrow. The foreground and background images and the pressed /
+ * hovered state UX.
+ */
+@SuppressLint("AppCompatCustomView")
+class PaginationArrow(context: Context, attrs: AttributeSet) : ImageView(context, attrs) {
+ private val bgCircle = ContextCompat.getDrawable(context, R.drawable.ic_circle)
+
+ init {
+ foreground = ContextCompat.getDrawable(context, R.drawable.ic_chevron_left_rounded_700)
+ }
+
+ override fun onTouchEvent(event: MotionEvent?): Boolean {
+ when (event?.action) {
+ MotionEvent.ACTION_DOWN -> {
+ background = bgCircle
+ background.alpha = BACKGROUND_PRESSED_OPACITY
+ }
+ MotionEvent.ACTION_UP -> background = null
+ }
+ return super.onTouchEvent(event)
+ }
+
+ override fun onHoverEvent(event: MotionEvent?): Boolean {
+ when (event?.action) {
+ MotionEvent.ACTION_HOVER_ENTER -> {
+ background = bgCircle
+ background.alpha = BACKGROUND_HOVERED_OPACITY
+ }
+ MotionEvent.ACTION_HOVER_EXIT -> background = null
+ }
+ return super.onHoverEvent(event)
+ }
+
+ companion object {
+ const val FULLY_OPAQUE = 1f
+ const val DISABLED_ARROW_OPACITY = .38f
+
+ // alpha ints are 0 - 255; the former being transparent and the latter being fully opaque
+ private const val BACKGROUND_HOVERED_OPACITY = 28 // 11%
+ private const val BACKGROUND_PRESSED_OPACITY = 38 // 15%
+ }
+}
diff --git a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
index 185c3ee9ed..e94f3a065d 100644
--- a/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
+++ b/src/com/android/launcher3/workprofile/PersonalWorkSlidingTabStrip.java
@@ -26,12 +26,9 @@ import androidx.annotation.Nullable;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
-import com.android.launcher3.pageindicators.Direction;
import com.android.launcher3.pageindicators.PageIndicator;
import com.android.launcher3.views.ActivityContext;
-import java.util.function.Consumer;
-
/**
* Supports two indicator colors, dedicated for personal and work tabs.
*/
@@ -80,11 +77,6 @@ public class PersonalWorkSlidingTabStrip extends LinearLayout implements PageInd
public void setMarkersCount(int numMarkers) {
}
- @Override
- public void setArrowClickListener(Consumer listener) {
- // No-Op. All Apps doesn't need accessibility arrows for single click navigation.
- }
-
@Override
public boolean hasOverlappingRendering() {
return false;