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 final private AdapterView.OnItemLongClickListener mOnLongClickListener = new AdapterView.OnItemLongClickListener() {
\r
57 public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
\r
58 return onListItemLongClick( (ListView) parent, view, position, id);
\r
63 ExpandableListAdapter mAdapter;
\r
64 ExpandableListView mList;
\r
66 TextView mStandardEmptyView;
\r
67 View mListContainer;
\r
68 boolean mSetEmptyText;
\r
70 boolean mFinishedStart = false;
\r
72 public ExpandableListFragment() {
\r
76 * Provide default implementation to return a simple list view. Subclasses
\r
77 * can override to replace with their own layout. If doing so, the
\r
78 * returned view hierarchy <em>must</em> have a ListView whose id
\r
79 * is {@link android.R.id#list android.R.id.list} and can optionally
\r
80 * have a sibling view id {@link android.R.id#empty android.R.id.empty}
\r
81 * that is to be shown when the list is empty.
\r
83 * <p>If you are overriding this method with your own custom content,
\r
84 * consider including the standard layout {@link android.R.layout#list_content}
\r
85 * in your layout file, so that you continue to retain all of the standard
\r
86 * behavior of ListFragment. In particular, this is currently the only
\r
87 * way to have the built-in indeterminant progress state be shown.
\r
90 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
\r
91 FrameLayout root = new FrameLayout(getActivity());
\r
93 TextView tv = new TextView(getActivity());
\r
94 tv.setId(INTERNAL_EMPTY_ID);
\r
95 tv.setGravity(Gravity.CENTER);
\r
97 new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
99 ExpandableListView lv = new ExpandableListView(getActivity());
\r
100 lv.setId(android.R.id.list);
\r
101 lv.setDrawSelectorOnTop(false);
\r
102 lv.setOnChildClickListener(this);
\r
103 lv.setOnGroupExpandListener(this);
\r
104 lv.setOnGroupCollapseListener(this);
\r
106 root.addView(lv, new FrameLayout.LayoutParams(
\r
107 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
109 ListView.LayoutParams lp =
\r
110 new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
\r
111 root.setLayoutParams(lp);
\r
117 * Attach to list view once the view hierarchy has been created.
\r
120 public void onViewCreated(View view, Bundle savedInstanceState) {
\r
121 super.onViewCreated(view, savedInstanceState);
\r
125 /** Detach from list view. */
\r
127 public void onDestroyView() {
\r
128 mHandler.removeCallbacks(mRequestFocus);
\r
130 super.onDestroyView();
\r
134 * This method will be called when an item in the list is selected.
\r
135 * Subclasses should override. Subclasses can call
\r
136 * getListView().getItemAtPosition(position) if they need to access the
\r
137 * data associated with the selected item.
\r
138 * @param l The ListView where the click happened
\r
139 * @param v The view that was clicked within the ListView
\r
140 * @param position The position of the view in the list
\r
141 * @param id The row id of the item that was clicked
\r
143 public void onListItemClick(ListView l, View v, int position, long id) {
\r
146 public boolean onListItemLongClick(ListView l, View v, int position, long id ) {
\r
150 /** Provide the cursor for the list view. */
\r
151 public void setListAdapter(ExpandableListAdapter adapter) {
\r
152 boolean hadAdapter = mAdapter != null;
\r
153 mAdapter = adapter;
\r
154 if (mList != null) {
\r
155 mList.setAdapter((ExpandableListAdapter) null);
\r
156 mList.setAdapter(adapter);
\r
157 if (!mListShown && !hadAdapter) {
\r
158 // The list was hidden, and previously didn't have an
\r
159 // adapter. It is now time to show it.
\r
160 setListShown(true, getView().getWindowToken() != null);
\r
166 * Set the currently selected list item to the specified
\r
167 * position with the adapter's data
\r
169 public void setSelection(int position) {
\r
171 mList.setSelection(position);
\r
174 public long getSelectedPosition() {
\r
176 return mList.getSelectedPosition();
\r
179 public long getSelectedId() {
\r
181 return mList.getSelectedId();
\r
184 public ExpandableListView getExpandableListView() {
\r
190 * The default content for a ListFragment has a TextView that can
\r
191 * be shown when the list is empty. If you would like to have it
\r
192 * shown, call this method to supply the text it should use.
\r
194 public void setEmptyText(CharSequence text) {
\r
196 if (mStandardEmptyView == null) {
\r
197 throw new IllegalStateException("Can't be used with a custom content view");
\r
199 mStandardEmptyView.setText(text);
\r
200 if (!mSetEmptyText) {
\r
201 mList.setEmptyView(mStandardEmptyView);
\r
202 mSetEmptyText = true;
\r
207 * Control whether the list is being displayed. You can make it not
\r
208 * displayed if you are waiting for the initial data to show in it. During
\r
209 * this time an indeterminant progress indicator will be shown instead.
\r
211 * <p>Applications do not normally need to use this themselves. The default
\r
212 * behavior of ListFragment is to start with the list not being shown, only
\r
213 * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
\r
214 * If the list at that point had not been shown, when it does get shown
\r
215 * it will be do without the user ever seeing the hidden state.
\r
216 * @param shown If true, the list view is shown; if false, the progress
\r
217 * indicator. The initial value is true.
\r
219 public void setListShown(boolean shown) {
\r
220 setListShown(shown, true);
\r
224 * Like {@link #setListShown(boolean)}, but no animation is used when
\r
225 * transitioning from the previous state.
\r
227 public void setListShownNoAnimation(boolean shown) {
\r
228 setListShown(shown, false);
\r
232 * Control whether the list is being displayed. You can make it not
\r
233 * displayed if you are waiting for the initial data to show in it. During
\r
234 * this time an indeterminant progress indicator will be shown instead.
\r
235 * @param shown If true, the list view is shown; if false, the progress
\r
236 * indicator. The initial value is true.
\r
237 * @param animate If true, an animation will be used to transition to the
\r
240 private void setListShown(boolean shown, boolean animate) {
\r
242 if (mListShown == shown) {
\r
245 mListShown = shown;
\r
246 if (mListContainer != null) {
\r
249 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
\r
251 mListContainer.setVisibility(View.VISIBLE);
\r
254 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out));
\r
256 mListContainer.setVisibility(View.GONE);
\r
261 /** Get the ListAdapter associated with this activity's ListView. */
\r
262 public ExpandableListAdapter getExpandableListAdapter() {
\r
266 private void ensureList() {
\r
267 if (mList != null) {
\r
270 View root = getView();
\r
271 if (root == null) {
\r
272 throw new IllegalStateException("Content view not yet created");
\r
274 if (root instanceof ExpandableListView) {
\r
275 mList = (ExpandableListView) root;
\r
277 mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID);
\r
278 if (mStandardEmptyView == null) {
\r
279 mEmptyView = root.findViewById(android.R.id.empty);
\r
281 mListContainer = root.findViewById(android.R.id.list);
\r
282 View rawListView = root.findViewById(android.R.id.list);
\r
283 if (!(rawListView instanceof ExpandableListView)) {
\r
284 if (rawListView == null) {
\r
285 throw new RuntimeException("Your content must have a ExpandableListView whose id attribute is " +
\r
286 "'android.R.id.list'");
\r
288 throw new RuntimeException("Content has view with id attribute 'android.R.id.list' " +
\r
289 "that is not a ExpandableListView class");
\r
291 mList = (ExpandableListView) rawListView;
\r
292 if (mEmptyView != null) {
\r
293 mList.setEmptyView(mEmptyView);
\r
297 mList.setOnItemClickListener(mOnClickListener);
\r
298 mList.setOnItemLongClickListener(mOnLongClickListener);
\r
299 if (mAdapter != null) {
\r
300 setListAdapter(mAdapter);
\r
302 // We are starting without an adapter, so assume we won't
\r
303 // have our data right away and start with the progress indicator.
\r
304 setListShown(false, false);
\r
306 mHandler.post(mRequestFocus);
\r
310 public void onGroupExpand(int arg0) {
\r
311 // TODO Auto-generated method stub
\r
316 public void onGroupCollapse(int arg0) {
\r
317 // TODO Auto-generated method stub
\r
322 public boolean onChildClick(ExpandableListView arg0, View arg1, int arg2, int arg3, long arg4) {
\r
323 // TODO Auto-generated method stub
\r
328 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
\r
331 public void onContentChanged() {
\r
332 View emptyView = getView().findViewById(android.R.id.empty);
\r
333 mList = (ExpandableListView) getView().findViewById(android.R.id.list);
\r
334 if (mList == null) {
\r
335 throw new RuntimeException(
\r
336 "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'");
\r
338 if (emptyView != null) {
\r
339 mList.setEmptyView(emptyView);
\r
341 mList.setOnChildClickListener(this);
\r
342 mList.setOnGroupExpandListener(this);
\r
343 mList.setOnGroupCollapseListener(this);
\r
345 if (mFinishedStart) {
\r
346 setListAdapter(mAdapter);
\r
348 mFinishedStart = true;
\r