как установить количество непрочитанных уведомлений в NavigationView DrawerLayout?

Я создал один NavigationView внутри DrawerLayout с использованием Библиотека поддержки дизайна Android

 <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>

Теперь я хочу установить счетчик непрочитанных уведомлений для каждого элемента NavigationView, как показано ниже:

счетчик непрочитанных уведомлений

как установить счетчик непрочитанных уведомлений на элемент NavigationView?


person Priyank Patel    schedule 14.09.2015    source источник
comment
Читая декомпилированный код NavigationView (не удалось найти оригинал ...), похоже, что с NavigationView это невозможно сделать. Придется реализовать свое собственное.   -  person Zharf    schedule 14.09.2015
comment
androidhive.info/2013/11/ это лучший пример для вашего вопроса   -  person impathuri    schedule 25.09.2015
comment
@SatishPathuri Я спрашиваю, как это сделать с помощью NavigationView? В вашей ссылке не используется NavigationView.   -  person Priyank Patel    schedule 25.09.2015
comment
Отвечает ли это на ваш вопрос? Элементы меню NavigationView со счетчиком справа   -  person Prince    schedule 26.12.2019


Ответы (5)


Обновленный ответ:

Использование app:actionLayout с библиотекой поддержки 23.1.1 или выше будет поддерживать настраиваемый макет, как показано ниже.

Создайте свой собственный макет счетчика, как показано ниже.

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" />

Ссылка на него в элементе меню вашего ящика в 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"
    />

Обратите внимание, что вы должны использовать пространство имен app, не пытайтесь использовать android.

В качестве альтернативы вы можете вручную установить вид действия с помощью метода MenuItem.setActionView().

Найдите пункт меню и установите счетчик, как показано ниже:

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

Обратите внимание, что вам нужно будет использовать MenuItemCompat, если вам нужно поддерживать версии Android 2.x.

Предыдущий ответ (для более старой версии):

Решено с ListView внутри NavigationView, как показано ниже ...

<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>

В вашем элементе списка действий установите, как показано ниже ...

    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);

Слушатель щелчков для ListView в панели навигации ...

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;
}

}
person Priyank Patel    schedule 14.11.2015
comment
Отличный ответ, это нужно беречь - person Sauron; 06.04.2016
comment
Мне нужно больше кнопок, чтобы проголосовать за. Одного недостаточно. Отличный ответ! - person burntblark; 05.01.2017
comment
Отличный ответ (обновленная часть вверху). Следует отметить одно: мне пришлось обернуть TextView в RelativeLayout и установить android:layout_centerInParent="true" в TextView, чтобы получить его вертикальное центрирование при использовании рисованного фона. С помощью этого метода мне просто нужно было вызвать actionView?.findViewById(R.id.text_view), чтобы получить ссылку на TextView. - person Daniel Nugent; 18.10.2019
comment
Работает отлично, спасибо за решение! Это сэкономило мне много времени! - person hetsgandhi; 03.12.2019
comment
Обновленный ответ скопирован отсюда: stackoverflow.com/questions/30560663/ - person Prince; 26.12.2019

Я нашел это легко реализуемое решение на этом веб-сайте https://android.jlelse.eu/android-adding-badge-or-count-to-the-navigation-drawer-84c93af1f4d9 Выполните следующие действия.

Шаг 1. Создайте проект Android Studio, вместо того, чтобы выбирать пустое действие, выберите «Действия с навигационным ящиком».

Шаг 2: добавление атрибута actionViewClass в меню панели навигации (т. е. menu / youractivityname_drawer.xml)

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

<group android:checkableBehavior="single">
    <item
        android:id="@+id/nav_camera"
        android:icon="@drawable/ic_menu_camera"
        android:title="Import" />
    <item
        android:id="@+id/nav_gallery"
        app:actionViewClass="android.widget.TextView"
        android:icon="@drawable/ic_menu_gallery"
        android:title="Gallery" />
    <item
        android:id="@+id/nav_slideshow"
        app:actionViewClass="android.widget.TextView"
        android:icon="@drawable/ic_menu_slideshow"
        android:title="Slideshow" />
    <item
        android:id="@+id/nav_manage"
        android:icon="@drawable/ic_menu_manage"
        android:title="Tools" />
</group>

Step 3 : Declare the Navigation Drawer menu item and initialize the item with the badge value. In your main Activity, declare the menu item of the Navigation Drawer as given below

//Create these objects above OnCreate()of your main activity
TextView slideshow,gallery;

//These lines should be added in the OnCreate() of your main activity
 NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
 navigationView.setNavigationItemSelectedListener(this);

gallery=(TextView) MenuItemCompat.getActionView(navigationView.getMenu().
        findItem(R.id.nav_gallery));

slideshow=(TextView) MenuItemCompat.getActionView(navigationView.getMenu().
        findItem(R.id.nav_slideshow));

//This method will initialize the count value
initializeCountDrawer();

Шаг 5. Инициализируйте initializeCountDrawer () там, где это необходимо. Его также можно использовать для обновления значения счетчика или значка в пункте меню панели навигации.

private void initializeCountDrawer(){

   //Gravity property aligns the text
   gallery.setGravity(Gravity.CENTER_VERTICAL);
   gallery.setTypeface(null, Typeface.BOLD);
   gallery.setTextColor(getResources().getColor(R.color.colorAccent));
   gallery.setText("99+");
   slideshow.setGravity(Gravity.CENTER_VERTICAL);
   slideshow.setTypeface(null,Typeface.BOLD);                                                                                                                    slideshow.setTextColor(getResources().getColor(R.color.colorAccent));
  //count is added     
  slideshow.setText("7");
}

Источник: https://android.jlelse.eu/android-adding-badge-or-count-to-the-navigation-drawer-84c93af1f4d9

person Seunope    schedule 17.04.2017

NavigationView разработан как простой способ реализовать базовую панель навигации, соответствующую рекомендациям по дизайну материалов.

Если вам нужно что-то большее, чем базовая панель навигации (например, с элементами текстовой навигации и необязательным заголовком), вам нужно будет создать свой собственный макет для панели навигации.

person Bryan Herbst    schedule 19.09.2015

Я предлагаю вам удалить NavigationView и добавить элементы навигационного ящика как фрагмент, то есть в файл DarawerLayout.

<android.support.v4.widget.DrawerLayout    xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<LinearLayout

<fragment
    android:id = "@+id/fragment_navigation_drawer"
    android:layout_width="280dp"
    android:layout_height="match_parent"
    android:layout_gravity = "start"
    android:layout= "@layout/fragment_navigation_drawer"
    android:name="com.your_package.NavigationDrawerFragment"
    tools:layout="@layout/fragment_navigation_drawer" />

</android.support.v4.widget.DrawerLayout>

Then create a class for the fragment and create a resource file for the class that will contain the elements for your drawer i.e.

public class NavigationDrawerFragment extends Fragment {
...

@Override
public View onCreateView(final LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View rootView = inflater.inflate(R.layout.fragment_navigation_drawer, container, false);
...

Затем вы можете добавить этот фрагмент в свою основную деятельность, т.е.

mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
    navigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.fragment_navigation_drawer);
    navigationDrawerFragment.setUp(R.id.fragment_navigation_drawer,mDrawerLayout, toolbar);

метод "настройки" находится во фрагменте, и именно там вы его инициализируете, т.е.

public void setUp(int fragmentId, DrawerLayout drawerLayout, final Toolbar toolbar) {

    containerView = getActivity().findViewById(fragmentId);
    mDrawerLayout = drawerLayout;
    mActionBarDrawerToggle = new ActionBarDrawerToggle(
            getActivity(), mDrawerLayout, toolbar,
            R.string.navigation_drawer_open, R.string.navigation_drawer_close
    ) {
        @Override
        public void onDrawerOpened(View drawerView) {
            super.onDrawerOpened(drawerView);

            }
            getActivity().invalidateOptionsMenu();

        }

        @Override
        public void onDrawerClosed(View drawerView) {
            super.onDrawerClosed(drawerView);


        }

}

В файле макета для ящика добавьте элементы, для которых вы хотите установить непрочитанное уведомление, а затем добавьте относительный макет, ориентацию которого вы установите вертикальным, т.е.

<RelativeLayout
    android:layout_below="@+id/drawer_layout_unread_notif"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="fill_parent">

Внутри этого вертикального относительного макета добавьте еще один относительный макет для элементов. Здесь вы можете добавить раздел «Оповещения», как на опубликованном вами изображении. Этот относительный макет должен быть горизонтальным, т.е.

<RelativeLayout
        android:layout_below="@+id/drawer_items_1"
        android:orientation="horizontal"
        android:background="@drawable/drawer_selector"
        android:clickable="true"
        android:layout_width="match_parent"
        android:id="@+id/drawer_items_2"
        android:layout_height="48dp">

        <ImageView
            android:src="@drawable/ic_notification"
            android:padding="8dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:layout_marginRight="16dp"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"/>

        <TextView
            android:text="Notifications"
            android:textColor="@color/primary_text"
            android:layout_marginLeft="72dp"
            android:layout_centerVertical="true"
            android:layout_gravity="center_vertical"
            android:padding="8dp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />

        <TextView
            android:background="@color/red"
            android:layout_marginRight="10dp"
            android:id="@+id/drawer_notifications"
            android:layout_alignParentRight="true"
            android:padding="8dp"
            android:layout_centerVertical="true"
            android:textColor="@color/white"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />


    </RelativeLayout>

Последний элемент textview в коде чуть выше него будет содержать счетчик, который вы хотите добавить для непрочитанных уведомлений. В xml его цвет установлен красный. Отсюда получите ссылку на него в классе фрагмента ящика навигации, используя его идентификатор (в oncreateview), и заполните его своим счетчиком.

Надеюсь это поможет!

person Gabriel Wamunyu    schedule 25.09.2015

Я полагаю, что поддержка этого была добавлена ​​в 23 библиотеки дизайна.

В XML-файле меню установите actionLayout в префиксе XML app:

<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.example.user.myapplication.MainActivity" >
    <item android:id="@+id/menu_one"
        android:checkable="true"
        android:title="Unread items"
        app:actionLayout="@layout/unread_items"
        />
</menu>

Затем включите макет меню для вычисления непрочитанных элементов, возможно, с использованием пользовательского представления или фрагмента для выборки данных.

person mmm111mmm    schedule 18.02.2016