18b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen/* 28b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Copyright (C) 2015 The Android Open Source Project 38b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * 48b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Licensed under the Apache License, Version 2.0 (the "License"); 58b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * you may not use this file except in compliance with the License. 68b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * You may obtain a copy of the License at 78b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * 88b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * http://www.apache.org/licenses/LICENSE-2.0 98b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * 108b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Unless required by applicable law or agreed to in writing, software 118b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * distributed under the License is distributed on an "AS IS" BASIS, 128b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 138b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * See the License for the specific language governing permissions and 148b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * limitations under the License. 158b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 168b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenpackage android.support.car.ui; 178b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 188b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport android.content.Context; 198b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport android.support.v7.widget.RecyclerView; 208b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport android.util.Log; 218b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport android.view.ViewGroup; 228b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 238b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport java.util.ArrayList; 248b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenimport java.util.List; 258b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 268b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen/** 278b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Maintains a list that groups adjacent items sharing the same value of 288b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * a "group-by" field. The list has three types of elements: stand-alone, group header and group 298b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * child. Groups are collapsible and collapsed by default. 308b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 318b7af7188228ca88838e31e070f0fca0d1f90581Yao Chenpublic abstract class GroupingRecyclerViewAdapter<E, VH extends RecyclerView.ViewHolder> 328b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen extends RecyclerView.Adapter<VH> { 338b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private static final String TAG = "CAR.UI.GroupingRecyclerViewAdapter"; 348b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 358b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public static final int VIEW_TYPE_STANDALONE = 0; 368b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public static final int VIEW_TYPE_GROUP_HEADER = 1; 378b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public static final int VIEW_TYPE_IN_GROUP = 2; 388b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 398b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen /** 408b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Build all groups based on grouping rules given cursor and calls {@link #addGroup} for 418b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * each of them. 428b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 438b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract void buildGroups(List<E> data); 448b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 458b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract VH onCreateStandAloneViewHolder(Context context, ViewGroup parent); 468b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract void onBindStandAloneViewHolder( 478b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen VH holder, Context context, int positionInData); 488b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 498b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract VH onCreateGroupViewHolder(Context context, ViewGroup parent); 508b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract void onBindGroupViewHolder(VH holder, Context context, int positionInData, 518b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int groupSize, boolean expanded); 528b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 538b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract VH onCreateChildViewHolder(Context context, ViewGroup parent); 548b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected abstract void onBindChildViewHolder(VH holder, Context context, int positionInData); 558b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 568b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected Context mContext; 578b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected List<E> mData; 588b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 598b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private int mCount; 608b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private List<GroupMetadata> mGroupMetadata; 618b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 628b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public GroupingRecyclerViewAdapter(Context context) { 638b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mContext = context; 648b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mGroupMetadata = new ArrayList<>(); 658b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen resetGroup(); 668b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 678b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 688b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public void setData(List<E> data) { 698b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mData = data; 708b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen resetGroup(); 718b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (mData != null) { 728b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen buildGroups(mData); 738b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen rebuildGroupMetadata(); 748b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 758b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen notifyDataSetChanged(); 768b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 778b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 788b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen @Override 798b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public int getItemCount() { 808b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (mData != null && mCount != -1) { 818b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return mCount; 828b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 838b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return 0; 848b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 858b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 868b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen @Override 878b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public long getItemId(int position) { 888b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen E item = getItem(position); 898b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (item != null) { 908b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return item.hashCode(); 918b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 928b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return 0; 938b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 948b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 958b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen @Override 968b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public int getItemViewType(int position) { 978b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return getPositionMetadata(position).itemType; 988b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 998b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1008b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public E getItem(int position) { 1018b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (mData == null) { 1028b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return null; 1038b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1048b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1058b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen PositionMetadata pMetadata = getPositionMetadata(position); 1068b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return mData.get(pMetadata.positionInData); 1078b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1088b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1098b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen @Override 1108b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public VH onCreateViewHolder(ViewGroup parent, int viewType) { 1118b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen switch (viewType) { 1128b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_STANDALONE: 1138b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return onCreateStandAloneViewHolder(mContext, parent); 1148b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_GROUP_HEADER: 1158b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return onCreateGroupViewHolder(mContext, parent); 1168b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_IN_GROUP: 1178b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return onCreateChildViewHolder(mContext, parent); 1188b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1198b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen Log.e(TAG, "Unknown viewType. Returning null ViewHolder"); 1208b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return null; 1218b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1228b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1238b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen @Override 1248b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public void onBindViewHolder(VH holder, int position) { 1258b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen PositionMetadata pMetadata = getPositionMetadata(position); 1268b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen switch (holder.getItemViewType()) { 1278b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_STANDALONE: 1288b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen onBindStandAloneViewHolder(holder, mContext, pMetadata.positionInData); 1298b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen break; 1308b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_GROUP_HEADER: 1318b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen onBindGroupViewHolder(holder, mContext, pMetadata.positionInData, 1328b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen pMetadata.gMetadata.itemNumber, pMetadata.gMetadata.isExpanded()); 1338b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen break; 1348b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen case VIEW_TYPE_IN_GROUP: 1358b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen onBindChildViewHolder(holder, mContext, pMetadata.positionInData); 1368b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen break; 1378b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1388b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1398b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1408b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public boolean toggleGroup(int positionInData, int positionOnUI) { 1418b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen PositionMetadata pMetadata = getPositionMetadata(positionInData); 1428b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (pMetadata.itemType != VIEW_TYPE_GROUP_HEADER) { 1438b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return false; 1448b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1458b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1468b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen pMetadata.gMetadata.isExpanded = !pMetadata.gMetadata.isExpanded; 1478b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen rebuildGroupMetadata(); 1488b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (pMetadata.gMetadata.isExpanded) { 1498b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen notifyItemRangeInserted(positionOnUI + 1, pMetadata.gMetadata.itemNumber); 1508b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } else { 1518b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen notifyItemRangeRemoved(positionOnUI + 1, pMetadata.gMetadata.itemNumber); 1528b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1538b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return true; 1548b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1558b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1568b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen /** 1578b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Return True if the item on the given position is a group header and the group is expanded, 1588b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * otherwise False. 1598b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 1608b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public boolean isGroupExpanded(int position) { 1618b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen PositionMetadata pMetadata = getPositionMetadata(position); 1628b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (pMetadata.itemType != VIEW_TYPE_GROUP_HEADER) { 1638b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return false; 1648b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1658b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1668b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return pMetadata.gMetadata.isExpanded(); 1678b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1688b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1698b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen /** 1708b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Records information about grouping in the list. Should only be called by the overridden 1718b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * {@link #buildGroups} method. 1728b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 1738b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected void addGroup(int offset, int size, boolean expanded) { 1748b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mGroupMetadata.add(GroupMetadata.obtain(offset, size, expanded)); 1758b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1768b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1778b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private void resetGroup() { 1788b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mCount = -1; 1798b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mGroupMetadata.clear(); 1808b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1818b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1828b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private void rebuildGroupMetadata() { 1838b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int currentPos = 0; 1848b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen for (int groupIndex = 0; groupIndex < mGroupMetadata.size(); groupIndex++) { 1858b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen GroupMetadata gMetadata = mGroupMetadata.get(groupIndex); 1868b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen gMetadata.offsetInDisplayList = currentPos; 1878b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen currentPos += gMetadata.getActualSize(); 1888b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1898b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mCount = currentPos; 1908b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 1918b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1928b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private PositionMetadata getPositionMetadata(int position) { 1938b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int left = 0; 1948b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int right = mGroupMetadata.size() - 1; 1958b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int mid; 1968b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen GroupMetadata midItem; 1978b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 1988b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen while (left <= right) { 1998b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen mid = (right - left) / 2 + left; 2008b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen midItem = mGroupMetadata.get(mid); 2018b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2028b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (position > midItem.offsetInDisplayList + midItem.getActualSize() - 1) { 2038b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen left = mid + 1; 2048b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen continue; 2058b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2068b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2078b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (position < midItem.offsetInDisplayList) { 2088b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen right = mid - 1; 2098b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen continue; 2108b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2118b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2128b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int cursorOffset = midItem.offsetInDataList + (position - midItem.offsetInDisplayList); 2138b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int viewType; 2148b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (midItem.offsetInDisplayList == position) { 2158b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (midItem.isStandAlone()) { 2168b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen viewType = VIEW_TYPE_STANDALONE; 2178b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } else { 2188b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen viewType = VIEW_TYPE_GROUP_HEADER; 2198b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2208b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } else { 2218b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen viewType = VIEW_TYPE_IN_GROUP; 2228b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen // Offset cursorOffset by 1, because the group_header and the first child 2238b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen // will share the same cursor. 2248b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen cursorOffset--; 2258b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2268b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return new PositionMetadata(viewType, cursorOffset, midItem); 2278b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2288b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2298b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen throw new IllegalStateException( 2308b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen "illegal position " + position + ", total size is " + mCount); 2318b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2328b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2338b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen /** 2348b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * Information about where groups are located in the list, how large they are 2358b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen * and whether they are expanded. 2368b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen */ 2378b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected static class GroupMetadata { 2388b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private int offsetInDisplayList; 2398b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private int offsetInDataList; 2408b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private int itemNumber; 2418b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen private boolean isExpanded; 2428b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2438b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen static GroupMetadata obtain(int offset, int itemNumber, boolean isExpanded) { 2448b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen GroupMetadata gm = new GroupMetadata(); 2458b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen gm.offsetInDataList = offset; 2468b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen gm.itemNumber = itemNumber; 2478b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen gm.isExpanded = isExpanded; 2488b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return gm; 2498b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2508b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2518b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public boolean isExpanded() { 2528b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return !isStandAlone() && isExpanded; 2538b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2548b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2558b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public boolean isStandAlone() { 2568b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return itemNumber == 1; 2578b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2588b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2598b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public int getActualSize() { 2608b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen if (!isExpanded()) { 2618b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return 1; 2628b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } else { 2638b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen return itemNumber + 1; 2648b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2658b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2668b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2678b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2688b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen protected static class PositionMetadata { 2698b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int itemType; 2708b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen int positionInData; 2718b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen GroupMetadata gMetadata; 2728b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen 2738b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen public PositionMetadata(int itemType, int positionInData, GroupMetadata gMetadata) { 2748b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen this.itemType = itemType; 2758b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen this.positionInData = positionInData; 2768b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen this.gMetadata = gMetadata; 2778b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2788b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen } 2798b7af7188228ca88838e31e070f0fca0d1f90581Yao Chen} 280