19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/* 29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2006 The Android Open Source Project 39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); 59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License. 69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at 79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software 119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and 149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License. 159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.widget; 189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.R; 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context; 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray; 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Canvas; 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.graphics.Rect; 25458034799861fef47e00d85d528b4dac5e00bd51Adam Powellimport android.graphics.drawable.Drawable; 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel; 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcelable; 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AttributeSet; 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextMenu; 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.SoundEffectConstants; 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.View; 329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.ContextMenu.ContextMenuInfo; 338a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityEvent; 348a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganovimport android.view.accessibility.AccessibilityNodeInfo; 359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.widget.ExpandableListConnector.PositionMetadata; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37458034799861fef47e00d85d528b4dac5e00bd51Adam Powellimport java.util.ArrayList; 38458034799861fef47e00d85d528b4dac5e00bd51Adam Powell 39f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglioimport static android.os.Build.VERSION_CODES.JELLY_BEAN_MR1; 40f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that shows items in a vertically scrolling two-level list. This 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * differs from the {@link ListView} by allowing two levels: groups which can 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * individually be expanded to show its children. The items come from the 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListAdapter} associated with this view. 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Expandable lists are able to show an indicator beside each item to display 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the item's current state (the states are usually one of expanded group, 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * collapsed group, child, or last child). Use 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setChildIndicator(Drawable)} or {@link #setGroupIndicator(Drawable)} 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (or the corresponding XML attributes) to set these indicators (see the docs 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for each method to see additional state that each Drawable can have). The 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default style for an {@link ExpandableListView} provides indicators which 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be shown next to Views given to the {@link ExpandableListView}. The 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layouts android.R.layout.simple_expandable_list_item_1 and 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.R.layout.simple_expandable_list_item_2 (which should be used with 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SimpleCursorTreeAdapter}) contain the preferred position information 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for indicators. 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The context menu information set by an {@link ExpandableListView} will be a 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListContextMenuInfo} object with 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListContextMenuInfo#packedPosition} being a packed position 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that can be used with {@link #getPackedPositionType(long)} and the other 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * similar methods. 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em><b>Note:</b></em> You cannot use the value <code>wrap_content</code> 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the <code>android:layout_height</code> attribute of a 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ExpandableListView in XML if the parent's size is also not strictly specified 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (for example, if the parent were ScrollView you could not specify 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wrap_content since it also can be any length. However, you can use 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wrap_content if the ExpandableListView parent has a specific size, such as 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 100 pixels. 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_groupIndicator 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_indicatorLeft 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_indicatorRight 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicator 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicatorLeft 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicatorRight 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childDivider 81f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @attr ref android.R.styleable#ExpandableListView_indicatorStart 82f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @attr ref android.R.styleable#ExpandableListView_indicatorEnd 83f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @attr ref android.R.styleable#ExpandableListView_childIndicatorStart 84f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @attr ref android.R.styleable#ExpandableListView_childIndicatorEnd 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ExpandableListView extends ListView { 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a group. 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_GROUP = 0; 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a child. 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_CHILD = 1; 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a neither/null/no preference. 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_NULL = 2; 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The value for a packed position that represents neither/null/no 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * preference. This value is not otherwise possible since a group type 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (first bit 0) should not have a child position filled. 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final long PACKED_POSITION_VALUE_NULL = 0x00000000FFFFFFFFL; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the child */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_CHILD = 0x00000000FFFFFFFFL; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the group */ 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_GROUP = 0x7FFFFFFF00000000L; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the type */ 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_TYPE = 0x8000000000000000L; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The shift amount (in packed position representation) for the group */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_SHIFT_GROUP = 32; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The shift amount (in packed position representation) for the type */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_SHIFT_TYPE = 63; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in integer child position representation) for the child */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_INT_MASK_CHILD = 0xFFFFFFFF; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in integer group position representation) for the group */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_INT_MASK_GROUP = 0x7FFFFFFF; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Serves as the glue/translator between a ListView and an ExpandableListView */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ExpandableListConnector mConnector; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Gives us Views through group+child positions */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ExpandableListAdapter mAdapter; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Left bound for drawing the indicator. */ 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mIndicatorLeft; 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Right bound for drawing the indicator. */ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mIndicatorRight; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 143f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** Start bound for drawing the indicator. */ 144f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private int mIndicatorStart; 145f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 146f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** End bound for drawing the indicator. */ 147f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private int mIndicatorEnd; 148f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Left bound for drawing the indicator of a child. Value of 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorLeft. 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mChildIndicatorLeft; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Right bound for drawing the indicator of a child. Value of 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorRight. 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mChildIndicatorRight; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 162f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Start bound for drawing the indicator of a child. Value of 163f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorStart. 164f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 165f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private int mChildIndicatorStart; 166f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 167f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 168f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * End bound for drawing the indicator of a child. Value of 169f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorEnd. 170f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 171f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private int mChildIndicatorEnd; 172f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 173f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes when a child indicator should inherit this bound from the generic 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicator bounds 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int CHILD_INDICATOR_INHERIT = -1; 178f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 179f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 180f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Denotes an undefined value for an indicator 181f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 182f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private static final int INDICATOR_UNDEFINED = -2; 183f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The indicator drawn next to a group. */ 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mGroupIndicator; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The indicator drawn next to a child. */ 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mChildIndicator; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] EMPTY_STATE_SET = {}; 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is expanded. */ 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EXPANDED_STATE_SET = 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_expanded}; 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is empty (has no children). */ 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EMPTY_STATE_SET = 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_empty}; 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is expanded and empty (has no children). */ 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EXPANDED_EMPTY_STATE_SET = 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_expanded, R.attr.state_empty}; 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** States for the group where the 0th bit is expanded and 1st bit is empty. */ 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[][] GROUP_STATE_SETS = { 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EMPTY_STATE_SET, // 00 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EXPANDED_STATE_SET, // 01 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EMPTY_STATE_SET, // 10 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EXPANDED_EMPTY_STATE_SET // 11 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the child is the last within its group. */ 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] CHILD_LAST_STATE_SET = 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_last}; 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Drawable to be used as a divider when it is adjacent to any children */ 2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mChildDivider; 2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bounds of the indicator to be drawn 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Rect mIndicatorRect = new Rect(); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListView(Context context) { 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListView(Context context, AttributeSet attrs) { 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, com.android.internal.R.attr.expandableListViewStyle); 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 230617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public ExpandableListView(Context context, AttributeSet attrs, int defStyleAttr) { 231617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette this(context, attrs, defStyleAttr, 0); 232617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette } 233617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette 234617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette public ExpandableListView( 235617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { 236617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette super(context, attrs, defStyleAttr, defStyleRes); 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 238617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette final TypedArray a = context.obtainStyledAttributes(attrs, 239617feb99a06e7ffb3894e86a286bf30e085f321aAlan Viverette com.android.internal.R.styleable.ExpandableListView, defStyleAttr, defStyleRes); 240f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 241f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mGroupIndicator = a.getDrawable( 242f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_groupIndicator); 243f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicator = a.getDrawable( 244f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childIndicator); 245f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorLeft = a.getDimensionPixelSize( 246f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0); 247f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorRight = a.getDimensionPixelSize( 248f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0); 249875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy if (mIndicatorRight == 0 && mGroupIndicator != null) { 250fb13abd800cd610c7f46815848545feff83e5748Romain Guy mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); 251fb13abd800cd610c7f46815848545feff83e5748Romain Guy } 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorLeft = a.getDimensionPixelSize( 253f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, 254f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio CHILD_INDICATOR_INHERIT); 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorRight = a.getDimensionPixelSize( 256f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childIndicatorRight, 257f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio CHILD_INDICATOR_INHERIT); 258f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildDivider = a.getDrawable( 259f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childDivider); 260f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 261f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (!isRtlCompatibilityMode()) { 262f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorStart = a.getDimensionPixelSize( 263f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_indicatorStart, 264f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio INDICATOR_UNDEFINED); 265f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorEnd = a.getDimensionPixelSize( 266f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_indicatorEnd, 267f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio INDICATOR_UNDEFINED); 268f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 269f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorStart = a.getDimensionPixelSize( 270f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childIndicatorStart, 271f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio CHILD_INDICATOR_INHERIT); 272f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorEnd = a.getDimensionPixelSize( 273f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio com.android.internal.R.styleable.ExpandableListView_childIndicatorEnd, 274f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio CHILD_INDICATOR_INHERIT); 275f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 276f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 279f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 280f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 281f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Return true if we are in RTL compatibility mode (either before Jelly Bean MR1 or 282f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * RTL not supported) 283f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 284f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private boolean isRtlCompatibilityMode() { 285f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio final int targetSdkVersion = mContext.getApplicationInfo().targetSdkVersion; 286f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio return targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport(); 287f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 288f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 289f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 290f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Return true if the application tag in the AndroidManifest has set "supportRtl" to true 291f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 292f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private boolean hasRtlSupport() { 293f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio return mContext.getApplicationInfo().hasRtlSupport(); 294f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 295f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 296f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio public void onRtlPropertiesChanged(int layoutDirection) { 297f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveIndicator(); 298f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveChildIndicator(); 299f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 300f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 301f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 302f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Resolve start/end indicator. start/end indicator always takes precedence over left/right 303f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * indicator when defined. 304f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 305f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private void resolveIndicator() { 306f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 307f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (isLayoutRtl) { 308f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mIndicatorStart >= 0) { 309f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorRight = mIndicatorStart; 310f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 311f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mIndicatorEnd >= 0) { 312f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorLeft = mIndicatorEnd; 313f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 314f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } else { 315f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mIndicatorStart >= 0) { 316f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorLeft = mIndicatorStart; 317f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 318f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mIndicatorEnd >= 0) { 319f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorRight = mIndicatorEnd; 320f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 321f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 322f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mIndicatorRight == 0 && mGroupIndicator != null) { 323f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); 324f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 325f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 326f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 327f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 328f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Resolve start/end child indicator. start/end child indicator always takes precedence over 329f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * left/right child indicator when defined. 330f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 331f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio private void resolveChildIndicator() { 332f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 333f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (isLayoutRtl) { 334f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mChildIndicatorStart >= CHILD_INDICATOR_INHERIT) { 335f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorRight = mChildIndicatorStart; 336f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 337f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mChildIndicatorEnd >= CHILD_INDICATOR_INHERIT) { 338f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorLeft = mChildIndicatorEnd; 339f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 340f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } else { 341f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mChildIndicatorStart >= CHILD_INDICATOR_INHERIT) { 342f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorLeft = mChildIndicatorStart; 343f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 344f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio if (mChildIndicatorEnd >= CHILD_INDICATOR_INHERIT) { 345f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorRight = mChildIndicatorEnd; 346f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 347f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 348f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 349f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dispatchDraw(Canvas canvas) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw children, etc. 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.dispatchDraw(canvas); 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we have any indicators to draw, we do it here 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mChildIndicator == null) && (mGroupIndicator == null)) { 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int saveCount = 0; 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clipToPadding) { 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project saveCount = canvas.save(); 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int scrollX = mScrollX; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int scrollY = mScrollY; 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop, 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollX + mRight - mLeft - mPaddingRight, 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollY + mBottom - mTop - mPaddingBottom); 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int headerViewsCount = getHeaderViewsCount(); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastChildFlPos = mItemCount - getFooterViewsCount() - headerViewsCount - 1; 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int myB = mBottom; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata pos; 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View item; 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable indicator; 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int t, b; 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start at a value that is neither child nor group 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastItemType = ~(ExpandableListPosition.CHILD | ExpandableListPosition.GROUP); 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Rect indicatorRect = mIndicatorRect; 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The "child" mentioned in the following two lines is this 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // View's child, not referring to an expandable list's 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // notion of a child (as opposed to a group) 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0, childFlPos = mFirstPosition - headerViewsCount; i < childCount; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++, childFlPos++) { 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childFlPos < 0) { 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This child is header 3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (childFlPos > lastChildFlPos) { 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This child is footer, so are all subsequent children 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item = getChildAt(i); 4039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = item.getTop(); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = item.getBottom(); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This item isn't on the screen 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((b < 0) || (t > myB)) continue; 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get more expandable list-related info for this item 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos = mConnector.getUnflattenedPos(childFlPos); 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 412605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio final boolean isLayoutRtl = isLayoutRtl(); 413605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio final int width = getWidth(); 414605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this item type and the previous item type are different, then we need to change 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the left & right bounds 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type != lastItemType) { 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type == ExpandableListPosition.CHILD) { 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.left = (mChildIndicatorLeft == CHILD_INDICATOR_INHERIT) ? 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorLeft : mChildIndicatorLeft; 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.right = (mChildIndicatorRight == CHILD_INDICATOR_INHERIT) ? 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorRight : mChildIndicatorRight; 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.left = mIndicatorLeft; 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.right = mIndicatorRight; 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 427605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio 428605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio if (isLayoutRtl) { 429605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio final int temp = indicatorRect.left; 430605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.left = width - indicatorRect.right; 431605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.right = width - temp; 432605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio 433605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.left -= mPaddingRight; 434605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.right -= mPaddingRight; 435605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio } else { 436605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.left += mPaddingLeft; 437605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio indicatorRect.right += mPaddingLeft; 438605c5af9c8d36aab16fb9d2313fecc57301104bdFabrice Di Meglio } 4393e5e6aced9848d1ce09082c72ba5cc422064d8eaAdam Powell 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastItemType = pos.position.type; 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicatorRect.left != indicatorRect.right) { 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use item's full height + the divider height 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See ListView#dispatchDraw 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.top = t;// - mDividerHeight; 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.bottom = b; 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.top = t; 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.bottom = b;// + mDividerHeight; 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the indicator (with its state set to the item's state) 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = getIndicator(pos); 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null) { 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw the indicator 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setBounds(indicatorRect); 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.draw(canvas); 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clipToPadding) { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restoreToCount(saveCount); 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the indicator for the item at the given position. If the indicator 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is stateful, the state will be given to the indicator. 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The flat list position of the item whose indicator 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be returned. 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The indicator in the proper state. 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable getIndicator(PositionMetadata pos) { 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable indicator; 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type == ExpandableListPosition.GROUP) { 4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = mGroupIndicator; 4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null && indicator.isStateful()) { 4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Empty check based on availability of data. If the groupMetadata isn't null, 4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we do a check on it. Otherwise, the group is collapsed so we consider it 4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // empty for performance reasons. 4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isEmpty = (pos.groupMetadata == null) || 4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (pos.groupMetadata.lastChildFlPos == pos.groupMetadata.flPos); 4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int stateSetIndex = 4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (pos.isExpanded() ? 1 : 0) | // Expanded? 4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (isEmpty ? 2 : 0); // Empty? 4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setState(GROUP_STATE_SETS[stateSetIndex]); 4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = mChildIndicator; 4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null && indicator.isStateful()) { 5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need for a state sets array for the child since it only has two states 5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int stateSet[] = pos.position.flatListPos == pos.groupMetadata.lastChildFlPos 5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? CHILD_LAST_STATE_SET 5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : EMPTY_STATE_SET; 5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setState(stateSet); 5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return indicator; 5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawable that will be drawn adjacent to every child in the list. This will 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be drawn using the same height as the normal divider ({@link #setDivider(Drawable)}) or 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if it does not have an intrinsic height, the height set by {@link #setDividerHeight(int)}. 5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childDivider The drawable to use. 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildDivider(Drawable childDivider) { 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildDivider = childDivider; 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void drawDivider(Canvas canvas, Rect bounds, int childIndex) { 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flatListPosition = childIndex + mFirstPosition; 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only proceed as possible child if the divider isn't above all items (if it is above 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // all items, then the item below it has to be a group) 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatListPosition >= 0) { 529272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 530272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne PositionMetadata pos = mConnector.getUnflattenedPos(adjustedPosition); 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this item is a child, or it is a non-empty group that is expanded 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((pos.position.type == ExpandableListPosition.CHILD) || (pos.isExpanded() && 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.groupMetadata.lastChildFlPos != pos.groupMetadata.flPos)) { 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // These are the cases where we draw the child divider 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable divider = mChildDivider; 53695930e13faac8c17dabfaa1478089baa772f091bRomain Guy divider.setBounds(bounds); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project divider.draw(canvas); 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Otherwise draw the default divider 5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.drawDivider(canvas, bounds, flatListPosition); 5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This overloaded method should not be used, instead use 5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setAdapter(ExpandableListAdapter)}. 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ListAdapter adapter) { 5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException( 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "For ExpandableListView, use setAdapter(ExpandableListAdapter) instead of " + 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "setAdapter(ListAdapter)"); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method should not be used, use {@link #getExpandableListAdapter()}. 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListAdapter getAdapter() { 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The developer should never really call this method on an 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ExpandableListView, so it would be nice to throw a RuntimeException, 5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but AdapterView calls this 5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getAdapter(); 5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when an item has been clicked and the 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller prefers to receive a ListView-style position instead of a group 5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and/or child position. In most cases, the caller should use 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setOnGroupClickListener} and/or {@link #setOnChildClickListener}. 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p /> 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnItemClickListener(OnItemClickListener l) { 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setOnItemClickListener(l); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the adapter that provides data to this view. 5899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param adapter The adapter that provides data to this view. 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ExpandableListAdapter adapter) { 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set member variable 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter = adapter; 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter != null) { 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create the connector 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector = new ExpandableListConnector(adapter); 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector = null; 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Link the ListView (superclass) to the expandable list data through the connector 6039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setAdapter(mConnector); 6049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the adapter that provides data to this view. 6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The adapter that provides data to this view. 6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListAdapter getExpandableListAdapter() { 6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter; 6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 614272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 615272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param position An absolute (including header and footer) flat list position. 616272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return true if the position corresponds to a header or a footer item. 617272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 61847ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne private boolean isHeaderOrFooterPosition(int position) { 61947ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne final int footerViewsStart = mItemCount - getFooterViewsCount(); 62047ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne return (position < getHeaderViewsCount() || position >= footerViewsStart); 62147ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne } 62247ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 623272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 624272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * Converts an absolute item flat position into a group/child flat position, shifting according 625272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * to the number of header items. 626272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * 627272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param flatListPosition The absolute flat position 628272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return A group/child flat position as expected by the connector. 629272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 630272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne private int getFlatPositionForConnector(int flatListPosition) { 631272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return flatListPosition - getHeaderViewsCount(); 632272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne } 633272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne 634272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 635272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * Converts a group/child flat position into an absolute flat position, that takes into account 636272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * the possible headers. 637272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * 638272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param flatListPosition The child/group flat position 639272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return An absolute flat position. 640272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 641272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne private int getAbsoluteFlatPosition(int flatListPosition) { 642272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return flatListPosition + getHeaderViewsCount(); 643272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne } 644272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performItemClick(View v, int position, long id) { 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Ignore clicks in header/footers 64847ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(position)) { 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clicked on a header/footer, so ignore pass it on to super 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.performItemClick(v, position, id); 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internally handle the item click 654272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(position); 655272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return handleItemClick(v, adjustedPosition, id); 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will either expand/collapse groups (if a group was clicked) or pass 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on the click to the proper child (if a child was clicked) 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The flat list position. This has already been factored to 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remove the header/footer. 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The ListAdapter ID, not the group or child ID. 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handleItemClick(View v, int position, long id) { 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final PositionMetadata posMetadata = mConnector.getUnflattenedPos(position); 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = getChildOrGroupId(posMetadata.position); 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean returnValue; 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (posMetadata.position.type == ExpandableListPosition.GROUP) { 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* It's a group, so handle collapsing/expanding */ 6744039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 6754039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy /* It's a group click, so pass on event */ 6764039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy if (mOnGroupClickListener != null) { 6774039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy if (mOnGroupClickListener.onGroupClick(this, v, 6784039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy posMetadata.position.groupPos, id)) { 6794039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy posMetadata.recycle(); 6804039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy return true; 6814039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy } 6824039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy } 6834039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (posMetadata.isExpanded()) { 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Collapse it */ 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.collapseGroup(posMetadata); 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 6894039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupCollapseListener != null) { 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener.onGroupCollapse(posMetadata.position.groupPos); 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Expand it */ 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.expandGroup(posMetadata); 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 6984039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupExpandListener != null) { 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener.onGroupExpand(posMetadata.position.groupPos); 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 702458034799861fef47e00d85d528b4dac5e00bd51Adam Powell 703458034799861fef47e00d85d528b4dac5e00bd51Adam Powell final int groupPos = posMetadata.position.groupPos; 704458034799861fef47e00d85d528b4dac5e00bd51Adam Powell final int groupFlatPos = posMetadata.position.flatListPos; 70552b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne 70652b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount(); 70752b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos), 70852b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne shiftedGroupPosition); 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7104039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnValue = true; 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* It's a child, so pass on event */ 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnChildClickListener != null) { 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mOnChildClickListener.onChildClick(this, v, posMetadata.position.groupPos, 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project posMetadata.position.childPos, id); 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7194039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnValue = false; 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7224039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project posMetadata.recycle(); 7244039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return returnValue; 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Expand a group in the grouped list view 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPos the group to be expanded 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the group was expanded, false otherwise (if the group 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was already expanded, this will return false) 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean expandGroup(int groupPos) { 73663f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck return expandGroup(groupPos, false); 73763f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck } 73863f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 73963f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck /** 74063f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * Expand a group in the grouped list view 74163f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * 74263f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @param groupPos the group to be expanded 74363f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @param animate true if the expanding group should be animated in 74463f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @return True if the group was expanded, false otherwise (if the group 74563f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * was already expanded, this will return false) 74663f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck */ 74763f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck public boolean expandGroup(int groupPos, boolean animate) { 748820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition elGroupPos = ExpandableListPosition.obtain( 749820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition.GROUP, groupPos, -1, -1); 750820b236adce43567b2effd92e246c34a8a76c9f9John Reck PositionMetadata pm = mConnector.getFlattenedPos(elGroupPos); 751820b236adce43567b2effd92e246c34a8a76c9f9John Reck elGroupPos.recycle(); 75263f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck boolean retValue = mConnector.expandGroup(pm); 7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupExpandListener != null) { 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener.onGroupExpand(groupPos); 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 75763f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 75863f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck if (animate) { 75963f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck final int groupFlatPos = pm.position.flatListPos; 76063f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 76163f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount(); 76263f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos), 76363f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck shiftedGroupPosition); 76463f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck } 76563f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck pm.recycle(); 76663f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retValue; 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Collapse a group in the grouped list view 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPos position of the group to collapse 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the group was collapsed, false otherwise (if the group 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was already collapsed, this will return false) 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean collapseGroup(int groupPos) { 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean retValue = mConnector.collapseGroup(groupPos); 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupCollapseListener != null) { 7819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener.onGroupCollapse(groupPos); 7829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retValue; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used for being notified when a group is collapsed */ 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupCollapseListener { 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been collapsed. 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was collapsed 7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onGroupCollapse(int groupPosition); 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupCollapseListener mOnGroupCollapseListener; 7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupCollapseListener( 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnGroupCollapseListener onGroupCollapseListener) { 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener = onGroupCollapseListener; 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used for being notified when a group is expanded */ 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupExpandListener { 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been expanded. 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was expanded 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onGroupExpand(int groupPosition); 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupExpandListener mOnGroupExpandListener; 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupExpandListener( 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnGroupExpandListener onGroupExpandListener) { 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener = onGroupExpandListener; 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when a group in this 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expandable list has been clicked. 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupClickListener { 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been clicked. 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The ExpandableListConnector where the click happened 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view within the expandable list/ListView that was clicked 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was clicked 8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The row id of the group that was clicked 8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the click was handled 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long id); 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupClickListener mOnGroupClickListener; 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) { 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupClickListener = onGroupClickListener; 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when a child in this 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expandable list has been clicked. 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnChildClickListener { 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a child in this expandable list has 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been clicked. 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The ExpandableListView where the click happened 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view within the expandable list/ListView that was clicked 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that contains the child that 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was clicked 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The child position within the group 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The row id of the child that was clicked 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the click was handled 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onChildClick(ExpandableListView parent, View v, int groupPosition, 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childPosition, long id); 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnChildClickListener mOnChildClickListener; 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnChildClickListener(OnChildClickListener onChildClickListener) { 8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnChildClickListener = onChildClickListener; 8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 87647ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * Converts a flat list position (the raw position of an item (child or group) 877f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in the list) to a group and/or child position (represented in a 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * packed position). This is useful in situations where the caller needs to 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use the underlying {@link ListView}'s methods. Use 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionType} , 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionChild}, 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionGroup} to unpack. 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flatListPosition The flat list position to be converted. 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The group and/or child position for the given flat list position 88647ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * in packed position representation. #PACKED_POSITION_VALUE_NULL if 88747ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * the position corresponds to a header or a footer item. 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getExpandableListPosition(int flatListPosition) { 89047ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(flatListPosition)) { 89147ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne return PACKED_POSITION_VALUE_NULL; 89247ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne } 89347ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 894272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 895272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition); 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPos = pm.position.getPackedPosition(); 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return packedPos; 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Converts a group and/or child position to a flat list position. This is 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in situations where the caller needs to use the underlying 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ListView}'s methods. 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The group and/or child positions to be converted in 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * packed position representation. Use 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)} or 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForGroup(int)}. 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The flat list position for the given child or group. 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getFlatListPosition(long packedPosition) { 913820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition elPackedPos = ExpandableListPosition 914820b236adce43567b2effd92e246c34a8a76c9f9John Reck .obtainPosition(packedPosition); 915820b236adce43567b2effd92e246c34a8a76c9f9John Reck PositionMetadata pm = mConnector.getFlattenedPos(elPackedPos); 916820b236adce43567b2effd92e246c34a8a76c9f9John Reck elPackedPos.recycle(); 917272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int flatListPosition = pm.position.flatListPos; 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 919272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return getAbsoluteFlatPosition(flatListPosition); 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the position of the currently selected group or child (along with 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its type). Can return {@link #PACKED_POSITION_VALUE_NULL} if no selection. 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A packed position containing the currently selected group or 92747ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * child's position and type. #PACKED_POSITION_VALUE_NULL if no selection 92847ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * or if selection is on a header or a footer item. 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getSelectedPosition() { 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPos = getSelectedItemPosition(); 93247ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 93347ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne // The case where there is no selection (selectedPos == -1) is also handled here. 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getExpandableListPosition(selectedPos); 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the ID of the currently selected group or child. Can return -1 if no 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The ID of the currently selected group or child. -1 if no 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getSelectedId() { 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPos = getSelectedPosition(); 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPos == PACKED_POSITION_VALUE_NULL) return -1; 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int groupPos = getPackedPositionGroup(packedPos); 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getPackedPositionType(packedPos) == PACKED_POSITION_TYPE_GROUP) { 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's a group 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getGroupId(groupPos); 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's a child 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getChildId(groupPos, getPackedPositionChild(packedPos)); 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the selection to the specified group. 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The position of the group that should be selected. 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelectedGroup(int groupPosition) { 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition elGroupPos = ExpandableListPosition 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .obtainGroupPosition(groupPosition); 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata pm = mConnector.getFlattenedPos(elGroupPos); 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project elGroupPos.recycle(); 968272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int absoluteFlatPosition = getAbsoluteFlatPosition(pm.position.flatListPos); 969272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne super.setSelection(absoluteFlatPosition); 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the selection to the specified child. If the child is in a collapsed 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * group, the group will only be expanded and child subsequently selected if 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * shouldExpandGroup is set to true, otherwise the method will return false. 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The position of the group that contains the child. 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The position of the child within the group. 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param shouldExpandGroup Whether the child's group should be expanded if 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it is collapsed. 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the selection was successfully set on the child. 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition elChildPos = ExpandableListPosition.obtainChildPosition( 9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupPosition, childPosition); 9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata flatChildPos = mConnector.getFlattenedPos(elChildPos); 9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatChildPos == null) { 9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The child's group isn't expanded 9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Shouldn't expand the group, so return false for we didn't set the selection 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!shouldExpandGroup) return false; 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expandGroup(groupPosition); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flatChildPos = mConnector.getFlattenedPos(elChildPos); 9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sanity check 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatChildPos == null) { 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("Could not find child"); 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1005272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne int absoluteFlatPosition = getAbsoluteFlatPosition(flatChildPos.position.flatListPos); 1006272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne super.setSelection(absoluteFlatPosition); 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project elChildPos.recycle(); 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flatChildPos.recycle(); 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether the given group is currently expanded. 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group to check. 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the group is currently expanded. 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isGroupExpanded(int groupPosition) { 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mConnector.isGroupExpanded(groupPosition); 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the type of a packed position. See 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position for which to return the type. 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The type of the position contained within the packed position, 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * either {@link #PACKED_POSITION_TYPE_CHILD}, {@link #PACKED_POSITION_TYPE_GROUP}, or 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #PACKED_POSITION_TYPE_NULL}. 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionType(long packedPosition) { 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) { 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PACKED_POSITION_TYPE_NULL; 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (packedPosition & PACKED_POSITION_MASK_TYPE) == PACKED_POSITION_MASK_TYPE 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? PACKED_POSITION_TYPE_CHILD 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : PACKED_POSITION_TYPE_GROUP; 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the group position from a packed position. See 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position from which the group position 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be returned. 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The group position portion of the packed position. If this does 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not contain a group, returns -1. 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionGroup(long packedPosition) { 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Null 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1; 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) ((packedPosition & PACKED_POSITION_MASK_GROUP) >> PACKED_POSITION_SHIFT_GROUP); 10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the child position from a packed position that is of 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #PACKED_POSITION_TYPE_CHILD} type (use {@link #getPackedPositionType(long)}). 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To get the group that this child belongs to, use 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionGroup(long)}. See 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position from which the child position 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be returned. 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The child position portion of the packed position. If this does 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not contain a child, returns -1. 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionChild(long packedPosition) { 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Null 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1; 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Group since a group type clears this bit 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((packedPosition & PACKED_POSITION_MASK_TYPE) != PACKED_POSITION_MASK_TYPE) return -1; 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) (packedPosition & PACKED_POSITION_MASK_CHILD); 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the packed position representation of a child's position. 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In general, a packed position should be used in 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * situations where the position given to/returned from an 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListAdapter} or {@link ExpandableListView} method can 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * either be a child or group. The two positions are packed into a single 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * long which can be unpacked using 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionChild(long)}, 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionGroup(long)}, and 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionType(long)}. 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The child's parent group's position. 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The child position within the group. 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The packed position representation of the child (and parent group). 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getPackedPositionForChild(int groupPosition, int childPosition) { 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (((long)PACKED_POSITION_TYPE_CHILD) << PACKED_POSITION_SHIFT_TYPE) 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP) 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << PACKED_POSITION_SHIFT_GROUP) 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | (childPosition & PACKED_POSITION_INT_MASK_CHILD); 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the packed position representation of a group's position. See 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The child's parent group's position. 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The packed position representation of the group. 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getPackedPositionForGroup(int groupPosition) { 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to OR a type in because PACKED_POSITION_GROUP == 0 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP) 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << PACKED_POSITION_SHIFT_GROUP); 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContextMenuInfo createContextMenuInfo(View view, int flatListPosition, long id) { 111947ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(flatListPosition)) { 112047ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne // Return normal info for header/footer view context menus 1121fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey return new AdapterContextMenuInfo(view, flatListPosition, id); 1122fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey } 1123fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey 1124272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 1125fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition); 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition pos = pm.position; 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = getChildOrGroupId(pos); 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPosition = pos.getPackedPosition(); 1130820b236adce43567b2effd92e246c34a8a76c9f9John Reck 1131820b236adce43567b2effd92e246c34a8a76c9f9John Reck pm.recycle(); 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new ExpandableListContextMenuInfo(view, packedPosition, id); 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the ID of the group or child at the given <code>position</code>. 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is useful since there is no ListAdapter ID -> ExpandableListAdapter 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ID conversion mechanism (in some cases, it isn't possible). 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The position of the child or group whose ID should be 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returned. 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long getChildOrGroupId(ExpandableListPosition position) { 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position.type == ExpandableListPosition.CHILD) { 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getChildId(position.groupPos, position.childPos); 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getGroupId(position.groupPos); 11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the indicator to be drawn next to a child. 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childIndicator The drawable to be used as an indicator. If the 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * child is the last child for a group, the state 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.R.attr#state_last} will be set. 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildIndicator(Drawable childIndicator) { 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicator = childIndicator; 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawing bounds for the child indicator. For either, you can 11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general 11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicator's bounds. 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setIndicatorBounds(int, int) 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param left The left position (relative to the left bounds of this View) 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to start drawing the indicator. 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param right The right position (relative to the left bounds of this 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * View) to end the drawing of the indicator. 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildIndicatorBounds(int left, int right) { 11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorLeft = left; 11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorRight = right; 1177f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveChildIndicator(); 11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1179f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 1180f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 1181f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Sets the relative drawing bounds for the child indicator. For either, you can 1182f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general 1183f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * indicator's bounds. 1184f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * 1185f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @see #setIndicatorBounds(int, int) 1186f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @param start The start position (relative to the start bounds of this View) 1187f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * to start drawing the indicator. 1188f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @param end The end position (relative to the end bounds of this 1189f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * View) to end the drawing of the indicator. 1190f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 1191f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio public void setChildIndicatorBoundsRelative(int start, int end) { 1192f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorStart = start; 1193f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mChildIndicatorEnd = end; 1194f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveChildIndicator(); 1195f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 1196f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the indicator to be drawn next to a group. 11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupIndicator The drawable to be used as an indicator. If the 12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * group is empty, the state {@link android.R.attr#state_empty} will be 12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set. If the group is expanded, the state 12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.R.attr#state_expanded} will be set. 12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupIndicator(Drawable groupIndicator) { 12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupIndicator = groupIndicator; 1207875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy if (mIndicatorRight == 0 && mGroupIndicator != null) { 1208875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); 1209875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy } 12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1211875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy 12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawing bounds for the indicators (at minimum, the group indicator 12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is affected by this; the child indicator is affected by this if the 12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * child indicator bounds are set to inherit). 12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setChildIndicatorBounds(int, int) 12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param left The left position (relative to the left bounds of this View) 12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to start drawing the indicator. 12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param right The right position (relative to the left bounds of this 12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * View) to end the drawing of the indicator. 12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setIndicatorBounds(int left, int right) { 12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorLeft = left; 12259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorRight = right; 1226f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveIndicator(); 12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1228f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 1229f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio /** 1230f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * Sets the relative drawing bounds for the indicators (at minimum, the group indicator 1231f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * is affected by this; the child indicator is affected by this if the 1232f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * child indicator bounds are set to inherit). 1233f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * 1234f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @see #setChildIndicatorBounds(int, int) 1235f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @param start The start position (relative to the start bounds of this View) 1236f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * to start drawing the indicator. 1237f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * @param end The end position (relative to the end bounds of this 1238f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio * View) to end the drawing of the indicator. 1239f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio */ 1240f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio public void setIndicatorBoundsRelative(int start, int end) { 1241f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorStart = start; 1242f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio mIndicatorEnd = end; 1243f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio resolveIndicator(); 1244f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio } 1245f4efad05515ae8bd8c826e2832be62a701e1c6e5Fabrice Di Meglio 12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extra menu information specific to an {@link ExpandableListView} provided 12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to the 12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) } 12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callback when a context menu is brought up for this AdapterView. 12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class ExpandableListContextMenuInfo implements ContextMenu.ContextMenuInfo { 12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListContextMenuInfo(View targetView, long packedPosition, long id) { 12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.targetView = targetView; 12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.packedPosition = packedPosition; 12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.id = id; 12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The view for which the context menu is being displayed. This 12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be one of the children Views of this {@link ExpandableListView}. 12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View targetView; 12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position in the list represented by the adapter for which 12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context menu is being displayed. Use the methods 12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionType}, 12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionChild}, and 12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionGroup} to unpack this. 12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long packedPosition; 12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The ID of the item (group or child) for which the context menu is 12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * being displayed. 12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long id; 12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class SavedState extends BaseSavedState { 12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList; 12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link ExpandableListView#onSaveInstanceState()} 12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState( 12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState, 12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList) { 12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.expandedGroupMetadataList = expandedGroupMetadataList; 12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link #CREATOR} 12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expandedGroupMetadataList = new ArrayList<ExpandableListConnector.GroupMetadata>(); 13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.readList(expandedGroupMetadataList, ExpandableListConnector.class.getClassLoader()); 13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel out, int flags) { 13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(out, flags); 13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeList(expandedGroupMetadataList); 13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Parcelable.Creator<SavedState> CREATOR 13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new Parcelable.Creator<SavedState>() { 13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parcelable onSaveInstanceState() { 13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(superState, 13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector != null ? mConnector.getExpandedGroupMetadataList() : null); 13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onRestoreInstanceState(Parcelable state) { 13317444e147a863b41e08815658f1bcbe426aba512bRomain Guy if (!(state instanceof SavedState)) { 13327444e147a863b41e08815658f1bcbe426aba512bRomain Guy super.onRestoreInstanceState(state); 13337444e147a863b41e08815658f1bcbe426aba512bRomain Guy return; 13347444e147a863b41e08815658f1bcbe426aba512bRomain Guy } 13357444e147a863b41e08815658f1bcbe426aba512bRomain Guy 13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 13389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mConnector != null && ss.expandedGroupMetadataList != null) { 13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.setExpandedGroupMetadataList(ss.expandedGroupMetadataList); 13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 13448a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 13458a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 13468a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 13478a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(ExpandableListView.class.getName()); 13488a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 13498a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 13508a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 13518a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 13528a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 13538a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(ExpandableListView.class.getName()); 13548a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1356