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    private int mExpandedGroupLayout;
42    private int mCollapsedGroupLayout;
43    private String[] mGroupFrom;
44    private int[] mGroupTo;
45
46    private List<? extends List<? extends Map<String, ?>>> mChildData;
47    private int mChildLayout;
48    private int mLastChildLayout;
49    private String[] mChildFrom;
50    private int[] mChildTo;
51
52    private LayoutInflater mInflater;
53
54    /**
55     * Constructor
56     *
57     * @param context The context where the {@link ExpandableListView}
58     *            associated with this {@link SimpleExpandableListAdapter} is
59     *            running
60     * @param groupData A List of Maps. Each entry in the List corresponds to
61     *            one group in the list. The Maps contain the data for each
62     *            group, and should include all the entries specified in
63     *            "groupFrom"
64     * @param groupFrom A list of keys that will be fetched from the Map
65     *            associated with each group.
66     * @param groupTo The group views that should display column in the
67     *            "groupFrom" parameter. These should all be TextViews. The
68     *            first N views in this list are given the values of the first N
69     *            columns in the groupFrom parameter.
70     * @param groupLayout resource identifier of a view layout that defines the
71     *            views for a group. The layout file should include at least
72     *            those named views defined in "groupTo"
73     * @param childData A List of List of Maps. Each entry in the outer List
74     *            corresponds to a group (index by group position), each entry
75     *            in the inner List corresponds to a child within the group
76     *            (index by child position), and the Map corresponds to the data
77     *            for a child (index by values in the childFrom array). The Map
78     *            contains the data for each child, and should include all the
79     *            entries specified in "childFrom"
80     * @param childFrom A list of keys that will be fetched from the Map
81     *            associated with each child.
82     * @param childTo The child views that should display column in the
83     *            "childFrom" parameter. These should all be TextViews. The
84     *            first N views in this list are given the values of the first N
85     *            columns in the childFrom parameter.
86     * @param childLayout resource identifier of a view layout that defines the
87     *            views for a child. The layout file should include at least
88     *            those named views defined in "childTo"
89     */
90    public SimpleExpandableListAdapter(Context context,
91            List<? extends Map<String, ?>> groupData, int groupLayout,
92            String[] groupFrom, int[] groupTo,
93            List<? extends List<? extends Map<String, ?>>> childData,
94            int childLayout, String[] childFrom, int[] childTo) {
95        this(context, groupData, groupLayout, groupLayout, groupFrom, groupTo, childData,
96                childLayout, childLayout, childFrom, childTo);
97    }
98
99    /**
100     * Constructor
101     *
102     * @param context The context where the {@link ExpandableListView}
103     *            associated with this {@link SimpleExpandableListAdapter} is
104     *            running
105     * @param groupData A List of Maps. Each entry in the List corresponds to
106     *            one group in the list. The Maps contain the data for each
107     *            group, and should include all the entries specified in
108     *            "groupFrom"
109     * @param groupFrom A list of keys that will be fetched from the Map
110     *            associated with each group.
111     * @param groupTo The group views that should display column in the
112     *            "groupFrom" parameter. These should all be TextViews. The
113     *            first N views in this list are given the values of the first N
114     *            columns in the groupFrom parameter.
115     * @param expandedGroupLayout resource identifier of a view layout that
116     *            defines the views for an expanded group. The layout file
117     *            should include at least those named views defined in "groupTo"
118     * @param collapsedGroupLayout resource identifier of a view layout that
119     *            defines the views for a collapsed group. The layout file
120     *            should include at least those named views defined in "groupTo"
121     * @param childData A List of List of Maps. Each entry in the outer List
122     *            corresponds to a group (index by group position), each entry
123     *            in the inner List corresponds to a child within the group
124     *            (index by child position), and the Map corresponds to the data
125     *            for a child (index by values in the childFrom array). The Map
126     *            contains the data for each child, and should include all the
127     *            entries specified in "childFrom"
128     * @param childFrom A list of keys that will be fetched from the Map
129     *            associated with each child.
130     * @param childTo The child views that should display column in the
131     *            "childFrom" parameter. These should all be TextViews. The
132     *            first N views in this list are given the values of the first N
133     *            columns in the childFrom parameter.
134     * @param childLayout resource identifier of a view layout that defines the
135     *            views for a child. The layout file should include at least
136     *            those named views defined in "childTo"
137     */
138    public SimpleExpandableListAdapter(Context context,
139            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
140            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
141            List<? extends List<? extends Map<String, ?>>> childData,
142            int childLayout, String[] childFrom, int[] childTo) {
143        this(context, groupData, expandedGroupLayout, collapsedGroupLayout,
144                groupFrom, groupTo, childData, childLayout, childLayout,
145                childFrom, childTo);
146    }
147
148    /**
149     * Constructor
150     *
151     * @param context The context where the {@link ExpandableListView}
152     *            associated with this {@link SimpleExpandableListAdapter} is
153     *            running
154     * @param groupData A List of Maps. Each entry in the List corresponds to
155     *            one group in the list. The Maps contain the data for each
156     *            group, and should include all the entries specified in
157     *            "groupFrom"
158     * @param groupFrom A list of keys that will be fetched from the Map
159     *            associated with each group.
160     * @param groupTo The group views that should display column in the
161     *            "groupFrom" parameter. These should all be TextViews. The
162     *            first N views in this list are given the values of the first N
163     *            columns in the groupFrom parameter.
164     * @param expandedGroupLayout resource identifier of a view layout that
165     *            defines the views for an expanded group. The layout file
166     *            should include at least those named views defined in "groupTo"
167     * @param collapsedGroupLayout resource identifier of a view layout that
168     *            defines the views for a collapsed group. The layout file
169     *            should include at least those named views defined in "groupTo"
170     * @param childData A List of List of Maps. Each entry in the outer List
171     *            corresponds to a group (index by group position), each entry
172     *            in the inner List corresponds to a child within the group
173     *            (index by child position), and the Map corresponds to the data
174     *            for a child (index by values in the childFrom array). The Map
175     *            contains the data for each child, and should include all the
176     *            entries specified in "childFrom"
177     * @param childFrom A list of keys that will be fetched from the Map
178     *            associated with each child.
179     * @param childTo The child views that should display column in the
180     *            "childFrom" parameter. These should all be TextViews. The
181     *            first N views in this list are given the values of the first N
182     *            columns in the childFrom parameter.
183     * @param childLayout resource identifier of a view layout that defines the
184     *            views for a child (unless it is the last child within a group,
185     *            in which case the lastChildLayout is used). The layout file
186     *            should include at least those named views defined in "childTo"
187     * @param lastChildLayout resource identifier of a view layout that defines
188     *            the views for the last child within each group. The layout
189     *            file should include at least those named views defined in
190     *            "childTo"
191     */
192    public SimpleExpandableListAdapter(Context context,
193            List<? extends Map<String, ?>> groupData, int expandedGroupLayout,
194            int collapsedGroupLayout, String[] groupFrom, int[] groupTo,
195            List<? extends List<? extends Map<String, ?>>> childData,
196            int childLayout, int lastChildLayout, String[] childFrom,
197            int[] childTo) {
198        mGroupData = groupData;
199        mExpandedGroupLayout = expandedGroupLayout;
200        mCollapsedGroupLayout = collapsedGroupLayout;
201        mGroupFrom = groupFrom;
202        mGroupTo = groupTo;
203
204        mChildData = childData;
205        mChildLayout = childLayout;
206        mLastChildLayout = lastChildLayout;
207        mChildFrom = childFrom;
208        mChildTo = childTo;
209
210        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
211    }
212
213    public Object getChild(int groupPosition, int childPosition) {
214        return mChildData.get(groupPosition).get(childPosition);
215    }
216
217    public long getChildId(int groupPosition, int childPosition) {
218        return childPosition;
219    }
220
221    public View getChildView(int groupPosition, int childPosition, boolean isLastChild,
222            View convertView, ViewGroup parent) {
223        View v;
224        if (convertView == null) {
225            v = newChildView(isLastChild, parent);
226        } else {
227            v = convertView;
228        }
229        bindView(v, mChildData.get(groupPosition).get(childPosition), mChildFrom, mChildTo);
230        return v;
231    }
232
233    /**
234     * Instantiates a new View for a child.
235     * @param isLastChild Whether the child is the last child within its group.
236     * @param parent The eventual parent of this new View.
237     * @return A new child View
238     */
239    public View newChildView(boolean isLastChild, ViewGroup parent) {
240        return mInflater.inflate((isLastChild) ? mLastChildLayout : mChildLayout, parent, false);
241    }
242
243    private void bindView(View view, Map<String, ?> data, String[] from, int[] to) {
244        int len = to.length;
245
246        for (int i = 0; i < len; i++) {
247            TextView v = (TextView)view.findViewById(to[i]);
248            if (v != null) {
249                v.setText((String)data.get(from[i]));
250            }
251        }
252    }
253
254    public int getChildrenCount(int groupPosition) {
255        return mChildData.get(groupPosition).size();
256    }
257
258    public Object getGroup(int groupPosition) {
259        return mGroupData.get(groupPosition);
260    }
261
262    public int getGroupCount() {
263        return mGroupData.size();
264    }
265
266    public long getGroupId(int groupPosition) {
267        return groupPosition;
268    }
269
270    public View getGroupView(int groupPosition, boolean isExpanded, View convertView,
271            ViewGroup parent) {
272        View v;
273        if (convertView == null) {
274            v = newGroupView(isExpanded, parent);
275        } else {
276            v = convertView;
277        }
278        bindView(v, mGroupData.get(groupPosition), mGroupFrom, mGroupTo);
279        return v;
280    }
281
282    /**
283     * Instantiates a new View for a group.
284     * @param isExpanded Whether the group is currently expanded.
285     * @param parent The eventual parent of this new View.
286     * @return A new group View
287     */
288    public View newGroupView(boolean isExpanded, ViewGroup parent) {
289        return mInflater.inflate((isExpanded) ? mExpandedGroupLayout : mCollapsedGroupLayout,
290                parent, false);
291    }
292
293    public boolean isChildSelectable(int groupPosition, int childPosition) {
294        return true;
295    }
296
297    public boolean hasStableIds() {
298        return true;
299    }
300
301}
302