Write a Custom Adapter for ListView - android

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.

Related

Should I use 2 ListViews or 2 Adapters with 1 ListView

When it comes to a screen that contains 2 different lists depending on the state of say a checkbox at the top, is it better to use 2 listviews that you hide/show when the checkbox is selected or should I have 2 different adapters and attach/detach each from a single listview?
Are there any benefits/downsides to either of these solutions?
You should go with 2 adapters and 1 ListView. the reason is simple - either way you are going to have 2 Adapters (as per your question). Having one ListView would make the code simpler and there will only be a single instance in your xml file. Depending upon the state of the checkbox, you just need to change the adapter the listview points to and notify of this change.
If you had two list views, you would have to hide one. Just because the ListView is hidden doesn't mean that Android does not have to bother about it. You just have an object (size will depend) consuming resources sitting in the background.
Both of the proposals are wrong.
If we assume that you have same Object type to be listed in a ListView (Let's say a user object with name and id fields), then you need to have one ListView and one Adapter. When user wants to switch the data, what you need to do is to send the new data set to your adapter and then refresh it by calling notifyDataSetChanged(); method of adapter.

android listview with custom cursor adapter and multiple views- bindView only specific view

I have a small problem with my listview. the list has 3 different views:
1 for the first list cell
1 for the second list cell
1 for all the rest list cells.
all the "rest" lists cells are populated using data from sqlite.
problem is that in the first 2 binds the cursor advances 2 times.
I know that i can rewind the cursor using cursor.moveToX methods but that involves counters
and syncing those counters each time the list is repopulated (which can be dangerous and buggy)
Is there a more elegant solution from my problem: bindView only to 1 view from the 3 i have?
Thanks!
Roy
If the first two rows are static and don't actually need to be configured by the list adapter, you can use ListView.addHeaderView() to add rows above the ones that your adapter builds. You must call this before you call setAdapter on the ListView.
Note that in any onItemClickListener you will need to offset the reported clicked position by the number of header views to find the correct item in your adapter's data set.
Some of the adapters have setViewBinder which can be used to custom bind the values to view.
Return false in setViewValue for the adapter to bind, and for the rest of the cases you should custom bind the values and return true

Android - ListView Adapter with items of two views

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.

Add multiple rows to ListView per item

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.

Android dynamically calculate number of columns

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.

Categories

Resources