0

I guess my situation should be quite common and it should have a simple solution (of which I'm not aware). Indeed, I want to use a TreeMap<String, ArrayList<String>> in my Adapter to show the countries in a ListView. I have created this list (shown in the following picture) without using ListView but it is quite inefficient.

My question:

Does ListView suit this task?
yes: How should I define the adapter?
No: What else can I use which is as efficient as the ListView?

BTW, my TreeMap is like This: ("C", {"Country1","Country2",...})

enter image description here

As you can see in the above image I want to use different dividers (the logic is obvious).

Mohsen Kamrani
  • 7,177
  • 5
  • 42
  • 66
  • But seems like the dividers are same? – starkshang Dec 21 '15 at 12:19
  • @FireSun If you notice, at the end of each group (for example countries which their names begin with B) the divider's width is full (the whole) screen. – Mohsen Kamrani Dec 21 '15 at 12:21
  • 1
    the easiest way is to use SectionIndexer ... `final int section = getSectionForPosition(position); if (position == getPositionForSection(section)) { final TextView text = (TextView) ret.findViewById(R.id.section); text.setVisibility(View.VISIBLE); text.setText((String)getSections()[section]); } else { ret.findViewById(R.id.section).setVisibility(View.INVISIBLE); }` TextView with R.id.section is your section – Selvin Dec 21 '15 at 13:21
  • @Selvin Thank you. It seams to be exactly the case. I found this source easily with the keyword you provide: http://androidopentutorials.com/android-listview-fastscroll/ – Mohsen Kamrani Dec 21 '15 at 13:30
  • 1
    :) http://selvin.pl/LooserSample.zip <=(name of project is historical, do not take to yourself) example usage (the code from comment is inside getView() - and could be better it just a prove of concept) and results => https://drive.google.com/file/d/0B61_ocdRW25TNWpaTURoemhPczA unfortunately(for you) it using ContentProvider and database :) (so CursorAdapter instead ArrayAdapter) – Selvin Dec 21 '15 at 13:37
  • @Selvin :) Thank you very much. I'll do the rest. – Mohsen Kamrani Dec 21 '15 at 13:55

2 Answers2

2

As far as I understood you want to use ListView with headers: 'A', 'B', 'C' etc. In that case you can rely to this answer

If you don't need headers, then you can feed your ListView with the values() of your TreeMap, maybe you'd like some ordering before passing it to the ListView. However I don't see why wouldn't you want headers if you have sorted collections by letters :)

So, for header views, you need to define you ListView's adapter in a specific way.

I must also mention, that there's a View with better performance overall than ListView, which is called RecyclerView, I suggest to have a check on that! It also has the option to add headers for the list items.

EDIT: I couldn't see the attached image, thus some more possibilities:

I'd suggest to use normal ListView/RecyclerView with a special Adapter, not a normal string one. Create a class which contains a String and a boolean, and transform your map to a list of these objects. Something like this:

public class ListItem{
    String name;
    String category;
    boolean isHeader;
    [...]
}

If the object is a first item, set the boolean true. In the list adapter you can check the item's Boolean, and create the actual item's view according to it, in your Adapter's getView() method.

Community
  • 1
  • 1
abbath
  • 2,444
  • 4
  • 28
  • 40
  • Thanks for mentioning the other option too. Also, I should mention that I put the key besides the first child, not above it. – Mohsen Kamrani Dec 21 '15 at 12:24
  • I will try to see whether I can use the first link first – Mohsen Kamrani Dec 21 '15 at 12:25
  • Oh sorry I couldn't load the image on my mobile, now I see it. – abbath Dec 21 '15 at 12:26
  • Did it affect your answer? – Mohsen Kamrani Dec 21 '15 at 12:29
  • I'd suggest to use normal ListView/RecyclerView with special adapter, not a normal string one. Create a class which contains a String and a Boolean, and transform your map to a list of these objects. If the object is a first item, set the Boolean true. In the list adapter you can check the item's Boolean, and create the actual item view according to it. – abbath Dec 21 '15 at 12:30
  • I know this solution, but this is something else. Do you think this is the best solution and I cannot pass a map to my adapter? – Mohsen Kamrani Dec 21 '15 at 12:32
  • Also you can set the letter to it, but as long as the list of the new class's objects are ordered by the names, you should get a satisfying result – abbath Dec 21 '15 at 12:33
  • So far I guess this is the best plausible solution, cause It seems using a map is not that much straightforward, is it? – Mohsen Kamrani Dec 21 '15 at 12:37
  • It can be used in the adapter, but maybe it's not very good for performance. – abbath Dec 21 '15 at 12:43
  • I guess using this approach (+1) in inevitable. – Mohsen Kamrani Dec 21 '15 at 12:52
1

I think ListView is suitable to do this,but RecyclerView will do better, just depends on how we custom the adapter for it.
And I think TreeMap will be slower and waste much memory,that is,it can make it but too waste.Simply you can use HashMap instead,more simplier,you can use SparseMap<List<String>> instead,the key is 0-25 and value is city list,this will use less memory.

starkshang
  • 8,228
  • 6
  • 41
  • 52
  • Thanks. Can I use a Map as the adapter? BTW, I use ThreeMap to get the keys in a sorted fashion. Filling it takes 1 milli-seconds. – Mohsen Kamrani Dec 21 '15 at 12:28
  • you can use the map as data source for adapter,and if you use `SparseMap` you can also get the sorted fashion,for example if you want to take value from starts with `A` to starts with `Z`,you just call `map.get(0-25)`. – starkshang Dec 21 '15 at 12:32
  • Great. But still I don't know how to use the map as data source. I have seen examples of map as the source but not any example with map as the data source. – Mohsen Kamrani Dec 21 '15 at 12:35
  • use this structor just for data management and use less memory,if you have achieve your goal by `TreeMap>`,that will be similar with it.just take list values from `String` like `A` to from `int` like `0`. – starkshang Dec 21 '15 at 12:44
  • Well, indeed you mentioned another issue (+1). My problem (using a map as the data source of the adapter) still exists. – Mohsen Kamrani Dec 21 '15 at 12:48
  • Will your city data change when app running? – starkshang Dec 21 '15 at 12:52
  • No. But I want to use this solution in another case wherein either the keys (parents, a-z e.g.) and the values (children, countries) may change. – Mohsen Kamrani Dec 21 '15 at 12:54