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 399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/** 409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * A view that shows items in a vertically scrolling two-level list. This 419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * differs from the {@link ListView} by allowing two levels: groups which can 429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * individually be expanded to show its children. The items come from the 439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListAdapter} associated with this view. 449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Expandable lists are able to show an indicator beside each item to display 469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the item's current state (the states are usually one of expanded group, 479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * collapsed group, child, or last child). Use 489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setChildIndicator(Drawable)} or {@link #setGroupIndicator(Drawable)} 499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (or the corresponding XML attributes) to set these indicators (see the docs 509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for each method to see additional state that each Drawable can have). The 519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * default style for an {@link ExpandableListView} provides indicators which 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be shown next to Views given to the {@link ExpandableListView}. The 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * layouts android.R.layout.simple_expandable_list_item_1 and 549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * android.R.layout.simple_expandable_list_item_2 (which should be used with 559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link SimpleCursorTreeAdapter}) contain the preferred position information 569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for indicators. 579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The context menu information set by an {@link ExpandableListView} will be a 599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListContextMenuInfo} object with 609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListContextMenuInfo#packedPosition} being a packed position 619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * that can be used with {@link #getPackedPositionType(long)} and the other 629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * similar methods. 639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <em><b>Note:</b></em> You cannot use the value <code>wrap_content</code> 659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * for the <code>android:layout_height</code> attribute of a 669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ExpandableListView in XML if the parent's size is also not strictly specified 679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (for example, if the parent were ScrollView you could not specify 689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wrap_content since it also can be any length. However, you can use 699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * wrap_content if the ExpandableListView parent has a specific size, such as 709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 100 pixels. 719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_groupIndicator 739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_indicatorLeft 749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_indicatorRight 759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicator 769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicatorLeft 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childIndicatorRight 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @attr ref android.R.styleable#ExpandableListView_childDivider 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class ExpandableListView extends ListView { 819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a group. 849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_GROUP = 0; 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a child. 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_CHILD = 1; 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position represents a neither/null/no preference. 949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int PACKED_POSITION_TYPE_NULL = 2; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The value for a packed position that represents neither/null/no 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * preference. This value is not otherwise possible since a group type 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * (first bit 0) should not have a child position filled. 1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final long PACKED_POSITION_VALUE_NULL = 0x00000000FFFFFFFFL; 1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the child */ 1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_CHILD = 0x00000000FFFFFFFFL; 1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the group */ 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_GROUP = 0x7FFFFFFF00000000L; 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in packed position representation) for the type */ 1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_MASK_TYPE = 0x8000000000000000L; 1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The shift amount (in packed position representation) for the group */ 1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_SHIFT_GROUP = 32; 1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The shift amount (in packed position representation) for the type */ 1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_SHIFT_TYPE = 63; 1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in integer child position representation) for the child */ 1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_INT_MASK_CHILD = 0xFFFFFFFF; 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The mask (in integer group position representation) for the group */ 1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final long PACKED_POSITION_INT_MASK_GROUP = 0x7FFFFFFF; 1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Serves as the glue/translator between a ListView and an ExpandableListView */ 1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ExpandableListConnector mConnector; 1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Gives us Views through group+child positions */ 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private ExpandableListAdapter mAdapter; 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Left bound for drawing the indicator. */ 1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mIndicatorLeft; 1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Right bound for drawing the indicator. */ 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mIndicatorRight; 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Left bound for drawing the indicator of a child. Value of 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorLeft. 1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mChildIndicatorLeft; 1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Right bound for drawing the indicator of a child. Value of 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #CHILD_INDICATOR_INHERIT} means use mIndicatorRight. 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private int mChildIndicatorRight; 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Denotes when a child indicator should inherit this bound from the generic 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicator bounds 1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final int CHILD_INDICATOR_INHERIT = -1; 1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The indicator drawn next to a group. */ 1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mGroupIndicator; 1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** The indicator drawn next to a child. */ 1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mChildIndicator; 1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] EMPTY_STATE_SET = {}; 1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is expanded. */ 1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EXPANDED_STATE_SET = 1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_expanded}; 1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is empty (has no children). */ 1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EMPTY_STATE_SET = 1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_empty}; 1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the group is expanded and empty (has no children). */ 1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] GROUP_EXPANDED_EMPTY_STATE_SET = 1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_expanded, R.attr.state_empty}; 1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** States for the group where the 0th bit is expanded and 1st bit is empty. */ 1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[][] GROUP_STATE_SETS = { 1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project EMPTY_STATE_SET, // 00 1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EXPANDED_STATE_SET, // 01 1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EMPTY_STATE_SET, // 10 1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project GROUP_EXPANDED_EMPTY_STATE_SET // 11 1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project }; 1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** State indicating the child is the last within its group. */ 1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private static final int[] CHILD_LAST_STATE_SET = 1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {R.attr.state_last}; 1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Drawable to be used as a divider when it is adjacent to any children */ 1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable mChildDivider; 1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Bounds of the indicator to be drawn 1919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private final Rect mIndicatorRect = new Rect(); 1929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListView(Context context) { 1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, null); 1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListView(Context context, AttributeSet attrs) { 1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this(context, attrs, com.android.internal.R.attr.expandableListViewStyle); 1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListView(Context context, AttributeSet attrs, int defStyle) { 2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(context, attrs, defStyle); 2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project TypedArray a = 2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.ExpandableListView, defStyle, 2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 0); 2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupIndicator = a 2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getDrawable(com.android.internal.R.styleable.ExpandableListView_groupIndicator); 2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicator = a 2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getDrawable(com.android.internal.R.styleable.ExpandableListView_childIndicator); 2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorLeft = a 2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorLeft, 0); 2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorRight = a 2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .getDimensionPixelSize(com.android.internal.R.styleable.ExpandableListView_indicatorRight, 0); 216875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy if (mIndicatorRight == 0 && mGroupIndicator != null) { 217fb13abd800cd610c7f46815848545feff83e5748Romain Guy mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); 218fb13abd800cd610c7f46815848545feff83e5748Romain Guy } 2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorLeft = a.getDimensionPixelSize( 2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.ExpandableListView_childIndicatorLeft, CHILD_INDICATOR_INHERIT); 2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorRight = a.getDimensionPixelSize( 2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project com.android.internal.R.styleable.ExpandableListView_childIndicatorRight, CHILD_INDICATOR_INHERIT); 2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildDivider = a.getDrawable(com.android.internal.R.styleable.ExpandableListView_childDivider); 2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project a.recycle(); 2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project protected void dispatchDraw(Canvas canvas) { 2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw children, etc. 2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.dispatchDraw(canvas); 2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If we have any indicators to draw, we do it here 2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((mChildIndicator == null) && (mGroupIndicator == null)) { 2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int saveCount = 0; 2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final boolean clipToPadding = (mGroupFlags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; 2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clipToPadding) { 2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project saveCount = canvas.save(); 2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int scrollX = mScrollX; 2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int scrollY = mScrollY; 2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.clipRect(scrollX + mPaddingLeft, scrollY + mPaddingTop, 2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollX + mRight - mLeft - mPaddingRight, 2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project scrollY + mBottom - mTop - mPaddingBottom); 2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int headerViewsCount = getHeaderViewsCount(); 2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int lastChildFlPos = mItemCount - getFooterViewsCount() - headerViewsCount - 1; 2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int myB = mBottom; 2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata pos; 2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project View item; 2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable indicator; 2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int t, b; 2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Start at a value that is neither child nor group 2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int lastItemType = ~(ExpandableListPosition.CHILD | ExpandableListPosition.GROUP); 2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Rect indicatorRect = mIndicatorRect; 2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The "child" mentioned in the following two lines is this 2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // View's child, not referring to an expandable list's 2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // notion of a child (as opposed to a group) 2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int childCount = getChildCount(); 2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project for (int i = 0, childFlPos = mFirstPosition - headerViewsCount; i < childCount; 2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project i++, childFlPos++) { 2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (childFlPos < 0) { 2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This child is header 2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project continue; 2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else if (childFlPos > lastChildFlPos) { 2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This child is footer, so are all subsequent children 2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project break; 2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project item = getChildAt(i); 2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project t = item.getTop(); 2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project b = item.getBottom(); 2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // This item isn't on the screen 2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((b < 0) || (t > myB)) continue; 2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get more expandable list-related info for this item 2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos = mConnector.getUnflattenedPos(childFlPos); 2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this item type and the previous item type are different, then we need to change 2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // the left & right bounds 2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type != lastItemType) { 2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type == ExpandableListPosition.CHILD) { 2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.left = (mChildIndicatorLeft == CHILD_INDICATOR_INHERIT) ? 2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorLeft : mChildIndicatorLeft; 2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.right = (mChildIndicatorRight == CHILD_INDICATOR_INHERIT) ? 2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorRight : mChildIndicatorRight; 2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.left = mIndicatorLeft; 3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.right = mIndicatorRight; 3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3043e5e6aced9848d1ce09082c72ba5cc422064d8eaAdam Powell indicatorRect.left += mPaddingLeft; 3053e5e6aced9848d1ce09082c72ba5cc422064d8eaAdam Powell indicatorRect.right += mPaddingLeft; 3063e5e6aced9848d1ce09082c72ba5cc422064d8eaAdam Powell 3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project lastItemType = pos.position.type; 3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicatorRect.left != indicatorRect.right) { 3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Use item's full height + the divider height 3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mStackFromBottom) { 3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // See ListView#dispatchDraw 3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.top = t;// - mDividerHeight; 3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.bottom = b; 3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.top = t; 3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicatorRect.bottom = b;// + mDividerHeight; 3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Get the indicator (with its state set to the item's state) 3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = getIndicator(pos); 3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null) { 3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Draw the indicator 3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setBounds(indicatorRect); 3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.draw(canvas); 3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (clipToPadding) { 3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project canvas.restoreToCount(saveCount); 3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the indicator for the item at the given position. If the indicator 3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is stateful, the state will be given to the indicator. 3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param pos The flat list position of the item whose indicator 3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * should be returned. 3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The indicator in the proper state. 3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private Drawable getIndicator(PositionMetadata pos) { 3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Drawable indicator; 3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (pos.position.type == ExpandableListPosition.GROUP) { 3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = mGroupIndicator; 3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null && indicator.isStateful()) { 3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Empty check based on availability of data. If the groupMetadata isn't null, 3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // we do a check on it. Otherwise, the group is collapsed so we consider it 3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // empty for performance reasons. 3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean isEmpty = (pos.groupMetadata == null) || 3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (pos.groupMetadata.lastChildFlPos == pos.groupMetadata.flPos); 3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int stateSetIndex = 3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (pos.isExpanded() ? 1 : 0) | // Expanded? 3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (isEmpty ? 2 : 0); // Empty? 3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setState(GROUP_STATE_SETS[stateSetIndex]); 3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator = mChildIndicator; 3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (indicator != null && indicator.isStateful()) { 3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need for a state sets array for the child since it only has two states 3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int stateSet[] = pos.position.flatListPos == pos.groupMetadata.lastChildFlPos 3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? CHILD_LAST_STATE_SET 3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : EMPTY_STATE_SET; 3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project indicator.setState(stateSet); 3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return indicator; 3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawable that will be drawn adjacent to every child in the list. This will 3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * be drawn using the same height as the normal divider ({@link #setDivider(Drawable)}) or 3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * if it does not have an intrinsic height, the height set by {@link #setDividerHeight(int)}. 3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childDivider The drawable to use. 3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildDivider(Drawable childDivider) { 3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildDivider = childDivider; 3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void drawDivider(Canvas canvas, Rect bounds, int childIndex) { 3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int flatListPosition = childIndex + mFirstPosition; 3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Only proceed as possible child if the divider isn't above all items (if it is above 3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // all items, then the item below it has to be a group) 3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatListPosition >= 0) { 396272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 397272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne PositionMetadata pos = mConnector.getUnflattenedPos(adjustedPosition); 3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // If this item is a child, or it is a non-empty group that is expanded 3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((pos.position.type == ExpandableListPosition.CHILD) || (pos.isExpanded() && 4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.groupMetadata.lastChildFlPos != pos.groupMetadata.flPos)) { 4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // These are the cases where we draw the child divider 4029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final Drawable divider = mChildDivider; 40395930e13faac8c17dabfaa1478089baa772f091bRomain Guy divider.setBounds(bounds); 4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project divider.draw(canvas); 4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return; 4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pos.recycle(); 4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Otherwise draw the default divider 4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.drawDivider(canvas, bounds, flatListPosition); 4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This overloaded method should not be used, instead use 4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setAdapter(ExpandableListAdapter)}. 4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ListAdapter adapter) { 4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new RuntimeException( 4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "For ExpandableListView, use setAdapter(ExpandableListAdapter) instead of " + 4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project "setAdapter(ListAdapter)"); 4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This method should not be used, use {@link #getExpandableListAdapter()}. 4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ListAdapter getAdapter() { 4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* 4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The developer should never really call this method on an 4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ExpandableListView, so it would be nice to throw a RuntimeException, 4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * but AdapterView calls this 4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.getAdapter(); 4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Register a callback to be invoked when an item has been clicked and the 4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * caller prefers to receive a ListView-style position instead of a group 4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * and/or child position. In most cases, the caller should use 4459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #setOnGroupClickListener} and/or {@link #setOnChildClickListener}. 4469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p /> 4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@inheritDoc} 4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnItemClickListener(OnItemClickListener l) { 4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setOnItemClickListener(l); 4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the adapter that provides data to this view. 4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param adapter The adapter that provides data to this view. 4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setAdapter(ExpandableListAdapter adapter) { 4599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Set member variable 4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mAdapter = adapter; 4619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (adapter != null) { 4639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Create the connector 4649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector = new ExpandableListConnector(adapter); 4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 4669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector = null; 4679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Link the ListView (superclass) to the expandable list data through the connector 4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.setAdapter(mConnector); 4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the adapter that provides data to this view. 4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The adapter that provides data to this view. 4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListAdapter getExpandableListAdapter() { 4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter; 4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 481272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 482272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param position An absolute (including header and footer) flat list position. 483272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return true if the position corresponds to a header or a footer item. 484272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 48547ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne private boolean isHeaderOrFooterPosition(int position) { 48647ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne final int footerViewsStart = mItemCount - getFooterViewsCount(); 48747ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne return (position < getHeaderViewsCount() || position >= footerViewsStart); 48847ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne } 48947ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 490272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 491272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * Converts an absolute item flat position into a group/child flat position, shifting according 492272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * to the number of header items. 493272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * 494272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param flatListPosition The absolute flat position 495272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return A group/child flat position as expected by the connector. 496272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 497272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne private int getFlatPositionForConnector(int flatListPosition) { 498272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return flatListPosition - getHeaderViewsCount(); 499272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne } 500272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne 501272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne /** 502272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * Converts a group/child flat position into an absolute flat position, that takes into account 503272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * the possible headers. 504272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * 505272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @param flatListPosition The child/group flat position 506272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne * @return An absolute flat position. 507272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne */ 508272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne private int getAbsoluteFlatPosition(int flatListPosition) { 509272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return flatListPosition + getHeaderViewsCount(); 510272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne } 511272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne 5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean performItemClick(View v, int position, long id) { 5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Ignore clicks in header/footers 51547ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(position)) { 5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Clicked on a header/footer, so ignore pass it on to super 5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return super.performItemClick(v, position, id); 5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Internally handle the item click 521272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(position); 522272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return handleItemClick(v, adjustedPosition, id); 5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This will either expand/collapse groups (if a group was clicked) or pass 5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * on the click to the proper child (if a child was clicked) 5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The flat list position. This has already been factored to 5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * remove the header/footer. 5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The ListAdapter ID, not the group or child ID. 5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean handleItemClick(View v, int position, long id) { 5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final PositionMetadata posMetadata = mConnector.getUnflattenedPos(position); 5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = getChildOrGroupId(posMetadata.position); 5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean returnValue; 5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (posMetadata.position.type == ExpandableListPosition.GROUP) { 5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* It's a group, so handle collapsing/expanding */ 5414039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5424039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy /* It's a group click, so pass on event */ 5434039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy if (mOnGroupClickListener != null) { 5444039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy if (mOnGroupClickListener.onGroupClick(this, v, 5454039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy posMetadata.position.groupPos, id)) { 5464039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy posMetadata.recycle(); 5474039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy return true; 5484039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy } 5494039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy } 5504039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (posMetadata.isExpanded()) { 5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Collapse it */ 5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.collapseGroup(posMetadata); 5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 5564039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupCollapseListener != null) { 5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener.onGroupCollapse(posMetadata.position.groupPos); 5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* Expand it */ 5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.expandGroup(posMetadata); 5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 5654039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupExpandListener != null) { 5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener.onGroupExpand(posMetadata.position.groupPos); 5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 569458034799861fef47e00d85d528b4dac5e00bd51Adam Powell 570458034799861fef47e00d85d528b4dac5e00bd51Adam Powell final int groupPos = posMetadata.position.groupPos; 571458034799861fef47e00d85d528b4dac5e00bd51Adam Powell final int groupFlatPos = posMetadata.position.flatListPos; 57252b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne 57352b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount(); 57452b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos), 57552b65d39aaa378c5bec389a1e8a977ec3ec6a522Gilles Debunne shiftedGroupPosition); 5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5774039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnValue = true; 5799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /* It's a child, so pass on event */ 5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnChildClickListener != null) { 5829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project playSoundEffect(SoundEffectConstants.CLICK); 5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mOnChildClickListener.onChildClick(this, v, posMetadata.position.groupPos, 5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project posMetadata.position.childPos, id); 5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5864039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project returnValue = false; 5889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5894039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project posMetadata.recycle(); 5914039545ed67c5a65cd0ccf2301bd8d8d9155c292Romain Guy 5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return returnValue; 5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Expand a group in the grouped list view 5979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPos the group to be expanded 5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the group was expanded, false otherwise (if the group 6009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was already expanded, this will return false) 6019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean expandGroup(int groupPos) { 60363f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck return expandGroup(groupPos, false); 60463f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck } 60563f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 60663f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck /** 60763f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * Expand a group in the grouped list view 60863f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * 60963f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @param groupPos the group to be expanded 61063f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @param animate true if the expanding group should be animated in 61163f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * @return True if the group was expanded, false otherwise (if the group 61263f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck * was already expanded, this will return false) 61363f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck */ 61463f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck public boolean expandGroup(int groupPos, boolean animate) { 615820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition elGroupPos = ExpandableListPosition.obtain( 616820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition.GROUP, groupPos, -1, -1); 617820b236adce43567b2effd92e246c34a8a76c9f9John Reck PositionMetadata pm = mConnector.getFlattenedPos(elGroupPos); 618820b236adce43567b2effd92e246c34a8a76c9f9John Reck elGroupPos.recycle(); 61963f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck boolean retValue = mConnector.expandGroup(pm); 6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupExpandListener != null) { 6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener.onGroupExpand(groupPos); 6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 62463f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 62563f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck if (animate) { 62663f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck final int groupFlatPos = pm.position.flatListPos; 62763f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 62863f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck final int shiftedGroupPosition = groupFlatPos + getHeaderViewsCount(); 62963f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck smoothScrollToPosition(shiftedGroupPosition + mAdapter.getChildrenCount(groupPos), 63063f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck shiftedGroupPosition); 63163f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck } 63263f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck pm.recycle(); 63363f46e7145fb2087515eb04015d84d956cbb00cdJohn Reck 6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retValue; 6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Collapse a group in the grouped list view 6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPos position of the group to collapse 6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the group was collapsed, false otherwise (if the group 6429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was already collapsed, this will return false) 6439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean collapseGroup(int groupPos) { 6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean retValue = mConnector.collapseGroup(groupPos); 6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mOnGroupCollapseListener != null) { 6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener.onGroupCollapse(groupPos); 6499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return retValue; 6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used for being notified when a group is collapsed */ 6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupCollapseListener { 6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been collapsed. 6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was collapsed 6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onGroupCollapse(int groupPosition); 6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupCollapseListener mOnGroupCollapseListener; 6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupCollapseListener( 6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnGroupCollapseListener onGroupCollapseListener) { 6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupCollapseListener = onGroupCollapseListener; 6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** Used for being notified when a group is expanded */ 6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupExpandListener { 6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been expanded. 6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was expanded 6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project void onGroupExpand(int groupPosition); 6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupExpandListener mOnGroupExpandListener; 6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupExpandListener( 6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project OnGroupExpandListener onGroupExpandListener) { 6879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupExpandListener = onGroupExpandListener; 6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when a group in this 6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expandable list has been clicked. 6939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 6949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnGroupClickListener { 6959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a group in this expandable list has 6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been clicked. 6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The ExpandableListConnector where the click happened 7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view within the expandable list/ListView that was clicked 7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that was clicked 7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The row id of the group that was clicked 7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the click was handled 7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onGroupClick(ExpandableListView parent, View v, int groupPosition, 7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long id); 7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnGroupClickListener mOnGroupClickListener; 7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnGroupClickListener(OnGroupClickListener onGroupClickListener) { 7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnGroupClickListener = onGroupClickListener; 7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Interface definition for a callback to be invoked when a child in this 7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * expandable list has been clicked. 7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public interface OnChildClickListener { 7209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Callback method to be invoked when a child in this expandable list has 7229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * been clicked. 7239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param parent The ExpandableListView where the click happened 7259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param v The view within the expandable list/ListView that was clicked 7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group position that contains the child that 7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * was clicked 7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The child position within the group 7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param id The row id of the child that was clicked 7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return True if the click was handled 7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project boolean onChildClick(ExpandableListView parent, View v, int groupPosition, 7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int childPosition, long id); 7349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private OnChildClickListener mOnChildClickListener; 7379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setOnChildClickListener(OnChildClickListener onChildClickListener) { 7399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mOnChildClickListener = onChildClickListener; 7409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 74347ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * Converts a flat list position (the raw position of an item (child or group) 744f76a50ce8fdc6aea22cabc77b2977a1a15a79630Ken Wakasa * in the list) to a group and/or child position (represented in a 7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * packed position). This is useful in situations where the caller needs to 7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use the underlying {@link ListView}'s methods. Use 7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionType} , 7489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionChild}, 7499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionGroup} to unpack. 7509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param flatListPosition The flat list position to be converted. 7529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The group and/or child position for the given flat list position 75347ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * in packed position representation. #PACKED_POSITION_VALUE_NULL if 75447ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * the position corresponds to a header or a footer item. 7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getExpandableListPosition(int flatListPosition) { 75747ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(flatListPosition)) { 75847ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne return PACKED_POSITION_VALUE_NULL; 75947ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne } 76047ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 761272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 762272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition); 7639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPos = pm.position.getPackedPosition(); 7649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 7659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return packedPos; 7669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Converts a group and/or child position to a flat list position. This is 7709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * useful in situations where the caller needs to use the underlying 7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ListView}'s methods. 7729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The group and/or child positions to be converted in 7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * packed position representation. Use 7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)} or 7769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForGroup(int)}. 7779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The flat list position for the given child or group. 7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public int getFlatListPosition(long packedPosition) { 780820b236adce43567b2effd92e246c34a8a76c9f9John Reck ExpandableListPosition elPackedPos = ExpandableListPosition 781820b236adce43567b2effd92e246c34a8a76c9f9John Reck .obtainPosition(packedPosition); 782820b236adce43567b2effd92e246c34a8a76c9f9John Reck PositionMetadata pm = mConnector.getFlattenedPos(elPackedPos); 783820b236adce43567b2effd92e246c34a8a76c9f9John Reck elPackedPos.recycle(); 784272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int flatListPosition = pm.position.flatListPos; 7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 786272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne return getAbsoluteFlatPosition(flatListPosition); 7879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the position of the currently selected group or child (along with 7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * its type). Can return {@link #PACKED_POSITION_VALUE_NULL} if no selection. 7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return A packed position containing the currently selected group or 79447ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * child's position and type. #PACKED_POSITION_VALUE_NULL if no selection 79547ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne * or if selection is on a header or a footer item. 7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getSelectedPosition() { 7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project final int selectedPos = getSelectedItemPosition(); 79947ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne 80047ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne // The case where there is no selection (selectedPos == -1) is also handled here. 8019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return getExpandableListPosition(selectedPos); 8029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the ID of the currently selected group or child. Can return -1 if no 8069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. 8079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The ID of the currently selected group or child. -1 if no 8099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * selection. 8109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long getSelectedId() { 8129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPos = getSelectedPosition(); 8139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPos == PACKED_POSITION_VALUE_NULL) return -1; 8149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project int groupPos = getPackedPositionGroup(packedPos); 8169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (getPackedPositionType(packedPos) == PACKED_POSITION_TYPE_GROUP) { 8189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's a group 8199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getGroupId(groupPos); 8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // It's a child 8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getChildId(groupPos, getPackedPositionChild(packedPos)); 8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the selection to the specified group. 8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The position of the group that should be selected. 8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setSelectedGroup(int groupPosition) { 8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition elGroupPos = ExpandableListPosition 8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project .obtainGroupPosition(groupPosition); 8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata pm = mConnector.getFlattenedPos(elGroupPos); 8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project elGroupPos.recycle(); 835272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int absoluteFlatPosition = getAbsoluteFlatPosition(pm.position.flatListPos); 836272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne super.setSelection(absoluteFlatPosition); 8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project pm.recycle(); 8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the selection to the specified child. If the child is in a collapsed 8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * group, the group will only be expanded and child subsequently selected if 8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * shouldExpandGroup is set to true, otherwise the method will return false. 8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The position of the group that contains the child. 8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The position of the child within the group. 8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param shouldExpandGroup Whether the child's group should be expanded if 8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * it is collapsed. 8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the selection was successfully set on the child. 8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean setSelectedChild(int groupPosition, int childPosition, boolean shouldExpandGroup) { 8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition elChildPos = ExpandableListPosition.obtainChildPosition( 8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project groupPosition, childPosition); 8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project PositionMetadata flatChildPos = mConnector.getFlattenedPos(elChildPos); 8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatChildPos == null) { 8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // The child's group isn't expanded 8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Shouldn't expand the group, so return false for we didn't set the selection 8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (!shouldExpandGroup) return false; 8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expandGroup(groupPosition); 8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flatChildPos = mConnector.getFlattenedPos(elChildPos); 8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Sanity check 8679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (flatChildPos == null) { 8689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project throw new IllegalStateException("Could not find child"); 8699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 872272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne int absoluteFlatPosition = getAbsoluteFlatPosition(flatChildPos.position.flatListPos); 873272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne super.setSelection(absoluteFlatPosition); 8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project elChildPos.recycle(); 8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project flatChildPos.recycle(); 8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return true; 8799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Whether the given group is currently expanded. 8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The group to check. 8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return Whether the group is currently expanded. 8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public boolean isGroupExpanded(int groupPosition) { 8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mConnector.isGroupExpanded(groupPosition); 8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the type of a packed position. See 8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position for which to return the type. 8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The type of the position contained within the packed position, 8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * either {@link #PACKED_POSITION_TYPE_CHILD}, {@link #PACKED_POSITION_TYPE_GROUP}, or 8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #PACKED_POSITION_TYPE_NULL}. 8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionType(long packedPosition) { 9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) { 9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return PACKED_POSITION_TYPE_NULL; 9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (packedPosition & PACKED_POSITION_MASK_TYPE) == PACKED_POSITION_MASK_TYPE 9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ? PACKED_POSITION_TYPE_CHILD 9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project : PACKED_POSITION_TYPE_GROUP; 9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the group position from a packed position. See 9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position from which the group position 9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be returned. 9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The group position portion of the packed position. If this does 9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not contain a group, returns -1. 9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionGroup(long packedPosition) { 9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Null 9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1; 9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) ((packedPosition & PACKED_POSITION_MASK_GROUP) >> PACKED_POSITION_SHIFT_GROUP); 9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the child position from a packed position that is of 9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #PACKED_POSITION_TYPE_CHILD} type (use {@link #getPackedPositionType(long)}). 9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * To get the group that this child belongs to, use 9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionGroup(long)}. See 9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param packedPosition The packed position from which the child position 9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be returned. 9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The child position portion of the packed position. If this does 9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * not contain a child, returns -1. 9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static int getPackedPositionChild(long packedPosition) { 9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Null 9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (packedPosition == PACKED_POSITION_VALUE_NULL) return -1; 9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // Group since a group type clears this bit 9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if ((packedPosition & PACKED_POSITION_MASK_TYPE) != PACKED_POSITION_MASK_TYPE) return -1; 9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (int) (packedPosition & PACKED_POSITION_MASK_CHILD); 9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the packed position representation of a child's position. 9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * <p> 9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * In general, a packed position should be used in 9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * situations where the position given to/returned from an 9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListAdapter} or {@link ExpandableListView} method can 9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * either be a child or group. The two positions are packed into a single 9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * long which can be unpacked using 9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionChild(long)}, 9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionGroup(long)}, and 9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionType(long)}. 9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The child's parent group's position. 9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childPosition The child position within the group. 9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The packed position representation of the child (and parent group). 9639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getPackedPositionForChild(int groupPosition, int childPosition) { 9659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return (((long)PACKED_POSITION_TYPE_CHILD) << PACKED_POSITION_SHIFT_TYPE) 9669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP) 9679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << PACKED_POSITION_SHIFT_GROUP) 9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project | (childPosition & PACKED_POSITION_INT_MASK_CHILD); 9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 9729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Returns the packed position representation of a group's position. See 9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link #getPackedPositionForChild(int, int)}. 9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupPosition The child's parent group's position. 9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @return The packed position representation of the group. 9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static long getPackedPositionForGroup(int groupPosition) { 9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project // No need to OR a type in because PACKED_POSITION_GROUP == 0 9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return ((((long)groupPosition) & PACKED_POSITION_INT_MASK_GROUP) 9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project << PACKED_POSITION_SHIFT_GROUP); 9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ContextMenuInfo createContextMenuInfo(View view, int flatListPosition, long id) { 98647ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne if (isHeaderOrFooterPosition(flatListPosition)) { 98747ccdf3760635a695b7c417a0df02f7e86ce6262Gilles Debunne // Return normal info for header/footer view context menus 988fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey return new AdapterContextMenuInfo(view, flatListPosition, id); 989fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey } 990fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey 991272f3a9474a70817f8089259da4c2696732dfecbGilles Debunne final int adjustedPosition = getFlatPositionForConnector(flatListPosition); 992fd0d627569cb250f7060a83161cc845b9616e5a1Jeff Sharkey PositionMetadata pm = mConnector.getUnflattenedPos(adjustedPosition); 9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ExpandableListPosition pos = pm.position; 9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project id = getChildOrGroupId(pos); 9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project long packedPosition = pos.getPackedPosition(); 997820b236adce43567b2effd92e246c34a8a76c9f9John Reck 998820b236adce43567b2effd92e246c34a8a76c9f9John Reck pm.recycle(); 9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new ExpandableListContextMenuInfo(view, packedPosition, id); 10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Gets the ID of the group or child at the given <code>position</code>. 10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This is useful since there is no ListAdapter ID -> ExpandableListAdapter 10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * ID conversion mechanism (in some cases, it isn't possible). 10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param position The position of the child or group whose ID should be 10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * returned. 10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private long getChildOrGroupId(ExpandableListPosition position) { 10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (position.type == ExpandableListPosition.CHILD) { 10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getChildId(position.groupPos, position.childPos); 10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } else { 10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return mAdapter.getGroupId(position.groupPos); 10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the indicator to be drawn next to a child. 10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param childIndicator The drawable to be used as an indicator. If the 10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * child is the last child for a group, the state 10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.R.attr#state_last} will be set. 10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildIndicator(Drawable childIndicator) { 10279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicator = childIndicator; 10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawing bounds for the child indicator. For either, you can 10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * specify {@link #CHILD_INDICATOR_INHERIT} to use inherit from the general 10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * indicator's bounds. 10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setIndicatorBounds(int, int) 10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param left The left position (relative to the left bounds of this View) 10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to start drawing the indicator. 10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param right The right position (relative to the left bounds of this 10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * View) to end the drawing of the indicator. 10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setChildIndicatorBounds(int left, int right) { 10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorLeft = left; 10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mChildIndicatorRight = right; 10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the indicator to be drawn next to a group. 10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param groupIndicator The drawable to be used as an indicator. If the 10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * group is empty, the state {@link android.R.attr#state_empty} will be 10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * set. If the group is expanded, the state 10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.R.attr#state_expanded} will be set. 10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setGroupIndicator(Drawable groupIndicator) { 10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mGroupIndicator = groupIndicator; 1056875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy if (mIndicatorRight == 0 && mGroupIndicator != null) { 1057875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy mIndicatorRight = mIndicatorLeft + mGroupIndicator.getIntrinsicWidth(); 1058875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy } 10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 1060875862e3ec85153553ce50acc02863ea0720ccb6Romain Guy 10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Sets the drawing bounds for the indicators (at minimum, the group indicator 10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * is affected by this; the child indicator is affected by this if the 10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * child indicator bounds are set to inherit). 10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * 10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @see #setChildIndicatorBounds(int, int) 10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param left The left position (relative to the left bounds of this View) 10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to start drawing the indicator. 10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * @param right The right position (relative to the left bounds of this 10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * View) to end the drawing of the indicator. 10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void setIndicatorBounds(int left, int right) { 10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorLeft = left; 10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mIndicatorRight = right; 10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Extra menu information specific to an {@link ExpandableListView} provided 10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * to the 10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link android.view.View.OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo) } 10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * callback when a context menu is brought up for this AdapterView. 10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static class ExpandableListContextMenuInfo implements ContextMenu.ContextMenuInfo { 10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public ExpandableListContextMenuInfo(View targetView, long packedPosition, long id) { 10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.targetView = targetView; 10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.packedPosition = packedPosition; 10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.id = id; 10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The view for which the context menu is being displayed. This 10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * will be one of the children Views of this {@link ExpandableListView}. 10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public View targetView; 10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The packed position in the list represented by the adapter for which 10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the context menu is being displayed. Use the methods 11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionType}, 11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionChild}, and 11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * {@link ExpandableListView#getPackedPositionGroup} to unpack this. 11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long packedPosition; 11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The ID of the item (group or child) for which the context menu is 11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * being displayed. 11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public long id; 11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project static class SavedState extends BaseSavedState { 11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList; 11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link ExpandableListView#onSaveInstanceState()} 11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState( 11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState, 11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project ArrayList<ExpandableListConnector.GroupMetadata> expandedGroupMetadataList) { 11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(superState); 11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project this.expandedGroupMetadataList = expandedGroupMetadataList; 11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project /** 11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Constructor called from {@link #CREATOR} 11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */ 11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project private SavedState(Parcel in) { 11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super(in); 11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project expandedGroupMetadataList = new ArrayList<ExpandableListConnector.GroupMetadata>(); 11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project in.readList(expandedGroupMetadataList, ExpandableListConnector.class.getClassLoader()); 11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void writeToParcel(Parcel out, int flags) { 11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.writeToParcel(out, flags); 11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project out.writeList(expandedGroupMetadataList); 11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public static final Parcelable.Creator<SavedState> CREATOR 11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project = new Parcelable.Creator<SavedState>() { 11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState createFromParcel(Parcel in) { 11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(in); 11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public SavedState[] newArray(int size) { 11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState[size]; 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 @Override 11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public Parcelable onSaveInstanceState() { 11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project Parcelable superState = super.onSaveInstanceState(); 11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return new SavedState(superState, 11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector != null ? mConnector.getExpandedGroupMetadataList() : null); 11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project @Override 11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project public void onRestoreInstanceState(Parcelable state) { 11627444e147a863b41e08815658f1bcbe426aba512bRomain Guy if (!(state instanceof SavedState)) { 11637444e147a863b41e08815658f1bcbe426aba512bRomain Guy super.onRestoreInstanceState(state); 11647444e147a863b41e08815658f1bcbe426aba512bRomain Guy return; 11657444e147a863b41e08815658f1bcbe426aba512bRomain Guy } 11667444e147a863b41e08815658f1bcbe426aba512bRomain Guy 11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project SavedState ss = (SavedState) state; 11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project super.onRestoreInstanceState(ss.getSuperState()); 11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (mConnector != null && ss.expandedGroupMetadataList != null) { 11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project mConnector.setExpandedGroupMetadataList(ss.expandedGroupMetadataList); 11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 11758a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 11768a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityEvent(AccessibilityEvent event) { 11778a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityEvent(event); 11788a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov event.setClassName(ExpandableListView.class.getName()); 11798a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 11808a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov 11818a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov @Override 11828a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) { 11838a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov super.onInitializeAccessibilityNodeInfo(info); 11848a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov info.setClassName(ExpandableListView.class.getName()); 11858a78fd4d9572dff95432fcc4ba0e87563415b728Svetoslav Ganov } 11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1187