162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu/* 262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Copyright (C) 2013 The Android Open Source Project 362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Licensed under the Apache License, Version 2.0 (the "License"); 562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * you may not use this file except in compliance with the License. 662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * You may obtain a copy of the License at 762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * http://www.apache.org/licenses/LICENSE-2.0 962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 1062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Unless required by applicable law or agreed to in writing, software 1162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * distributed under the License is distributed on an "AS IS" BASIS, 1262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * See the License for the specific language governing permissions and 1462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * limitations under the License. 1562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 1662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 1762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescupackage com.android.photos.views; 1862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 1962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.content.Context; 2062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.database.DataSetObservable; 2162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.database.DataSetObserver; 2262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.util.AttributeSet; 2362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.view.View; 2462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.view.ViewGroup; 2562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.AdapterView; 2662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.Filter; 2762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.Filterable; 2862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.FrameLayout; 2962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.GridView; 3062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.ListAdapter; 3162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport android.widget.WrapperListAdapter; 3262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 3362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescuimport java.util.ArrayList; 3462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 3562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu/** 3662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * A {@link GridView} that supports adding header rows in a 3762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * very similar way to {@link ListView}. 3862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * See {@link HeaderGridView#addHeaderView(View, Object, boolean)} 3962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 4062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescupublic class HeaderGridView extends GridView { 4162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private static final String TAG = "HeaderGridView"; 4262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 4362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** 4462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * A class that represents a fixed view in a list, for example a header at the top 4562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * or a footer at the bottom. 4662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 4762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private static class FixedViewInfo { 4862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** The view to add to the grid */ 4962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public View view; 5062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public ViewGroup viewContainer; 5162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */ 5262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public Object data; 5362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** <code>true</code> if the fixed view should be selectable in the grid */ 5462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean isSelectable; 5562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 5662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 5762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private ArrayList<FixedViewInfo> mHeaderViewInfos = new ArrayList<FixedViewInfo>(); 5862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 5962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private void initHeaderGridView() { 6062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super.setClipChildren(false); 6162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 6262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 6362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public HeaderGridView(Context context) { 6462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super(context); 6562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu initHeaderGridView(); 6662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 6762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 6862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public HeaderGridView(Context context, AttributeSet attrs) { 6962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super(context, attrs); 7062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu initHeaderGridView(); 7162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 7262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 7362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public HeaderGridView(Context context, AttributeSet attrs, int defStyle) { 7462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super(context, attrs, defStyle); 7562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu initHeaderGridView(); 7662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 7762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 7862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 7962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 8062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super.onMeasure(widthMeasureSpec, heightMeasureSpec); 8162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ListAdapter adapter = getAdapter(); 8262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adapter != null && adapter instanceof HeaderViewGridAdapter) { 8362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ((HeaderViewGridAdapter) adapter).setNumColumns(getNumColumns()); 8462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 8562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 8662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 8762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 8862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void setClipChildren(boolean clipChildren) { 8962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Ignore, since the header rows depend on not being clipped 9062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 9162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 9262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** 9362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Add a fixed view to appear at the top of the grid. If addHeaderView is 9462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * called more than once, the views will appear in the order they were 9562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * added. Views added using this call can take focus if they want. 9662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * <p> 9762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap 9862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * the supplied cursor with one that will also account for header views. 9962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 10062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @param v The view to add. 10162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @param data Data to associate with this view 10262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @param isSelectable whether the item is selectable 10362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 10462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void addHeaderView(View v, Object data, boolean isSelectable) { 10562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ListAdapter adapter = getAdapter(); 10662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 10762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adapter != null && ! (adapter instanceof HeaderViewGridAdapter)) { 10862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new IllegalStateException( 10962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu "Cannot add header view to grid -- setAdapter has already been called."); 11062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 11162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 11262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu FixedViewInfo info = new FixedViewInfo(); 11362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu FrameLayout fl = new FullWidthFixedViewLayout(getContext()); 11462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu fl.addView(v); 11562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu info.view = v; 11662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu info.viewContainer = fl; 11762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu info.data = data; 11862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu info.isSelectable = isSelectable; 11962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mHeaderViewInfos.add(info); 12062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 12162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // in the case of re-adding a header view, or adding one later on, 12262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // we need to notify the observer 12362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adapter != null) { 12462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ((HeaderViewGridAdapter) adapter).notifyDataSetChanged(); 12562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 12662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 12762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 12862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** 12962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Add a fixed view to appear at the top of the grid. If addHeaderView is 13062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * called more than once, the views will appear in the order they were 13162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * added. Views added using this call can take focus if they want. 13262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * <p> 13362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * NOTE: Call this before calling setAdapter. This is so HeaderGridView can wrap 13462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * the supplied cursor with one that will also account for header views. 13562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 13662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @param v The view to add. 13762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 13862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void addHeaderView(View v) { 13962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu addHeaderView(v, null, true); 14062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 14162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 14262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public int getHeaderViewCount() { 14362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mHeaderViewInfos.size(); 14462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 14562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 14662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** 14762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * Removes a previously-added header view. 14862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * 14962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @param v The view to remove 15062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * @return true if the view was removed, false if the view was not a header 15162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * view 15262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 15362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean removeHeaderView(View v) { 15462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mHeaderViewInfos.size() > 0) { 15562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu boolean result = false; 15662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ListAdapter adapter = getAdapter(); 15762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adapter != null && ((HeaderViewGridAdapter) adapter).removeHeader(v)) { 15862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu result = true; 15962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 16062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu removeFixedViewInfo(v, mHeaderViewInfos); 16162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return result; 16262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 16362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return false; 16462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 16562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 16662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private void removeFixedViewInfo(View v, ArrayList<FixedViewInfo> where) { 16762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int len = where.size(); 16862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu for (int i = 0; i < len; ++i) { 16962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu FixedViewInfo info = where.get(i); 17062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (info.view == v) { 17162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu where.remove(i); 17262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu break; 17362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 17462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 17562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 17662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 17762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 17862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void setAdapter(ListAdapter adapter) { 17962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mHeaderViewInfos.size() > 0) { 18062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu HeaderViewGridAdapter hadapter = new HeaderViewGridAdapter(mHeaderViewInfos, adapter); 18162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numColumns = getNumColumns(); 18262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (numColumns > 1) { 18362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu hadapter.setNumColumns(numColumns); 18462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 18562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super.setAdapter(hadapter); 18662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } else { 18762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super.setAdapter(adapter); 18862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 18962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 19062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 19162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private class FullWidthFixedViewLayout extends FrameLayout { 19262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public FullWidthFixedViewLayout(Context context) { 19362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super(context); 19462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 19562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 19662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 19762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 19862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int targetWidth = HeaderGridView.this.getMeasuredWidth() 19962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu - HeaderGridView.this.getPaddingLeft() 20062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu - HeaderGridView.this.getPaddingRight(); 20162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu widthMeasureSpec = MeasureSpec.makeMeasureSpec(targetWidth, 20262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu MeasureSpec.getMode(widthMeasureSpec)); 20362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu super.onMeasure(widthMeasureSpec, heightMeasureSpec); 20462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 20562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 20662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 20762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu /** 20862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * ListAdapter used when a HeaderGridView has header views. This ListAdapter 20962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * wraps another one and also keeps track of the header views and their 21062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * associated data objects. 21162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu *<p>This is intended as a base class; you will probably not need to 21262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu * use this class directly in your own code. 21362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu */ 21462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private static class HeaderViewGridAdapter implements WrapperListAdapter, Filterable { 21562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 21662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // This is used to notify the container of updates relating to number of columns 21762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // or headers changing, which changes the number of placeholders needed 21862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private final DataSetObservable mDataSetObservable = new DataSetObservable(); 21962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 22062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private final ListAdapter mAdapter; 22162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private int mNumColumns = 1; 22262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 22362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // This ArrayList is assumed to NOT be null. 22462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu ArrayList<FixedViewInfo> mHeaderViewInfos; 22562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 22662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu boolean mAreAllFixedViewsSelectable; 22762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 22862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private final boolean mIsFilterable; 22962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 23062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public HeaderViewGridAdapter(ArrayList<FixedViewInfo> headerViewInfos, ListAdapter adapter) { 23162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mAdapter = adapter; 23262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mIsFilterable = adapter instanceof Filterable; 23362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 23462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (headerViewInfos == null) { 23562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new IllegalArgumentException("headerViewInfos cannot be null"); 23662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 23762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mHeaderViewInfos = headerViewInfos; 23862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 23962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos); 24062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 24162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 24262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public int getHeadersCount() { 24362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mHeaderViewInfos.size(); 24462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 24562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 24662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 24762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean isEmpty() { 24862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return (mAdapter == null || mAdapter.isEmpty()) && getHeadersCount() == 0; 24962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 25062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 25162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void setNumColumns(int numColumns) { 25262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (numColumns < 1) { 25362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new IllegalArgumentException("Number of columns must be 1 or more"); 25462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 25562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mNumColumns != numColumns) { 25662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mNumColumns = numColumns; 25762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu notifyDataSetChanged(); 25862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 25962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 26062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 26162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu private boolean areAllListInfosSelectable(ArrayList<FixedViewInfo> infos) { 26262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (infos != null) { 26362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu for (FixedViewInfo info : infos) { 26462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (!info.isSelectable) { 26562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return false; 26662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 26762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 26862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 26962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return true; 27062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 27162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 27262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean removeHeader(View v) { 27362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu for (int i = 0; i < mHeaderViewInfos.size(); i++) { 27462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu FixedViewInfo info = mHeaderViewInfos.get(i); 27562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (info.view == v) { 27662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mHeaderViewInfos.remove(i); 27762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 27862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mAreAllFixedViewsSelectable = areAllListInfosSelectable(mHeaderViewInfos); 27962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 28062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mDataSetObservable.notifyChanged(); 28162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return true; 28262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 28362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 28462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 28562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return false; 28662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 28762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 28862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 28962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public int getCount() { 29062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 29162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return getHeadersCount() * mNumColumns + mAdapter.getCount(); 29262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } else { 29362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return getHeadersCount() * mNumColumns; 29462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 29562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 29662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 29762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 29862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean areAllItemsEnabled() { 29962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 30062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAreAllFixedViewsSelectable && mAdapter.areAllItemsEnabled(); 30162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } else { 30262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return true; 30362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 30462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 30562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 30662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 30762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean isEnabled(int position) { 30862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Header (negative positions will throw an ArrayIndexOutOfBoundsException) 30962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; 31062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position < numHeadersAndPlaceholders) { 31162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return (position % mNumColumns == 0) 31262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu && mHeaderViewInfos.get(position / mNumColumns).isSelectable; 31362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 31462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 31562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Adapter 31662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu final int adjPosition = position - numHeadersAndPlaceholders; 31762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adapterCount = 0; 31862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 31962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu adapterCount = mAdapter.getCount(); 32062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adjPosition < adapterCount) { 32162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.isEnabled(adjPosition); 32262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 32362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 32462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 32562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new ArrayIndexOutOfBoundsException(position); 32662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 32762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 32862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 32962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public Object getItem(int position) { 33062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Header (negative positions will throw an ArrayIndexOutOfBoundsException) 33162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; 33262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position < numHeadersAndPlaceholders) { 33362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position % mNumColumns == 0) { 33462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mHeaderViewInfos.get(position / mNumColumns).data; 33562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 33662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return null; 33762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 33862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 33962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Adapter 34062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu final int adjPosition = position - numHeadersAndPlaceholders; 34162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adapterCount = 0; 34262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 34362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu adapterCount = mAdapter.getCount(); 34462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adjPosition < adapterCount) { 34562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.getItem(adjPosition); 34662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 34762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 34862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 34962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new ArrayIndexOutOfBoundsException(position); 35062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 35162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 35262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 35362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public long getItemId(int position) { 35462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; 35562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null && position >= numHeadersAndPlaceholders) { 35662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adjPosition = position - numHeadersAndPlaceholders; 35762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adapterCount = mAdapter.getCount(); 35862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adjPosition < adapterCount) { 35962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.getItemId(adjPosition); 36062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 36162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 36262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return -1; 36362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 36462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 36562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 36662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public boolean hasStableIds() { 36762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 36862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.hasStableIds(); 36962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 37062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return false; 37162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 37262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 37362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 37462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public View getView(int position, View convertView, ViewGroup parent) { 37562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Header (negative positions will throw an ArrayIndexOutOfBoundsException) 37662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns ; 37762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position < numHeadersAndPlaceholders) { 37862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu View headerViewContainer = mHeaderViewInfos 37962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu .get(position / mNumColumns).viewContainer; 38062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position % mNumColumns == 0) { 38162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return headerViewContainer; 38262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } else { 38362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (convertView == null) { 38462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu convertView = new View(parent.getContext()); 38562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 38662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // We need to do this because GridView uses the height of the last item 38762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // in a row to determine the height for the entire row. 38862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu convertView.setVisibility(View.INVISIBLE); 38962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu convertView.setMinimumHeight(headerViewContainer.getHeight()); 39062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return convertView; 39162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 39262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 39362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 39462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Adapter 39562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu final int adjPosition = position - numHeadersAndPlaceholders; 39662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adapterCount = 0; 39762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 39862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu adapterCount = mAdapter.getCount(); 39962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adjPosition < adapterCount) { 40062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.getView(adjPosition, convertView, parent); 40162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 40262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 40362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 40462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu throw new ArrayIndexOutOfBoundsException(position); 40562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 40662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 40762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 40862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public int getItemViewType(int position) { 40962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int numHeadersAndPlaceholders = getHeadersCount() * mNumColumns; 41062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (position < numHeadersAndPlaceholders && (position % mNumColumns != 0)) { 41162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu // Placeholders get the last view type number 41262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter != null ? mAdapter.getViewTypeCount() : 1; 41362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 41462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null && position >= numHeadersAndPlaceholders) { 41562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adjPosition = position - numHeadersAndPlaceholders; 41662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu int adapterCount = mAdapter.getCount(); 41762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (adjPosition < adapterCount) { 41862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.getItemViewType(adjPosition); 41962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 42062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 42162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 42262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER; 42362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 42462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 42562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 42662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public int getViewTypeCount() { 42762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 42862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter.getViewTypeCount() + 1; 42962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 43062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return 2; 43162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 43262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 43362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 43462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void registerDataSetObserver(DataSetObserver observer) { 43562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mDataSetObservable.registerObserver(observer); 43662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 43762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mAdapter.registerDataSetObserver(observer); 43862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 43962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 44062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 44162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 44262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void unregisterDataSetObserver(DataSetObserver observer) { 44362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mDataSetObservable.unregisterObserver(observer); 44462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mAdapter != null) { 44562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mAdapter.unregisterDataSetObserver(observer); 44662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 44762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 44862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 44962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 45062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public Filter getFilter() { 45162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu if (mIsFilterable) { 45262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return ((Filterable) mAdapter).getFilter(); 45362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 45462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return null; 45562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 45662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 45762cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu @Override 45862cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public ListAdapter getWrappedAdapter() { 45962cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu return mAdapter; 46062cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 46162cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu 46262cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu public void notifyDataSetChanged() { 46362cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu mDataSetObservable.notifyChanged(); 46462cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 46562cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu } 46662cc2aa4400a4ad03cfc6025e9d25c61015cdef4Bobby Georgescu} 467