1 package net.sf.openrocket.android.util;
\r
3 import android.os.Bundle;
\r
4 import android.os.Handler;
\r
5 import android.view.ContextMenu;
\r
6 import android.view.ContextMenu.ContextMenuInfo;
\r
7 import android.view.Gravity;
\r
8 import android.view.LayoutInflater;
\r
9 import android.view.View;
\r
10 import android.view.View.OnCreateContextMenuListener;
\r
11 import android.view.ViewGroup;
\r
12 import android.view.animation.AnimationUtils;
\r
13 import android.widget.AdapterView;
\r
14 import android.widget.ExpandableListAdapter;
\r
15 import android.widget.ExpandableListView;
\r
16 import android.widget.FrameLayout;
\r
17 import android.widget.ListAdapter;
\r
18 import android.widget.ListView;
\r
19 import android.widget.TextView;
\r
21 import com.actionbarsherlock.app.SherlockFragment;
\r
25 * Pulled from https://gist.github.com/1316903
\r
27 * This class has originally been taken from
\r
28 * http://stackoverflow.com/questions/6051050/expandablelistfragment-with-loadermanager-for-compatibility-package
\r
29 * and then modified by Manfred Moser <manfred@simpligility.com> to get it to work with the v4 r4 compatibility
\r
30 * library. With inspirations from the library source.
\r
32 * All ASLv2 licensed.
\r
34 public class ExpandableListFragment extends SherlockFragment
\r
35 implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener,
\r
36 ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener
\r
39 static final int INTERNAL_EMPTY_ID = 0x00ff0001;
\r
41 final private Handler mHandler = new Handler();
\r
43 final private Runnable mRequestFocus = new Runnable() {
\r
45 mList.focusableViewAvailable(mList);
\r
49 final private AdapterView.OnItemClickListener mOnClickListener = new AdapterView.OnItemClickListener() {
\r
50 public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
\r
51 onListItemClick((ListView) parent, v, position, id);
\r
55 ExpandableListAdapter mAdapter;
\r
56 ExpandableListView mList;
\r
58 TextView mStandardEmptyView;
\r
59 View mListContainer;
\r
60 boolean mSetEmptyText;
\r
62 boolean mFinishedStart = false;
\r
64 public ExpandableListFragment() {
\r
68 * Provide default implementation to return a simple list view. Subclasses
\r
69 * can override to replace with their own layout. If doing so, the
\r
70 * returned view hierarchy <em>must</em> have a ListView whose id
\r
71 * is {@link android.R.id#list android.R.id.list} and can optionally
\r
72 * have a sibling view id {@link android.R.id#empty android.R.id.empty}
\r
73 * that is to be shown when the list is empty.
\r
75 * <p>If you are overriding this method with your own custom content,
\r
76 * consider including the standard layout {@link android.R.layout#list_content}
\r
77 * in your layout file, so that you continue to retain all of the standard
\r
78 * behavior of ListFragment. In particular, this is currently the only
\r
79 * way to have the built-in indeterminant progress state be shown.
\r
82 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
\r
83 FrameLayout root = new FrameLayout(getActivity());
\r
85 TextView tv = new TextView(getActivity());
\r
86 tv.setId(INTERNAL_EMPTY_ID);
\r
87 tv.setGravity(Gravity.CENTER);
\r
89 new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
91 ExpandableListView lv = new ExpandableListView(getActivity());
\r
92 lv.setId(android.R.id.list);
\r
93 lv.setDrawSelectorOnTop(false);
\r
94 lv.setOnChildClickListener(this);
\r
95 lv.setOnGroupExpandListener(this);
\r
96 lv.setOnGroupCollapseListener(this);
\r
98 root.addView(lv, new FrameLayout.LayoutParams(
\r
99 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
101 ListView.LayoutParams lp =
\r
102 new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
\r
103 root.setLayoutParams(lp);
\r
109 * Attach to list view once the view hierarchy has been created.
\r
112 public void onViewCreated(View view, Bundle savedInstanceState) {
\r
113 super.onViewCreated(view, savedInstanceState);
\r
117 /** Detach from list view. */
\r
119 public void onDestroyView() {
\r
120 mHandler.removeCallbacks(mRequestFocus);
\r
122 super.onDestroyView();
\r
126 * This method will be called when an item in the list is selected.
\r
127 * Subclasses should override. Subclasses can call
\r
128 * getListView().getItemAtPosition(position) if they need to access the
\r
129 * data associated with the selected item.
\r
130 * @param l The ListView where the click happened
\r
131 * @param v The view that was clicked within the ListView
\r
132 * @param position The position of the view in the list
\r
133 * @param id The row id of the item that was clicked
\r
135 public void onListItemClick(ListView l, View v, int position, long id) {
\r
138 /** Provide the cursor for the list view. */
\r
139 public void setListAdapter(ExpandableListAdapter adapter) {
\r
140 boolean hadAdapter = mAdapter != null;
\r
141 mAdapter = adapter;
\r
142 if (mList != null) {
\r
143 mList.setAdapter((ExpandableListAdapter) null);
\r
144 mList.setAdapter(adapter);
\r
145 if (!mListShown && !hadAdapter) {
\r
146 // The list was hidden, and previously didn't have an
\r
147 // adapter. It is now time to show it.
\r
148 setListShown(true, getView().getWindowToken() != null);
\r
154 * Set the currently selected list item to the specified
\r
155 * position with the adapter's data
\r
157 public void setSelection(int position) {
\r
159 mList.setSelection(position);
\r
162 public long getSelectedPosition() {
\r
164 return mList.getSelectedPosition();
\r
167 public long getSelectedId() {
\r
169 return mList.getSelectedId();
\r
172 public ExpandableListView getExpandableListView() {
\r
178 * The default content for a ListFragment has a TextView that can
\r
179 * be shown when the list is empty. If you would like to have it
\r
180 * shown, call this method to supply the text it should use.
\r
182 public void setEmptyText(CharSequence text) {
\r
184 if (mStandardEmptyView == null) {
\r
185 throw new IllegalStateException("Can't be used with a custom content view");
\r
187 mStandardEmptyView.setText(text);
\r
188 if (!mSetEmptyText) {
\r
189 mList.setEmptyView(mStandardEmptyView);
\r
190 mSetEmptyText = true;
\r
195 * Control whether the list is being displayed. You can make it not
\r
196 * displayed if you are waiting for the initial data to show in it. During
\r
197 * this time an indeterminant progress indicator will be shown instead.
\r
199 * <p>Applications do not normally need to use this themselves. The default
\r
200 * behavior of ListFragment is to start with the list not being shown, only
\r
201 * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
\r
202 * If the list at that point had not been shown, when it does get shown
\r
203 * it will be do without the user ever seeing the hidden state.
\r
204 * @param shown If true, the list view is shown; if false, the progress
\r
205 * indicator. The initial value is true.
\r
207 public void setListShown(boolean shown) {
\r
208 setListShown(shown, true);
\r
212 * Like {@link #setListShown(boolean)}, but no animation is used when
\r
213 * transitioning from the previous state.
\r
215 public void setListShownNoAnimation(boolean shown) {
\r
216 setListShown(shown, false);
\r
220 * Control whether the list is being displayed. You can make it not
\r
221 * displayed if you are waiting for the initial data to show in it. During
\r
222 * this time an indeterminant progress indicator will be shown instead.
\r
223 * @param shown If true, the list view is shown; if false, the progress
\r
224 * indicator. The initial value is true.
\r
225 * @param animate If true, an animation will be used to transition to the
\r
228 private void setListShown(boolean shown, boolean animate) {
\r
230 if (mListShown == shown) {
\r
233 mListShown = shown;
\r
234 if (mListContainer != null) {
\r
237 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
\r
239 mListContainer.setVisibility(View.VISIBLE);
\r
242 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out));
\r
244 mListContainer.setVisibility(View.GONE);
\r
249 /** Get the ListAdapter associated with this activity's ListView. */
\r
250 public ExpandableListAdapter getExpandableListAdapter() {
\r
254 private void ensureList() {
\r
255 if (mList != null) {
\r
258 View root = getView();
\r
259 if (root == null) {
\r
260 throw new IllegalStateException("Content view not yet created");
\r
262 if (root instanceof ExpandableListView) {
\r
263 mList = (ExpandableListView) root;
\r
265 mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID);
\r
266 if (mStandardEmptyView == null) {
\r
267 mEmptyView = root.findViewById(android.R.id.empty);
\r
269 mListContainer = root.findViewById(android.R.id.list);
\r
270 View rawListView = root.findViewById(android.R.id.list);
\r
271 if (!(rawListView instanceof ExpandableListView)) {
\r
272 if (rawListView == null) {
\r
273 throw new RuntimeException("Your content must have a ExpandableListView whose id attribute is " +
\r
274 "'android.R.id.list'");
\r
276 throw new RuntimeException("Content has view with id attribute 'android.R.id.list' " +
\r
277 "that is not a ExpandableListView class");
\r
279 mList = (ExpandableListView) rawListView;
\r
280 if (mEmptyView != null) {
\r
281 mList.setEmptyView(mEmptyView);
\r
285 mList.setOnItemClickListener(mOnClickListener);
\r
286 if (mAdapter != null) {
\r
287 setListAdapter(mAdapter);
\r
289 // We are starting without an adapter, so assume we won't
\r
290 // have our data right away and start with the progress indicator.
\r
291 setListShown(false, false);
\r
293 mHandler.post(mRequestFocus);
\r
297 public void onGroupExpand(int arg0) {
\r
298 // TODO Auto-generated method stub
\r
303 public void onGroupCollapse(int arg0) {
\r
304 // TODO Auto-generated method stub
\r
309 public boolean onChildClick(ExpandableListView arg0, View arg1, int arg2, int arg3, long arg4) {
\r
310 // TODO Auto-generated method stub
\r
315 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
\r
318 public void onContentChanged() {
\r
319 View emptyView = getView().findViewById(android.R.id.empty);
\r
320 mList = (ExpandableListView) getView().findViewById(android.R.id.list);
\r
321 if (mList == null) {
\r
322 throw new RuntimeException(
\r
323 "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'");
\r
325 if (emptyView != null) {
\r
326 mList.setEmptyView(emptyView);
\r
328 mList.setOnChildClickListener(this);
\r
329 mList.setOnGroupExpandListener(this);
\r
330 mList.setOnGroupCollapseListener(this);
\r
332 if (mFinishedStart) {
\r
333 setListAdapter(mAdapter);
\r
335 mFinishedStart = true;
\r