Skip to content

Commit

Permalink
For mozilla-mobile#9932 - Add isSticky support to most of the menu items
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Mugurell committed Apr 14, 2021
1 parent 8bf476a commit 4ff10cf
Show file tree
Hide file tree
Showing 17 changed files with 70 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

/**
Expand All @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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 }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ 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.
*/
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 = {}
Expand All @@ -52,6 +55,7 @@ class BrowserMenuHighlightableItem(
iconTintColorResource,
textColorResource,
isCollapsingMenuLimit,
isSticky,
listener
), HighlightableMenuItem {

Expand All @@ -66,6 +70,7 @@ class BrowserMenuHighlightableItem(
@ColorRes
textColorResource: Int = NO_ID,
isCollapsingMenuLimit: Boolean = false,
isSticky: Boolean = false,
highlight: Highlight? = null,
listener: () -> Unit = {}
) : this(
Expand All @@ -74,6 +79,7 @@ class BrowserMenuHighlightableItem(
iconTintColorResource,
textColorResource,
isCollapsingMenuLimit,
isSticky,
highlight ?: defaultHighlight,
{ highlight != null },
listener
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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 {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Button>,
override val isCollapsingMenuLimit: Boolean = false
override val isCollapsingMenuLimit: Boolean = false,
override val isSticky: Boolean = false
) : BrowserMenuItem {
override var visible: () -> Boolean = { true }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,18 @@ import mozilla.components.concept.menu.candidate.CompoundMenuCandidate
*
* @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.
*/
class BrowserMenuSwitch(
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_switch

override fun asCandidate(context: Context) = super.asCandidate(context).copy(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ import mozilla.components.concept.menu.candidate.TextStyle
* @param iconTintColorResource Optional ID of color resource to tint the icon.
* @param textColorResource Optional ID of color resource to tint the text.
* @property subMenu Target sub menu to be shown when this menu item is clicked.
* @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 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.
*/
@Suppress("LongParameterList")
class ParentBrowserMenuItem(
Expand All @@ -42,6 +47,7 @@ class ParentBrowserMenuItem(
private val textColorResource: Int = NO_ID,
internal val subMenu: BrowserMenu,
override val isCollapsingMenuLimit: Boolean = false,
override val isSticky: Boolean = false,
endOfMenuAlwaysVisible: Boolean = false
) : AbstractParentBrowserMenuItem(subMenu, isCollapsingMenuLimit, endOfMenuAlwaysVisible) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ import mozilla.components.concept.menu.candidate.TextStyle
* @param textColorResource Optional ID of color resource to tint the text.
* @param textSize The size of the label.
* @param backgroundTint Tint for the menu item background color
* @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 isHighlighted Whether or not to display the highlight
* @param listener Callback to be invoked when this menu item is clicked.
*/
Expand All @@ -37,6 +40,7 @@ class SimpleBrowserMenuHighlightableItem(
private val textSize: Float = NO_ID.toFloat(),
@ColorInt val backgroundTint: Int,
override val isCollapsingMenuLimit: Boolean = false,
override val isSticky: Boolean = false,
var isHighlighted: () -> Boolean = { true },
private val listener: () -> Unit = {}
) : BrowserMenuItem {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,15 @@ import mozilla.components.support.base.log.Log
* @param action the [Action] to display.
* @param listener a callback to be invoked when this menu item is clicked.
* @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 WebExtensionBrowserMenuItem(
internal var action: Action,
internal val listener: () -> Unit,
internal val id: String = "",
override val isCollapsingMenuLimit: Boolean = false
override val isCollapsingMenuLimit: Boolean = false,
override val isSticky: Boolean = false
) : BrowserMenuItem {
override var visible: () -> Boolean = { true }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ class BrowserMenuCompoundButtonTest {
label: String,
initialState: () -> Boolean = { false },
listener: (Boolean) -> Unit
) : BrowserMenuCompoundButton(label, false, initialState, listener) {
) : BrowserMenuCompoundButton(label, false, false, initialState, listener) {
override fun getLayoutResource(): Int = R.layout.mozac_browser_menu_item_simple
}
}
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ permalink: /changelog/

* **browser-menu**:
* 🌟️ New StickyHeaderLinearLayoutManager and StickyFooterLinearLayoutManager that can be used to keep an item from being scrolled off-screen.
* To use this set `isSticky = true` for any menu item of the menu. Since only one sticky item is supported if more items have this property the sticky item will be the one closest to the top the menu anchor.

* **browser-menu**:
* 🚒 Bug fixed [issue #](https://github.com/mozilla-mobile/android-components/issues/10032) - Fix a recent issue with ExpandableLayout - user touches on an expanded menu might not have any effect on Samsung devices.
Expand Down

0 comments on commit 4ff10cf

Please sign in to comment.