Ferran Negre
Ferran Negre

Reputation: 3801

Add header in ChildView from ExpandableListView (Android)

I'm trying to find a solution for my answer through the Internet but I can't find a good one. I looked this topic: Android ExpandableListView Child Headers but it doesn't work for me.

What I have now (Screen):

And my code is:

private void fillData() {
    ExpandableListView lv;
    lv = (ExpandableListView) getActivity().findViewById(R.id.grades_view);
    lv.setItemsCanFocus(false);
    lv.setChoiceMode(ExpandableListView.CHOICE_MODE_SINGLE);

    View view = View.inflate(getActivity(), R.layout.list_header, null);
    lv.addHeaderView(view, null, false);

    dbh = new DatabaseHelper(getActivity());
    MyExpandableListAdapter mAdapter = new MyExpandableListAdapter(
            getActivity(), dbh);
    mAdapter.synchronize();
    lv.setAdapter(mAdapter);
    registerForContextMenu(lv);
}

public class MyExpandableListAdapter extends BaseExpandableListAdapter {

    private List<Subject> mSubjects = new ArrayList<Subject>();
    private List<List<Course>> mCourse = new ArrayList<List<Course>>();
    private DatabaseHelper dbh;
    private LayoutInflater inflater;

    public MyExpandableListAdapter(Context context, DatabaseHelper dbh) {
        this.dbh = dbh;
        this.inflater = LayoutInflater.from(context);
    }

    public void synchronize() {

        mSubjects = dbh.getSubjects();

        for (Subject s : mSubjects) {
            mCourse.add(dbh.getCourses(s));
        }
    }

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        return mCourse.get(groupPosition).get(childPosition);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        return getChild(groupPosition, childPosition).hashCode();
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

        Course c = (Course) getChild(groupPosition, childPosition);

        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_item_child,
                    parent, false);

        TextView txt = (TextView) convertView.findViewById(R.id.code);
        txt.setText(c.getCode());
        TextView txt1 = (TextView) convertView.findViewById(R.id.ects);
        txt1.setText(String.valueOf(c.getEcts()));
        TextView txt2 = (TextView) convertView.findViewById(R.id.grade);

        if (c.getGrade() == -1) {
            txt2.setText("-");
        } else {
            txt2.setText(String.valueOf(c.getGrade()));
        }

        return convertView;
    }

    @Override
    public int getChildrenCount(int groupPosition) {
        return mCourse.get(groupPosition).size();
    }

    @Override
    public Object getGroup(int groupPosition) {
        return mSubjects.get(groupPosition);
    }

    @Override
    public int getGroupCount() {
        return mSubjects.size();
    }

    @Override
    public long getGroupId(int groupPosition) {
        return mSubjects.get(groupPosition).hashCode();
    }

    @Override
    public View getGroupView(int groupPosition, boolean isExpanded,
            View convertView, ViewGroup parent) {

        Subject s = (Subject) getGroup(groupPosition);

        if (convertView == null)
            convertView = inflater.inflate(R.layout.list_item, parent,
                    false);

        TextView txt1 = (TextView) convertView.findViewById(R.id.name);
        txt1.setText(String.valueOf(s.getName()));
        TextView txt2 = (TextView) convertView.findViewById(R.id.semester);
        txt2.setText(String.valueOf(s.getSemester()));

        return convertView;

    }

    @Override
    public boolean hasStableIds() {
        return true;
    }

    @Override
    public boolean isChildSelectable(int groupPosition, int childPosition) {
        return true;
    }

}

As we can see, to put the first-level header (Name and Sem) I used:

View view = View.inflate(getActivity(), R.layout.list_header, null);
lv.addHeaderView(view, null, false);

But I don't know how to do the same with the children (a header with Code, ECTS and Grade).

Thank you in advance.

Upvotes: 3

Views: 7601

Answers (3)

Oscar Josue Alvrez
Oscar Josue Alvrez

Reputation: 414

1.-Include the header in your xml of group, for example:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content" >
    //Your elementsof group
</LinearLayout>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/headerList"
    android:orientation="horizontal" >
    //the elements of your header (ID,counter, description, etc..)
</LinearLayout>

2.-Now, with that ID in your method getGroupView()...

LinearLayout headerList = (LinearLayout) view.findViewById(R.id.headerList);
    if(isExpanded)
        headerList.setVisibility(View.VISIBLE);
    else
        headerList.setVisibility(View.GONE);

A year later, i hope it works for you :)

Upvotes: 5

Jerry Abraham
Jerry Abraham

Reputation: 1039

The above Solution of Guillermo Orellana Ruiz will work fine , but Note that only if " "extra child" is added to the array of child elements to the 0th postion,then only all exact child elements will be displayed ,otherwise one child element will be missing, if you are not adding one extra child to the 0 th position to the child array or child elements,,

What happens from my understanding from my task,is that when an "extra child" is added the 0th position takes that "extra child" and that child will not be displayed, instead of that "extra child" the header view is displayed, this is done by :

      if (childPosition == 0) {
       // your header
        convertView = inflater.inflate(R.layout.list_item_child, null);            

        return convertView;
    } 

Also please note that extra child adding to the child array must stay in the 0th position other wise the extra child will be displayed in your child list view and your actual data in the 0th position will not be displayed

I just mentioned this because when i used this code for my task, one of the child elements was not displaying,it was missing and i wondered for a while ,so it took some time for me to understand this , so i just post this as a Note so that people who use the accepted answer must not waste his/her time .

Upvotes: 1

Just add an "extra child"

    @Override
    public Object getChild(int groupPosition, int childPosition) {
        if (childPosition == 0)
            return null;

        return mCourse.get(groupPosition).get(childPosition - 1);
    }

    @Override
    public long getChildId(int groupPosition, int childPosition) {
        if (childPosition == 0)
            return 0;

        return getChild(groupPosition, childPosition).hashCode();
    }

    @Override
    public View getChildView(int groupPosition, int childPosition,
            boolean isLastChild, View convertView, ViewGroup parent) {

        if (childPosition == 0) {
            convertView = inflater.inflate(R.layout.list_item_child, null);

            // your special header

            return convertView;
        } 

        // rest of your method

    }

Where you can have a different layout or whatever you like.

Upvotes: 1

Related Questions