Navigation Drawer with counter

In my previous post I described how to create a Navigation Drawer.
Some readers asked me how to integrate the menu with a counter, just as it appears in the official documentation.

Something like this...


I think we can achieve it in many ways.
Let's start with row layout.


<!--xml version="1.0" encoding="utf-8"?-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/ns_menu_row"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="48dp" >

        <!-- icon -->
        <ImageView
            android:id="@+id/menurow_icon"
            android:layout_width="48dp"
            android:layout_height="48dp"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="12dp"
            android:layout_marginRight="12dp"
            android:src="@drawable/ic_launcher_" />

        <!-- text -->
        <TextView
            android:id="@+id/menurow_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_toRightOf="@+id/menurow_icon"
            android:gravity="center_vertical"
            android:minHeight="?android:attr/listPreferredItemHeightSmall"
            android:textAppearance="?android:attr/textAppearanceListItemSmall" />

        <!-- counter -->
        <TextView
            android:id="@+id/menurow_counter"
            android:layout_width="32dp"
            android:layout_height="32dp"
            android:layout_alignParentRight="true"
            android:layout_marginRight="8dp"
            android:layout_marginTop="8dp"
            android:background="@drawable/rectangle"
            android:gravity="center"
            android:minHeight="?android:attr/listPreferredItemHeightSmall"
            android:padding="6dp"
            android:textAppearance="?android:attr/textAppearanceListItemSmall"
            android:textColor="#FFFFFF"
            android:textSize="12sp"
            android:textStyle="bold" />
    </RelativeLayout>

    <!-- divider -->
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_marginBottom="1dp"
        android:layout_marginTop="1dp"
        android:background="#DADADC" />

</LinearLayout>
For each row we use a RelativeLayout with a ImageView which is icon, a TextView which is the title and an other TextView which is the counter.
Our counter is a simple TextView.
We use android:layout_alignParentRight="true" to align it on the right.

It is very important this line: android:background="@drawable/rectangle".
We use a rectangular shape with rounded corners to draw the counter's background.
Here you can find rectangle.xml:

<!--xml version="1.0" encoding="utf-8"?-->
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
   <solid android:color="#5490CC"/>
   <corners android:radius="8px"/> 
   <stroke  android:width="2dip" android:color="#A4C2E0"/>  
</shape>
Now we need to adjust our Model and Adapter:
public class NsMenuItemModel {

    public int title;
    public int iconRes;
    public int counter; //counter
    public boolean isHeader;
       
           ....

}
public class NsMenuAdapter extends ArrayAdapter {

      ......

      public static class ViewHolder {
           public final TextView textHolder;
           public final ImageView imageHolder;
           public final TextView textCounterHolder;

           public ViewHolder(TextView text1, ImageView image1,TextView textcounter1) {
              this.textHolder = text1;
              this.imageHolder = image1;
              this.textCounterHolder=textcounter1;
           }
      }

      public View getView(int position, View convertView, ViewGroup parent) {

           NsMenuItemModel item = getItem(position);
           ViewHolder holder = null;
           View view = convertView;

           if (view == null) {
                int layout = R.layout.ns_menu_row_counter;
                if (item.isHeader)
                     layout = R.layout.ns_menu_row_header;

                view = LayoutInflater.from(getContext()).inflate(layout, null);

                TextView text1 = (TextView) view.findViewById(R.id.menurow_title);
                ImageView image1 = (ImageView) view.findViewById(R.id.menurow_icon);
                TextView textcounter1 = (TextView) view.findViewById(R.id.menurow_counter);
                view.setTag(new ViewHolder(text1, image1,textcounter1));
           }

           if (holder == null && view != null) {
                Object tag = view.getTag();
                if (tag instanceof ViewHolder) {
                       holder = (ViewHolder) tag;
                }
           }
  
  
           if(item != null && holder != null){

                if (holder.textHolder != null)
                       holder.textHolder.setText(item.title);
      
                //Counter
                if (holder.textCounterHolder != null){                      
                       if (item.counter > 0){
                            holder.textCounterHolder.setVisibility(View.VISIBLE);
                            holder.textCounterHolder.setText(""+item.counter);
                       }else{
                            //Hide counter if == 0 
                            holder.textCounterHolder.setVisibility(View.GONE);
                       }
                }
      
                if (holder.imageHolder != null) {
                       if (item.iconRes > 0) {
                             holder.imageHolder.setVisibility(View.VISIBLE);
                             holder.imageHolder.setImageResource(item.iconRes);
                       } else {
                             holder.imageHolder.setVisibility(View.GONE);
                       }
                }
           }
     
           return view;  
      }
}
One last thing, you should reset counter when you click on the item.
That's all!


You can get code from GitHub:

Comments

Popular posts from this blog

AntiPattern: freezing a UI with Broadcast Receiver

How to centralize the support libraries dependencies in gradle

NotificationListenerService and kitkat