Search code examples
androidandroid-toolbarhighlightmenuitemactionmenuview

Highlight menu item in ActionMenuView after click


I am using an ActionMenuView to display set of filters that the user can select. After selecting a menu item in the ActionMenuView, I want this menu item to be highlighted until another menu item has been selected.

How do I keep the highlight of the menu item once it has been clicked? The desired result occurs when i put a breakpoint in the onMenuItemClick function, it is as follows:

Desired Result

EDIT Solved the problem, see my answer below


Solution

  • I managed to do this by modifying the icons of the ActionMenuView using layer-list (no highlight by default):

    <!-- drawable/filter_trade_requests_sort_by_creation_date.xml -->
    <?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item android:id="@+id/action_view_menu_base_currency_icon_background">
            <shape android:shape="oval">
                <solid android:color="#00000000" />
                <size
                    android:width="100dp"
                    android:height="100dp" />
            </shape>
        </item>
        <item
            android:drawable="@drawable/ic_baseline_arrow_upward_24px"
            android:gravity="center" />
    
    </layer-list>
    

    using the following ActionmenuView:

            <com.google.android.material.appbar.AppBarLayout
                android:id="@+id/fragment_trade_requests_app_bar"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fitsSystemWindows="true"
                android:theme="@style/AppTheme.AppBarOverlay">
    
                <androidx.appcompat.widget.ActionMenuView
                    android:id="@+id/fragment_trade_requests_action_menu_view"
                    android:layout_width="match_parent"
                    android:layout_height="?attr/actionBarSize"
                    android:background="?attr/colorPrimary"
                    app:popupTheme="@style/AppTheme.PopupOverlay" />
    
            </com.google.android.material.appbar.AppBarLayout>
    

    After an icon in the ActionMenuView is selected, I clear all highlights of the icons in the ActionMenuView and set the highlight of the currently selected icon. The methods are as follows:

    private fun setFilterIconHighLight(menuItem: MenuItem?, layerId: Int, color: Int) {
        val icon = menuItem?.icon as? LayerDrawable
        val background =
            icon?.findDrawableByLayerId(layerId) as? GradientDrawable
        background?.setColor(color)
    }
    
    private fun clearAllIconHighLights(menu: Menu) {
        for (menuItem in menu.iterator()) {
            val icon = menuItem.icon as? LayerDrawable
            val nrOfLayers = icon?.numberOfLayers
            if (nrOfLayers != null && nrOfLayers > 1) {
                for (i in 0 until nrOfLayers) {
                    val layer = icon.getDrawable(i)
                    if (layer is GradientDrawable) {
                        layer.setColor(ColorUtils.setAlphaComponent(Color.WHITE, 0))
                    }
                }
            }
        }
    }
    

    With the drawable listed above, usage would be as follows:

    private fun updateFilterUI(binding: FragmentTradeRequestsBinding) {
        val actionMenuView = binding.fragmentTradeRequestsActionMenuView.menu
        // Some condition that indicates that we need to highlight
        val menuItem = actionMenuView.findItem(R.id.filter_trade_requests_sort_by_creation_date)
        clearAllIconHighLights(actionMenuView)
        setFilterIconHighLight(
            menuItem,
            R.id.action_view_menu_date_icon_background,
            ColorUtils.setAlphaComponent(Color.WHITE, 50)
        )
    }
    

    A color with an alpha value of 50 is considered a highlight, while a color with an alpha value of 0 is not visible and thus clears the highlight