Search code examples
androidxmlnavigation-drawermaterial-designcustom-lists

Custom List View in Navigation Drawer


I am trying to populate Navigation Drawer with some custom layout. XML file for that layout is below:

<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@+id/toolbar">

    <!-- The main content view -->

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

    </FrameLayout>
    <!-- The navigation drawer -->

    <LinearLayout
        android:orientation="vertical"
        android:id="@+id/left_drawer"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:divider="@android:color/transparent"
        android:dividerHeight="0dp"
        android:background="#FFFFFF">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_marginLeft="40px"
            android:layout_marginTop="40px">
            <ImageView
                android:id="@+id/imgUser"
                android:src="@drawable/empty_profile"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                />
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginLeft="20px"
                android:layout_marginTop="20px">
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="15sp"
                    android:text="Waqas Ahmed Ansari"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="63km"/>
                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:text="Joined: Feb '16"/>
            </LinearLayout>

        </LinearLayout>

        <ListView
            android:id="@+id/lstDrawerItems"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:choiceMode="singleChoice"
            android:layout_marginTop="20sp" />

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

Then I made a CustomAdapter class for ListView lstDrawerItems Here it is.

public class CustomAdapter extends BaseAdapter {
public ArrayList<HashMap<String, String>> list;
Activity activity;
TextView txtFirst;
ImageView imgView;

public CustomAdapter(Activity activity, ArrayList<HashMap<String, String>> list) {
    super();
    this.activity=activity;
    this.list=list;
}

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

    LayoutInflater inflater=activity.getLayoutInflater();

    if(convertView == null){
        convertView = inflater.inflate(R.layout.custom_drawer_list, null);

        txtFirst = (TextView) convertView.findViewById(R.id.drawer_itemName);
        imgView = (ImageView) convertView.findViewById((R.id.drawer_icon));
    }

    HashMap<String, String> map=list.get(position);
    txtFirst.setText(map.get("name"));
    imgView.setImageResource(Integer.parseInt(map.get("imgDrawerIcon")));
    return convertView;
}

@Override
public int getCount() {
    return 0;
}

@Override
public Object getItem(int position) {
    return null;
}

@Override
public long getItemId(int position) {
    return 0;
}

}

When I set list adapter, I am not able to see anything. I set custom adapter here. CustomAdapter adapter = new CustomAdapter(HomeNoVehicle.this, list); ListView drawerList = (ListView) findViewById(R.id.lstDrawerItems); drawerList.setAdapter(adapter); enter image description here

But when I set the entries attribute if list, it works well. enter image description here Can't figure out what the problem is.


Solution

  • In order to make a custom list, the way that I like to start is design the cell, or cells you wish to display in the list. Something maybe like this:

    Custom Cell

    Then I like to make a Class to go with that cell:

    public class ProfileCell extends RelativeLayout {
        ImageView imageView;
        TextView name;
        TextView dateJoined;
        TextView distance;
    
        String nameText;
        String dateJoinedText;
        String distanceText;
    
        public ProfileCell(Context context) {
            super(context);
            inflate(context, R.layout.nav_list_row, this);
            name = (TextView)findViewById(R.id.name);
            dateJoined = (TextView)findViewById(R.id.date_joined);
            distance = (TextView)findViewById(R.id.distance);
            imageView = (ImageView)findViewById(R.id.imgUser);
            //set Image to a default value
            imageView.setImageResource(R.mipmap.ic_launcher);
        }
        public String getNameText() {
            return nameText;
        }
    
        public void setNameText(String nameText) {
            this.nameText = nameText;
            name.setText(nameText);
        }
    
        public ImageView imageView() {
            return imageView;
        }
        public String getDateJoinedText() {
            return dateJoinedText;
        }
    
        public void setDateJoinedText(String dateJoinedText) {
            this.dateJoinedText = dateJoinedText;
            dateJoined.setText(dateJoinedText);
        }
    
        public String getDistanceText() {
            return distanceText;
        }
    
        public void setDistanceText(String distanceText) {
            this.distanceText = distanceText;
            distance.setText(distanceText);
        }
    }
    

    Then I also find it convenient to make a class that can hold the information that I want to put in that cell:

    public class Profile {//Information about Users Profile
    
    
    
        public String name;
        public String dateJoined;
        public String distance;
    /////////possibly have image url here ....
    
        public Profile(String name, String dateJoined, String distance)
        {
            this.name = name;
            this.dateJoined = dateJoined;
            this.distance = distance;
        }
    
    }
    

    Then I make my custom adapter class:

    public class CustomAdapter extends BaseAdapter {
        ArrayList<Profile> profiles;
        Context context;
    
        public CustomAdapter(Context context, ArrayList<Profile> profiles)
        {
            this.context = context;
            this.profiles = profiles;
        }
    
        @Override
        public int getCount() {
            return profiles.size();
        }
    
        @Override
        public Profile getItem(int position) {
            return profiles.get(position);
        }
    
        @Override
        public long getItemId(int position) {
            return position;
        }
    
        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            if (convertView == null)
            {
                //Custom Cell is inflated inside of the Profile view class
                convertView = new ProfileCell(context);
    
            }
            ProfileCell cell = (ProfileCell) convertView;
            Profile profile = getItem(position);
            cell.setNameText(profile.name);
            cell.setDateJoinedText(profile.dateJoined);
            cell.setDistanceText(profile.distance);
            //Then you would set the image view to something...
            // cell.imageView().setImageResource(R.mipmap.ic_launcher);
            //something like that maybe
    
            return cell;
        }
    }
    

    Then if I have set up my list view where I want it, in your case inside a navigation drawer then inside of your navigation activity you can do this:

    //A list of data to display in list
            ArrayList<Profile> profiles = new ArrayList<>();
    
            for (int i = 0; i < 15; i++)
            {
                profiles.add(profile);//Adding same profile over an over
            }
    
            CustomAdapter adapter = new CustomAdapter(this,profiles);
    
            listView.setAdapter(adapter);
    

    And then this would display whatever you put in those cells.

    I put the full code for this up here: https://github.com/amffz9/NavigationProject