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