• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 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 package com.android.internal.widget;
17 
18 import android.annotation.IdRes;
19 import android.content.Context;
20 import android.util.AttributeSet;
21 import android.view.View;
22 import android.view.ViewGroup;
23 import android.widget.AdapterView;
24 import android.widget.ListAdapter;
25 import android.widget.ListView;
26 import android.widget.HeaderViewListAdapter;
27 
28 import java.util.ArrayList;
29 
30 import com.android.internal.util.Predicate;
31 
32 public class WatchHeaderListView extends ListView {
33     private View mTopPanel;
34 
WatchHeaderListView(Context context, AttributeSet attrs)35     public WatchHeaderListView(Context context, AttributeSet attrs) {
36         super(context, attrs);
37     }
38 
WatchHeaderListView(Context context, AttributeSet attrs, int defStyleAttr)39     public WatchHeaderListView(Context context, AttributeSet attrs, int defStyleAttr) {
40         super(context, attrs, defStyleAttr);
41     }
42 
WatchHeaderListView( Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes)43     public WatchHeaderListView(
44             Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
45         super(context, attrs, defStyleAttr, defStyleRes);
46     }
47 
48     @Override
wrapHeaderListAdapterInternal( ArrayList<ListView.FixedViewInfo> headerViewInfos, ArrayList<ListView.FixedViewInfo> footerViewInfos, ListAdapter adapter)49     protected HeaderViewListAdapter wrapHeaderListAdapterInternal(
50             ArrayList<ListView.FixedViewInfo> headerViewInfos,
51             ArrayList<ListView.FixedViewInfo> footerViewInfos,
52             ListAdapter adapter) {
53         return new WatchHeaderListAdapter(headerViewInfos, footerViewInfos, adapter);
54     }
55 
56     @Override
addView(View child, ViewGroup.LayoutParams params)57     public void addView(View child, ViewGroup.LayoutParams params) {
58         if (mTopPanel == null) {
59             setTopPanel(child);
60         } else {
61             throw new IllegalStateException("WatchHeaderListView can host only one header");
62         }
63     }
64 
setTopPanel(View v)65     public void setTopPanel(View v) {
66         mTopPanel = v;
67         wrapAdapterIfNecessary();
68     }
69 
70     @Override
setAdapter(ListAdapter adapter)71     public void setAdapter(ListAdapter adapter) {
72         super.setAdapter(adapter);
73         wrapAdapterIfNecessary();
74     }
75 
76     @Override
findViewTraversal(@dRes int id)77     protected View findViewTraversal(@IdRes int id) {
78         View v = super.findViewTraversal(id);
79         if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) {
80             return mTopPanel.findViewById(id);
81         }
82         return v;
83     }
84 
85     @Override
findViewWithTagTraversal(Object tag)86     protected View findViewWithTagTraversal(Object tag) {
87         View v = super.findViewWithTagTraversal(tag);
88         if (v == null && mTopPanel != null && !mTopPanel.isRootNamespace()) {
89             return mTopPanel.findViewWithTag(tag);
90         }
91         return v;
92     }
93 
94     @Override
findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip)95     protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
96         View v = super.findViewByPredicateTraversal(predicate, childToSkip);
97         if (v == null && mTopPanel != null && mTopPanel != childToSkip
98                 && !mTopPanel.isRootNamespace()) {
99             return mTopPanel.findViewByPredicate(predicate);
100         }
101         return v;
102     }
103 
104     @Override
getHeaderViewsCount()105     public int getHeaderViewsCount() {
106         return mTopPanel == null ? super.getHeaderViewsCount() : super.getHeaderViewsCount() + 1;
107     }
108 
wrapAdapterIfNecessary()109     private void wrapAdapterIfNecessary() {
110         ListAdapter adapter = getAdapter();
111         if (adapter != null && mTopPanel != null) {
112             if (!(adapter instanceof WatchHeaderListAdapter)) {
113                 wrapHeaderListAdapterInternal();
114             }
115 
116             ((WatchHeaderListAdapter) getAdapter()).setTopPanel(mTopPanel);
117             dispatchDataSetObserverOnChangedInternal();
118         }
119     }
120 
121     private static class WatchHeaderListAdapter extends HeaderViewListAdapter {
122         private View mTopPanel;
123 
WatchHeaderListAdapter( ArrayList<ListView.FixedViewInfo> headerViewInfos, ArrayList<ListView.FixedViewInfo> footerViewInfos, ListAdapter adapter)124         public WatchHeaderListAdapter(
125                 ArrayList<ListView.FixedViewInfo> headerViewInfos,
126                 ArrayList<ListView.FixedViewInfo> footerViewInfos,
127                 ListAdapter adapter) {
128             super(headerViewInfos, footerViewInfos, adapter);
129         }
130 
setTopPanel(View v)131         public void setTopPanel(View v) {
132             mTopPanel = v;
133         }
134 
getTopPanelCount()135         private int getTopPanelCount() {
136             return mTopPanel == null ? 0 : 1;
137         }
138 
139         @Override
getCount()140         public int getCount() {
141             return super.getCount() + getTopPanelCount();
142         }
143 
144         @Override
areAllItemsEnabled()145         public boolean areAllItemsEnabled() {
146             return mTopPanel == null && super.areAllItemsEnabled();
147         }
148 
149         @Override
isEnabled(int position)150         public boolean isEnabled(int position) {
151             if (mTopPanel != null) {
152                 if (position == 0) {
153                     return false;
154                 } else {
155                     return super.isEnabled(position - 1);
156                 }
157             }
158 
159             return super.isEnabled(position);
160         }
161 
162         @Override
getItem(int position)163         public Object getItem(int position) {
164             if (mTopPanel != null) {
165                 if (position == 0) {
166                     return null;
167                 } else {
168                     return super.getItem(position - 1);
169                 }
170             }
171 
172             return super.getItem(position);
173         }
174 
175         @Override
getItemId(int position)176         public long getItemId(int position) {
177             int numHeaders = getHeadersCount() + getTopPanelCount();
178             if (getWrappedAdapter() != null && position >= numHeaders) {
179                 int adjPosition = position - numHeaders;
180                 int adapterCount = getWrappedAdapter().getCount();
181                 if (adjPosition < adapterCount) {
182                     return getWrappedAdapter().getItemId(adjPosition);
183                 }
184             }
185             return -1;
186         }
187 
188         @Override
getView(int position, View convertView, ViewGroup parent)189         public View getView(int position, View convertView, ViewGroup parent) {
190             if (mTopPanel != null) {
191                 if (position == 0) {
192                     return mTopPanel;
193                 } else {
194                     return super.getView(position - 1, convertView, parent);
195                 }
196             }
197 
198             return super.getView(position, convertView, parent);
199         }
200 
201         @Override
getItemViewType(int position)202         public int getItemViewType(int position) {
203             int numHeaders = getHeadersCount() + getTopPanelCount();
204             if (getWrappedAdapter() != null && position >= numHeaders) {
205                 int adjPosition = position - numHeaders;
206                 int adapterCount = getWrappedAdapter().getCount();
207                 if (adjPosition < adapterCount) {
208                     return getWrappedAdapter().getItemViewType(adjPosition);
209                 }
210             }
211 
212             return AdapterView.ITEM_VIEW_TYPE_HEADER_OR_FOOTER;
213         }
214     }
215 }
216