I am trying to determine the best way to have a single ListView that contains different layouts for each row. I know how to create a custom row + custom array adapter to support a custom row for the entire list view, but how can I implement many different row styles in the ListView?
Since you know how many types of layout you would have - it's possible to use those methods.
getViewTypeCount() - this methods returns information how many types of rows do you have in your list
getItemViewType(int position) - returns information which layout type you should use based on position
Then you inflate layout only if it's null and determine type using
Look at this tutorial for further information.
To achieve some optimizations in structure that you've described in comment I would suggest:
ViewHolder. It would increase speed because you won't have to call
findViewById()every time in
getViewmethod. See List14 in API demos.
I hope that will help you. If you could provide some XML stub with your data structure and information how exactly you want to map it into row, I would be able to give you more precise advise. By pixel.
I know how to create a custom row + custom array adapter to support a custom row for the entire list view. But how can one listview support many different row styles?
You already know the basics. You just need to get your custom adapter to return a different layout/view based on the row/cursor information being provided.
ListView can support multiple row styles because it derives from AdapterView:
An AdapterView is a view whose children are determined by an Adapter.
If you look at the Adapter, you'll see methods that account for using row-specific views:
abstract int getViewTypeCount() // Returns the number of types of Views that will be created ... abstract int getItemViewType(int position) // Get the type of View that will be created ... abstract View getView(int position, View convertView, ViewGroup parent) // Get a View that displays the data ...
The latter two methods provide the position so you can use that to determine the type of view you should use for that row.
Of course, you generally don't use AdapterView and Adapter directly, but rather use or derive from one of their subclasses. The subclasses of Adapter may add additional functionality that change how to get custom layouts for different rows. Since the view used for a given row is driven by the adapter, the trick is to get the adapter to return the desired view for a given row. How to do this differs depending on the specific adapter.
For example, to use ArrayAdapter,
getView()to inflate, populate, and return the desired view for the given position. The
getView()method includes an opportunity reuse views via the
But to use derivatives of CursorAdapter,
newView()to inflate, populate, and return the desired view for the current cursor state (i.e. the current "row") [you also need to override
bindViewso that widget can reuse views]
However, to use SimpleCursorAdapter,
setViewValue()method to inflate, populate, and return the desired view for a given row (current cursor state) and data "column". The method can define just the "special" views and defer to SimpleCursorAdapter's standard behavior for the "normal" bindings.
Look up the specific examples/tutorials for the kind of adapter you end up using.