5

The getView method in my custom ArrayAdapter is getting called multiple times, which I assume it is meant to. Problem is, I have a quantity TextView which is dynamically set but when you scroll and the box goes off screen the value disappears. I am not sure what I am doing wrong and Google is not proving to be much help. Hopefully someone here can help me.

The adapater is called:

adapter = new MenuAdapter(thisActivity, R.layout.menu, list);
setListAdapter(adapter);

My Custom ArrayAdapter:

public MenuAdapter(Context context, int textViewResourceId, ArrayList<Object> menu) {
    super(context, textViewResourceId, menu);
    this.menu = menu;
    vi = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    
    public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
          
            Object cat = menu.get(position);
            if (cat.getClass().equals(Category.class)) {
                v = vi.inflate(R.layout.category, null);
                Category item = (Category)cat;
                v.setOnClickListener(null);
            v.setOnLongClickListener(null);
            v.setLongClickable(false);
            
                TextView tt = (TextView) v.findViewById(R.id.category);
                tt.setText(item.getName());      
         
            } else if (cat.getClass().equals(OrderItem.class)) {
                v = vi.inflate(R.layout.menu, null);
                OrderItem orderItem = (OrderItem)cat;
                Item item = orderItem.getItem();
                TextView tt = (TextView) v.findViewById(R.id.title);
                tt.setText(item.getName());   
                
                TextView bt = (TextView) v.findViewById(R.id.desc);
                bt.setText(item.getDescription());
                
                TextView qty = (TextView) v.findViewById(R.id.qty);
                qty.setId(item.getId());
                
                
                ImageButton minus = (ImageButton) v.findViewById(R.id.qtyMinus);
                minus.setTag(item);
                ImageButton plus = (ImageButton) v.findViewById(R.id.qtyPlus);
                plus.setTag(item);          
            }
            
            return v;
    }

The menu layout:

<?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="?android:attr/listPreferredItemHeight"
    android:padding="6dip"
    android:background="#FFFFFF">
        
    <RelativeLayout
        android:orientation="vertical"
        android:layout_width="0dip"
        android:layout_weight="1"
        android:layout_height="fill_parent"
        android:cacheColorHint="#FFFFFF"
        android:background="#FFFFFF">

        <TextView
            android:id="@+id/title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="center_vertical"
            android:textSize="16px"
            android:textColor="#000000"
        />
        <TextView
            android:id="@+id/desc"
            android:layout_below="@id/title"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:textSize="11px"
            android:textStyle="italic"
            android:textColor="#000000"
        />
    </RelativeLayout>
    <ImageButton
    android:id="@+id/qtyMinus"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/minus"
    android:paddingTop="15px"
    android:onClick="minusQty"  />
    <TextView
    android:id="@+id/qty"
    android:layout_width="50px"
    android:layout_height="50px"
    android:textColor="#000000"
    android:textSize="18px"
    android:gravity="center_vertical|center_horizontal"
    android:freezesText="true"
    android:background="@android:drawable/editbox_background"/>
    <ImageButton
    android:id="@+id/qtyPlus"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/plus"
    android:paddingTop="15px"
    android:onClick="addQty" />
</LinearLayout>
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Paul Blundell
  • 1,857
  • 4
  • 22
  • 27
  • Do u have 2 types of views? As in you have a Category Item and Order Item? If thats true then you need to change the way u r handling them. Your design needs a little more work. – Shubhayu Mar 24 '12 at 18:13

2 Answers2

5

getView() will be called multiple times as you note. It shouldn't matter, because your array adapter is based on the state of it's internal data model (array, list of objects, whatever). getView() should be idempotent in that calling it multiple times shouldn't change the result.

You say "when you scroll and the box goes off screen the value disappears". Note sure what mean. When you scroll one of the views generated in getView() off the visible area, and when you scroll it back, the value is different? without any other information, I'd have to say that's not possible. The reason is again that unless you are modifying the internal state of the adapter, or changing the adapter, you will always generate the same view for a given position.

By the way, convertView can be null, so you want to do something like,

View v = convertView;
if (v == null) {
  v = inflater.inflate(...);
}

// now use v in the rest of the method
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Jeffrey Blattman
  • 22,176
  • 9
  • 79
  • 134
  • Thanks for the fast response! You are correct. If I was to set the qty for an item to 5, if i scroll down and that item goes off screen when I scroll back up the value is now blank. – Paul Blundell Mar 24 '12 at 16:45
  • one possibility is that that object type in your "menu" collection in your adapter is neither a category or an order item. not sure how that would happen though. i would recommend that you add logging to getView() so you can see exactly what you are generating for each position, for each call. the only way the view could be empty is if you are generating an empty view. – Jeffrey Blattman Mar 24 '12 at 16:50
  • whats odd is if I add the if statement to check v is null before inflating, when I scroll to the bottom of the list I get a null pointer exception on this line: tt.setText(item.getName()); any ideas? – Paul Blundell Mar 24 '12 at 17:20
  • yes, it's bc of the arrangement of your getView(). you actually inflate one of two different views depending on the object type that's backing it. the convert coming in is most likely not the type of view you think it is, so the elements you are accessing are not avaialable. this is not a pattern i've seen before. i would recommend having a single view, where you make on section or the other visible depending on the object type. this is likely a source of your problems as well, but i can't say for sure. – Jeffrey Blattman Mar 24 '12 at 17:37
  • Thank you. From what you told me I changed it to a single view which then eventually took me in the right direction to fixing the issue. Many thanks. – Paul Blundell Mar 25 '12 at 10:20
-1

In your listview set android:height = "match_parent". Now getview called your dataset count. we can reuse the convertview. Check the convertview if it is NULL inflate your view. Otherwise, write your remaining code.

if(convertView ! = null)
{
 //rest of your Code
}
else
{
//inflate that view
}
Tyler Jandreau
  • 4,245
  • 1
  • 22
  • 47
Reeganth A
  • 11
  • 4