SimpleExpandableListAdapter.java revision b49e4d63d1976b673b4763bc012d152833609688
1/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.widget;
18
19import android.content.Context;
20import android.view.View;
21import android.view.ViewGroup;
22import android.view.LayoutInflater;
23
24import java.util.List;
25import java.util.Map;
26
27/**
28 * An easy adapter to map static data to group and child views defined in an XML
29 * file. You can separately specify the data backing the group as a List of
30 * Maps. Each entry in the ArrayList corresponds to one group in the expandable
31 * list. The Maps contain the data for each row. You also specify an XML file
32 * that defines the views used to display a group, and a mapping from keys in
33 * the Map to specific views. This process is similar for a child, except it is
34 * one-level deeper so the data backing is specified as a List<List<Map>>,
35 * where the first List corresponds to the group of the child, the second List
36 * corresponds to the position of the child within the group, and finally the
37 * Map holds the data for that particular child.
38 */
39public class SimpleExpandableListAdapter extends BaseExpandableListAdapter {
40    private List<? extends Map<String, ?>> mGroupData;
41    // Keeps track of if a group is currently expanded or not
42    private boolean[] mIsGroupExpanded;
43    private int mExpandedGroupLayout;
44    private int mCollapsedGroupLayout;
45    private String[] mGroupFrom;
46    private int[] mGroupTo;
47
48    private List<? extends List<? extends Map<String, ?>>> mChildData;
49    private int mChildLayout;
50    private int mLastChildLayout;
51    private String[] mChildFrom;
52    private int[] mChildTo;
53
54    private LayoutInflater mInflater;
55
56    /**
57     * Constructor
58     *
59     * @param context The context where the {@link ExpandableListView}
60     *            associated with this {@link SimpleExpandableListAdapter} is
61     *            running
62     * @param groupData A List of Maps. Each entry in the List corresponds to
63     *            one group in the list. The Maps contain the data for each
64     *            group, and should include all the entries specified in
65     *            "groupFrom"
66     * @param groupFrom A list of keys that will be fetched from the Map
67     *            associated with each group.
68     * @param groupTo The group views that should display column in the
69     *            "groupFrom" parameter. These should all be TextViews. The
70     *            first N views in this list are given the values of the first N
71     *            columns in the groupFrom parameter.
72     * @param groupLayout resource identifier of a view layout that defines the
73     *            views for a group. The layout file should include at least
74     *            those named views defined in "groupTo"
75     * @param childData A List of List of Maps. Each entry in the outer List
76     *            corresponds to a group (index by group position), each entry
77     *            in the inner List corresponds to a child within the group
78     *            (index by child position), and the Map corresponds to the data
79     *            for a child (index by values in the childFrom array). The Map
80     *            contains the data for each child, and should include all the
81     *            entries specified in "childFrom"
82     * @param childFrom A list of keys that will be fetched from the Map
83     *            associated with each child.
84     * @param childTo The child views that should display column in the
85     *            "childFrom" parameter. These should all be TextViews. The
86     *            first N views in this list are given the values of the first N
87     *            columns in the childFrom parameter.
88     * @param childLayout resource identifier of a view layout that defines the
89     *            views for a child. The layout file should include at least
90     *            those named views defined in "childTo"
91     */
92    public SimpleExpandableListAdapter(Context context,
93            List<? extends Map<String, ?>> groupData, int groupLayout,
94            String[] groupFrom, int[] groupTo,
95            List<? extends List<? extends Map<String, ?>>> childData,
96            int childLayout, String[] childFrom, int[] childTo) {
97        this(context, groupData, groupLayout, groupLayout, groupFrom, groupTo, childData,
98                childLayout, childLayout, childFrom, childTo);
99    }
100
101    /**
102     * Constructor
103     *
104     * @param context The context where the {@link ExpandableListView}
105     *            associated with this {@link SimpleExpandableListAdapter} is
106     *            running
107     * @param groupData A List of Maps. Each entry in the List corresponds to
108     *            one group in the list. The Maps contain the data for each
109     *            group, and should include all the entries specified in
110     *            "groupFrom"
111     * @param groupFrom A list of keys that will be fetched from the Map
112     *            associated with each group.
113     * @param groupTo The group views that should display column in the
114     *            "groupFrom" parameter. These should all be TextViews. The
115     *            first N views in this list are given the values of the first N
116     *            columns in the groupFrom parameter.
117     * @param expandedGroupLayout resource identifier of a view layout that
118     *            defines the views for an expanded group. The layout file
119     *            should include at least those named views defined in "groupTo"
120     * @param collapsedGroupLayout resource identifier of a view layout that
121     *            defines the views for a collapsed group. The layout file
122     *            should include at least those named views defined in "groupTo"
123     * @param childData A List of List of Maps. Each entry in the outer List
124     *            corresponds to a group (index by group position), each entry
125     *            in the inner List corresponds to a child within the group
126     *            (index by child position), and the Map corresponds to the data
127     *            for a child (index by values in the childFrom array). The Map
128     *            contains the data for each child, and should include all the
129     *            entries specified in "childFrom"
130     * @param childFrom A list of keys that will be fetched from the Map
131     *            associated with each child.
132     * @param childTo The child views that should display column in the
133     *            "childFrom" parameter. These should all be TextViews. The
134     *            first N views in this list are given the values of the first N
135     *            columns in the childFrom parameter.
136     * @param childLayout resource identifier of a view layout that defines the
137     *            views for a child. The layout file should include at least
138     *            those named views defined in "childTo"
139     */
140    public SimpleExpandableListAdapter(Context context,
141            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
142            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
143            List<? extends List<? extends Map<String, ?>>> childData,
144            int childLayout, String[] childFrom, int[] childTo) {
145        this(context, groupData, expandedGroupLayout, collapsedGroupLayout,
146                groupFrom, groupTo, childData, childLayout, childLayout,
147                childFrom, childTo);
148    }
149
150    /**
151     * Constructor
152     *
153     * @param context The context where the {@link ExpandableListView}
154     *            associated with this {@link SimpleExpandableListAdapter} is
155     *            running
156     * @param groupData A List of Maps. Each entry in the List corresponds to
157     *            one group in the list. The Maps contain the data for each
158     *            group, and should include all the entries specified in
159     *            "groupFrom"
160     * @param groupFrom A list of keys that will be fetched from the Map
161     *            associated with each group.
162     * @param groupTo The group views that should display column in the
163     *            "groupFrom" parameter. These should all be TextViews. The
164     *            first N views in this list are given the values of the first N
165     *            columns in the groupFrom parameter.
166     * @param expandedGroupLayout resource identifier of a view layout that
167     *            defines the views for an expanded group. The layout file
168     *            should include at least those named views defined in "groupTo"
169     * @param collapsedGroupLayout resource identifier of a view layout that
170     *            defines the views for a collapsed group. The layout file
171     *            should include at least those named views defined in "groupTo"
172     * @param childData A List of List of Maps. Each entry in the outer List
173     *            corresponds to a group (index by group position), each entry
174     *            in the inner List corresponds to a child within the group
175     *            (index by child position), and the Map corresponds to the data
176     *            for a child (index by values in the childFrom array). The Map
177     *            contains the data for each child, and should include all the
178     *            entries specified in "childFrom"
179     * @param childFrom A list of keys that will be fetched from the Map
180     *            associated with each child.
181     * @param childTo The child views that should display column in the
182     *            "childFrom" parameter. These should all be TextViews. The
183     *            first N views in this list are given the values of the first N
184     *            columns in the childFrom parameter.
185     * @param childLayout resource identifier of a view layout that defines the
186     *            views for a child (unless it is the last child within a group,
187     *            in which case the lastChildLayout is used). The layout file
188     *            should include at least those named views defined in "childTo"
189     * @param lastChildLayout resource identifier of a view layout that defines
190     *            the views for the last child within each group. The layout
191     *            file should include at least those named views defined in
192     *            "childTo"
193     */
194    public SimpleExpandableListAdapter(Context context,
195            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
196            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
197            List<? extends List<? extends Map<String, ?>>> childData,
198            int childLayout, int lastChildLayout, String[] childFrom,
199            int[] childTo) {
200        mGroupData = groupData;
201        // Initially all groups are not expanded
202        mIsGroupExpanded = new boolean[groupData.size()];
203        mExpandedGroupLayout = expandedGroupLayout;
204        mCollapsedGroupLayout = collapsedGroupLayout;
205        mGroupFrom = groupFrom;
206        mGroupTo = groupTo;
207
208        mChildData = childData;
209        mChildLayout = childLayout;
210        mLastChildLayout = lastChildLayout;
211        mChildFrom = childFrom;
212        mChildTo = childTo;
213
214        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
215    }
216
217    public Object getChild(int groupPosition, int childPosition) {
218        return mChildData.get(groupPosition).get(childPosition);
219    }
220
221    public long getChildId(int groupPosition, int childPosition) {
222        return childPosition;
223    }
224
225    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
226            View convertView, ViewGroup parent) {
227        View v;
228        if (convertView == null) {
229            v = newChildView(isLastChild, parent);
230        } else {
231            v = convertView;
232        }
233        bindView(v, mChildData.get(groupPosition).get(childPosition), mChildFrom, mChildTo);
234        return v;
235    }
236
237    /**
238     * Instantiates a new View for a child.
239     * @param isLastChild Whether the child is the last child within its group.
240     * @param parent The eventual parent of this new View.
241     * @return A new child View
242     */
243    public View newChildView(boolean isLastChild, ViewGroup parent) {
244        return mInflater.inflate((isLastChild) ? mLastChildLayout : mChildLayout, parent, false);
245    }
246
247    private void bindView(View view, Map<String, ?> data, String[] from, int[] to) {
248        int len = to.length;
249
250        for (int i = 0; i < len; i++) {
251            TextView v = (TextView)view.findViewById(to[i]);
252            if (v != null) {
253                v.setText((String)data.get(from[i]));
254            }
255        }
256    }
257
258    public int getChildrenCount(int groupPosition) {
259        return mChildData.get(groupPosition).size();
260    }
261
262    public Object getGroup(int groupPosition) {
263        return mGroupData.get(groupPosition);
264    }
265
266    public int getGroupCount() {
267        return mGroupData.size();
268    }
269
270    public long getGroupId(int groupPosition) {
271        return groupPosition;
272    }
273
274    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
275            ViewGroup parent) {
276        View v;
277        if (convertView == null) {
278            v = newGroupView(isExpanded, parent);
279        } else {
280            v = convertView;
281        }
282        bindView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);
283        return v;
284    }
285
286    /**
287     * Instantiates a new View for a group.
288     * @param isExpanded Whether the group is currently expanded.
289     * @param parent The eventual parent of this new View.
290     * @return A new group View
291     */
292    public View newGroupView(boolean isExpanded, ViewGroup parent) {
293        return mInflater.inflate((isExpanded) ? mExpandedGroupLayout : mCollapsedGroupLayout,
294                parent, false);
295    }
296
297    public boolean isChildSelectable(int groupPosition, int childPosition) {
298        return true;
299    }
300
301    public boolean hasStableIds() {
302        return true;
303    }
304
305    /**
306     * {@inheritDoc}
307     * @return 1 for the last child in a group, 0 for the other children.
308     */
309    @Override
310    public int getChildType(int groupPosition, int childPosition) {
311        final int childrenInGroup = getChildrenCount(groupPosition);
312        return childPosition == childrenInGroup - 1 ? 1 : 0;
313    }
314
315    /**
316     * {@inheritDoc}
317     * @return 2, one type for the last child in a group, one for the other children.
318     */
319    @Override
320    public int getChildTypeCount() {
321        return 2;
322    }
323
324    /**
325     * {@inheritDoc}
326     * @return 1 for an expanded group view, 0 for a collapsed one.
327     */
328    @Override
329    public int getGroupType(int groupPosition) {
330        return mIsGroupExpanded[groupPosition] ? 1 : 0;
331    }
332
333    /**
334     * {@inheritDoc}
335     * @return 2, one for a collapsed group view, one for an expanded one.
336     */
337    @Override
338    public int getGroupTypeCount() {
339        return 2;
340    }
341
342    /** {@inheritDoc} */
343    @Override
344    public void onGroupCollapsed(int groupPosition) {
345        mIsGroupExpanded[groupPosition] = false;
346    }
347
348    /** {@inheritDoc} */
349    @Override
350    public void onGroupExpanded(int groupPosition) {
351        mIsGroupExpanded[groupPosition] = true;
352    }
353}
354