Search code examples
androidandroid-support-librarydrawerlayoutandroid-design-librarynavigationview

how to set unread notification count in NavigationView of DrawerLayout?


I have created one NavigationView inside DrawerLayout using Android Design Support Library

 <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_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:fitsSystemWindows="true">

     <!-- other views -->

     <android.support.design.widget.NavigationView
         android:id="@+id/navigation"
         android:layout_width="wrap_content"
         android:layout_height="match_parent"
         android:layout_gravity="start"
         app:menu="@menu/my_navigation_items" />
 </android.support.v4.widget.DrawerLayout>

my_navigation_items.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/bookmarks_drawer"
            android:icon="@drawable/ic_drawer_bookmarks"
            android:title="@string/bookmarks" />
        <item
            android:id="@+id/alerts_drawer"
            android:icon="@drawable/ic_drawer_alerts"
            android:title="@string/alerts" />
        <item
            android:id="@+id/settings_drawer"
            android:icon="@drawable/ic_drawer_settings"
            android:title="@string/settings" />
    </group> 
</menu>

Now, I want to set unread notification counter for each item of NavigationView like below image:

unread notification counter

how to set unread notification counter on item of NavigationView ?


Solution

  • Updated answer:

    Using app:actionLayout with support library 23.1.1 or higher will support the custom layout as below.

    Create your custom counter layout like below.

    menu_counter.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:textAppearance="@style/TextAppearance.AppCompat.Body2" />
    

    Reference it in your drawer menu item in xml.

    menu/drawer.xml:

    <item
        android:id="@+id/navigation_drawer_item_1"
        android:icon="@drawable/ic_menu_1"
        android:title="@string/navigation_drawer_item_1"
        app:actionLayout="@layout/menu_counter"
        />
    

    Note that you should use app namespace, don't try to use android.

    Alternatively you can manually set action view with MenuItem.setActionView() method.

    Find menu item and set counter like below code:

    private void setMenuCounter(@IdRes int itemId, int count) {
        TextView view = (TextView) navigationView.getMenu().findItem(itemId).getActionView();
        view.setText(count > 0 ? String.valueOf(count) : null);
    }
    

    Note, that you will need to use MenuItemCompat if you have to support Android 2.x versions.

    Previous Answer (For older version) :

    Solved with ListView inside NavigationView as below code...

    <android.support.design.widget.NavigationView
        android:id="@+id/my_courses_nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header" >
    
        <FrameLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="150dp" > <!-- Give layout margin top according to "headerLayout" height -->
    
            <ListView
                android:id="@+id/left_drawer"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@android:color/white"
                android:cacheColorHint="@android:color/transparent"
                android:choiceMode="singleChoice"
                android:divider="@android:color/transparent"
                android:dividerHeight="0dp" />
    
        </FrameLayout>
    </android.support.design.widget.NavigationView>
    

    In your activity set list item as below...

        private final String[] mMenuTitles = { getResources().getString(R.string.bookmarks), getResources().getString(R.string.alerts), getResources().getString(R.string.settings)  };
        private final int[] mMenuIconId = { R.drawable.ic_drawer_bookmarks, R.drawable.ic_drawer_alerts, R.drawable.ic_drawer_settings };
    
    
        ListView mDrawerList = (ListView) findViewById(R.id.left_drawer);
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
    
        private ArrayList<SlideMenuItem> drawerItemList = new ArrayList<SlideMenuItem>();           
        for( int i = 0; i < mMenuTitles.length; i++ ) {
            SlideMenuItem item = new SlideMenuItem();
            item.setTitle(mMenuTitles[i]);
            item.setIconID(mMenuIconId[i]);
            // item..setUnread(5) //set or update unread count & notify dataset changed to adapter
            drawerItemList.add(item);
        }
    
        MenuAdapter mMenuAdapter = new MenuAdapter( MyCoursesActivity.this, R.layout.drawer_list_item, drawerItemList);
        mDrawerList.setAdapter(mMenuAdapter);
    

    The click listener for ListView in the navigation drawer...

    private class DrawerItemClickListener implements ListView.OnItemClickListener {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            try {
                mDrawerLayout.closeDrawers();
                SlideMenuItem item =  (SlideMenuItem) parent.getItemAtPosition(position);
                switch (item.getIconId()) {
    
                    case R.drawable.ic_drawer_bookmarks: {
    
                    }
                    break;
                    case R.drawable.ic_drawer_alerts: {
    
                    }
                    break;
                    case R.drawable.ic_drawer_settings: {
    
                    }
                    break;                  
                    default: {
                    }
                    break;
                }
            } catch (Exception e) {             
            }
    
        }
    }
    

    MenuAdapter..java

    public class MenuAdapter extends ArrayAdapter<SlideMenuItem> {
    
    private Activity activity;
    private List<SlideMenuItem> itemList;
    private SlideMenuItem item;
    private int row;
    
    public MenuAdapter(Activity act, int resource, List<SlideMenuItem> arrayList) {
        super(act, resource, arrayList);
        this.activity = act;
        this.row = resource;
        this.itemList = arrayList;
    }
    
    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        View view = convertView;
        ViewHolder holder;
        if (view == null) {
            LayoutInflater inflater = (LayoutInflater) activity
                    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            view = inflater.inflate(row, null);
    
            holder = new ViewHolder();
            holder.tvTitle = (TextView) view.findViewById(R.id.menu_title);
            holder.imgView = (ImageView) view.findViewById(R.id.menu_icon);
            holder.tvUnread = (TextView) view.findViewById(R.id.unread_count);
            view.setTag(holder);
        } else {
            holder = (ViewHolder) view.getTag();
        }
    
        if ((itemList == null) || ((position + 1) > itemList.size()))
            return view;
    
        item = itemList.get(position);
    
        holder.tvTitle.setText(item.getTitle());
        holder.imgView.setImageResource(item.getIconId());
        if( item.getUnreadCount() > 0 ) {
            holder.tvUnread.setVisibility(View.VISIBLE);
            holder.tvUnread.setText(item.getUnread());
            if( MyCoursesActivity.DRAWER_MENU_ALERTS_POSITION == position ) {
                holder.tvUnread.setBackgroundResource(R.drawable.round_unread_count_bg_red);    
            }
            else {
                holder.tvUnread.setBackgroundResource(R.drawable.round_unread_count_bg_green);
            }
        }
        else {
            holder.tvUnread.setVisibility(View.GONE);
        }
        return view;
    }
    
    public class ViewHolder {
    
        public TextView tvTitle;
        public ImageView imgView;
        public TextView tvUnread;
    }
    
    }
    

    drawer_list_item.xml

    <LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:orientation="vertical">
    
    <RelativeLayout
    android:id="@+id/drawar_list_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
    
    <ImageView
        android:id="@+id/menu_icon"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:gravity="center_vertical"
        android:src="@drawable/ic_drawer" />
    
    <TextView
        android:id="@+id/menu_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toLeftOf="@+id/unread_count"
        android:layout_toRightOf="@+id/menu_icon"
        android:minHeight="?attr/listPreferredItemHeightSmall"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:text="About Us"
        android:gravity="center_vertical"
        android:textAppearance="?android:attr/textAppearanceSmall"
        android:textColor="@android:color/black" />
    
    <TextView
        android:id="@+id/unread_count"
        android:layout_width="20dp"
        android:layout_height="20dp"
        android:layout_alignParentRight="true"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:gravity="center" 
        android:text="99+"
        android:textColor="@android:color/white"
        android:textSize="10sp"
        android:visibility="gone" />
    

    SlideMenuItem.java

    public class SlideMenuItem {
    
    private Bitmap icon;
    private String title;
    private String unread;
    private int iconID;
    
    public String getTitle() {
        return title;
    }
    
    public void setTitle(String title) {
        this.title = title;
    }
    
    public Bitmap getIcon() {
        return icon;
    }
    
    public void setIcon(Bitmap icon) {
        this.icon = icon;
    }
    
    public int getIconId() {
        return iconID;
    }
    
    public void setIconID(int icon) {
        this.iconID = icon;
    }
    
    public String getUnread() {
        return unread;
    }
    
    public int getUnreadCount() {
        int count = Flinnt.INVALID;
        try {
            if( null != unread ) {
                count = Integer.parseInt(unread);
            }
        } catch (Exception e) {
        }
        return count;
    }
    
    public void setUnread(String unread) {
        this.unread = unread;
    }
    
    }