androidlistviewindexerlist-separator

how to add separators in a listview at specific positions?


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;
    }

}


}

Solution

  • 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>
    

    enter image description here