How to generate a dynamic menu with NavigationView that contains a notification counter?

12

I am developing an Android application that contains a menu that is generated dynamically, so the menu is generated by programming:

private void cargarAvisosMenu() 
{
    // Menu
    final Menu menu = this.mNavigationView.getMenu();


    // Carga de datos
    CentroSelection selection = new CentroSelection();
    CentroCursor cur = selection.query(getApplicationContext().getContentResolver());

    // Recorro el cursor de centros
    while (cur.moveToNext()) {
        boolean avisosTipoA = false;
        boolean avisosTipoB = false;

        Centro c = Centro.getFromCursor(cur);
        if (c.getIsTipoAVisible() && c.getComponenteTipoA().getControlesTipoAPendientes() > 0) {
            avisosTipoA = true;
        }
        if (c.getIsTipoBVisible() && c.getComponenteTipoB().getControlesTipoBPendientes() > 0){
            avisosTipoB = true;
        }

        if (avisosTipoA || avisosTipoB) {
            // Añado la sección y los items.
            final SubMenu subMenu = menu.addSubMenu(c.getNombre());
            if (avisosTipoA) {
                subMenu.add("TipoA").setIcon(R.drawable.ic_tipoA);
            }
            if (avisosTipoB) {
                subMenu.add("TipoB").setIcon(R.drawable.ic_tipoB);
            }
        }
    }
}

My intention is to add a counter that indicates the number of notifications (in the style of gmail).

According to the documentation this is possible, either through an xml menu, using the app:actionLayout attribute, or using the MenuItemCompat.setActionView() function. Since the menu I am developing is dynamic, I opted for the second option, so that the code would look like this:

private void cargarAvisosMenu() 
{
    // Menu
    final Menu menu = this.mNavigationView.getMenu();


    // Carga de datos
    CentroSelection selection = new CentroSelection();
    CentroCursor cur = selection.query(getApplicationContext().getContentResolver());

    // Recorro el cursor de centros
    while (cur.moveToNext()) {
        boolean avisosTipoA = false;
        boolean avisosTipoB = false;

        Centro c = Centro.getFromCursor(cur);
        if (c.getIsTipoAVisible() && c.getComponenteTipoA().getControlesTipoAPendientes() > 0) {
            avisosTipoA = true;
        }
        if (c.getIsTipoBVisible() && c.getComponenteTipoB().getControlesTipoBPendientes() > 0){
            avisosTipoB = true;
        }

        if (avisosTipoA || avisosTipoB) {
            // Añado la sección y los items.
            final SubMenu subMenu = menu.addSubMenu(c.getNombre());
            if (avisosTipoA) {
                subMenu.add("TipoA").setIcon(R.drawable.ic_tipoA);
            }
            if (avisosTipoB) {
                // subMenu.add("TipoB").setIcon(R.drawable.ic_tipoB);
                int itemId = subMenu.add("TipoB").getItemId();
                View menuItem = MenuItemCompat.setActionView(subMenu.findItem(itemId), R.layout.menu_notificaciones).getActionView();
                ((ImageView) menuItem.findViewById(R.id.ivMenuNotificaciones)).setBackground(getDrawable(R.drawable.ic_barcode));
                ((TextView) menuItem.findViewById(R.id.tvMenuNotificaciones)).setText("TipoB");
                ((TextView) menuItem.findViewById(R.id.tvContadorNotificaciones)).setText("100");
            }
        }
    }
}

And the file "menu_notificaciones.xml":

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="horizontal">
    <ImageView
        android:id="@+id/ivMenuNotificaciones"
        android:layout_width="64dp"
        android:layout_height="match_parent" />
    <TextView
        android:id="@+id/tvMenuNotificaciones"
        android:layout_width="wrap_content"
        android:layout_height="match_parent" />
    <TextView
        android:id="@+id/tvContadorNotificaciones"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="right"/>
</LinearLayout>

However, the menu does not load the "menu_notifications" view.

    
asked by hecnabae 10.12.2015 в 10:25
source

2 answers

5

Finally I solved the problem by creating the menu manually, entering a ListView within the NavigationView component.

<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/toolbar_actionbar"
    android:fitsSystemWindows="true">

    <!-- Contenido principal -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

        <FrameLayout
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clickable="true" />
    </LinearLayout>

    <!-- Menú Deslizable -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nvMenu"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="@android:color/white"
        android:fitsSystemWindows="true">

        <!-- Menú Deslizable basado en ListView -->
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <ListView
                android:id="@+id/left_drawer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/white"
                android:cacheColorHint="@android:color/transparent"
                android:choiceMode="singleChoice"
                android:divider="@android:color/transparent"
                android:dividerHeight="0dp" />
        </FrameLayout>
    </android.support.design.widget.NavigationView>
</android.support.v4.widget.DrawerLayout>

If I'm not mistaken, this is the mode that was used in the past for the development of menus. I am aware that it is not the solution I was looking for, however I can not find the way to add the counter by code directly to the control NavigationView .

    
answered by 14.12.2015 / 10:58
source
5

According to setActionView the action will be replaced when this Item is shown as an action within the father.

You need to indicate this action. You can do this using setShowAsAction . This describes when this item can be displayed.

    
answered by 10.12.2015 в 17:14