From 932e7b01444cae5f488279020c396a2ed4f5f6d3 Mon Sep 17 00:00:00 2001 From: Mugurell Date: Mon, 12 Apr 2021 13:58:46 +0300 Subject: [PATCH] For #9932 - Add isSticky support to most of the menu items Most of the menu items should support this new property and allow AC clients to configure the menus such that a specific menu item will not be scrolled off-screen but rather anchored to the top/bottom of the menu following where the menu is anchored. --- .../mozilla/components/browser/menu/BrowserMenuItem.kt | 8 ++++++++ .../browser/menu/item/AbstractParentBrowserMenuItem.kt | 5 ++++- .../components/browser/menu/item/BrowserMenuCategory.kt | 5 ++++- .../components/browser/menu/item/BrowserMenuCheckbox.kt | 5 ++++- .../browser/menu/item/BrowserMenuCompoundButton.kt | 3 +++ .../browser/menu/item/BrowserMenuHighlightableItem.kt | 6 ++++++ .../browser/menu/item/BrowserMenuHighlightableSwitch.kt | 5 ++++- .../browser/menu/item/BrowserMenuImageSwitch.kt | 6 +++++- .../components/browser/menu/item/BrowserMenuImageText.kt | 3 +++ .../menu/item/BrowserMenuImageTextCheckboxButton.kt | 6 +++++- .../browser/menu/item/BrowserMenuItemToolbar.kt | 5 ++++- .../components/browser/menu/item/BrowserMenuSwitch.kt | 5 ++++- .../components/browser/menu/item/ParentBrowserMenuItem.kt | 6 ++++++ .../menu/item/SimpleBrowserMenuHighlightableItem.kt | 4 ++++ .../browser/menu/item/WebExtensionBrowserMenuItem.kt | 5 ++++- .../browser/menu/item/BrowserMenuCompoundButtonTest.kt | 2 +- docs/changelog.md | 1 + 17 files changed, 70 insertions(+), 10 deletions(-) diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/BrowserMenuItem.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/BrowserMenuItem.kt index ed22994c4dd..b9dd7114d70 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/BrowserMenuItem.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/BrowserMenuItem.kt @@ -7,6 +7,7 @@ package mozilla.components.browser.menu import android.content.Context import android.view.View import mozilla.components.browser.menu.view.ExpandableLayout +import mozilla.components.browser.menu.view.StickyItemsLinearLayoutManager import mozilla.components.concept.menu.candidate.MenuCandidate /** @@ -33,6 +34,13 @@ interface BrowserMenuItem { */ val isCollapsingMenuLimit: Boolean get() = false + /** + * Whether this menu item should not be scrollable off-screen. + * + * @see [StickyItemsLinearLayoutManager] + */ + val isSticky: Boolean get() = false + /** * Returns the layout resource ID of the layout to be inflated for showing a menu item of this * type. diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/AbstractParentBrowserMenuItem.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/AbstractParentBrowserMenuItem.kt index 010014d3fe1..cce160b4860 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/AbstractParentBrowserMenuItem.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/AbstractParentBrowserMenuItem.kt @@ -16,11 +16,14 @@ import mozilla.components.browser.menu.BrowserMenuItem * @param endOfMenuAlwaysVisible when is set to true makes sure the bottom of the menu is always visible * otherwise, the top of the menu is always visible. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). */ abstract class AbstractParentBrowserMenuItem( private val subMenu: BrowserMenu, private val endOfMenuAlwaysVisible: Boolean, - override val isCollapsingMenuLimit: Boolean = false + override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false ) : BrowserMenuItem { /** * Listener called when the sub menu is shown. diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCategory.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCategory.kt index 5ade2350222..f3abefbec47 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCategory.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCategory.kt @@ -28,6 +28,8 @@ import mozilla.components.concept.menu.candidate.TypefaceStyle * @param textStyle: The style to apply to the text. * @param textAlignment The alignment of text * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). */ @Suppress("LongParameterList") class BrowserMenuCategory( @@ -37,7 +39,8 @@ class BrowserMenuCategory( private val textColorResource: Int = NO_ID, @TypefaceStyle private val textStyle: Int = Typeface.BOLD, @TextAlignment private val textAlignment: Int = View.TEXT_ALIGNMENT_VIEW_START, - override val isCollapsingMenuLimit: Boolean = false + override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false ) : BrowserMenuItem { override var visible: () -> Boolean = { true } diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCheckbox.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCheckbox.kt index ffa673a3c4c..c728d30ba69 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCheckbox.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCheckbox.kt @@ -14,14 +14,17 @@ import mozilla.components.concept.menu.candidate.CompoundMenuCandidate * @param label The visible label of this menu item. * @param initialState The initial value the checkbox should have. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param listener Callback to be invoked when this menu item is checked. */ class BrowserMenuCheckbox( label: String, initialState: () -> Boolean = { false }, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, listener: (Boolean) -> Unit -) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, initialState, listener) { +) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, isSticky, initialState, listener) { override fun getLayoutResource() = R.layout.mozac_browser_menu_item_checkbox override fun asCandidate(context: Context) = super.asCandidate(context).copy( diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCompoundButton.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCompoundButton.kt index 1dc0ca119da..86b6550308a 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCompoundButton.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuCompoundButton.kt @@ -20,6 +20,8 @@ import java.lang.reflect.Modifier.PRIVATE * * @param label The visible label of this menu item. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param initialState The initial value the checkbox should have. * @param listener Callback to be invoked when this menu item is checked. */ @@ -27,6 +29,7 @@ abstract class BrowserMenuCompoundButton( @VisibleForTesting(otherwise = PRIVATE) val label: String, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, private val initialState: () -> Boolean = { false }, private val listener: (Boolean) -> Unit ) : BrowserMenuItem { diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableItem.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableItem.kt index c3fa7f088c7..e6db9c6b089 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableItem.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableItem.kt @@ -32,6 +32,8 @@ private val defaultHighlight = BrowserMenuHighlightableItem.Highlight(0, 0, 0, 0 * @param iconTintColorResource Optional ID of color resource to tint the icon. * @param textColorResource Optional ID of color resource to tint the text. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param highlight Highlight object representing how the menu item will be displayed when highlighted. * @param isHighlighted Whether or not to display the highlight * @param listener Callback to be invoked when this menu item is clicked. @@ -43,6 +45,7 @@ class BrowserMenuHighlightableItem( @ColorRes private val iconTintColorResource: Int = NO_ID, @ColorRes private val textColorResource: Int = NO_ID, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, override val highlight: BrowserMenuHighlight, override val isHighlighted: () -> Boolean = { true }, private val listener: () -> Unit = {} @@ -52,6 +55,7 @@ class BrowserMenuHighlightableItem( iconTintColorResource, textColorResource, isCollapsingMenuLimit, + isSticky, listener ), HighlightableMenuItem { @@ -66,6 +70,7 @@ class BrowserMenuHighlightableItem( @ColorRes textColorResource: Int = NO_ID, isCollapsingMenuLimit: Boolean = false, + isSticky: Boolean = false, highlight: Highlight? = null, listener: () -> Unit = {} ) : this( @@ -74,6 +79,7 @@ class BrowserMenuHighlightableItem( iconTintColorResource, textColorResource, isCollapsingMenuLimit, + isSticky, highlight ?: defaultHighlight, { highlight != null }, listener diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableSwitch.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableSwitch.kt index fee7b8abbc4..234ac495ffd 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableSwitch.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuHighlightableSwitch.kt @@ -25,6 +25,8 @@ import mozilla.components.concept.menu.candidate.LowPriorityHighlightEffect * * @param label The visible label of this menu item. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param initialState The initial value the checkbox should have. * @param listener Callback to be invoked when this menu item is checked. */ @@ -35,11 +37,12 @@ class BrowserMenuHighlightableSwitch( @ColorRes private val iconTintColorResource: Int = NO_ID, @ColorRes private val textColorResource: Int = NO_ID, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, override val highlight: BrowserMenuHighlight.LowPriority, override val isHighlighted: () -> Boolean = { true }, initialState: () -> Boolean = { false }, listener: (Boolean) -> Unit -) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, initialState, listener), HighlightableMenuItem { +) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, isSticky, initialState, listener), HighlightableMenuItem { private var wasHighlighted = false diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageSwitch.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageSwitch.kt index 76b902a8ed1..3fb1d613662 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageSwitch.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageSwitch.kt @@ -21,18 +21,22 @@ import java.lang.reflect.Modifier * @param imageResource ID of a drawable resource to be shown as icon. * @param label The visible label of this menu item. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param initialState The initial value the checkbox should have. * @param listener Callback to be invoked when this menu item is checked. */ +@Suppress("LongParameterList") class BrowserMenuImageSwitch( @VisibleForTesting(otherwise = Modifier.PRIVATE) @DrawableRes val imageResource: Int, label: String, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, initialState: () -> Boolean = { false }, listener: (Boolean) -> Unit -) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, initialState, listener) { +) : BrowserMenuCompoundButton(label, isCollapsingMenuLimit, isSticky, initialState, listener) { override fun getLayoutResource(): Int = R.layout.mozac_browser_menu_item_image_switch override fun bind(menu: BrowserMenu, view: View) { diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageText.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageText.kt index 761afe38228..b1e05b0d024 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageText.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageText.kt @@ -44,6 +44,8 @@ internal fun TextView.setColorResource(@ColorRes textColorResource: Int) { * @param iconTintColorResource Optional ID of color resource to tint the icon. * @param textColorResource Optional ID of color resource to tint the text. * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param listener Callback to be invoked when this menu item is clicked. */ @Suppress("LongParameterList") @@ -56,6 +58,7 @@ open class BrowserMenuImageText( @ColorRes private val textColorResource: Int = NO_ID, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, private val listener: () -> Unit = {} ) : BrowserMenuItem { diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageTextCheckboxButton.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageTextCheckboxButton.kt index 2c2c5328136..bce0324e89b 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageTextCheckboxButton.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuImageTextCheckboxButton.kt @@ -24,6 +24,9 @@ import mozilla.components.support.ktx.android.util.dpToPx * @param labelListener Callback to be invoked when this menu item is clicked. * @param primaryStateIconResource ID of a drawable resource for checkbox drawable in primary state. * @param secondaryStateIconResource ID of a drawable resource for checkbox drawable in secondary state. + * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). * @param iconTintColorResource Optional ID of color resource to tint the checkbox drawable. * @param primaryLabel The visible label of the checkbox in primary state. * @param secondaryLabel The visible label of this menu item in secondary state. @@ -43,10 +46,11 @@ class BrowserMenuImageTextCheckboxButton( private val primaryLabel: String, private val secondaryLabel: String, override val isCollapsingMenuLimit: Boolean = false, + override val isSticky: Boolean = false, val isInPrimaryState: () -> Boolean = { true }, private val onCheckedChangedListener: (Boolean) -> Unit ) : BrowserMenuImageText( - label, imageResource, iconTintColorResource, textColorResource, isCollapsingMenuLimit, labelListener + label, imageResource, iconTintColorResource, textColorResource, isCollapsingMenuLimit, isSticky, labelListener ) { override var visible: () -> Boolean = { true } override fun getLayoutResource(): Int = R.layout.mozac_browser_menu_item_image_text_checkbox_button diff --git a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuItemToolbar.kt b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuItemToolbar.kt index 3db897a90c6..9efa58c62a4 100644 --- a/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuItemToolbar.kt +++ b/components/browser/menu/src/main/java/mozilla/components/browser/menu/item/BrowserMenuItemToolbar.kt @@ -29,10 +29,13 @@ import mozilla.components.support.ktx.android.content.res.resolveAttribute * * @param items buttons that will be shown in a horizontal layout * @param isCollapsingMenuLimit Whether this menu item can serve as the limit of a collapsing menu. + * @param isSticky whether this item menu should not be scrolled offscreen (downwards or upwards + * depending on the menu position). */ class BrowserMenuItemToolbar( private val items: List