How to set adapter in case of multiple textviews per listview?
Asked Answered
N

3

10

I have a multiple TextViews per list item in my ListView. I've learned to write a proper getView method I believe but I'm not sure ho do I use setAdapter to call that method.

private static String[] project = {"proj1","proj2"};
private static String[] workRequests = {"requirement gathering", "design"};
private static String[] startDate = {"02/21/2012","07/15/2011"};
private static String[] status = {"WIP","DONE"};

ListView mListView;

public class MyDashboardActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mydashboard);

        final LayoutInflater mInflater = LayoutInflater.from(this);
        mListView = (ListView)findViewById(R.id.dashboardList);
        mListView.setAdapter(
                // How do I set the adapter?
                );
    }

    public View getView(int position, View convertView, ViewGroup parent) {
        System.out.println("enters");
        if(convertView == null){
            convertView = LayoutInflater.from(this).inflate(R.layout.mydashboard,null);
        }

        ((TextView) convertView.findViewById(R.id.project)).setText(project[position]);
        ((TextView) convertView.findViewById(R.id.work_request)).setText(workRequests[position]);
        ((TextView) convertView.findViewById(R.id.start_date)).setText(startDate[position]);
        ((TextView) convertView.findViewById(R.id.status)).setText(status[position]);

        return convertView;
    }

This is the xml layout:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/home_root"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- Include Action Bar -->
    <include layout="@layout/actionbar_layout" />

    <ListView
        android:id="@+id/dashboardList"
        style="@style/LeftHeaderText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        android:background="@drawable/innerdashboard_bg"
        android:textColor="@color/textColor" >

        <TextView android:id="@+id/project" />

        <TextView android:id="@+id/work_request" />

        <TextView android:id="@+id/start_date" />

        <TextView android:id="@+id/status" />

    </ListView>

</LinearLayout>

I've tried a few ways, none of which worked. Could anyone please suggest how to set the adapter in this case? Thanks!

Namangan answered 19/6, 2012 at 17:43 Comment(4)
see this complete example android-example-code.blogspot.in/p/…Trombley
some code missing... where is the class extending baseAdapter???Silicium
Is your getView() part of your Adapter class?Buzzer
I'm new to android guys, I'm not sure what I was trying to do. @gtumca-MAC works like a charm! Thank you.Namangan
C
19

You need to implement your own Adapter. My way is to also define an object which "represents" a view.

Below, there is a very simple example with two TextViews to fit your needs.

The object which represents a view (a row in the ListView) :

public class CustomObject {

    private String prop1; 
    private String prop2;

    public CustomObject(String prop1, String prop2) {
        this.prop1 = prop1;
        this.prop2 = prop2;
    }

    public String getProp1() {
        return prop1;
    }

    public String getProp2() {
       return prop2;
    }
}

Next the custom adapter :

public class CustomAdapter extends BaseAdapter {

   private LayoutInflater inflater;
  private ArrayList<CustomObject> objects;

   private class ViewHolder {
      TextView textView1;
      TextView textView2;
   }

   public CustomAdapter(Context context, ArrayList<CustomObject> objects) {
      inflater = LayoutInflater.from(context);
      this.objects = objects;
   }

   public int getCount() {
      return objects.size();
   }

   public CustomObject getItem(int position) {
      return objects.get(position);
   }

   public long getItemId(int position) {
      return position;
   }

   public View getView(int position, View convertView, ViewGroup parent) {
      ViewHolder holder = null;
      if(convertView == null) {
         holder = new ViewHolder();
         convertView = inflater.inflate(R.layout.your_view_layout, null);
         holder.textView1 = (TextView) convertView.findViewById(R.id.id_textView1);
        holder.textView2 = (TextView) convertView.findViewById(R.id.list_id_textView2);
         convertView.setTag(holder);
      } else {
         holder = (ViewHolder) convertView.getTag();
      }
      holder.textView1.setText(objects.get(position).getprop1());
      holder.textView2.setText(objects.get(position).getprop2());
      return convertView;
   }
}

Now you can define and set your adapter in your activity :

ArrayList<CustomObject> objects = new ArrayList<CustomObject>();
CustomAdapter customAdapter = new CustomAdapter(this, objects);
listView.setAdapter(customAdapter);

Now you only have to manage your CustomObject's in the objects list. Don't forget to invoke customAdapter.notifyDataSetChanged() when you want repercute modifications on the ListView.

Contortion answered 19/6, 2012 at 19:2 Comment(5)
Thank a lot, I'm trying it out.Namangan
So do I have to create custom adapters for every new ListView I create? (Which has multiple TextViews ofcourse)Namangan
@Harsh, If you want different views in your ListView's and if basic adapters aren't sufficient, yes you have to. Note that you can easily make much more complex views than just some TextView.Contortion
Or you could make your custom adapter extend ArrayAdapterFimble
How will we manage CustomObject? For example, I have a HashMap. How will I populate the objects?Immunoreaction
P
4

Your getView() code needs to go into a class that extends BaseAdapter or one of its subclasses.

One way to do this is to create a private class within your MyDashboardActivity. Here's a quick example below (some additional code will be required). You'll probably also want a custom object to associate all the things you want to display in one list item. Instead of multiple arrays, have one array of a custom type that has properties for each value you are tracking.

One more thing: your four TextViews should go into their own layout file (see list_item.xml here). That item layout file gets hooked up through the constructor of the custom adapter (I added a comment in the code below to highlight this).

protected CustomAdapter mAdapter;

public class MyDashboardActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mydashboard);

        final LayoutInflater mInflater = LayoutInflater.from(this);
        mListView = (ListView)findViewById(R.id.dashboardList);

        mAdapter = new CustomAdapter(this, <array to be adapted>);
        mListView.setAdapter(mAdapter);
    }

    private class CustomAdapter extends ArrayAdapter<String> {

        protected Context mContext;
        protected ArrayList<String> mItems;

        public CustomAdapter(Context context, ArrayList<String> items) {
            super(context, R.layout.custom_list_item, items); // Use a custom layout file
            mContext = context;
            mItems = items;
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            System.out.println("enters");
            if(convertView == null){
                convertView = LayoutInflater.from(this).inflate(R.layout.mydashboard,null);
            }

            // You'll need to use the mItems array to populate these...
            ((TextView) convertView.findViewById(R.id.project)).setText(project[position]);
            ((TextView) convertView.findViewById(R.id.work_request)).setText(workRequests[position]);
            ((TextView) convertView.findViewById(R.id.start_date)).setText(startDate[position]);
            ((TextView) convertView.findViewById(R.id.status)).setText(status[position]);

            return convertView;
        }
    }
}
Piotr answered 19/6, 2012 at 18:26 Comment(2)
You are a lifesaver dude. I love youJohen
Thanks for this, I'm using it. But one small suggestion: IntelliJ IDEA gives a warning for "inflate(R.layout.mydashboard,null)", and this answer https://mcmap.net/q/108141/-avoid-passing-null-as-the-view-root-need-to-resolve-layout-parameters-on-the-inflated-layout-39-s-root-element suggests changing that to "inflate(R.layout.mydashboard,parent,false)". I did that and IntelliJ stopped nagging me and it still works.Juna
S
2

There are a few ways to do this. I'll show you my way wich contains two layouts, the first being just the ListView its self and the other is how the text should appear per list item.

listset.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical">

    <ListView
        android:id="@+id/shipMenu"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</LinearLayout>

listitems.xml (You can also put images in here, the idea here is control)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/makerID"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:textSize="25dp"/>

</LinearLayout>

With the above I don't have the artwork yet but I intend to add an ImageView for icons (and you can add more TextViews too). Here is my custom adapter class.

ListAdapter.java

class ListAdapter extends ArrayAdapter <String>
{

    public ListAdapter(Context context, String[] values) {

        super(context, R.layout.listitems, values); //set the layout that contains your views (not the one with the ListView)
    }

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

        LayoutInflater inflater = LayoutInflater.from(getContext());
        View view = inflater.inflate(R.layout.listitems, parent, false); //same here.

        String text = getItem(position);

        TextView makerID = (TextView) view.findViewById(R.id.makerID);
        makerID.setText(text);

        return view;
    }

}

In your main activity file set

setContentView (R.layout.listset);

And add this underneath in same brackets as setContentView()

ListAdapter adapter = new ListAdapter(this, MyString[]); //place your String array in place of MyString

        ListView lv = (ListView) findViewById(R.id.ListViewID); //the ID you set your ListView to.
        lv.setAdapter(adapter);

Edit

I'm a bit late to the party it looks like but maybe this will help someone.

Satan answered 28/10, 2015 at 23:47 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.