I have a ListView that has a custom ArrayAdapter with a custom XML row.
I am passing in objects and everything words fine. However, I want to repeat each row 5 times within the ArrayAdapter. In the adapter, I would like to make minor adjustments to each and the current setup it isn't feasible to make adjustments prior to passing in to the adapter.
Is it possible to do this? I can't seem to conjure up the correct search terms to find any hints.
There are two ways i know:
1. Add repeated items to the dataset multiple times. Since you are referencing to the same object it is pretty cheap.
You can store the number of repetitions in the objects, and implement methods getCount(), getObject(), getView(), getItemId() remembering the count of repetitions.
f.e. if you have Foo object with 2 repetitions and Bar with no repetitions getCount should return (2 + 1) + 1. You also probably would like to count that values in the constructor or maybe when the data set changes to speed up ui a litle bit.
Related
I'm new at Android programming and I'm stuck in a situation for two days that I can't seem to solve.
I've got a ListActivity that should be populated with two different views that has almost no simularity. Untill now I've used MergeAdapter and it worked fine but my outcome was like this:
Adapter1,Adapter2. and I didn't have the ability to change the order of the items coming to the list.
My question is: is it possible to create an adapter that is holding items of two views and not adapters of two views so I'll have my items sorted by the way I input them?
For simplicity sake, I got an ArrayList of those two items and each has "int position" so I'll be able to insert them into the list sorted by position.
EDIT: I've tried extending BaseAdapter but once again I need two adapters as I've read online but if I do so, I won't be able to control the place of an item on the list.
I hope I'm more clear this time.
Welcoming any response.
Thank you.
You can subclass BaseAdapter and utilize the following methods:
getItemViewType(int position)
getViewTypeCount()
getViewTypeCount() should return the number of different row types your adapter supports. getItemViewType() is where you implement the "decision" of which view type a particular row should have. If, for example, getViewTypeCount() returns 3, then getItemViewType() method should return 0, 1, or 2.
You can use this inside of getView to inflate/create a different layout for different row types.
EDIT:
Since it's a custom adapter, you can implement it in whatever way makes sense for your data. If you can create a data structure that works for what you want, then just make the adapter able to work with that. In the worst case, you might just have an array (or list) of Objects and have to use instanceof to do the decision work.
I'm trying to make list of items, where each item may have other item with a value connected to it.
Something like:
Item 1
**SubItem1.1 - val1
**SubItem1.2 - val2
Item 2
**SubItem2.1 - val3
Item3
**SubItem3.1 - val4
**SubItem3.2 - val5
**SubItem3.3 - val6
There might be a dynamic number of Items and a dynamic number of Sub-items for each Item. There is always one value for each subitem.
The Items, subItems and values are found from a database, but there are an alogrithm with calculations to get the correct subitems and values for each Item, so I do not think I can use a SimpleCursorAdapter directly.
How should I write this adapter and what should the xml-files look like. Do I need two xml-files with ListView? (Since there basically are two lists? (One with Items, and one list for each Item with Sub-items/values))
If your data comes from a Cursor, this implentation looks interesting. Otherwise, this implementation works fine.
And finally, there is one you can get from RoboSpice motivations repo : for a more static data set.
You should only take great care, inside you getView method to use the recycled pool of views and to avoid instanciating too many objects. To avoid using instanceof (as it is costly) to test the recycled views, you must use getViewTypeCount and getViewType correctly.
I have to implement something like that:
"ListViews"
I call month.setadapter(adapter) once for each year but it's not working because the last month overwrites the information of the previous last one.
Please help me regarding this.
What I normally do in a situation like this is implement it as a single custom adapter.
Derive from BaseAdapter
Set your data as a non-generic ArrayList. You can fill your ArrayList with data representing your month rows and the detail rows within each month. You need some way of differentiating them in the adapter, so wrap things in custom objects that allow you to do this. In your example above, I'd say you can iterate through your data and insert a Date object each time you reach a row with a different month than the previous data row.
Your adapter should override getItemViewType and getItemViewCount. getItemViewCount returns the total number of different view types (looks like you'll return 2 from this method).
In getView, take the position parameter and pass it to getItemViewType. In getItemViewType, get the item in your ArrayList at the current position and test it for its data type. Return a constant representing which type of data to display.
In getView, now that you have the data type to display, run code appropriate for this display - inflate the layout representing the appropriate row type and set the appropriate data on the child views of the layout.
All of this is covered in the "World of ListView" video from Google I/O 2010 that ALL Android programmers should watch at least once:
http://www.youtube.com/watch?v=wDBM6wVEO70
I have a dynamically created list of items which should be displayed in either two or one column depending on the space the containing text needs e.g. if the text is long it will only be one item per row, otherwise two. Obviously they should all be the same size (half the screen size).
As far as I know there's no standard Android view with Adapter that does that. With a GridView you can have multiple columns, but not some rows one column and others two. A TableLayout could stretch views, but also here you have to know how many columns you need per row. Plus it doesn't have an Adapter.
So what I want to know a) is there any control that I'm missing that supports something like this or b) what would be the easiest solution for this problem?
EDIT: the items also contain a CheckBox and I need to keep track of the checked state so I can't just put two items in one view using an Adapter.
I'd say that this is a hard problem to solve using standard components, due to the problem of mapping data to items to rows.
If you for example use a Cursor with x rows to feed the adapter with data, then the total item count as seen from the Adapter is also x. However, since you're conditionally mapping two items to the same row, it means that a ListView will see y rows in the Adapter, where y <= x. But you cannot easily tell from the beginning what y will be. Furthermore, if the ListView asks the Adapter for item i where 0 <= i < y, there would be no (easy) way for the Adapter to determine which elements from the Cursor that i would map to.
That being said, a viable solution would be to subclass AdapterView or ListView and implement the layout of the elements yourself. As you're getting each item from the Adapter, you'll measure and layout it, depending on the sizes of the surrounding adapter items.
A different solution that could work for you if you don't have a large number of elements is to use two custom Adapters, one called ItemAdapter and one called RowAdapter. The ItemAdapter will inflate the actual items based on (the presumed) Cursor. The RowAdapter will use the ItemAdapter to get the items and merge them into rows. The ListView will in turn use the RowAdapter. The issue is that to know how many rows the RowAdapter will produce, it is necessary to measure all the items from ItemAdapter before the RowAdapter is connected to the ListView.
As far as I know there is no ready solution for your problem. I haven't yet tried something like this, but I would use a LinearLayout as the list item. Then just create your own Deflater (e.g. CursorAdapter) that deflates the Layout and checks the length. If needed you should be able to add a new View (e.g. TextView) to the LinearLayout.
I have a custom adapter to display a list of items with section headings. I've looked at Jeff Sharkey's SeparatedListAdapter and CommonsWare's MergeAdapter as examples of how to achieve this, and I now have a solution which works by providing a separate adapter for the content of each section.
This creates a big performance problem, though. In my case, there are potentially thousands of items in the list, each with an associated date, and I want to use the date as section heading for all the items with that date.
So, without section headings, I'd have a single Cursor which returns the items sorted by date. Nice and easy.
With section headings, I'm currently doing this:
One Cursor to select all distinct dates in the dataset
For each distinct date, a separate Cursor to return the items matching that date
Pour the dates (section headings) and separate SimpleCursorAdapters for each date's items, into my custom adapter.
This requires many more database queries and Cursors to be generated than I want, and there's a delay of several seconds before the ListView appears.
I suspect there might be a simpler solution where getView does something clever and detects when the date has changed between successive items, and then sneaks in a new heading by itself, thus requiring just the one Cursor. Can anyone suggest a way of doing this?
I guess the easiest way would be to check within every getView call whether the previous item has a different date, and if so to simply embed the header within the current view.
You can try http://code.google.com/p/android-section-list/, which requires just single cursor behind (returning cursor + section in one object). However it will anyhow have to go through all the elements (once) to calculate the size of resulting list+headers (needed by list adapter) - so it might still be slow.