0

I want to implement section headers similar to the one used by pirate Bay enter image description here

Basically a Listview like this:

header Name list Item list Item list Item list Item header Name list Item list Item list Item

Which is the best way to achieve this? I have read on section headers and merge adapters but they are not working to my needs...How would I achieve section headers

James Wahome
  • 588
  • 11
  • 31

2 Answers2

5

Here is how I solved it:

I taught my custom ListAdapter to return heading rows as well as detail rows ,this involves overriding methods getViewTypeCount() and getItemViewType() in your ListAdapter, plus I got getView() to know the difference between the row types. The following code should give you a hint..The code for ListViewAdapter (commented most parts)

public class ListViewAdapter extends ArrayAdapter<ListViewItemModel> {

public ListViewAdapter(Context context) {
    super(context, 0);
}

public void addHeader(int title) { //expects The Title for the header as an Arugment to it
    add(new ListViewItemModel(title, -1, true));//add the object to the Bottom of the array
}

public void addItem(int title, int icon) {
    add(new ListViewItemModel(title, icon, false));
}

public void addItem(ListViewItemModel itemModel) {
    add(itemModel);
}

@Override
public int getViewTypeCount() {  //Returns the number of types of Views that will be created by getView(int, View, ViewGroup).
    return 2; //we will create 2 types of views
}

@Override
public int getItemViewType(int position) { //framework calls getItemViewType for row n, the row it is about to display.
    //Get the type of View that will be created by getView(int, View, ViewGroup) for the specified item.
    return getItem(position).isHeader ? 0 : 1; // get position passes (n) and accertain  is its a header  or not
}

@Override
public boolean isEnabled(int position) {
    return !getItem(position).isHeader;
}

public static class ViewHolder {
    public final TextView textHolder;
    public final ImageView imageHolder;

    public ViewHolder(TextView text1, ImageView image1) {
        this.textHolder = text1;
        this.imageHolder = image1;
    }
}

public View getView(int position, View convertView, ViewGroup parent) {
  //Abstract View --> Get a View that displays the data at the specified position in the data set.
    ListViewItemModel item = getItem(position);
    ViewHolder holder = null;
    View view = convertView;

    if (view == null) {
        int layout = R.layout.list_view_row;
        if (item.isHeader)
            layout = R.layout.list_view_row_header;

        view = LayoutInflater.from(getContext()).inflate(layout, null);

        TextView text1 = (TextView) view.findViewById(R.id.menurow_title);
        ImageView image1 = (ImageView) view.findViewById(R.id.menurow_icon);
        view.setTag(new ViewHolder(text1, image1));
    }

    if (holder == null && view != null) {
        Object tag = view.getTag();
        if (tag instanceof ViewHolder) {
            holder = (ViewHolder) tag;
        }
    }

    if (item != null && holder != null) {
        if (holder.textHolder != null)
            holder.textHolder.setText(item.title);

        if (holder.imageHolder != null) {
            if (item.iconRes > 0) {

                holder.imageHolder.setVisibility(View.VISIBLE);
                holder.imageHolder.setImageResource(item.iconRes);
            } else {
                holder.imageHolder.setVisibility(View.GONE);
            }
        }
    }

    return view;
}

}

And a Model for the ArrayAdapter to use

 public class ListViewItemModel {

public int title;
public int iconRes;
public boolean isHeader;

public ListViewItemModel(int title, int iconRes, boolean header) {
    this.title = title;
    this.iconRes = iconRes;
    this.isHeader = header;
}

public ListViewItemModel(int title, int iconRes) {
    this(title, iconRes, false);
}

}

Now in the class that I will be using this custom listview in the navigation

ListViewAdapter mAdapter = new ListViewAdapter(this);// Add First Header        
mAdapter.addHeader(R.string.menu_data);
menu_One = getResources().getStringArray(R.array.menu_one); // Load list view data     array strings
    String[] menuOneIcons =   getResources().getStringArray(R.array.menu_two_one);// Load list view image array strings


    int oneIcons = 0;
    for (String item : menuItemsData) { //enhanced For loop, iterate on elements from the collection named menuItemsData

        int id_menu_one = getResources().getIdentifier(item, "string",this.getPackageName());

        int id_menu_one_icons = getResources().getIdentifier(menuOneIcons[oneIcons], "drawable",this.getPackageName());



        ListViewItemModel mItem = new ListViewItemModel(id_data_title,id_data_icon);

        mAdapter.addItem(mItem);
        oneIcons++;
    }
    // Add second header

    mAdapter.addHeader(R.string.menu_two); //second Header here

    menu_Two = getResources().getStringArray(R.array.menu_two);
    String[] menuTwoIcons = getResources().getStringArray(R.array._menu_two_icons);


    int twoIcons = 0;
    for (String item : menu_Two) {

        int id_menu_two = getResources().getIdentifier(item, "string",this.getPackageName());

        int id_menu_two_icons = getResources().getIdentifier(enuTwoIcons[twoIcons], "drawable",this.getPackageName());


        // creating drawer menu model
        ListViewItemModel mItem = new ListViewItemModel(id_menu_two,id_menu_two_icons);

        mAdapter.addItem(mItem);
        twoIcons++;
    }
James Wahome
  • 588
  • 11
  • 31
0

Just use an ExpandableListView with one group per header.

Stephane Mathis
  • 6,542
  • 6
  • 43
  • 69
  • that will not work since an expandable Listview must be explicitly expanded to display content (I stand corrected) where as In my case I need the list to just have section headers – James Wahome Jun 11 '13 at 09:46
  • use any implementation listview with headers http://stackoverflow.com/questions/13590627/android-listview-headers http://stackoverflow.com/questions/1966802/android-listview-headers – Georgy Gobozov Jun 11 '13 at 09:49
  • When you notify your adapter you just need to call expandGroup(int index) on your list. You can also force each view to remain open even if the user clicks on the group. I've used this solution for one of my apps. – Stephane Mathis Jun 11 '13 at 09:52