1

I have an Apple class with two fields, colour and rotation, and an AppleView View which draws the apple in that colour and rotation in its onDraw method (this is a simplification of my actual code). The AppleView has a default apple (let's say, red and rotated by 0 degrees) which can be reassigned. Here is some pseudocode for the two classes:

public class Apple {
    int colour;
    int rotation;
}

public class AppleView extends View {
    Apple apple = getDefaultApple();

    @Override
    protected void onDraw(Canvas canvas) {
        drawApple(canvas, apple);
    }
}

I'd like to make a ListView of AppleViews from an ArrayList of apples. I create two layouts: a ListView (R.layout.list_view):

<?xml version="1.0" encoding="utf-8"?>
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:id="@android:id/list">
</ListView>

and a list item, which is just an AppleView (R.layout.list_item):

<?xml version="1.0" encoding="utf-8"?>
<com.mypackage.AppleView xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:id="@+id/apple">
</com.mypackage.AppleView>

Finally, I extend ListActivity and use a custom adapter class to draw the list items:

public class MyListActivity extends ListActivity {

    ArrayList<Apple> apples = new ArrayList<Apple>();

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_view);

        // Add 100 random apples to the list for demonstration.
        for (int i = 0; i < 100; i++) {
            apples.add(getRandomApple());
        }

        getListView().setAdapter(new MyAdapter(this, R.layout.list_item, apples));
    }

    class MyAdapter extends ArrayAdapter<Apple> {
        public MyAdapter(Context context, int resourceID, ArrayList<Apple> items) {
            super(context, resourceID, items);
        }

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

            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.list_item, parent, false);
            }

            // Change this AppleView's apple to the new ArrayList element at this position.
            AppleView appleView = (AppleView) convertView.findViewById(R.id.apple);
            appleView.apple = apples.get(position);

            return convertView;
        }
    }
}

Although all the right methods are being called (i.e. getView and onDraw for each apple), the ListView does not display:

enter image description here

Where is the error in the above code?

1''
  • 26,823
  • 32
  • 143
  • 200
  • my guess: there is something wrong with your drawApple() method. The adapter looks fine. – Philipp Jahoda Sep 14 '13 at 18:30
  • @PhilippJahoda I've already used the drawApple() method to draw individual apples, so the method itself is definitely not the issue. – 1'' Sep 14 '13 at 18:37
  • set the layout_width and layout_height of your apple view to a fixed valued e.g. 100dp for testing purposes. match parent doesn't really make sense in this case. – Suau Sep 14 '13 at 18:46
  • Post the constructor of your custom-view. – Philipp Jahoda Sep 14 '13 at 18:49
  • i'd also try to set a background color on the listview e.g. green and a background color for your apples e.g. red, just to see if they are actually drawn on screen. – Suau Sep 14 '13 at 18:49
  • @PhilippJahoda The constructor is just `super(context, attrs);` and a bunch of `Paint` initialization. I'm sure the problem isn't there. – 1'' Sep 15 '13 at 01:08
  • @Su-AuHwang You're right about needing a fixed value - but for the height only. – 1'' Sep 15 '13 at 04:39
  • I think ListView actually applies wrap_content, when it detects match_parent for layout_height (not verified, just my experience), so your AppleView probably needs some changes in onMeasure. – Suau Sep 16 '13 at 03:30
  • @Su-AuHwang That's a good alternative to my solution in cases where a fixed height is impractical, for instance when the ListView elements need to take up a fixed fraction of the screen height. – 1'' Sep 16 '13 at 03:34

2 Answers2

0

The height of a ListView element set to match_parent is not defined (i.e. it's 0) because the height is determined by the size of the content. To fix the issue, specify a fixed height for the element, e.g.:

<?xml version="1.0" encoding="utf-8"?>
<com.mypackage.AppleView xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="match_parent"
      android:layout_height="100dp" /* THIS LINE CHANGED */
      android:id="@+id/apple">
</com.mypackage.AppleView>
1''
  • 26,823
  • 32
  • 143
  • 200
0
I have made some change with your arrayadapter.
 class MyAdapter extends ArrayAdapter<ArrayList<Apple>> {
        private ArrayList<Apple> apple = null;
        public MyAdapter(Context context, int resourceID, ArrayList<Apple> items) {
            super(context, resourceID, items);
            this.apple = items;
        }


  @Override
        public int getCount() {
    //Check with this size if it is greater than zero,then list is visible
            return apple.size();
        }


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

            if (convertView == null) {
                convertView = getLayoutInflater().inflate(R.layout.list_item, parent, false);
            }

            // Change this AppleView's apple to the new ArrayList element at this position.
            AppleView appleView = (AppleView) convertView.findViewById(R.id.apple);
            appleView.apple = apple.get(position);

            return convertView;
        }
    }
ygsankar
  • 119
  • 2
  • 13