1cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/*
2cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Copyright (C) 2011 The Android Open Source Project
3cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
4cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Licensed under the Apache License, Version 2.0 (the "License");
5cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * you may not use this file except in compliance with the License.
6cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * You may obtain a copy of the License at
7cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
8cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *      http://www.apache.org/licenses/LICENSE-2.0
9cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn *
10cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Unless required by applicable law or agreed to in writing, software
11cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * distributed under the License is distributed on an "AS IS" BASIS,
12cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * See the License for the specific language governing permissions and
14cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * limitations under the License.
15cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
16cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
17cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpackage android.support.v4.app;
18cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
19f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackbornimport android.content.Context;
20cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.os.Bundle;
21cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.os.Handler;
22cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.view.Gravity;
23cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.view.LayoutInflater;
24cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.view.View;
25cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.view.ViewGroup;
26cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.view.animation.AnimationUtils;
27cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.widget.AdapterView;
28cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.widget.FrameLayout;
29f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackbornimport android.widget.LinearLayout;
30cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.widget.ListAdapter;
31cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.widget.ListView;
32f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackbornimport android.widget.ProgressBar;
33cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornimport android.widget.TextView;
34cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
35cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn/**
36cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Static library support version of the framework's {@link android.app.ListFragment}.
37cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * Used to write apps that run on platforms prior to Android 3.0.  When running
38cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * on Android 3.0 or above, this implementation is still used; it does not try
39cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * to switch to the framework's implementation.  See the framework SDK
40cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn * documentation for a class overview.
41cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn */
42cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackbornpublic class ListFragment extends Fragment {
43cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    static final int INTERNAL_EMPTY_ID = 0x00ff0001;
44f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn    static final int INTERNAL_PROGRESS_CONTAINER_ID = 0x00ff0002;
45f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn    static final int INTERNAL_LIST_CONTAINER_ID = 0x00ff0003;
46cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
47cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final private Handler mHandler = new Handler();
48cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
49cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final private Runnable mRequestFocus = new Runnable() {
5090ac236504c1a4cac7e91f1ffc523334f2a8f399Aurimas Liutikas        @Override
51cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void run() {
52cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mList.focusableViewAvailable(mList);
53cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
54cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    };
55cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
56cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    final private AdapterView.OnItemClickListener mOnClickListener
57cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            = new AdapterView.OnItemClickListener() {
5890ac236504c1a4cac7e91f1ffc523334f2a8f399Aurimas Liutikas        @Override
59cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
60cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            onListItemClick((ListView)parent, v, position, id);
61cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
62cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    };
63cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
64cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    ListAdapter mAdapter;
65cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    ListView mList;
66cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    View mEmptyView;
67cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    TextView mStandardEmptyView;
68cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    View mProgressContainer;
69cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    View mListContainer;
709c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn    CharSequence mEmptyText;
71cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    boolean mListShown;
72cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
73cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public ListFragment() {
74cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
75cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
76cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
77cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Provide default implementation to return a simple list view.  Subclasses
78cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * can override to replace with their own layout.  If doing so, the
79cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * returned view hierarchy <em>must</em> have a ListView whose id
80cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * is {@link android.R.id#list android.R.id.list} and can optionally
81cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * have a sibling view id {@link android.R.id#empty android.R.id.empty}
82cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * that is to be shown when the list is empty.
83cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
84cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>If you are overriding this method with your own custom content,
85cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * consider including the standard layout {@link android.R.layout#list_content}
86cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * in your layout file, so that you continue to retain all of the standard
87cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * behavior of ListFragment.  In particular, this is currently the only
88cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * way to have the built-in indeterminant progress state be shown.
89cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
90cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
91cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public View onCreateView(LayoutInflater inflater, ViewGroup container,
92cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            Bundle savedInstanceState) {
9305c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell        final Context context = getContext();
94f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
95f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        FrameLayout root = new FrameLayout(context);
96f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
97f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        // ------------------------------------------------------------------
98f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
99f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        LinearLayout pframe = new LinearLayout(context);
100f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        pframe.setId(INTERNAL_PROGRESS_CONTAINER_ID);
101f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        pframe.setOrientation(LinearLayout.VERTICAL);
102f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        pframe.setVisibility(View.GONE);
103f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        pframe.setGravity(Gravity.CENTER);
104f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
105f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        ProgressBar progress = new ProgressBar(context, null,
106f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn                android.R.attr.progressBarStyleLarge);
107f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        pframe.addView(progress, new FrameLayout.LayoutParams(
108f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn                ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
109f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
110f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        root.addView(pframe, new FrameLayout.LayoutParams(
111e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
112f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
113f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        // ------------------------------------------------------------------
114f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
115f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        FrameLayout lframe = new FrameLayout(context);
116f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        lframe.setId(INTERNAL_LIST_CONTAINER_ID);
117e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas
11805c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell        TextView tv = new TextView(context);
119cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        tv.setId(INTERNAL_EMPTY_ID);
120cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        tv.setGravity(Gravity.CENTER);
121f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        lframe.addView(tv, new FrameLayout.LayoutParams(
122e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
123e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas
12405c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell        ListView lv = new ListView(context);
125cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        lv.setId(android.R.id.list);
126cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        lv.setDrawSelectorOnTop(false);
127f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        lframe.addView(lv, new FrameLayout.LayoutParams(
128e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
129f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
130f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        root.addView(lframe, new FrameLayout.LayoutParams(
131e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
132e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas
133f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        // ------------------------------------------------------------------
134f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn
135f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn        root.setLayoutParams(new FrameLayout.LayoutParams(
136e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas                ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
137e12dfa03641ad9cf0ddf272675bbe7d1198adbfdAurimas Liutikas
138cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return root;
139cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
140cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
141cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
142e4417c91a0bb2fba42a0aaa99edcca1b238af21aDianne Hackborn     * Attach to list view once the view hierarchy has been created.
143cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
144cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
145e4417c91a0bb2fba42a0aaa99edcca1b238af21aDianne Hackborn    public void onViewCreated(View view, Bundle savedInstanceState) {
146e4417c91a0bb2fba42a0aaa99edcca1b238af21aDianne Hackborn        super.onViewCreated(view, savedInstanceState);
147cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
148cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
149cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
150cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
151cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Detach from list view.
152cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
153cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    @Override
154cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void onDestroyView() {
155cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mHandler.removeCallbacks(mRequestFocus);
156cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mList = null;
1579c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        mListShown = false;
1589c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        mEmptyView = mProgressContainer = mListContainer = null;
1599c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        mStandardEmptyView = null;
160cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        super.onDestroyView();
161cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
162cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
163cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
164cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * This method will be called when an item in the list is selected.
165cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Subclasses should override. Subclasses can call
166cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * getListView().getItemAtPosition(position) if they need to access the
167cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * data associated with the selected item.
168cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
169cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param l The ListView where the click happened
170cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param v The view that was clicked within the ListView
171cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param position The position of the view in the list
172cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param id The row id of the item that was clicked
173cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
174cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void onListItemClick(ListView l, View v, int position, long id) {
175cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
176cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
177cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
178cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Provide the cursor for the list view.
179cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
180cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setListAdapter(ListAdapter adapter) {
181cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        boolean hadAdapter = mAdapter != null;
182cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mAdapter = adapter;
183cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mList != null) {
184cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mList.setAdapter(adapter);
185cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (!mListShown && !hadAdapter) {
186cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // The list was hidden, and previously didn't have an
187cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                // adapter.  It is now time to show it.
188cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                setListShown(true, getView().getWindowToken() != null);
189cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
190cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
191cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
192cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
193cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
194cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Set the currently selected list item to the specified
195cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * position with the adapter's data
196cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
197cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param position
198cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
199cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setSelection(int position) {
200cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
201cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mList.setSelection(position);
202cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
203cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
204cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
205cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Get the position of the currently selected list item.
206cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
207cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public int getSelectedItemPosition() {
208cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
209cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mList.getSelectedItemPosition();
210cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
211cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
212cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
213cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Get the cursor row ID of the currently selected list item.
214cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
215cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public long getSelectedItemId() {
216cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
217cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mList.getSelectedItemId();
218cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
219cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
220cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
22105c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell     * Get the fragment's list view widget.
222cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
223cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public ListView getListView() {
224cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
225cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mList;
226cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
227cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
228cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
229cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * The default content for a ListFragment has a TextView that can
230cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * be shown when the list is empty.  If you would like to have it
231cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * shown, call this method to supply the text it should use.
232cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
233cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setEmptyText(CharSequence text) {
234cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
235cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mStandardEmptyView == null) {
236cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Can't be used with a custom content view");
237cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
238cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mStandardEmptyView.setText(text);
2399c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        if (mEmptyText == null) {
240cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mList.setEmptyView(mStandardEmptyView);
241cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
2429c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn        mEmptyText = text;
243cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
244cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
245cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
246cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Control whether the list is being displayed.  You can make it not
247cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * displayed if you are waiting for the initial data to show in it.  During
248cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * this time an indeterminant progress indicator will be shown instead.
249cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
250cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * <p>Applications do not normally need to use this themselves.  The default
251cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * behavior of ListFragment is to start with the list not being shown, only
252cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * showing it once an adapter is given with {@link #setListAdapter(ListAdapter)}.
253cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * If the list at that point had not been shown, when it does get shown
254cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * it will be do without the user ever seeing the hidden state.
255cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
256cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param shown If true, the list view is shown; if false, the progress
257cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * indicator.  The initial value is true.
258cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
259cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setListShown(boolean shown) {
260cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        setListShown(shown, true);
261cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
262cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
263cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
264cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Like {@link #setListShown(boolean)}, but no animation is used when
265cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * transitioning from the previous state.
266cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
267cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public void setListShownNoAnimation(boolean shown) {
268cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        setListShown(shown, false);
269cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
270cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
271cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
272cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * Control whether the list is being displayed.  You can make it not
273cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * displayed if you are waiting for the initial data to show in it.  During
274cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * this time an indeterminant progress indicator will be shown instead.
275cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     *
276cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param shown If true, the list view is shown; if false, the progress
277cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * indicator.  The initial value is true.
278cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * @param animate If true, an animation will be used to transition to the
279cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     * new state.
280cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
281cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private void setListShown(boolean shown, boolean animate) {
282cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        ensureList();
283cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mProgressContainer == null) {
284cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Can't be used with a custom content view");
285cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
286cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mListShown == shown) {
287cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
288cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
289cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mListShown = shown;
290cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (shown) {
291cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (animate) {
292cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
29305c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell                        getContext(), android.R.anim.fade_out));
294cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mListContainer.startAnimation(AnimationUtils.loadAnimation(
29505c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell                        getContext(), android.R.anim.fade_in));
2969c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            } else {
2979c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mProgressContainer.clearAnimation();
2989c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mListContainer.clearAnimation();
299cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
300cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mProgressContainer.setVisibility(View.GONE);
301cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mListContainer.setVisibility(View.VISIBLE);
302cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
303cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (animate) {
304cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mProgressContainer.startAnimation(AnimationUtils.loadAnimation(
30505c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell                        getContext(), android.R.anim.fade_in));
306cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mListContainer.startAnimation(AnimationUtils.loadAnimation(
30705c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell                        getContext(), android.R.anim.fade_out));
3089c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            } else {
3099c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mProgressContainer.clearAnimation();
3109c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mListContainer.clearAnimation();
311cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
312cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mProgressContainer.setVisibility(View.VISIBLE);
313cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mListContainer.setVisibility(View.GONE);
314cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
315cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
316cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
317cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    /**
31805c8a189672f5d883555e068549c0a84eeeff4aaAdam Powell     * Get the ListAdapter associated with this fragment's ListView.
319cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn     */
320cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    public ListAdapter getListAdapter() {
321cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        return mAdapter;
322cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
323cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn
324cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    private void ensureList() {
325cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mList != null) {
326cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            return;
327cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
328cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        View root = getView();
329cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (root == null) {
330cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            throw new IllegalStateException("Content view not yet created");
331cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
332cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (root instanceof ListView) {
333cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mList = (ListView)root;
334cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
335cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mStandardEmptyView = (TextView)root.findViewById(INTERNAL_EMPTY_ID);
336cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mStandardEmptyView == null) {
337cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mEmptyView = root.findViewById(android.R.id.empty);
3389c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            } else {
3399c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mStandardEmptyView.setVisibility(View.GONE);
340cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
341f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn            mProgressContainer = root.findViewById(INTERNAL_PROGRESS_CONTAINER_ID);
342f81fd8c39e5ca44a4adb2fb45f9b382305842d87Dianne Hackborn            mListContainer = root.findViewById(INTERNAL_LIST_CONTAINER_ID);
343cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            View rawListView = root.findViewById(android.R.id.list);
344cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (!(rawListView instanceof ListView)) {
345cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                if (rawListView == null) {
346cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                    throw new RuntimeException(
347cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            "Your content must have a ListView whose id attribute is " +
348cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                            "'android.R.id.list'");
349cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                }
350cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                throw new RuntimeException(
351cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        "Content has view with id attribute 'android.R.id.list' "
352cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                        + "that is not a ListView class");
353cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
354cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            mList = (ListView)rawListView;
355cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mEmptyView != null) {
356cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                mList.setEmptyView(mEmptyView);
3579c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            } else if (mEmptyText != null) {
3589c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mStandardEmptyView.setText(mEmptyText);
3599c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn                mList.setEmptyView(mStandardEmptyView);
360cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
361cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
362cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mListShown = true;
363cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mList.setOnItemClickListener(mOnClickListener);
364cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        if (mAdapter != null) {
3659c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            ListAdapter adapter = mAdapter;
3669c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            mAdapter = null;
3679c53b844bd525e6a04e17291efc38713893074cdDianne Hackborn            setListAdapter(adapter);
368cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        } else {
369cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // We are starting without an adapter, so assume we won't
370cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            // have our data right away and start with the progress indicator.
371cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            if (mProgressContainer != null) {
372cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn                setListShown(false, false);
373cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn            }
374cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        }
375cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn        mHandler.post(mRequestFocus);
376cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn    }
377cba2e2c881e8e16ea5025b564c94320174d65f01Dianne Hackborn}
378