switch to alsa.omap3 module
[android_pandora.git] / apps / AndroidSupportV2 / src / android / support / v2 / app / ListFragment.java
1 /*
2  * Copyright (C) 2011 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
17 package android.support.v2.app;
18
19 import android.os.Bundle;
20 import android.os.Handler;
21 import android.view.Gravity;
22 import android.view.LayoutInflater;
23 import android.view.View;
24 import android.view.ViewGroup;
25 import android.view.animation.AnimationUtils;
26 import android.widget.AdapterView;
27 import android.widget.FrameLayout;
28 import android.widget.ListAdapter;
29 import android.widget.ListView;
30 import android.widget.TextView;
31
32 /**
33  * Static library support version of the framework's {@link android.app.ListFragment}.
34  * Used to write apps that run on platforms prior to Android 3.0.  When running
35  * on Android 3.0 or above, this implementation is still used; it does not try
36  * to switch to the framework's implementation.  See the framework SDK
37  * documentation for a class overview.
38  */
39 public class ListFragment extends Fragment {
40     static final int INTERNAL_EMPTY_ID = 0x00ff0001;
41     
42     final private Handler mHandler = new Handler();
43
44     final private Runnable mRequestFocus = new Runnable() {
45         public void run() {
46             mList.focusableViewAvailable(mList);
47         }
48     };
49     
50     final private AdapterView.OnItemClickListener mOnClickListener
51             = new AdapterView.OnItemClickListener() {
52         public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
53             onListItemClick((ListView)parent, v, position, id);
54         }
55     };
56
57     ListAdapter mAdapter;
58     ListView mList;
59     View mEmptyView;
60     TextView mStandardEmptyView;
61     View mProgressContainer;
62     View mListContainer;
63     boolean mSetEmptyText;
64     boolean mListShown;
65
66     public ListFragment() {
67     }
68
69     /**
70      * Provide default implementation to return a simple list view.  Subclasses
71      * can override to replace with their own layout.  If doing so, the
72      * returned view hierarchy <em>must</em> have a ListView whose id
73      * is {@link android.R.id#list android.R.id.list} and can optionally
74      * have a sibling view id {@link android.R.id#empty android.R.id.empty}
75      * that is to be shown when the list is empty.
76      * 
77      * <p>If you are overriding this method with your own custom content,
78      * consider including the standard layout {@link android.R.layout#list_content}
79      * in your layout file, so that you continue to retain all of the standard
80      * behavior of ListFragment.  In particular, this is currently the only
81      * way to have the built-in indeterminant progress state be shown.
82      */
83     @Override
84     public View onCreateView(LayoutInflater inflater, ViewGroup container,
85             Bundle savedInstanceState) {
86         FrameLayout root = new FrameLayout(getActivity());
87         
88         TextView tv = new TextView(getActivity());
89         tv.setId(INTERNAL_EMPTY_ID);
90         tv.setGravity(Gravity.CENTER);
91         root.addView(tv, new FrameLayout.LayoutParams(
92                 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
93         
94         ListView lv = new ListView(getActivity());
95         lv.setId(android.R.id.list);
96         lv.setDrawSelectorOnTop(false);
97         root.addView(lv, new FrameLayout.LayoutParams(
98                 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
99         
100         ListView.LayoutParams lp = new ListView.LayoutParams(
101                 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
102         root.setLayoutParams(lp);
103         
104         return root;
105     }
106
107     /**
108      * Attach to list view once Fragment is ready to run.
109      */
110     @Override
111     public void onActivityCreated(Bundle savedInstanceState) {
112         super.onActivityCreated(savedInstanceState);
113         ensureList();
114     }
115
116     /**
117      * Detach from list view.
118      */
119     @Override
120     public void onDestroyView() {
121         mHandler.removeCallbacks(mRequestFocus);
122         mList = null;
123         super.onDestroyView();
124     }
125
126     /**
127      * This method will be called when an item in the list is selected.
128      * Subclasses should override. Subclasses can call
129      * getListView().getItemAtPosition(position) if they need to access the
130      * data associated with the selected item.
131      *
132      * @param l The ListView where the click happened
133      * @param v The view that was clicked within the ListView
134      * @param position The position of the view in the list
135      * @param id The row id of the item that was clicked
136      */
137     public void onListItemClick(ListView l, View v, int position, long id) {
138     }
139
140     /**
141      * Provide the cursor for the list view.
142      */
143     public void setListAdapter(ListAdapter adapter) {
144         boolean hadAdapter = mAdapter != null;
145         mAdapter = adapter;
146         if (mList != null) {
147             mList.setAdapter(adapter);
148             if (!mListShown && !hadAdapter) {
149                 // The list was hidden, and previously didn't have an
150                 // adapter.  It is now time to show it.
151                 setListShown(true, getView().getWindowToken() != null);
152             }
153         }
154     }
155
156     /**
157      * Set the currently selected list item to the specified
158      * position with the adapter's data
159      *
160      * @param position
161      */
162     public void setSelection(int position) {
163         ensureList();
164         mList.setSelection(position);
165     }
166
167     /**
168      * Get the position of the currently selected list item.
169      */
170     public int getSelectedItemPosition() {
171         ensureList();
172         return mList.getSelectedItemPosition();
173     }
174
175     /**
176      * Get the cursor row ID of the currently selected list item.
177      */
178     public long getSelectedItemId() {
179         ensureList();
180         return mList.getSelectedItemId();
181     }
182
183     /**
184      * Get the activity's list view widget.
185      */
186     public ListView getListView() {
187         ensureList();
188         return mList;
189     }
190
191     /**
192      * The default content for a ListFragment has a TextView that can
193      * be shown when the list is empty.  If you would like to have it
194      * shown, call this method to supply the text it should use.
195      */
196     public void setEmptyText(CharSequence text) {
197         ensureList();
198         if (mStandardEmptyView == null) {
199             throw new IllegalStateException("Can't be used with a custom content view");
200         }
201         mStandardEmptyView.setText(text);
202         if (!mSetEmptyText) {
203             mList.setEmptyView(mStandardEmptyView);
204             mSetEmptyText = true;
205         }
206     }
207     
208     /**
209      * Control whether the list is being displayed.  You can make it not
210      * displayed if you are waiting for the initial data to show in it.  During
211      * this time an indeterminant progress indicator will be shown instead.
212      * 
213      * <p>Applications do not normally need to use this themselves.  The default
214      * behavior of ListFragment is to start with the list not being shown, only
215      * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
216      * If the list at that point had not been shown, when it does get shown
217      * it will be do without the user ever seeing the hidden state.
218      * 
219      * @param shown If true, the list view is shown; if false, the progress
220      * indicator.  The initial value is true.
221      */
222     public void setListShown(boolean shown) {
223         setListShown(shown, true);
224     }
225     
226     /**
227      * Like {@link #setListShown(boolean)}, but no animation is used when
228      * transitioning from the previous state.
229      */
230     public void setListShownNoAnimation(boolean shown) {
231         setListShown(shown, false);
232     }
233     
234     /**
235      * Control whether the list is being displayed.  You can make it not
236      * displayed if you are waiting for the initial data to show in it.  During
237      * this time an indeterminant progress indicator will be shown instead.
238      * 
239      * @param shown If true, the list view is shown; if false, the progress
240      * indicator.  The initial value is true.
241      * @param animate If true, an animation will be used to transition to the
242      * new state.
243      */
244     private void setListShown(boolean shown, boolean animate) {
245         ensureList();
246         if (mProgressContainer == null) {
247             throw new IllegalStateException("Can't be used with a custom content view");
248         }
249         if (mListShown == shown) {
250             return;
251         }
252         mListShown = shown;
253         if (shown) {
254             if (animate) {
255                 mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
256                         getActivity(), android.R.anim.fade_out));
257                 mListContainer.startAnimation(AnimationUtils.loadAnimation(
258                         getActivity(), android.R.anim.fade_in));
259             }
260             mProgressContainer.setVisibility(View.GONE);
261             mListContainer.setVisibility(View.VISIBLE);
262         } else {
263             if (animate) {
264                 mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
265                         getActivity(), android.R.anim.fade_in));
266                 mListContainer.startAnimation(AnimationUtils.loadAnimation(
267                         getActivity(), android.R.anim.fade_out));
268             }
269             mProgressContainer.setVisibility(View.VISIBLE);
270             mListContainer.setVisibility(View.GONE);
271         }
272     }
273     
274     /**
275      * Get the ListAdapter associated with this activity's ListView.
276      */
277     public ListAdapter getListAdapter() {
278         return mAdapter;
279     }
280
281     private void ensureList() {
282         if (mList != null) {
283             return;
284         }
285         View root = getView();
286         if (root == null) {
287             throw new IllegalStateException("Content view not yet created");
288         }
289         if (root instanceof ListView) {
290             mList = (ListView)root;
291         } else {
292             mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID);
293             if (mStandardEmptyView == null) {
294                 mEmptyView = root.findViewById(android.R.id.empty);
295             }
296             mProgressContainer = null; //root.findViewById(com.android.internal.R.id.progressContainer);
297             mListContainer = null; //root.findViewById(com.android.internal.R.id.listContainer);
298             View rawListView = root.findViewById(android.R.id.list);
299             if (!(rawListView instanceof ListView)) {
300                 if (rawListView == null) {
301                     throw new RuntimeException(
302                             "Your content must have a ListView whose id attribute is " +
303                             "'android.R.id.list'");
304                 }
305                 throw new RuntimeException(
306                         "Content has view with id attribute 'android.R.id.list' "
307                         + "that is not a ListView class");
308             }
309             mList = (ListView)rawListView;
310             if (mEmptyView != null) {
311                 mList.setEmptyView(mEmptyView);
312             }
313         }
314         mListShown = true;
315         mList.setOnItemClickListener(mOnClickListener);
316         if (mAdapter != null) {
317             setListAdapter(mAdapter);
318         } else {
319             // We are starting without an adapter, so assume we won't
320             // have our data right away and start with the progress indicator.
321             if (mProgressContainer != null) {
322                 setListShown(false, false);
323             }
324         }
325         mHandler.post(mRequestFocus);
326     }
327 }