blob: 10d50b8112899dad7f2956e52f65de286caf8b95 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.widget;
18
Mathew Inwooda85f4eb2018-08-21 16:08:34 +010019import android.annotation.UnsupportedAppUsage;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.database.DataSetObserver;
21import android.view.View;
22import android.view.ViewGroup;
23
24import java.util.ArrayList;
25
26/**
27 * ListAdapter used when a ListView has header views. This ListAdapter
28 * wraps another one and also keeps track of the header views and their
29 * associated data objects.
30 *<p>This is intended as a base class; you will probably not need to
31 * use this class directly in your own code.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080032 */
33public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {
34
Mathew Inwooda85f4eb2018-08-21 16:08:34 +010035 @UnsupportedAppUsage
Gilles Debunne478a7452010-03-23 16:44:48 -070036 private final ListAdapter mAdapter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037
Gilles Debunne176f9fc2010-03-02 11:00:50 -080038 // These two ArrayList are assumed to NOT be null.
Gilles Debunne478a7452010-03-23 16:44:48 -070039 // They are indeed created when declared in ListView and then shared.
Mathew Inwooda85f4eb2018-08-21 16:08:34 +010040 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041 ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
Mathew Inwooda85f4eb2018-08-21 16:08:34 +010042 @UnsupportedAppUsage
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080043 ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
Gilles Debunne478a7452010-03-23 16:44:48 -070044
45 // Used as a placeholder in case the provided info views are indeed null.
46 // Currently only used by some CTS tests, which may be removed.
47 static final ArrayList<ListView.FixedViewInfo> EMPTY_INFO_LIST =
48 new ArrayList<ListView.FixedViewInfo>();
49
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080050 boolean mAreAllFixedViewsSelectable;
51
Gilles Debunne478a7452010-03-23 16:44:48 -070052 private final boolean mIsFilterable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080053
54 public HeaderViewListAdapter(ArrayList<ListView.FixedViewInfo> headerViewInfos,
55 ArrayList<ListView.FixedViewInfo> footerViewInfos,
56 ListAdapter adapter) {
57 mAdapter = adapter;
58 mIsFilterable = adapter instanceof Filterable;
59
Gilles Debunne478a7452010-03-23 16:44:48 -070060 if (headerViewInfos == null) {
61 mHeaderViewInfos = EMPTY_INFO_LIST;
62 } else {
63 mHeaderViewInfos = headerViewInfos;
64 }
65
66 if (footerViewInfos == null) {
67 mFooterViewInfos = EMPTY_INFO_LIST;
68 } else {
69 mFooterViewInfos = footerViewInfos;
70 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080071
72 mAreAllFixedViewsSelectable =
73 areAllListInfosSelectable(mHeaderViewInfos)
74 && areAllListInfosSelectable(mFooterViewInfos);
75 }
76
77 public int getHeadersCount() {
Gilles Debunne176f9fc2010-03-02 11:00:50 -080078 return mHeaderViewInfos.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079 }
80
81 public int getFootersCount() {
Gilles Debunne176f9fc2010-03-02 11:00:50 -080082 return mFooterViewInfos.size();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080083 }
84
85 public boolean isEmpty() {
Adam Powellfc93d0c2013-06-12 17:38:25 -070086 return mAdapter == null || mAdapter.isEmpty();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080087 }
88
89 private boolean areAllListInfosSelectable(ArrayList<ListView.FixedViewInfo> infos) {
90 if (infos != null) {
91 for (ListView.FixedViewInfo info : infos) {
92 if (!info.isSelectable) {
93 return false;
94 }
95 }
96 }
97 return true;
98 }
99
100 public boolean removeHeader(View v) {
101 for (int i = 0; i < mHeaderViewInfos.size(); i++) {
102 ListView.FixedViewInfo info = mHeaderViewInfos.get(i);
103 if (info.view == v) {
104 mHeaderViewInfos.remove(i);
105
106 mAreAllFixedViewsSelectable =
107 areAllListInfosSelectable(mHeaderViewInfos)
108 && areAllListInfosSelectable(mFooterViewInfos);
109
110 return true;
111 }
112 }
113
114 return false;
115 }
116
117 public boolean removeFooter(View v) {
118 for (int i = 0; i < mFooterViewInfos.size(); i++) {
119 ListView.FixedViewInfo info = mFooterViewInfos.get(i);
120 if (info.view == v) {
121 mFooterViewInfos.remove(i);
122
123 mAreAllFixedViewsSelectable =
124 areAllListInfosSelectable(mHeaderViewInfos)
125 && areAllListInfosSelectable(mFooterViewInfos);
126
127 return true;
128 }
129 }
130
131 return false;
132 }
133
134 public int getCount() {
135 if (mAdapter != null) {
136 return getFootersCount() + getHeadersCount() + mAdapter.getCount();
137 } else {
138 return getFootersCount() + getHeadersCount();
139 }
140 }
141
142 public boolean areAllItemsEnabled() {
143 if (mAdapter != null) {
144 return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled();
145 } else {
146 return true;
147 }
148 }
149
150 public boolean isEnabled(int position) {
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700151 // Header (negative positions will throw an IndexOutOfBoundsException)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800152 int numHeaders = getHeadersCount();
Gilles Debunne34783aa2010-03-24 14:47:28 -0700153 if (position < numHeaders) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800154 return mHeaderViewInfos.get(position).isSelectable;
155 }
Gilles Debunne34783aa2010-03-24 14:47:28 -0700156
157 // Adapter
158 final int adjPosition = position - numHeaders;
159 int adapterCount = 0;
160 if (mAdapter != null) {
161 adapterCount = mAdapter.getCount();
162 if (adjPosition < adapterCount) {
163 return mAdapter.isEnabled(adjPosition);
164 }
165 }
166
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700167 // Footer (off-limits positions will throw an IndexOutOfBoundsException)
Gilles Debunne34783aa2010-03-24 14:47:28 -0700168 return mFooterViewInfos.get(adjPosition - adapterCount).isSelectable;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800169 }
170
171 public Object getItem(int position) {
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700172 // Header (negative positions will throw an IndexOutOfBoundsException)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800173 int numHeaders = getHeadersCount();
Gilles Debunne34783aa2010-03-24 14:47:28 -0700174 if (position < numHeaders) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800175 return mHeaderViewInfos.get(position).data;
176 }
Gilles Debunne34783aa2010-03-24 14:47:28 -0700177
178 // Adapter
179 final int adjPosition = position - numHeaders;
180 int adapterCount = 0;
181 if (mAdapter != null) {
182 adapterCount = mAdapter.getCount();
183 if (adjPosition < adapterCount) {
184 return mAdapter.getItem(adjPosition);
185 }
186 }
187
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700188 // Footer (off-limits positions will throw an IndexOutOfBoundsException)
Gilles Debunne34783aa2010-03-24 14:47:28 -0700189 return mFooterViewInfos.get(adjPosition - adapterCount).data;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 }
191
192 public long getItemId(int position) {
193 int numHeaders = getHeadersCount();
194 if (mAdapter != null && position >= numHeaders) {
195 int adjPosition = position - numHeaders;
Gilles Debunne34783aa2010-03-24 14:47:28 -0700196 int adapterCount = mAdapter.getCount();
197 if (adjPosition < adapterCount) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800198 return mAdapter.getItemId(adjPosition);
199 }
200 }
201 return -1;
202 }
203
204 public boolean hasStableIds() {
205 if (mAdapter != null) {
206 return mAdapter.hasStableIds();
207 }
208 return false;
209 }
210
211 public View getView(int position, View convertView, ViewGroup parent) {
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700212 // Header (negative positions will throw an IndexOutOfBoundsException)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800213 int numHeaders = getHeadersCount();
Gilles Debunne34783aa2010-03-24 14:47:28 -0700214 if (position < numHeaders) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 return mHeaderViewInfos.get(position).view;
216 }
Gilles Debunne34783aa2010-03-24 14:47:28 -0700217
218 // Adapter
219 final int adjPosition = position - numHeaders;
220 int adapterCount = 0;
221 if (mAdapter != null) {
222 adapterCount = mAdapter.getCount();
223 if (adjPosition < adapterCount) {
224 return mAdapter.getView(adjPosition, convertView, parent);
225 }
226 }
227
Taylor H. Perkins62b2bb82013-04-30 12:04:52 -0700228 // Footer (off-limits positions will throw an IndexOutOfBoundsException)
Gilles Debunne34783aa2010-03-24 14:47:28 -0700229 return mFooterViewInfos.get(adjPosition - adapterCount).view;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 }
231
232 public int getItemViewType(int position) {
233 int numHeaders = getHeadersCount();
234 if (mAdapter != null && position >= numHeaders) {
235 int adjPosition = position - numHeaders;
236 int adapterCount = mAdapter.getCount();
237 if (adjPosition < adapterCount) {
238 return mAdapter.getItemViewType(adjPosition);
239 }
240 }
241
242 return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
243 }
244
245 public int getViewTypeCount() {
246 if (mAdapter != null) {
247 return mAdapter.getViewTypeCount();
248 }
249 return 1;
250 }
251
252 public void registerDataSetObserver(DataSetObserver observer) {
253 if (mAdapter != null) {
254 mAdapter.registerDataSetObserver(observer);
255 }
256 }
257
258 public void unregisterDataSetObserver(DataSetObserver observer) {
259 if (mAdapter != null) {
260 mAdapter.unregisterDataSetObserver(observer);
261 }
262 }
263
264 public Filter getFilter() {
265 if (mIsFilterable) {
266 return ((Filterable) mAdapter).getFilter();
267 }
268 return null;
269 }
270
271 public ListAdapter getWrappedAdapter() {
272 return mAdapter;
273 }
274}