From c547affdc9ba3677f5a2234c0838fd5136f54d6b Mon Sep 17 00:00:00 2001 From: Stefan Andonian Date: Fri, 11 Apr 2025 15:31:36 -0700 Subject: [PATCH 1/2] Moved PageIndicatorDots to their own ImageViews. Previously, they were simply included in PageIndicatorDots via Canvas drawing. This worked well to keep behavior encapsulated within PageIndicatorDots class. But it didn't work for Accessibility Services which require an actual view in order to focus properly. Bug: 409629978 Test: Verified manually. See video on bug comment: https://b.corp.google.com/issues/394355070#comment23 Flag: com.android.launcher3.enable_launcher_visual_refresh Change-Id: I212bf3dbee82e449088536fa841b02a3644df7d3 --- res/drawable/ic_chevron_left_rounded_700.xml | 2 +- res/drawable/ic_chevron_right_rounded_700.xml | 11 --- res/layout/user_folder_icon_normalized.xml | 20 ++++ res/values/dimens.xml | 1 + res/values/strings.xml | 2 + src/com/android/launcher3/folder/Folder.java | 33 ++++++- .../launcher3/folder/FolderPagedView.java | 4 +- .../pageindicators/PageIndicator.java | 10 -- .../pageindicators/PageIndicatorDots.java | 93 ------------------- .../pageindicators/PaginationArrow.kt | 41 ++++++++ .../PersonalWorkSlidingTabStrip.java | 8 -- 11 files changed, 97 insertions(+), 128 deletions(-) delete mode 100644 res/drawable/ic_chevron_right_rounded_700.xml create mode 100644 src/com/android/launcher3/pageindicators/PaginationArrow.kt diff --git a/res/drawable/ic_chevron_left_rounded_700.xml b/res/drawable/ic_chevron_left_rounded_700.xml index 17cc7f89b4..c3730d3a57 100644 --- a/res/drawable/ic_chevron_left_rounded_700.xml +++ b/res/drawable/ic_chevron_left_rounded_700.xml @@ -6,6 +6,6 @@ android:tint="?attr/colorControlNormal" android:autoMirrored="true"> diff --git a/res/drawable/ic_chevron_right_rounded_700.xml b/res/drawable/ic_chevron_right_rounded_700.xml deleted file mode 100644 index 8125d64783..0000000000 --- a/res/drawable/ic_chevron_right_rounded_700.xml +++ /dev/null @@ -1,11 +0,0 @@ - - - diff --git a/res/layout/user_folder_icon_normalized.xml b/res/layout/user_folder_icon_normalized.xml index 002e7b7eec..4c1464af56 100644 --- a/res/layout/user_folder_icon_normalized.xml +++ b/res/layout/user_folder_icon_normalized.xml @@ -53,6 +53,16 @@ android:textColorHighlight="?android:attr/colorControlHighlight" android:textColorHint="?attr/folderHintTextColor"/> + + + diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 2ec73c0564..88f542eb5c 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -545,6 +545,7 @@ 24dp 20dp + 32dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 9426b923c8..ea1acffd66 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -272,6 +272,8 @@ Edit Name + Paginate left + Paginate right diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index af44391b7b..ecf1ff1336 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -28,6 +28,8 @@ import static com.android.launcher3.folder.FolderGridOrganizer.createFolderGridO import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED; import static com.android.launcher3.model.data.FolderInfo.willAcceptItemType; +import static com.android.launcher3.pageindicators.PaginationArrow.DISABLED_ARROW_OPACITY; +import static com.android.launcher3.pageindicators.PaginationArrow.FULLY_OPAQUE; import static com.android.launcher3.testing.shared.TestProtocol.FOLDER_OPENED_MESSAGE; import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs; @@ -97,6 +99,7 @@ import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemFactory; import com.android.launcher3.model.data.WorkspaceItemInfo; import com.android.launcher3.pageindicators.PageIndicatorDots; +import com.android.launcher3.pageindicators.PaginationArrow; import com.android.launcher3.util.Executors; import com.android.launcher3.util.LauncherBindableItemsContainer; import com.android.launcher3.util.Thunk; @@ -204,6 +207,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo FolderPagedView mContent; private FolderNameEditText mFolderName; private PageIndicatorDots mPageIndicator; + private PaginationArrow mLeftArrow; + private PaginationArrow mRightArrow; protected View mFooter; private int mFooterHeight; @@ -312,6 +317,15 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mFolderName.forceDisableSuggestions(true); mKeyboardInsetAnimationCallback = new KeyboardInsetAnimationCallback(this); setWindowInsetsAnimationCallback(mKeyboardInsetAnimationCallback); + + if (enableLauncherVisualRefresh()) { + mLeftArrow = findViewById(R.id.left_indicator_arrow); + mRightArrow = findViewById(R.id.right_indicator_arrow); + mRightArrow.setOnClickListener(v -> mContent.snapToPage( + mContent.getCurrentPage() + 1)); + mLeftArrow.setOnClickListener(v -> mContent.snapToPage( + mContent.getCurrentPage() - 1)); + } } /** If arrows are visible, replace the container padding with indicator padding */ @@ -320,13 +334,28 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (mPageIndicator.getVisibility() == View.VISIBLE) { // Replace the container padding with indicator padding for arrows mFooter.setPadding(0, 0, 0, 0); - mPageIndicator.setPadding(sidePadding, 0, sidePadding, 0); ((MarginLayoutParams) mFolderName.getLayoutParams()) .setMarginStart(sidePadding); + mLeftArrow.setVisibility(View.VISIBLE); + mRightArrow.setVisibility(View.VISIBLE); } else { mFooter.setPadding(sidePadding, 0, sidePadding, 0); - mPageIndicator.setPadding(0, 0, 0, 0); ((MarginLayoutParams) mFolderName.getLayoutParams()).setMarginStart(0); + mLeftArrow.setVisibility(View.GONE); + mRightArrow.setVisibility(View.GONE); + } + } + + /** + * Called when the page is switched. Sets arrow UX to a disabled appearance if the page is at + * one end or the other. + */ + public void updateArrowAlphas() { + if (enableLauncherVisualRefresh()) { + mLeftArrow.setAlpha( + 0 == mContent.getCurrentPage() ? DISABLED_ARROW_OPACITY : FULLY_OPAQUE); + mRightArrow.setAlpha(mContent.getPageCount() == mContent.getCurrentPage() + 1 + ? DISABLED_ARROW_OPACITY : FULLY_OPAQUE); } } diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 4c86b09275..ceac72d5c4 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -48,7 +48,6 @@ import com.android.launcher3.keyboard.ViewGroupFocusHelper; import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemInfo; -import com.android.launcher3.pageindicators.Direction; import com.android.launcher3.pageindicators.PageIndicatorDots; import com.android.launcher3.util.LauncherBindableItemsContainer.ItemOperator; import com.android.launcher3.util.Thunk; @@ -131,8 +130,6 @@ public class FolderPagedView extends PagedView implements Cli public void setFolder(Folder folder) { mFolder = folder; mPageIndicator = folder.findViewById(R.id.folder_page_indicator); - mPageIndicator.setArrowClickListener(direction -> snapToPage( - (Direction.END == direction) ? mCurrentPage + 1 : mCurrentPage - 1)); initParentViews(folder); } @@ -489,6 +486,7 @@ public class FolderPagedView extends PagedView implements Cli super.notifyPageSwitchListener(prevPage); if (mFolder != null) { mFolder.updateTextViewFocus(); + mFolder.updateArrowAlphas(); } } diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java index a6f76c4d44..0640bf3672 100644 --- a/src/com/android/launcher3/pageindicators/PageIndicator.java +++ b/src/com/android/launcher3/pageindicators/PageIndicator.java @@ -15,8 +15,6 @@ */ package com.android.launcher3.pageindicators; -import java.util.function.Consumer; - /** * Base class for a page indicator. */ @@ -28,14 +26,6 @@ public interface PageIndicator { void setMarkersCount(int numMarkers); - /** - * This is only going to be used by the FolderPagedView's PageIndicator. A refactor is planned - * to separate the two purposes of this class, but in the meantime, this indicator will serve to - * let the folder snap to the page of its click, and also tell the PageIndicator not to draw - * arrows if the click listener is null (at least until after this is refactored). - */ - void setArrowClickListener(Consumer 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 b43a830cea..7ce410e2b8 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); } @@ -572,17 +522,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 @@ -639,17 +578,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 } } - @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..1ca21f9f4a --- /dev/null +++ b/src/com/android/launcher3/pageindicators/PaginationArrow.kt @@ -0,0 +1,41 @@ +/* + * 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.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) { + + init { + foreground = ContextCompat.getDrawable(context, R.drawable.ic_chevron_left_rounded_700) + } + + companion object { + const val FULLY_OPAQUE = 1f + const val DISABLED_ARROW_OPACITY = .38f + } +} 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; From 71170e927638ec181d2756494347aa9ed390f962 Mon Sep 17 00:00:00 2001 From: Stefan Andonian Date: Fri, 11 Apr 2025 15:52:24 -0700 Subject: [PATCH 2/2] Implement Folder Pagination Arrow Hover / Pressed UX Bug: 394355070 Test: Verified locally that everything works. Check out bug for video test. Flag: com.android.launcher3.enable_launcher_visual_refresh Change-Id: Ief4b895d8eb31e6ed53b05aad4b733e8de41e4d9 --- res/drawable/ic_circle.xml | 26 +++++++++++++++++ res/values/attrs.xml | 1 + res/values/colors.xml | 3 ++ res/values/styles.xml | 2 ++ .../pageindicators/PaginationArrow.kt | 28 +++++++++++++++++++ 5 files changed, 60 insertions(+) create mode 100644 res/drawable/ic_circle.xml diff --git a/res/drawable/ic_circle.xml b/res/drawable/ic_circle.xml new file mode 100644 index 0000000000..2f5cf218e1 --- /dev/null +++ b/res/drawable/ic_circle.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 83c7ba3fd3..7d50d7dc02 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -48,6 +48,7 @@ + diff --git a/res/values/colors.xml b/res/values/colors.xml index 914ffd64c9..bfa588841e 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -75,6 +75,9 @@ #0B57D0 #A8C7FA + #000000 + #FFFFFF + #FFFFFFFF #FFFFFFFF #CCFFFFFF diff --git a/res/values/styles.xml b/res/values/styles.xml index e45176efac..b7e19e5aa9 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -60,6 +60,7 @@ #89000000 @style/WidgetContainerTheme @color/page_indicator_dot_color_light + @color/page_indicator_arrow_bg_light @color/materialColorSecondaryFixed @color/materialColorOnSecondaryFixedVariant @color/folder_preview_light @@ -130,6 +131,7 @@ @color/notification_dot_color_dark @style/WidgetContainerTheme.Dark @color/page_indicator_dot_color_dark + @color/page_indicator_arrow_bg_dark @color/folder_preview_dark @color/folder_background_dark ?android:attr/colorPrimary diff --git a/src/com/android/launcher3/pageindicators/PaginationArrow.kt b/src/com/android/launcher3/pageindicators/PaginationArrow.kt index 1ca21f9f4a..77a9e3c232 100644 --- a/src/com/android/launcher3/pageindicators/PaginationArrow.kt +++ b/src/com/android/launcher3/pageindicators/PaginationArrow.kt @@ -19,6 +19,7 @@ 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 @@ -29,13 +30,40 @@ import com.android.launcher3.R */ @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% } }