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 17 package android.app; 18 19 import android.database.Cursor; 20 import android.os.Bundle; 21 import java.util.List; 22 import android.view.ContextMenu; 23 import android.view.View; 24 import android.view.ContextMenu.ContextMenuInfo; 25 import android.view.View.OnCreateContextMenuListener; 26 import android.widget.ExpandableListAdapter; 27 import android.widget.ExpandableListView; 28 import android.widget.SimpleCursorTreeAdapter; 29 import android.widget.SimpleExpandableListAdapter; 30 31 import java.util.Map; 32 33 /** 34 * An activity that displays an expandable list of items by binding to a data 35 * source implementing the ExpandableListAdapter, and exposes event handlers 36 * when the user selects an item. 37 * <p> 38 * ExpandableListActivity hosts a 39 * {@link android.widget.ExpandableListView ExpandableListView} object that can 40 * be bound to different data sources that provide a two-levels of data (the 41 * top-level is group, and below each group are children). Binding, screen 42 * layout, and row layout are discussed in the following sections. 43 * <p> 44 * <strong>Screen Layout</strong> 45 * </p> 46 * <p> 47 * ExpandableListActivity has a default layout that consists of a single, 48 * full-screen, centered expandable list. However, if you desire, you can 49 * customize the screen layout by setting your own view layout with 50 * setContentView() in onCreate(). To do this, your own view MUST contain an 51 * ExpandableListView object with the id "@android:id/list" (or 52 * {@link android.R.id#list} if it's in code) 53 * <p> 54 * Optionally, your custom view can contain another view object of any type to 55 * display when the list view is empty. This "empty list" notifier must have an 56 * id "android:empty". Note that when an empty view is present, the expandable 57 * list view will be hidden when there is no data to display. 58 * <p> 59 * The following code demonstrates an (ugly) custom screen layout. It has a list 60 * with a green background, and an alternate red "no data" message. 61 * </p> 62 * 63 * <pre> 64 * <?xml version="1.0" encoding="UTF-8"?> 65 * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 66 * android:orientation="vertical" 67 * android:layout_width="match_parent" 68 * android:layout_height="match_parent" 69 * android:paddingLeft="8dp" 70 * android:paddingRight="8dp"> 71 * 72 * <ExpandableListView android:id="@id/android:list" 73 * android:layout_width="match_parent" 74 * android:layout_height="match_parent" 75 * android:background="#00FF00" 76 * android:layout_weight="1" 77 * android:drawSelectorOnTop="false"/> 78 * 79 * <TextView android:id="@id/android:empty" 80 * android:layout_width="match_parent" 81 * android:layout_height="match_parent" 82 * android:background="#FF0000" 83 * android:text="No data"/> 84 * </LinearLayout> 85 * </pre> 86 * 87 * <p> 88 * <strong>Row Layout</strong> 89 * </p> 90 * The {@link ExpandableListAdapter} set in the {@link ExpandableListActivity} 91 * via {@link #setListAdapter(ExpandableListAdapter)} provides the {@link View}s 92 * for each row. This adapter has separate methods for providing the group 93 * {@link View}s and child {@link View}s. There are a couple provided 94 * {@link ExpandableListAdapter}s that simplify use of adapters: 95 * {@link SimpleCursorTreeAdapter} and {@link SimpleExpandableListAdapter}. 96 * <p> 97 * With these, you can specify the layout of individual rows for groups and 98 * children in the list. These constructor takes a few parameters that specify 99 * layout resources for groups and children. It also has additional parameters 100 * that let you specify which data field to associate with which object in the 101 * row layout resource. The {@link SimpleCursorTreeAdapter} fetches data from 102 * {@link Cursor}s and the {@link SimpleExpandableListAdapter} fetches data 103 * from {@link List}s of {@link Map}s. 104 * </p> 105 * <p> 106 * Android provides some standard row layout resources. These are in the 107 * {@link android.R.layout} class, and have names such as simple_list_item_1, 108 * simple_list_item_2, and two_line_list_item. The following layout XML is the 109 * source for the resource two_line_list_item, which displays two data 110 * fields,one above the other, for each list row. 111 * </p> 112 * 113 * <pre> 114 * <?xml version="1.0" encoding="utf-8"?> 115 * <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 116 * android:layout_width="match_parent" 117 * android:layout_height="wrap_content" 118 * android:orientation="vertical"> 119 * 120 * <TextView android:id="@+id/text1" 121 * android:textSize="16sp" 122 * android:textStyle="bold" 123 * android:layout_width="match_parent" 124 * android:layout_height="wrap_content"/> 125 * 126 * <TextView android:id="@+id/text2" 127 * android:textSize="16sp" 128 * android:layout_width="match_parent" 129 * android:layout_height="wrap_content"/> 130 * </LinearLayout> 131 * </pre> 132 * 133 * <p> 134 * You must identify the data bound to each TextView object in this layout. The 135 * syntax for this is discussed in the next section. 136 * </p> 137 * <p> 138 * <strong>Binding to Data</strong> 139 * </p> 140 * <p> 141 * You bind the ExpandableListActivity's ExpandableListView object to data using 142 * a class that implements the 143 * {@link android.widget.ExpandableListAdapter ExpandableListAdapter} interface. 144 * Android provides two standard list adapters: 145 * {@link android.widget.SimpleExpandableListAdapter SimpleExpandableListAdapter} 146 * for static data (Maps), and 147 * {@link android.widget.SimpleCursorTreeAdapter SimpleCursorTreeAdapter} for 148 * Cursor query results. 149 * </p> 150 * 151 * @see #setListAdapter 152 * @see android.widget.ExpandableListView 153 * 154 * @deprecated Use {@link androidx.recyclerview.widget.RecyclerView} or use 155 * {@link android.widget.ExpandableListView} directly 156 */ 157 @Deprecated 158 public class ExpandableListActivity extends Activity implements 159 OnCreateContextMenuListener, 160 ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupCollapseListener, 161 ExpandableListView.OnGroupExpandListener { 162 ExpandableListAdapter mAdapter; 163 ExpandableListView mList; 164 boolean mFinishedStart = false; 165 166 /** 167 * Override this to populate the context menu when an item is long pressed. menuInfo 168 * will contain an {@link android.widget.ExpandableListView.ExpandableListContextMenuInfo} 169 * whose packedPosition is a packed position 170 * that should be used with {@link ExpandableListView#getPackedPositionType(long)} and 171 * the other similar methods. 172 * <p> 173 * {@inheritDoc} 174 */ 175 @Override onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)176 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 177 } 178 179 /** 180 * Override this for receiving callbacks when a child has been clicked. 181 * <p> 182 * {@inheritDoc} 183 */ onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id)184 public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, 185 int childPosition, long id) { 186 return false; 187 } 188 189 /** 190 * Override this for receiving callbacks when a group has been collapsed. 191 */ onGroupCollapse(int groupPosition)192 public void onGroupCollapse(int groupPosition) { 193 } 194 195 /** 196 * Override this for receiving callbacks when a group has been expanded. 197 */ onGroupExpand(int groupPosition)198 public void onGroupExpand(int groupPosition) { 199 } 200 201 /** 202 * Ensures the expandable list view has been created before Activity restores all 203 * of the view states. 204 * 205 *@see Activity#onRestoreInstanceState(Bundle) 206 */ 207 @Override onRestoreInstanceState(Bundle state)208 protected void onRestoreInstanceState(Bundle state) { 209 ensureList(); 210 super.onRestoreInstanceState(state); 211 } 212 213 /** 214 * Updates the screen state (current list and other views) when the 215 * content changes. 216 * 217 * @see Activity#onContentChanged() 218 */ 219 @Override onContentChanged()220 public void onContentChanged() { 221 super.onContentChanged(); 222 View emptyView = findViewById(com.android.internal.R.id.empty); 223 mList = (ExpandableListView)findViewById(com.android.internal.R.id.list); 224 if (mList == null) { 225 throw new RuntimeException( 226 "Your content must have a ExpandableListView whose id attribute is " + 227 "'android.R.id.list'"); 228 } 229 if (emptyView != null) { 230 mList.setEmptyView(emptyView); 231 } 232 mList.setOnChildClickListener(this); 233 mList.setOnGroupExpandListener(this); 234 mList.setOnGroupCollapseListener(this); 235 236 if (mFinishedStart) { 237 setListAdapter(mAdapter); 238 } 239 mFinishedStart = true; 240 } 241 242 /** 243 * Provide the adapter for the expandable list. 244 */ setListAdapter(ExpandableListAdapter adapter)245 public void setListAdapter(ExpandableListAdapter adapter) { 246 synchronized (this) { 247 ensureList(); 248 mAdapter = adapter; 249 mList.setAdapter(adapter); 250 } 251 } 252 253 /** 254 * Get the activity's expandable list view widget. This can be used to get the selection, 255 * set the selection, and many other useful functions. 256 * 257 * @see ExpandableListView 258 */ getExpandableListView()259 public ExpandableListView getExpandableListView() { 260 ensureList(); 261 return mList; 262 } 263 264 /** 265 * Get the ExpandableListAdapter associated with this activity's 266 * ExpandableListView. 267 */ getExpandableListAdapter()268 public ExpandableListAdapter getExpandableListAdapter() { 269 return mAdapter; 270 } 271 ensureList()272 private void ensureList() { 273 if (mList != null) { 274 return; 275 } 276 setContentView(com.android.internal.R.layout.expandable_list_content); 277 } 278 279 /** 280 * Gets the ID of the currently selected group or child. 281 * 282 * @return The ID of the currently selected group or child. 283 */ getSelectedId()284 public long getSelectedId() { 285 return mList.getSelectedId(); 286 } 287 288 /** 289 * Gets the position (in packed position representation) of the currently 290 * selected group or child. Use 291 * {@link ExpandableListView#getPackedPositionType}, 292 * {@link ExpandableListView#getPackedPositionGroup}, and 293 * {@link ExpandableListView#getPackedPositionChild} to unpack the returned 294 * packed position. 295 * 296 * @return A packed position representation containing the currently 297 * selected group or child's position and type. 298 */ getSelectedPosition()299 public long getSelectedPosition() { 300 return mList.getSelectedPosition(); 301 } 302 303 /** 304 * Sets the selection to the specified child. If the child is in a collapsed 305 * group, the group will only be expanded and child subsequently selected if 306 * shouldExpandGroup is set to true, otherwise the method will return false. 307 * 308 * @param groupPosition The position of the group that contains the child. 309 * @param childPosition The position of the child within the group. 310 * @param shouldExpandGroup Whether the child's group should be expanded if 311 * it is collapsed. 312 * @return Whether the selection was successfully set on the child. 313 */ setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup)314 public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { 315 return mList.setSelectedChild(groupPosition, childPosition, shouldExpandGroup); 316 } 317 318 /** 319 * Sets the selection to the specified group. 320 * @param groupPosition The position of the group that should be selected. 321 */ setSelectedGroup(int groupPosition)322 public void setSelectedGroup(int groupPosition) { 323 mList.setSelectedGroup(groupPosition); 324 } 325 326 } 327 328