137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson/* 237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Copyright (C) 2011 The Android Open Source Project 337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Licensed under the Apache License, Version 2.0 (the "License"); 537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * you may not use this file except in compliance with the License. 637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * You may obtain a copy of the License at 737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * http://www.apache.org/licenses/LICENSE-2.0 937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 1037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Unless required by applicable law or agreed to in writing, software 1137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * distributed under the License is distributed on an "AS IS" BASIS, 1237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * See the License for the specific language governing permissions and 1437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * limitations under the License. 1537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson */ 1637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 1737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonpackage com.android.calendar; 1837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 1937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.content.Context; 2037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.graphics.Color; 2137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.util.AttributeSet; 2237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.view.Gravity; 2337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.view.View; 2437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.view.ViewGroup; 2537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.widget.AbsListView; 2637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.widget.AbsListView.OnScrollListener; 2737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.widget.Adapter; 2837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.widget.FrameLayout; 2937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonimport android.widget.ListView; 3037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 3137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson/** 3237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Implements a ListView class with a sticky header at the top. The header is 3337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * per section and it is pinned to the top as long as its section is at the top 3437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * of the view. If it is not, the header slides up or down (depending on the 3537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * scroll movement) and the header of the current section slides to the top. 3637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Notes: 3737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 1. The class uses the first available child ListView as the working 3837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * ListView. If no ListView child exists, the class will create a default one. 3937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 2. The ListView's adapter must be passed to this class using the 'setAdapter' 4037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * method. The adapter must implement the HeaderIndexer interface. If no adapter 4137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * is specified, the class will try to extract it from the ListView 4237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 3. The class registers itself as a listener to scroll events (OnScrollListener), if the 4337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * ListView needs to receive scroll events, it must register its listener using 4437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * this class' setOnScrollListener method. 4537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 4. Headers for the list view must be added before using the StickyHeaderListView 4637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 5. The implementation should register to listen to dataset changes. Right now this is not done 4737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * since a change the dataset in a listview forces a call to OnScroll. The needed code is 4837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * commented out. 4937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson */ 5037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelsonpublic class StickyHeaderListView extends FrameLayout implements OnScrollListener { 5137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 5237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson private static final String TAG = "StickyHeaderListView"; 5337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected boolean mChildViewsCreated = false; 5437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected boolean mDoHeaderReset = false; 5537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 5637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected Context mContext = null; 5737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected Adapter mAdapter = null; 5837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected HeaderIndexer mIndexer = null; 59c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson protected HeaderHeightListener mHeaderHeightListener = null; 6037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected View mStickyHeader = null; 6137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected View mDummyHeader = null; // A invisible header used when a section has no header 6237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected ListView mListView = null; 6337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected ListView.OnScrollListener mListener = null; 6437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 65e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson private int mSeparatorWidth; 66e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson private View mSeparatorView; 67c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson private int mLastStickyHeaderHeight = 0; 68e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson 6937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // This code is needed only if dataset changes do not force a call to OnScroll 7037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // protected DataSetObserver mListDataObserver = null; 7137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 7237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 7337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected int mCurrentSectionPos = -1; // Position of section that has its header on the 7437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // top of the view 7537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected int mNextSectionPosition = -1; // Position of next section's header 7637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected int mListViewHeadersCount = 0; 7737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 7837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson /** 7937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Interface that must be implemented by the ListView adapter to provide headers locations 8037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * and number of items under each header. 8137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 8237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson */ 8337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson public interface HeaderIndexer { 8437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson /** 8537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Calculates the position of the header of a specific item in the adapter's data set. 8637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * For example: Assuming you have a list with albums and songs names: 8737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * Album A, song 1, song 2, ...., song 10, Album B, song 1, ..., song 7. A call to 8837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * this method with the position of song 5 in Album B, should return the position 8937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * of Album B. 9037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * @param position - Position of the item in the ListView dataset 9137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * @return Position of header. -1 if the is no header 9237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson */ 9337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 9437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int getHeaderPositionFromItemPosition(int position); 9537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 9637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson /** 97980d530f002b335916e8b31662e50a94b43cae18Isaac Katzenelson * Calculates the number of items in the section defined by the header (not including 9837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * the header). 9937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * For example: A list with albums and songs, the method should return 10037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * the number of songs names (without the album name). 10137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * 10237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * @param headerPosition - the value returned by 'getHeaderPositionFromItemPosition' 10337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson * @return Number of items. -1 on error. 10437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson */ 10537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int getHeaderItemsNumber(int headerPosition); 10637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 10737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 108c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson /*** 109c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * 110c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * Interface that is used to update the sticky header's height 111c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * 112c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson */ 113c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson public interface HeaderHeightListener { 114c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson 115c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson /*** 116c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * Updated a change in the sticky header's size 117c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * 118c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson * @param height - new height of sticky header 119c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson */ 120c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson void OnHeaderHeightChanged(int height); 121c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson } 122c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson 123e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 124e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Sets the adapter to be used by the class to get views of headers 125e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 126e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param adapter - The adapter. 127e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 12837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 129e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson public void setAdapter(Adapter adapter) { 130e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson 131e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // This code is needed only if dataset changes do not force a call to 132e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // OnScroll 13337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // if (mAdapter != null && mListDataObserver != null) { 134e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // mAdapter.unregisterDataSetObserver(mListDataObserver); 13537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // } 13637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 137e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson if (adapter != null) { 138e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson mAdapter = adapter; 139e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // This code is needed only if dataset changes do not force a call 140e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // to OnScroll 141e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson // mAdapter.registerDataSetObserver(mListDataObserver); 14237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 14337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 14437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 145e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 146e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Sets the indexer object (that implements the HeaderIndexer interface). 147e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 148e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param indexer - The indexer. 149e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 150e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson 151e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson public void setIndexer(HeaderIndexer indexer) { 152e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson mIndexer = indexer; 15337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 15437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 155e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 156e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Sets the list view that is displayed 157e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param lv - The list view. 158e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 159e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson 16037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson public void setListView(ListView lv) { 16137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mListView = lv; 16237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mListView.setOnScrollListener(this); 16337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mListViewHeadersCount = mListView.getHeaderViewsCount(); 16437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 16537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 166e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 167e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Sets an external OnScroll listener. Since the StickyHeaderListView sets 168e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * itself as the scroll events listener of the listview, this method allows 169e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * the user to register another listener that will be called after this 170e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * class listener is called. 171e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 172e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param listener - The external listener. 173e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 174e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson public void setOnScrollListener(ListView.OnScrollListener listener) { 175e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson mListener = listener; 17637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 17737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 178c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson public void setHeaderHeightListener(HeaderHeightListener listener) { 179c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson mHeaderHeightListener = listener; 180c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson } 181c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson 18237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // This code is needed only if dataset changes do not force a call to OnScroll 18337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // protected void createDataListener() { 18437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // mListDataObserver = new DataSetObserver() { 18537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // @Override 18637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // public void onChanged() { 18737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // onDataChanged(); 18837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // } 18937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // }; 19037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // } 19137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 192e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 193e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Constructor 194e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 195e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param context - application context. 196e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param attrs - layout attributes. 197e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 19837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson public StickyHeaderListView(Context context, AttributeSet attrs) { 19937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson super(context, attrs); 20037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mContext = context; 20137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // This code is needed only if dataset changes do not force a call to OnScroll 20237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // createDataListener(); 20337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 20437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 205e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 206e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Scroll status changes listener 207e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 208e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param view - the scrolled view 209e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param scrollState - new scroll state. 210e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 211e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson @Override 21237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson public void onScrollStateChanged(AbsListView view, int scrollState) { 21337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mListener != null) { 21437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mListener.onScrollStateChanged(view, scrollState); 21537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 21637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 21737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 218e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson /** 219e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * Scroll events listener 220e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * 221e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param view - the scrolled view 222e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param firstVisibleItem - the index (in the list's adapter) of the top 223e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * visible item. 224e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param visibleItemCount - the number of visible items in the list 225e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson * @param totalItemCount - the total number items in the list 226e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson */ 227e2ed3678c5fb9434f5e89d3278dea8daff44de58Isaac Katzenelson @Override 22837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, 22937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int totalItemCount) { 23037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 23137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson updateStickyHeader(firstVisibleItem); 23237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 23337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mListener != null) { 23437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); 23537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 23637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 23737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 238e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson /** 239e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson * Sets a separator below the sticky header, which will be visible while the sticky header 240e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson * is not scrolling up. 241e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson * @param color - color of separator 242e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson * @param width - width in pixels of separator 243e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson */ 244e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson public void setHeaderSeparator(int color, int width) { 245e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView = new View(mContext); 246e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson ViewGroup.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, 247e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson width, Gravity.TOP); 248e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setLayoutParams(params); 249e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setBackgroundColor(color); 250e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorWidth = width; 251e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson this.addView(mSeparatorView); 252e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson } 253e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson 25437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected void updateStickyHeader(int firstVisibleItem) { 25537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 25637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Try to make sure we have an adapter to work with (may not succeed). 25737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mAdapter == null && mListView != null) { 25837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson setAdapter(mListView.getAdapter()); 25937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 26037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 26137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson firstVisibleItem -= mListViewHeadersCount; 26237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mAdapter != null && mIndexer != null && mDoHeaderReset) { 26337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 26437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Get the section header position 26537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int sectionSize = 0; 26637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int sectionPos = mIndexer.getHeaderPositionFromItemPosition(firstVisibleItem); 26737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 26837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // New section - set it in the header view 26937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson boolean newView = false; 27037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (sectionPos != mCurrentSectionPos) { 27137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 272e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson // No header for current position , use the dummy invisible one, hide the separator 27337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (sectionPos == -1) { 27437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson sectionSize = 0; 27537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson this.removeView(mStickyHeader); 27637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader = mDummyHeader; 277e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson if (mSeparatorView != null) { 278e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setVisibility(View.GONE); 279e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson } 28037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson newView = true; 28137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } else { 28237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Create a copy of the header view to show on top 28337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson sectionSize = mIndexer.getHeaderItemsNumber(sectionPos); 28437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson View v = mAdapter.getView(sectionPos + mListViewHeadersCount, null, mListView); 28537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson v.measure(MeasureSpec.makeMeasureSpec(mListView.getWidth(), 28637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(mListView.getHeight(), 28737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson MeasureSpec.AT_MOST)); 28837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson this.removeView(mStickyHeader); 28937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader = v; 29037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson newView = true; 29137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 29237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mCurrentSectionPos = sectionPos; 29337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mNextSectionPosition = sectionSize + sectionPos + 1; 29437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 29537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 29637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 29737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Do transitions 29837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // If position of bottom of last item in a section is smaller than the height of the 29937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // sticky header - shift drawable of header. 30037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mStickyHeader != null) { 30137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int sectionLastItemPosition = mNextSectionPosition - firstVisibleItem - 1; 30237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int stickyHeaderHeight = mStickyHeader.getHeight(); 30337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (stickyHeaderHeight == 0) { 30437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson stickyHeaderHeight = mStickyHeader.getMeasuredHeight(); 30537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 306c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson 307c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson // Update new header height 308c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson if (mHeaderHeightListener != null && 309c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson mLastStickyHeaderHeight != stickyHeaderHeight) { 310c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson mLastStickyHeaderHeight = stickyHeaderHeight; 311c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson mHeaderHeightListener.OnHeaderHeightChanged(stickyHeaderHeight); 312c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson } 313c1fae4df6202ac82c3facd76e5f33c7cbacb39d1Isaac Katzenelson 31437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson View SectionLastView = mListView.getChildAt(sectionLastItemPosition); 31537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (SectionLastView != null && SectionLastView.getBottom() <= stickyHeaderHeight) { 31637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int lastViewBottom = SectionLastView.getBottom(); 31737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader.setTranslationY(lastViewBottom - stickyHeaderHeight); 318e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson if (mSeparatorView != null) { 319e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setVisibility(View.GONE); 320e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson } 32137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } else if (stickyHeaderHeight != 0) { 32237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader.setTranslationY(0); 32351cd31c8ed558530bab70ac9f7a84b2e456368ebIsaac Katzenelson if (mSeparatorView != null && !mStickyHeader.equals(mDummyHeader)) { 324e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setVisibility(View.VISIBLE); 325e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson } 32637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 32737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (newView) { 32837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader.setVisibility(View.INVISIBLE); 32937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson this.addView(mStickyHeader); 330e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson if (mSeparatorView != null && !mStickyHeader.equals(mDummyHeader)){ 331e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson FrameLayout.LayoutParams params = 332e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson new FrameLayout.LayoutParams(LayoutParams.MATCH_PARENT, 333e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorWidth); 334e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson params.setMargins(0, mStickyHeader.getMeasuredHeight(), 0, 0); 335e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setLayoutParams(params); 336e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson mSeparatorView.setVisibility(View.VISIBLE); 337e0983f72aa6b33e8733699b6f72d67126fc785bdIsaac Katzenelson } 33837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mStickyHeader.setVisibility(View.VISIBLE); 33937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 34037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 34137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 34237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 34337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 34437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson @Override 34537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected void onFinishInflate() { 34637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson super.onFinishInflate(); 34737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (!mChildViewsCreated) { 34837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson setChildViews(); 34937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 35037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mDoHeaderReset = true; 35137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 35237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 35337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson @Override 35437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson protected void onAttachedToWindow() { 35537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson super.onAttachedToWindow(); 35637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (!mChildViewsCreated) { 35737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson setChildViews(); 35837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 35937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mDoHeaderReset = true; 36037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 36137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 36237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 36337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Resets the sticky header when the adapter data set was changed 36437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // This code is needed only if dataset changes do not force a call to OnScroll 36537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // protected void onDataChanged() { 36637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Should do a call to updateStickyHeader if needed 36737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // } 36837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 36937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson private void setChildViews() { 37037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 37137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Find a child ListView (if any) 37237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson int iChildNum = getChildCount(); 37337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson for (int i = 0; i < iChildNum; i++) { 37437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson Object v = getChildAt(i); 37537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (v instanceof ListView) { 37637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson setListView((ListView) v); 37737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 37837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 37937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 38037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // No child ListView - add one 38137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson if (mListView == null) { 38237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson setListView(new ListView(mContext)); 38337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 38437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 38537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson // Create a dummy view , it will be used in case a section has no header 38637f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mDummyHeader = new View (mContext); 38737f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson ViewGroup.LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT, 38837f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 1, Gravity.TOP); 38937f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mDummyHeader.setLayoutParams(params); 39037f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mDummyHeader.setBackgroundColor(Color.TRANSPARENT); 39137f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 39237f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson mChildViewsCreated = true; 39337f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson } 39437f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson 39537f12e5cee7ed2d354e9366bd6d8e15d1a934f2aIsaac Katzenelson} 396