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