4

I am trying to populate a listview where each row has 2 textviews and a button. I think I nearly have it working properly but right now the ListView only shows 1 item in the ListView and ignores the other data. I also have 2 xml files (shelfrow.xml (2 textfields, 1 button) and shelflist.xml(contains the listview)). Here is the core code of my Shelf.java class. (MyListItemModel is a class for storing each book)

List<MyItemModel> myListModel = new ArrayList<MyItemModel>();
try{
JSONArray entries = json.getJSONArray("entries");
for(int i=0;i<entries.length();i++){                        
     MyItemModel item = new MyItemModel();    
     JSONObject e = entries.getJSONObject(i);
     alKey.add(e.getInt("key")); 
     item.id = i;
     item.title = e.getString("title");
     item.description = e.getString("description");

      myListModel.add(item);
 }

}catch(JSONException e)        {
Log.e("log_tag", "Error parsing data "+e.toString());
}
//THIS IS THE PROBLEM I THINK - ERROR: The method inflate(int, ViewGroup) in the type LayoutInflater is not applicable for the arguments (int,Shelf)
MyListAdapter adapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.shelfrow,this));

adapter.setModel(myListModel);
setListAdapter(adapter);
lv = getListView();
lv.setTextFilterEnabled(true); 

and some of the code in my class MyListAdapter

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

 if(convertView==null){
   convertView = renderer;

    }
    MyListItemModel item = items.get(position);
     // replace those R.ids by the ones inside your custom list_item layout.
     TextView label = (TextView)convertView.findViewById(R.id.item_title);
     label.setText(item.getTitle());
     TextView label2 = (TextView)convertView.findViewById(R.id.item_subtitle);
    label2.setText(item.getDescription());
    Button button = (Button)convertView.findViewById(R.id.btn_download);
    button.setOnClickListener(item.listener);
    //}
    return convertView;
}
Plokoon
  • 125
  • 2
  • 4
  • 9

1 Answers1

9

It is because you inflate the View when you create the Adapter. Since you only create the Adapter once, you only inflate one View. A View needs to be inflated for every visible row in your ListView.

Instead of passing the inflated View to the constructor of MyListAdapter:

MyListAdapter adapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.shelfrow,this));

...

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

    if(convertView == null) {
        convertView = renderer;
    }
    ...
}

Thy this:

// Remove the constructor you created that takes a View.
MyListAdapter adapter = new MyListAdapter();

...

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

    if(convertView == null) {
        // Inflate a new View every time a new row requires one.
        convertView = LayoutInflater.from(context).inflate(R.layout.shelfrow, parent, false);
    }
    ...
}
Gyan aka Gary Buyn
  • 12,242
  • 2
  • 23
  • 26
  • do i inflate like this? cause it doesn't quite work.. LayoutInflater mLayoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); renderer = mLayoutInflater.inflate(R.layout.shelf,null); – Plokoon May 21 '11 at 23:12
  • i'm quite new to android and kinda struggle with this. Also don't know how to bridge my adapter with the data properly.. this isn't quite right -- //MyListAdapter adapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.shelf, this)); //adapter.setModel(myListModel); //setListAdapter(adapter); – Plokoon May 21 '11 at 23:14
  • You'll need to be more specific than _it doesn't quite work_. If you are having problems other than the one already detailed in your question could you add to the question or open new questions? Thanks. – Gyan aka Gary Buyn May 21 '11 at 23:54
  • my first post shows the code for my class. It works ok until I try creating an instance of MyListAdapter - I don't know how to code it properly to pass my arraylist into MyListAdapter. I also don't know how to code the inflate view stuff.. – Plokoon May 22 '11 at 00:02
  • //THis is wrong..ERROR: The method inflate(int, ViewGroup) in the type LayoutInflater is not applicable for the arguments (int,Shelf) MyListAdapter adapter = new MyListAdapter(getLayoutInflater().inflate(R.layout.shelfrow,this)); – Plokoon May 22 '11 at 00:04
  • The error you receive is because you are passing an instance of `Shelf` (which, although you don't show it, I think extends `ListActivity`) when the method requires an instance of `ViewGroup`. I still think my original answer is what you need to do. I'm going to elaborate on the code in my answer now, hopefully that will help make it clearer. – Gyan aka Gary Buyn May 22 '11 at 01:50
  • I get this error now: context cannot be resolved to a variable (in my class MyListAdapter which extends BaseAdapter) – Plokoon May 22 '11 at 11:47
  • So then I added a variable at the top of my class 'private Context context' - this all compiled but when I ran it it crashed – Plokoon May 22 '11 at 12:04
  • Oh, that was a copy and paste error on my behalf. The concept of a [context](http://en.wikipedia.org/wiki/Context_(computing)) is common in software frameworks. A context contains the environment specific information needed for some tasks within the framework. So, you can see how creating your own (empty) context does not work as hoped. In Android every Activity is itself a context. – Gyan aka Gary Buyn May 22 '11 at 20:38