I have a ListView
with custom Adapter
. I have to add at position 2,6,9 separators. How to do that?
Here is my code
class MyIndexerAdapter<T> extends ArrayAdapter<T> implements SectionIndexer {
ArrayList<String> myElements;
HashMap<String, Integer> alphaIndexer;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
TreeSet mSeparatorsSet = new TreeSet();
String[] sections;
LayoutInflater mInflater;
public MyIndexerAdapter(Context context, int textViewResourceId,
List<T> objects) {
super(context, textViewResourceId, objects);
mInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myElements = (ArrayList<String>) objects;
// here is the tricky stuff
alphaIndexer = new HashMap<String, Integer>();
// in this hashmap we will store here the positions for
// the sections
int size = elements.size();
for (int i = size - 1; i >= 0; i--) {
String element = elements.get(i);
alphaIndexer.put(element.substring(0, 1), i);
//We store the first letter of the word, and its index.
//The Hashmap will replace the value for identical keys are putted in
}
// now we have an hashmap containing for each first-letter
// sections(key), the index(value) in where this sections begins
// we have now to build the sections(letters to be displayed)
// array .it must contains the keys, and must (I do so...) be
// ordered alphabetically
Set<String> keys = alphaIndexer.keySet(); // set of letters ...sets
// cannot be sorted...
Iterator<String> it = keys.iterator();
ArrayList<String> keyList = new ArrayList<String>(); // list can be
// sorted
while (it.hasNext()) {
String key = it.next();
keyList.add(key);
}
Collections.sort(keyList);
sections = new String[keyList.size()]; // simple conversion to an
// array of object
keyList.toArray(sections);
// ooOO00K !
}
public int getItemViewType(int position)
{
return mSeparatorsSet.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
public int getViewTypeCount()
{
return TYPE_MAX_COUNT;
}
public int getPositionForSection(int section) {
// Log.v("getPositionForSection", ""+section);
String letter = sections[section];
return alphaIndexer.get(letter);
}
public int getSectionForPosition(int position) {
// you will notice it will be never called (right?)
Log.v("getSectionForPosition", "called");
getSections();
return 0;
}
public Object[] getSections() {
return sections; // to string will be called each object, to display
// the letter
}
public void onListItemClick(ListView parent,View v, int position, long id)
{
Toast.makeText(getContext(), "you have selected" + elements.get(position), Toast.LENGTH_SHORT).show();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
switch (type) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.main, null);
holder.textView = (TextView)convertView.findViewById(R.id.text);
//break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.textView.setText(elements.get(position));
return convertView;
}
}
}
In your getView()
of MyIndexerAdapter, use the position argument to check whether it is 2.6.9 and then add the separator in code
if(position==2 || position==6||position==9){
//code for adding separators to the convertview
}
Try the below completed code, it was running for me :
This code also shows how to use adapter methods like getItemViewType()
, getViewTypeCount()
, getView()
when needed to display different types of views at different positions.
It also shows how to implement a SectionIndexer
and its methods.
I added some random data at position 2,6,9 where you wanted the separators. This made things easier.
public class FastScrollActivity extends Activity {
ListView myListView;
ArrayList<String> elements;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// elements
String s = "QWERTZUIOPASDFGHJKLYXCVBNM";
Random r = new Random();
elements = new ArrayList<String>();
for (int i = 0; i < 300; i++) {
elements.add(s.substring(r.nextInt(s.length())));
}
Collections.sort(elements); // Must be sorted!
//for 2,6,9 Adding some random data--use an array of positions if you want to :
elements.add(2,"Don't care");
elements.add(6,"Don't care");
elements.add(9,"Don't care");
// listview
myListView = (ListView) findViewById(R.id.myListView);
myListView.setFastScrollEnabled(true);
myListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
Toast.makeText(FastScrollActivity.this, "clicked pos = "+arg2, Toast.LENGTH_SHORT).show();
}
});
//myListView.
MyIndexerAdapter<String> adapter = new MyIndexerAdapter<String>(
this, R.layout.simple_layout,
elements);
myListView.setAdapter(adapter);
// if (myListView.getFirstVisiblePosition() > adapter.getItemId( adapter.getCount()) || myListView.getLastVisiblePosition() <= adapter.getCount()) {
// myListView.smoothScrollToPosition( adapter.getCount());}
}
class MyIndexerAdapter<T> extends ArrayAdapter<String> implements SectionIndexer {
ArrayList<String> myElements;
HashMap<String, Integer> alphaIndexer;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private static final int TYPE_MAX_COUNT = TYPE_SEPARATOR + 1;
TreeSet<String> mSeparatorsSet = new TreeSet<String>();
String[] sections;
LayoutInflater mInflater;
int MytextViewResourceId;
public MyIndexerAdapter(Context context, int textViewResourceId,
ArrayList<String> objects) {
super(context, textViewResourceId, objects);
mInflater=(LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
myElements = objects;
// here is the tricky stuff
alphaIndexer = new HashMap<String, Integer>();
// in this hashmap we will store here the positions for
// the sections
//Adding positions in the separator set
mSeparatorsSet.add("2");
mSeparatorsSet.add("6");
mSeparatorsSet.add("9");
int size = elements.size();
for (int i = size - 1; i >= 0; i--) {
String element = elements.get(i);
alphaIndexer.put(element.substring(0, 1), i);
//We store the first letter of the word, and its index.
//The Hashmap will replace the value for identical keys are putted in
}
// now we have an hashmap containing for each first-letter
// sections(key), the index(value) in where this sections begins
// we have now to build the sections(letters to be displayed)
// array .it must contains the keys, and must (I do so...) be
// ordered alphabetically
Set<String> keys = alphaIndexer.keySet(); // set of letters ...sets
// cannot be sorted...
Iterator<String> it = keys.iterator();
ArrayList<String> keyList = new ArrayList<String>(); // list can be
// sorted
while (it.hasNext()) {
String key = it.next();
keyList.add(key);
}
Collections.sort(keyList);
sections = new String[keyList.size()]; // simple conversion to an
// array of object
keyList.toArray(sections);
// ooOO00K !
}
public int getItemViewType(int position)
{
return mSeparatorsSet.contains(position+"") ? TYPE_SEPARATOR : TYPE_ITEM;
}
public int getViewTypeCount()
{
return TYPE_MAX_COUNT;
}
public int getPositionForSection(int section) {
// Log.v("getPositionForSection", ""+section);
String letter = sections[section];
return alphaIndexer.get(letter);
}
public int getSectionForPosition(int position) {
// you will notice it will be never called (right?)
Log.v("getSectionForPosition", "called");
getSections();
return 0;
}
public Object[] getSections() {
return sections; // to string will be called each object, to display
// the letter
}
public void onListItemClick(ListView parent,View v, int position, long id)
{
Toast.makeText(getContext(), "you have selected" + elements.get(position), Toast.LENGTH_SHORT).show();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int type = getItemViewType(position);
System.out.println("getView " + position + " " + convertView + " type = " + type);
if (convertView == null) {
holder = new ViewHolder();
convertView = mInflater.inflate(R.layout.simple_layout, null);
holder.textView = (TextView)convertView.findViewById(R.id.textView1);
holder.textView.setBackgroundColor(android.R.attr.colorBackground);
switch (type) {
//break;
case TYPE_SEPARATOR:
/*convertView = mInflater.inflate(R.layout.item1, null);
holder.textView = (TextView)convertView.findViewById(R.id.textSeparator);
*/
holder.textView .setOnClickListener(null);
holder.textView .setOnLongClickListener(null);
holder.textView .setLongClickable(false);
holder.textView.setFocusable(false);
holder.textView.setTextColor(Color.WHITE);
holder.textView.setBackgroundColor(Color.RED);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder)convertView.getTag();
}
if(type==TYPE_ITEM)
holder.textView.setText(elements.get(position));
//holder.textView.setMinHeight(android.R.attr.listPreferredItemHeight);
//holder.textView.setTextAppearance(getContext(), android.R.attr.textAppearanceLarge);
return convertView;
}
}
/* public void quickScroll(View v) {
String alphabet = (String)v.getTag();
int index = 0;
//find the index of the separator row view
list.setSelectionFromTop(index, 0);
}*/
public static class ViewHolder {
public TextView textView;
}
}
the xml I used is :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:gravity="center_vertical"
android:paddingLeft="6dip"
android:minHeight="?android:attr/listPreferredItemHeight"
/>
</RelativeLayout>