pez pez - 13 days ago 4
Android Question

Custom adapter for navigation drawer

I have a working navigation drawer that uses

ArrayAdapter
as shown in the documentation. I want to set
ImageView
icons for each of the navigation drawer items, so I need to create a custom adapter to use, but I am unsure of how to do that. What I have below runs without crashing the app, but the navigation drawer opens up empty, with nothing in it. Can you please help me out? Thanks in advance!

What I've done for a custom adapter so far:

public class CustomAdapter extends ArrayAdapter
{
private final Context context;

public CustomAdapter(Context context)
{
super(context, R.layout.drawer_list_item);
this.context = context;
}

@Override
public View getView(int position, View convertView, ViewGroup parent)
{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

View v = inflater.inflate(R.layout.drawer_list_item, parent, false);
TextView textViewHome = (TextView) v.findViewById(R.id.drawerHomeTextView);
ImageView imageViewHome = (ImageView) v.findViewById(R.id.drawerHomeImage);
TextView textViewList = (TextView) v.findViewById(R.id.drawerListTextView);
ImageView imageViewList = (ImageView) v.findViewById(R.id.drawerListImage);

return v;
}
}


Setting up the drawer in
MainActivity
:

mDrawerList = (ListView) findViewById(R.id.leftDrawer);

mDrawerList.setAdapter(new CustomAdapter(this));


The
ListView
used:

<ListView android:id="@+id/leftDrawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="left"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp"
android:background="#111"/>


drawer_list_item.xml
:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:layout_width="match_parent">

<RelativeLayout
android:id="@+id/drawerRelativeLayoutHome"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/drawerHomeImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:paddingStart="4dp"
android:paddingEnd="4dp"
android:paddingLeft="4dp"
android:src="@drawable/ic_menu_home"/>

<TextView
android:id="@+id/drawerHomeTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/drawerHomeImage"
android:layout_toEndOf="@+id/drawerHomeImage"
android:background="@drawable/background_activated"
android:paddingLeft="4dp"
android:paddingRight="4dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:text="Home"
android:textSize="20sp"/>
</RelativeLayout>

<RelativeLayout
android:id="@+id/drawerRelativeLayoutList"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/drawerRelativeLayoutHome">

<!-- same as above, but ic_menu_archive as drawable, and "List" as text -->

</RelativeLayout>

</RelativeLayout>

Answer

For your custom adapter:

public class NavDrawerAdapter extends ArrayAdapter<NavDrawerItem>
{
    private final Context context;
    private final int layoutResourceId;
    private NavDrawerItem data[] = null;

    public NavDrawerAdapter(Context context, int layoutResourceId, NavDrawerItem [] data)
    {
        super(context, layoutResourceId, data);
        this.context = context;
        this.layoutResourceId = layoutResourceId;
        this.data = data;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent)
    {
        LayoutInflater inflater = ((Activity) context).getLayoutInflater();

        View v = inflater.inflate(layoutResourceId, parent, false);

        ImageView imageView = (ImageView) v.findViewById(R.id.navDrawerImageView);
        TextView textView = (TextView) v.findViewById(R.id.navDrawerTextView);

        NavDrawerItem choice = data[position];

        imageView.setImageResource(choice.icon);
        textView.setText(choice.name);

        return v;
    }
}

For NavDrawerItem:

public class NavDrawerItem
{
    public int icon;
    public String name;

    public NavDrawerItem(int icon, String name)
    {
        this.icon = icon;
        this.name = name;
    }
}

For drawer_list_item.xml:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_height="wrap_content"
    android:layout_width="match_parent"
    android:background="?android:attr/activatedBackgroundIndicator"
    android:minHeight="?android:attr/listPreferredItemHeightSmall"
    android:padding ="10dp">

    <ImageView
        android:id="@+id/navDrawerImageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:paddingRight="10dp"/>

    <TextView
       android:id="@+id/navDrawerTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_toRightOf="@+id/navDrawerImageView"
        android:paddingRight="10dp"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"/>

</RelativeLayout>

In MainActivity.java, instantiate an array of NavDrawerItem objects, with the appropriate drawable and name for each, and then pass this array when you set the adapter, like so:

mDrawerList.setAdapter(new YourAdapter(this, R.layout.drawer_list_item, yourArray));