1 package net.sf.openrocket.android.util;
\r
3 import android.os.Bundle;
\r
4 import android.os.Handler;
\r
5 import android.support.v4.app.Fragment;
\r
6 import android.view.ContextMenu;
\r
7 import android.view.ContextMenu.ContextMenuInfo;
\r
8 import android.view.Gravity;
\r
9 import android.view.LayoutInflater;
\r
10 import android.view.View;
\r
11 import android.view.View.OnCreateContextMenuListener;
\r
12 import android.view.ViewGroup;
\r
13 import android.view.animation.AnimationUtils;
\r
14 import android.widget.AdapterView;
\r
15 import android.widget.ExpandableListAdapter;
\r
16 import android.widget.ExpandableListView;
\r
17 import android.widget.FrameLayout;
\r
18 import android.widget.ListAdapter;
\r
19 import android.widget.ListView;
\r
20 import android.widget.TextView;
\r
24 * Pulled from https://gist.github.com/1316903
\r
26 * This class has originally been taken from
\r
27 * http://stackoverflow.com/questions/6051050/expandablelistfragment-with-loadermanager-for-compatibility-package
\r
28 * and then modified by Manfred Moser <manfred@simpligility.com> to get it to work with the v4 r4 compatibility
\r
29 * library. With inspirations from the library source.
\r
31 * All ASLv2 licensed.
\r
33 public class ExpandableListFragment extends Fragment
\r
34 implements OnCreateContextMenuListener, ExpandableListView.OnChildClickListener,
\r
35 ExpandableListView.OnGroupCollapseListener, ExpandableListView.OnGroupExpandListener
\r
38 static final int INTERNAL_EMPTY_ID = 0x00ff0001;
\r
39 static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003;
\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 FrameLayout lframe = new FrameLayout(getActivity());
\r
86 lframe.setId(INTERNAL_LIST_CONTAINER_ID);
\r
88 TextView tv = new TextView(getActivity());
\r
89 tv.setId(INTERNAL_EMPTY_ID);
\r
90 tv.setGravity(Gravity.CENTER);
\r
92 new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
94 ExpandableListView lv = new ExpandableListView(getActivity());
\r
95 lv.setId(android.R.id.list);
\r
96 lv.setDrawSelectorOnTop(false);
\r
97 lv.setOnChildClickListener(this);
\r
98 lv.setOnGroupExpandListener(this);
\r
99 lv.setOnGroupCollapseListener(this);
\r
102 new FrameLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
104 root.addView(lframe, new FrameLayout.LayoutParams(
\r
105 ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
\r
107 ListView.LayoutParams lp =
\r
108 new ListView.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT);
\r
109 root.setLayoutParams(lp);
\r
115 * Attach to list view once the view hierarchy has been created.
\r
118 public void onViewCreated(View view, Bundle savedInstanceState) {
\r
119 super.onViewCreated(view, savedInstanceState);
\r
123 /** Detach from list view. */
\r
125 public void onDestroyView() {
\r
126 mHandler.removeCallbacks(mRequestFocus);
\r
128 super.onDestroyView();
\r
132 * This method will be called when an item in the list is selected.
\r
133 * Subclasses should override. Subclasses can call
\r
134 * getListView().getItemAtPosition(position) if they need to access the
\r
135 * data associated with the selected item.
\r
136 * @param l The ListView where the click happened
\r
137 * @param v The view that was clicked within the ListView
\r
138 * @param position The position of the view in the list
\r
139 * @param id The row id of the item that was clicked
\r
141 public void onListItemClick(ListView l, View v, int position, long id) {
\r
144 /** Provide the cursor for the list view. */
\r
145 public void setListAdapter(ExpandableListAdapter adapter) {
\r
146 boolean hadAdapter = mAdapter != null;
\r
147 mAdapter = adapter;
\r
148 if (mList != null) {
\r
149 mList.setAdapter((ExpandableListAdapter) null);
\r
150 mList.setAdapter(adapter);
\r
151 if (!mListShown && !hadAdapter) {
\r
152 // The list was hidden, and previously didn't have an
\r
153 // adapter. It is now time to show it.
\r
154 setListShown(true, getView().getWindowToken() != null);
\r
160 * Set the currently selected list item to the specified
\r
161 * position with the adapter's data
\r
163 public void setSelection(int position) {
\r
165 mList.setSelection(position);
\r
168 public long getSelectedPosition() {
\r
170 return mList.getSelectedPosition();
\r
173 public long getSelectedId() {
\r
175 return mList.getSelectedId();
\r
178 public ExpandableListView getExpandableListView() {
\r
184 * The default content for a ListFragment has a TextView that can
\r
185 * be shown when the list is empty. If you would like to have it
\r
186 * shown, call this method to supply the text it should use.
\r
188 public void setEmptyText(CharSequence text) {
\r
190 if (mStandardEmptyView == null) {
\r
191 throw new IllegalStateException("Can't be used with a custom content view");
\r
193 mStandardEmptyView.setText(text);
\r
194 if (!mSetEmptyText) {
\r
195 mList.setEmptyView(mStandardEmptyView);
\r
196 mSetEmptyText = true;
\r
201 * Control whether the list is being displayed. You can make it not
\r
202 * displayed if you are waiting for the initial data to show in it. During
\r
203 * this time an indeterminant progress indicator will be shown instead.
\r
205 * <p>Applications do not normally need to use this themselves. The default
\r
206 * behavior of ListFragment is to start with the list not being shown, only
\r
207 * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
\r
208 * If the list at that point had not been shown, when it does get shown
\r
209 * it will be do without the user ever seeing the hidden state.
\r
210 * @param shown If true, the list view is shown; if false, the progress
\r
211 * indicator. The initial value is true.
\r
213 public void setListShown(boolean shown) {
\r
214 setListShown(shown, true);
\r
218 * Like {@link #setListShown(boolean)}, but no animation is used when
\r
219 * transitioning from the previous state.
\r
221 public void setListShownNoAnimation(boolean shown) {
\r
222 setListShown(shown, false);
\r
226 * Control whether the list is being displayed. You can make it not
\r
227 * displayed if you are waiting for the initial data to show in it. During
\r
228 * this time an indeterminant progress indicator will be shown instead.
\r
229 * @param shown If true, the list view is shown; if false, the progress
\r
230 * indicator. The initial value is true.
\r
231 * @param animate If true, an animation will be used to transition to the
\r
234 private void setListShown(boolean shown, boolean animate) {
\r
236 if (mListShown == shown) {
\r
239 mListShown = shown;
\r
240 if (mListContainer != null) {
\r
243 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_in));
\r
245 mListContainer.setVisibility(View.VISIBLE);
\r
248 mListContainer.startAnimation(AnimationUtils.loadAnimation(getActivity(), android.R.anim.fade_out));
\r
250 mListContainer.setVisibility(View.GONE);
\r
255 /** Get the ListAdapter associated with this activity's ListView. */
\r
256 public ExpandableListAdapter getExpandableListAdapter() {
\r
260 private void ensureList() {
\r
261 if (mList != null) {
\r
264 View root = getView();
\r
265 if (root == null) {
\r
266 throw new IllegalStateException("Content view not yet created");
\r
268 if (root instanceof ExpandableListView) {
\r
269 mList = (ExpandableListView) root;
\r
271 mStandardEmptyView = (TextView) root.findViewById(INTERNAL_EMPTY_ID);
\r
272 if (mStandardEmptyView == null) {
\r
273 mEmptyView = root.findViewById(android.R.id.empty);
\r
275 mListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID);
\r
276 View rawListView = root.findViewById(android.R.id.list);
\r
277 if (!(rawListView instanceof ExpandableListView)) {
\r
278 if (rawListView == null) {
\r
279 throw new RuntimeException("Your content must have a ExpandableListView whose id attribute is " +
\r
280 "'android.R.id.list'");
\r
282 throw new RuntimeException("Content has view with id attribute 'android.R.id.list' " +
\r
283 "that is not a ExpandableListView class");
\r
285 mList = (ExpandableListView) rawListView;
\r
286 if (mEmptyView != null) {
\r
287 mList.setEmptyView(mEmptyView);
\r
291 mList.setOnItemClickListener(mOnClickListener);
\r
292 if (mAdapter != null) {
\r
293 setListAdapter(mAdapter);
\r
295 // We are starting without an adapter, so assume we won't
\r
296 // have our data right away and start with the progress indicator.
\r
297 setListShown(false, false);
\r
299 mHandler.post(mRequestFocus);
\r
303 public void onGroupExpand(int arg0) {
\r
304 // TODO Auto-generated method stub
\r
309 public void onGroupCollapse(int arg0) {
\r
310 // TODO Auto-generated method stub
\r
315 public boolean onChildClick(ExpandableListView arg0, View arg1, int arg2, int arg3, long arg4) {
\r
316 // TODO Auto-generated method stub
\r
321 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
\r
324 public void onContentChanged() {
\r
325 View emptyView = getView().findViewById(android.R.id.empty);
\r
326 mList = (ExpandableListView) getView().findViewById(android.R.id.list);
\r
327 if (mList == null) {
\r
328 throw new RuntimeException(
\r
329 "Your content must have a ExpandableListView whose id attribute is " + "'android.R.id.list'");
\r
331 if (emptyView != null) {
\r
332 mList.setEmptyView(emptyView);
\r
334 mList.setOnChildClickListener(this);
\r
335 mList.setOnGroupExpandListener(this);
\r
336 mList.setOnGroupCollapseListener(this);
\r
338 if (mFinishedStart) {
\r
339 setListAdapter(mAdapter);
\r
341 mFinishedStart = true;
\r