am 67117872: am b181a0d1: Merge "New API demos showing use of tabs with fragments." into honeycomb-mr2
* commit '67117872570ae826923c496055d153df473f7740': New API demos showing use of tabs with fragments.
This commit is contained in:
@@ -38,7 +38,10 @@
|
||||
|
||||
<uses-sdk android:minSdkVersion="7" android:targetSdkVersion="11" />
|
||||
|
||||
<!-- This app has not been optimized for large screens. -->
|
||||
<!-- The smallest screen this app works on is a phone. The app will
|
||||
scale its UI to larger screens but doesn't make good use of them
|
||||
so allow the compatibility mode button to be shown (mostly because
|
||||
this is just convenient for testing). -->
|
||||
<supports-screens android:requiresSmallestWidthDp="320"
|
||||
android:compatibleWidthLimitDp="480" />
|
||||
|
||||
@@ -361,6 +364,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.FragmentTabs"
|
||||
android:label="@string/fragment_tabs"
|
||||
android:enabled="@bool/atLeastHoneycomb">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<!-- Loader Samples -->
|
||||
|
||||
<activity android:name=".app.LoaderCursor"
|
||||
|
||||
@@ -150,6 +150,8 @@
|
||||
<string name="fragment_stack">App/Fragment/Stack</string>
|
||||
<string name="new_fragment">New fragment</string>
|
||||
|
||||
<string name="fragment_tabs">App/Fragment/Tabs</string>
|
||||
|
||||
<string name="loader_cursor">App/Loader/Cursor</string>
|
||||
|
||||
<string name="loader_custom">App/Loader/Custom</string>
|
||||
|
||||
@@ -78,6 +78,11 @@ public class ActionBarTabs extends Activity {
|
||||
* to it, it will be committed at the end of the full tab switch operation.
|
||||
* This lets tab switches be atomic without the app needing to track
|
||||
* the interactions between different tabs.
|
||||
*
|
||||
* NOTE: This is a very simple implementation that does not retain
|
||||
* fragment state of the non-visible tabs across activity instances.
|
||||
* Look at the FragmentTabs example for how to do a more complete
|
||||
* implementation.
|
||||
*/
|
||||
private class TabListener implements ActionBar.TabListener {
|
||||
private TabContentFragment mFragment;
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.apis.app;
|
||||
|
||||
import com.example.android.apis.R;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.ActionBar.Tab;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
/**
|
||||
* This demonstrates the use of action bar tabs and how they interact
|
||||
* with other action bar features.
|
||||
*/
|
||||
public class FragmentTabs extends Activity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
final ActionBar bar = getActionBar();
|
||||
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
|
||||
bar.addTab(bar.newTab()
|
||||
.setText("Simple")
|
||||
.setTabListener(new TabListener<FragmentStack.CountingFragment>(
|
||||
this, "simple", FragmentStack.CountingFragment.class)));
|
||||
bar.addTab(bar.newTab()
|
||||
.setText("Contacts")
|
||||
.setTabListener(new TabListener<LoaderCursor.CursorLoaderListFragment>(
|
||||
this, "contacts", LoaderCursor.CursorLoaderListFragment.class)));
|
||||
bar.addTab(bar.newTab()
|
||||
.setText("Apps")
|
||||
.setTabListener(new TabListener<LoaderCustom.AppListFragment>(
|
||||
this, "apps", LoaderCustom.AppListFragment.class)));
|
||||
bar.addTab(bar.newTab()
|
||||
.setText("Throttle")
|
||||
.setTabListener(new TabListener<LoaderThrottle.ThrottledLoaderListFragment>(
|
||||
this, "throttle", LoaderThrottle.ThrottledLoaderListFragment.class)));
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
|
||||
}
|
||||
|
||||
public static class TabListener<T extends Fragment> implements ActionBar.TabListener {
|
||||
private final Activity mActivity;
|
||||
private final String mTag;
|
||||
private final Class<T> mClass;
|
||||
private final Bundle mArgs;
|
||||
private Fragment mFragment;
|
||||
|
||||
public TabListener(Activity activity, String tag, Class<T> clz) {
|
||||
this(activity, tag, clz, null);
|
||||
}
|
||||
|
||||
public TabListener(Activity activity, String tag, Class<T> clz, Bundle args) {
|
||||
mActivity = activity;
|
||||
mTag = tag;
|
||||
mClass = clz;
|
||||
mArgs = args;
|
||||
|
||||
// Check to see if we already have a fragment for this tab, probably
|
||||
// from a previously saved state. If so, deactivate it, because our
|
||||
// initial state is that a tab isn't shown.
|
||||
mFragment = mActivity.getFragmentManager().findFragmentByTag(mTag);
|
||||
if (mFragment != null && !mFragment.isDetached()) {
|
||||
FragmentTransaction ft = mActivity.getFragmentManager().beginTransaction();
|
||||
ft.detach(mFragment);
|
||||
ft.commit();
|
||||
}
|
||||
}
|
||||
|
||||
public void onTabSelected(Tab tab, FragmentTransaction ft) {
|
||||
if (mFragment == null) {
|
||||
mFragment = Fragment.instantiate(mActivity, mClass.getName(), mArgs);
|
||||
ft.add(android.R.id.content, mFragment, mTag);
|
||||
} else {
|
||||
ft.attach(mFragment);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
|
||||
if (mFragment != null) {
|
||||
ft.detach(mFragment);
|
||||
}
|
||||
}
|
||||
|
||||
public void onTabReselected(Tab tab, FragmentTransaction ft) {
|
||||
Toast.makeText(mActivity, "Reselected!", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -159,7 +159,11 @@ public class LoaderCursor extends Activity {
|
||||
mAdapter.swapCursor(data);
|
||||
|
||||
// The list should now be shown.
|
||||
setListShown(true);
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -466,7 +466,11 @@ public class LoaderCustom extends Activity {
|
||||
mAdapter.setData(data);
|
||||
|
||||
// The list should now be shown.
|
||||
setListShown(true);
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onLoaderReset(Loader<List<AppEntry>> loader) {
|
||||
|
||||
@@ -409,6 +409,9 @@ public class LoaderThrottle extends Activity {
|
||||
new int[] { android.R.id.text1 }, 0);
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// Prepare the loader. Either re-connect with an existing one,
|
||||
// or start a new one.
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
@@ -492,6 +495,13 @@ public class LoaderThrottle extends Activity {
|
||||
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||
mAdapter.swapCursor(data);
|
||||
|
||||
// The list should now be shown.
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
|
||||
@@ -134,6 +134,10 @@
|
||||
<dd>Demonstrates creating a stack of Fragment instances similar to the
|
||||
traditional stack of activities.</dd>
|
||||
|
||||
<dt><a href="FragmentTabs.html">Fragment Tabs</a></dt>
|
||||
<dd>Demonstrates implementing ActionBar tabs by switching between
|
||||
Fragments.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
@@ -145,9 +149,10 @@ menu. This demo is for informative purposes only; see Usage for an example of us
|
||||
Action Bar in a more idiomatic manner.</dd>
|
||||
<dt><a href="ActionBarTabs.html">Action Bar Tabs</a></dt>
|
||||
<dd>Demonstrates the use of Action Bar tabs and how they interact with other action bar
|
||||
features.</dd>
|
||||
features. Also see the <a href="FragmentTabs.html">Fragment Tabs</a> for a more
|
||||
complete example of how to switch between fragments.</dd>
|
||||
<dt><a href="ActionBarUsage.html">Action Bar Usage</a></dt>
|
||||
<dd>Demonstrates imple usage of the Action Bar, including a SearchView as an action item. The
|
||||
<dd>Demonstrates simple usage of the Action Bar, including a SearchView as an action item. The
|
||||
default Honeycomb theme includes the Action Bar by default and a menu resource is used to populate
|
||||
the menu data itself. If you'd like to see how these things work under the hood, see
|
||||
Mechanics.</dd>
|
||||
@@ -162,6 +167,10 @@ Mechanics.</dd>
|
||||
<dd>Demonstrates use of LoaderManager to perform a query for a Cursor that
|
||||
populates a ListFragment.</dd>
|
||||
|
||||
<dt><a href="LoaderCustom.html">Loader Custom</a></dt>
|
||||
<dd>Demonstrates implementation and use of a custom Loader class. The
|
||||
custom class here "loads" the currently installed applications.</dd>
|
||||
|
||||
<dt><a href="LoaderThrottle.html">Loader Throttle</a></dt>
|
||||
<dd>Complete end-to-end demonstration of a simple content provider that
|
||||
populates data in a list through a cursor loader. The UI allows the list
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
|
||||
<uses-sdk android:minSdkVersion="13" />
|
||||
|
||||
<!-- This app has not been optimized for large screens. -->
|
||||
<!-- The smallest screen this app works on is a phone. The app will
|
||||
scale its UI to larger screens but doesn't make good use of them
|
||||
so allow the compatibility mode button to be shown (mostly because
|
||||
this is just convenient for testing). -->
|
||||
<supports-screens android:requiresSmallestWidthDp="320"
|
||||
android:compatibleWidthLimitDp="480" />
|
||||
|
||||
@@ -60,5 +63,13 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.ActionBarTabsPager"
|
||||
android:label="@string/action_bar_tabs_pager">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.example.android.supportv13.SUPPORT13_SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -29,4 +29,5 @@
|
||||
|
||||
<string name="fragment_state_pager_support">Fragment/State Pager</string>
|
||||
|
||||
<string name="action_bar_tabs_pager">Fragment/Action Bar Tabs Pager</string>
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.supportv13.app;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.example.android.supportv13.R;
|
||||
|
||||
import android.app.ActionBar;
|
||||
import android.app.ActionBar.Tab;
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentTransaction;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v13.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
|
||||
/**
|
||||
* This demonstrates the use of action bar tabs and how they interact
|
||||
* with other action bar features.
|
||||
*/
|
||||
public class ActionBarTabsPager extends Activity {
|
||||
ViewPager mViewPager;
|
||||
TabsAdapter mTabsAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mViewPager = new ViewPager(this);
|
||||
mViewPager.setId(R.id.pager);
|
||||
setContentView(mViewPager);
|
||||
|
||||
final ActionBar bar = getActionBar();
|
||||
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
|
||||
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
|
||||
|
||||
mTabsAdapter = new TabsAdapter(this, mViewPager);
|
||||
mTabsAdapter.addTab(bar.newTab().setText("Simple"),
|
||||
CountingFragment.class, null);
|
||||
mTabsAdapter.addTab(bar.newTab().setText("List"),
|
||||
FragmentPagerSupport.ArrayListFragment.class, null);
|
||||
mTabsAdapter.addTab(bar.newTab().setText("Cursor"),
|
||||
CursorFragment.class, null);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putInt("tab", getActionBar().getSelectedNavigationIndex());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a helper class that implements the management of tabs and all
|
||||
* details of connecting a ViewPager with associated TabHost. It relies on a
|
||||
* trick. Normally a tab host has a simple API for supplying a View or
|
||||
* Intent that each tab will show. This is not sufficient for switching
|
||||
* between pages. So instead we make the content part of the tab host
|
||||
* 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
|
||||
* view to show as the tab content. It listens to changes in tabs, and takes
|
||||
* care of switch to the correct paged in the ViewPager whenever the selected
|
||||
* tab changes.
|
||||
*/
|
||||
public static class TabsAdapter extends FragmentPagerAdapter
|
||||
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
|
||||
private final Context mContext;
|
||||
private final ActionBar mActionBar;
|
||||
private final ViewPager mViewPager;
|
||||
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
|
||||
|
||||
static final class TabInfo {
|
||||
private final Class<?> clss;
|
||||
private final Bundle args;
|
||||
|
||||
TabInfo(Class<?> _class, Bundle _args) {
|
||||
clss = _class;
|
||||
args = _args;
|
||||
}
|
||||
}
|
||||
|
||||
public TabsAdapter(Activity activity, ViewPager pager) {
|
||||
super(activity.getFragmentManager());
|
||||
mContext = activity;
|
||||
mActionBar = activity.getActionBar();
|
||||
mViewPager = pager;
|
||||
mViewPager.setAdapter(this);
|
||||
mViewPager.setOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
|
||||
TabInfo info = new TabInfo(clss, args);
|
||||
tab.setTag(info);
|
||||
tab.setTabListener(this);
|
||||
mTabs.add(info);
|
||||
mActionBar.addTab(tab);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mTabs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
TabInfo info = mTabs.get(position);
|
||||
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
mActionBar.setSelectedNavigationItem(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabSelected(Tab tab, FragmentTransaction ft) {
|
||||
Object tag = tab.getTag();
|
||||
for (int i=0; i<mTabs.size(); i++) {
|
||||
if (mTabs.get(i) == tag) {
|
||||
mViewPager.setCurrentItem(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabReselected(Tab tab, FragmentTransaction ft) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.supportv13.app;
|
||||
|
||||
import com.example.android.supportv13.R;
|
||||
|
||||
import android.app.Fragment;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class CountingFragment extends Fragment {
|
||||
int mNum;
|
||||
|
||||
/**
|
||||
* Create a new instance of CountingFragment, providing "num"
|
||||
* as an argument.
|
||||
*/
|
||||
static CountingFragment newInstance(int num) {
|
||||
CountingFragment f = new CountingFragment();
|
||||
|
||||
// Supply num input as an argument.
|
||||
Bundle args = new Bundle();
|
||||
args.putInt("num", num);
|
||||
f.setArguments(args);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
/**
|
||||
* When creating, retrieve this instance's number from its arguments.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mNum = getArguments() != null ? getArguments().getInt("num") : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Fragment's UI is just a simple text view showing its
|
||||
* instance number.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View v = inflater.inflate(R.layout.hello_world, container, false);
|
||||
View tv = v.findViewById(R.id.text);
|
||||
((TextView)tv).setText("Fragment #" + mNum);
|
||||
tv.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.gallery_thumb));
|
||||
return v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.supportv13.app;
|
||||
|
||||
import android.app.ListFragment;
|
||||
import android.app.LoaderManager;
|
||||
import android.content.CursorLoader;
|
||||
import android.content.Loader;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.provider.ContactsContract.Contacts;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.SimpleCursorAdapter;
|
||||
import android.widget.SearchView.OnQueryTextListener;
|
||||
|
||||
|
||||
public class CursorFragment extends ListFragment
|
||||
implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
// This is the Adapter being used to display the list's data.
|
||||
SimpleCursorAdapter mAdapter;
|
||||
|
||||
// If non-null, this is the current filter the user has provided.
|
||||
String mCurFilter;
|
||||
|
||||
@Override public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
// Give some text to display if there is no data. In a real
|
||||
// application this would come from a resource.
|
||||
setEmptyText("No phone numbers");
|
||||
|
||||
// We have a menu item to show in action bar.
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// Create an empty adapter we will use to display the loaded data.
|
||||
mAdapter = new SimpleCursorAdapter(getActivity(),
|
||||
android.R.layout.simple_list_item_2, null,
|
||||
new String[] { Contacts.DISPLAY_NAME, Contacts.CONTACT_STATUS },
|
||||
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// Prepare the loader. Either re-connect with an existing one,
|
||||
// or start a new one.
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
// Place an action bar item for searching.
|
||||
MenuItem item = menu.add("Search");
|
||||
item.setIcon(android.R.drawable.ic_menu_search);
|
||||
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
SearchView sv = new SearchView(getActivity());
|
||||
sv.setOnQueryTextListener(this);
|
||||
item.setActionView(sv);
|
||||
}
|
||||
|
||||
public boolean onQueryTextChange(String newText) {
|
||||
// Called when the action bar search text has changed. Update
|
||||
// the search filter, and restart the loader to do a new query
|
||||
// with this filter.
|
||||
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
|
||||
getLoaderManager().restartLoader(0, null, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public boolean onQueryTextSubmit(String query) {
|
||||
// Don't care about this.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
// Insert desired behavior here.
|
||||
Log.i("FragmentComplexList", "Item clicked: " + id);
|
||||
}
|
||||
|
||||
// These are the Contacts rows that we will retrieve.
|
||||
static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] {
|
||||
Contacts._ID,
|
||||
Contacts.DISPLAY_NAME,
|
||||
Contacts.CONTACT_STATUS,
|
||||
Contacts.CONTACT_PRESENCE,
|
||||
Contacts.PHOTO_ID,
|
||||
Contacts.LOOKUP_KEY,
|
||||
};
|
||||
|
||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||
// This is called when a new Loader needs to be created. This
|
||||
// sample only has one Loader, so we don't care about the ID.
|
||||
// First, pick the base URI to use depending on whether we are
|
||||
// currently filtering.
|
||||
Uri baseUri;
|
||||
if (mCurFilter != null) {
|
||||
baseUri = Uri.withAppendedPath(Contacts.CONTENT_FILTER_URI,
|
||||
Uri.encode(mCurFilter));
|
||||
} else {
|
||||
baseUri = Contacts.CONTENT_URI;
|
||||
}
|
||||
|
||||
// Now create and return a CursorLoader that will take care of
|
||||
// creating a Cursor for the data being displayed.
|
||||
String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND ("
|
||||
+ Contacts.HAS_PHONE_NUMBER + "=1) AND ("
|
||||
+ Contacts.DISPLAY_NAME + " != '' ))";
|
||||
return new CursorLoader(getActivity(), baseUri,
|
||||
CONTACTS_SUMMARY_PROJECTION, select, null,
|
||||
Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
|
||||
}
|
||||
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||
// Swap the new cursor in. (The framework will take care of closing the
|
||||
// old cursor once we return.)
|
||||
mAdapter.swapCursor(data);
|
||||
|
||||
// The list should now be shown.
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
// This is called when the last Cursor provided to onLoadFinished()
|
||||
// above is about to be closed. We need to make sure we are no
|
||||
// longer using it.
|
||||
mAdapter.swapCursor(null);
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,16 @@ package features of the static support library fir API 13 or later.
|
||||
|
||||
<h3 id="Fragment">Fragment</h3>
|
||||
<dl>
|
||||
<dt><a href="ActionBarTabsPager.html">Action Bar Tabs Pager</a></dt>
|
||||
<dd>Demonstrates the use of fragments to implement switching between
|
||||
ActionBar tabs, using a ViewPager to manager the fragments so that
|
||||
the user can also fling left and right to switch tabs.</dd>
|
||||
|
||||
<dt><a href="FragmentPagerSupport.html">Fragment Pager Support</a></dt>
|
||||
<dd>Demonstrates the use of the v4 support class ViewPager with a
|
||||
FragmentPagerAdapter to build a user interface where the user can fling
|
||||
left or right to switch between fragments.</dd>
|
||||
|
||||
<dt><a href="FragmentStatePagerSupport.html">Fragment State Pager Support</a></dt>
|
||||
<dd>Demonstrates the use of the v4 support class ViewPager with a
|
||||
FragmentStatePagerAdapter to build a user interface where the user can fling
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
|
||||
<uses-sdk android:minSdkVersion="4" android:targetSdkVersion="13" />
|
||||
|
||||
<!-- This app has not been optimized for large screens. -->
|
||||
<!-- The smallest screen this app works on is a phone. The app will
|
||||
scale its UI to larger screens but doesn't make good use of them
|
||||
so allow the compatibility mode button to be shown (mostly because
|
||||
this is just convenient for testing). -->
|
||||
<supports-screens android:requiresSmallestWidthDp="320"
|
||||
android:compatibleWidthLimitDp="480" />
|
||||
|
||||
@@ -147,6 +150,22 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.FragmentTabs"
|
||||
android:label="@string/fragment_tabs">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.FragmentTabsPager"
|
||||
android:label="@string/fragment_tabs_pager">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.FragmentPagerSupport"
|
||||
android:label="@string/fragment_pager_support">
|
||||
<intent-filter>
|
||||
@@ -171,6 +190,14 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.LoaderCustomSupport"
|
||||
android:label="@string/loader_custom_support">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="com.example.android.supportv4.SUPPORT4_SAMPLE_CODE" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:name=".app.LoaderThrottleSupport"
|
||||
android:label="@string/loader_throttle_support">
|
||||
<intent-filter>
|
||||
|
||||
52
samples/Support4Demos/res/layout/fragment_tabs.xml
Normal file
52
samples/Support4Demos/res/layout/fragment_tabs.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/* //device/apps/common/assets/res/layout/tab_content.xml
|
||||
**
|
||||
** Copyright 2011, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<TabHost
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabhost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="0"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+android:id/realtabcontent"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
52
samples/Support4Demos/res/layout/fragment_tabs_pager.xml
Normal file
52
samples/Support4Demos/res/layout/fragment_tabs_pager.xml
Normal file
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/* //device/apps/common/assets/res/layout/tab_content.xml
|
||||
**
|
||||
** Copyright 2011, The Android Open Source Project
|
||||
**
|
||||
** Licensed under the Apache License, Version 2.0 (the "License");
|
||||
** you may not use this file except in compliance with the License.
|
||||
** You may obtain a copy of the License at
|
||||
**
|
||||
** http://www.apache.org/licenses/LICENSE-2.0
|
||||
**
|
||||
** Unless required by applicable law or agreed to in writing, software
|
||||
** distributed under the License is distributed on an "AS IS" BASIS,
|
||||
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
** See the License for the specific language governing permissions and
|
||||
** limitations under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<TabHost
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@android:id/tabhost"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TabWidget
|
||||
android:id="@android:id/tabs"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="0"/>
|
||||
|
||||
<FrameLayout
|
||||
android:id="@android:id/tabcontent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="0"/>
|
||||
|
||||
<android.support.v4.view.ViewPager
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
</LinearLayout>
|
||||
</TabHost>
|
||||
32
samples/Support4Demos/res/layout/list_item_icon_text.xml
Normal file
32
samples/Support4Demos/res/layout/list_item_icon_text.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2007 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<ImageView android:id="@+id/icon"
|
||||
android:layout_width="48dip"
|
||||
android:layout_height="48dip" />
|
||||
|
||||
<TextView android:id="@+id/text"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_width="0dip"
|
||||
android:layout_weight="1.0"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -77,6 +77,10 @@
|
||||
<string name="fragment_stack_support">Fragment/Stack</string>
|
||||
<string name="new_fragment">New fragment</string>
|
||||
|
||||
<string name="fragment_tabs">Fragment/Tabs</string>
|
||||
|
||||
<string name="fragment_tabs_pager">Fragment/Tabs and Pager</string>
|
||||
|
||||
<string name="fragment_pager_support">Fragment/Pager</string>
|
||||
<string name="first">First</string>
|
||||
<string name="last">Last</string>
|
||||
@@ -85,6 +89,8 @@
|
||||
|
||||
<string name="loader_cursor_support">Loader/Cursor</string>
|
||||
|
||||
<string name="loader_custom_support">Loader/Custom</string>
|
||||
|
||||
<string name="loader_throttle_support">Loader/Throttle</string>
|
||||
|
||||
</resources>
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.supportv4.app;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
import com.example.android.supportv4.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.View;
|
||||
import android.widget.TabHost;
|
||||
|
||||
/**
|
||||
* This demonstrates how you can implement switching between the tabs of a
|
||||
* TabHost through fragments. It uses a trick (see the code below) to allow
|
||||
* the tabs to switch between fragments instead of simple views.
|
||||
*/
|
||||
public class FragmentTabs extends FragmentActivity {
|
||||
TabHost mTabHost;
|
||||
TabManager mTabManager;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.fragment_tabs);
|
||||
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
|
||||
mTabHost.setup();
|
||||
|
||||
mTabManager = new TabManager(this, mTabHost, R.id.realtabcontent);
|
||||
|
||||
mTabManager.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
|
||||
FragmentStackSupport.CountingFragment.class, null);
|
||||
mTabManager.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
|
||||
LoaderCursorSupport.CursorLoaderListFragment.class, null);
|
||||
mTabManager.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
|
||||
LoaderCustomSupport.AppListFragment.class, null);
|
||||
mTabManager.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
|
||||
LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString("tab", mTabHost.getCurrentTabTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a helper class that implements a generic mechanism for
|
||||
* associating fragments with the tabs in a tab host. It relies on a
|
||||
* trick. Normally a tab host has a simple API for supplying a View or
|
||||
* Intent that each tab will show. This is not sufficient for switching
|
||||
* between fragments. So instead we make the content part of the tab host
|
||||
* 0dp high (it is not shown) and the TabManager supplies its own dummy
|
||||
* view to show as the tab content. It listens to changes in tabs, and takes
|
||||
* care of switch to the correct fragment shown in a separate content area
|
||||
* whenever the selected tab changes.
|
||||
*/
|
||||
public static class TabManager implements TabHost.OnTabChangeListener {
|
||||
private final FragmentActivity mActivity;
|
||||
private final TabHost mTabHost;
|
||||
private final int mContainerId;
|
||||
private final HashMap<String, TabInfo> mTabs = new HashMap<String, TabInfo>();
|
||||
TabInfo mLastTab;
|
||||
|
||||
static final class TabInfo {
|
||||
private final String tag;
|
||||
private final Class<?> clss;
|
||||
private final Bundle args;
|
||||
private Fragment fragment;
|
||||
|
||||
TabInfo(String _tag, Class<?> _class, Bundle _args) {
|
||||
tag = _tag;
|
||||
clss = _class;
|
||||
args = _args;
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyTabFactory implements TabHost.TabContentFactory {
|
||||
private final Context mContext;
|
||||
|
||||
public DummyTabFactory(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createTabContent(String tag) {
|
||||
View v = new View(mContext);
|
||||
v.setMinimumWidth(0);
|
||||
v.setMinimumHeight(0);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public TabManager(FragmentActivity activity, TabHost tabHost, int containerId) {
|
||||
mActivity = activity;
|
||||
mTabHost = tabHost;
|
||||
mContainerId = containerId;
|
||||
mTabHost.setOnTabChangedListener(this);
|
||||
}
|
||||
|
||||
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
|
||||
tabSpec.setContent(new DummyTabFactory(mActivity));
|
||||
String tag = tabSpec.getTag();
|
||||
|
||||
TabInfo info = new TabInfo(tag, clss, args);
|
||||
|
||||
// Check to see if we already have a fragment for this tab, probably
|
||||
// from a previously saved state. If so, deactivate it, because our
|
||||
// initial state is that a tab isn't shown.
|
||||
info.fragment = mActivity.getSupportFragmentManager().findFragmentByTag(tag);
|
||||
if (info.fragment != null && !info.fragment.isDetached()) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
ft.detach(info.fragment);
|
||||
ft.commit();
|
||||
}
|
||||
|
||||
mTabs.put(tag, info);
|
||||
mTabHost.addTab(tabSpec);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabChanged(String tabId) {
|
||||
TabInfo newTab = mTabs.get(tabId);
|
||||
if (mLastTab != newTab) {
|
||||
FragmentTransaction ft = mActivity.getSupportFragmentManager().beginTransaction();
|
||||
if (mLastTab != null) {
|
||||
if (mLastTab.fragment != null) {
|
||||
ft.detach(mLastTab.fragment);
|
||||
}
|
||||
}
|
||||
if (newTab != null) {
|
||||
if (newTab.fragment == null) {
|
||||
newTab.fragment = Fragment.instantiate(mActivity,
|
||||
newTab.clss.getName(), newTab.args);
|
||||
ft.add(mContainerId, newTab.fragment, newTab.tag);
|
||||
} else {
|
||||
ft.attach(newTab.fragment);
|
||||
}
|
||||
}
|
||||
|
||||
mLastTab = newTab;
|
||||
ft.commit();
|
||||
mActivity.getSupportFragmentManager().executePendingTransactions();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (C) 2011 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.example.android.supportv4.app;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.example.android.supportv4.R;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.view.View;
|
||||
import android.widget.TabHost;
|
||||
|
||||
/**
|
||||
* Demonstrates combining a TabHost with a ViewPager to implement a tab UI
|
||||
* that switches between tabs and also allows the user to perform horizontal
|
||||
* flicks to move between the tabs.
|
||||
*/
|
||||
public class FragmentTabsPager extends FragmentActivity {
|
||||
TabHost mTabHost;
|
||||
ViewPager mViewPager;
|
||||
TabsAdapter mTabsAdapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.fragment_tabs_pager);
|
||||
mTabHost = (TabHost)findViewById(android.R.id.tabhost);
|
||||
mTabHost.setup();
|
||||
|
||||
mViewPager = (ViewPager)findViewById(R.id.pager);
|
||||
|
||||
mTabsAdapter = new TabsAdapter(this, mTabHost, mViewPager);
|
||||
|
||||
mTabsAdapter.addTab(mTabHost.newTabSpec("simple").setIndicator("Simple"),
|
||||
FragmentStackSupport.CountingFragment.class, null);
|
||||
mTabsAdapter.addTab(mTabHost.newTabSpec("contacts").setIndicator("Contacts"),
|
||||
LoaderCursorSupport.CursorLoaderListFragment.class, null);
|
||||
mTabsAdapter.addTab(mTabHost.newTabSpec("custom").setIndicator("Custom"),
|
||||
LoaderCustomSupport.AppListFragment.class, null);
|
||||
mTabsAdapter.addTab(mTabHost.newTabSpec("throttle").setIndicator("Throttle"),
|
||||
LoaderThrottleSupport.ThrottledLoaderListFragment.class, null);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
mTabHost.setCurrentTabByTag(savedInstanceState.getString("tab"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
outState.putString("tab", mTabHost.getCurrentTabTag());
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a helper class that implements the management of tabs and all
|
||||
* details of connecting a ViewPager with associated TabHost. It relies on a
|
||||
* trick. Normally a tab host has a simple API for supplying a View or
|
||||
* Intent that each tab will show. This is not sufficient for switching
|
||||
* between pages. So instead we make the content part of the tab host
|
||||
* 0dp high (it is not shown) and the TabsAdapter supplies its own dummy
|
||||
* view to show as the tab content. It listens to changes in tabs, and takes
|
||||
* care of switch to the correct paged in the ViewPager whenever the selected
|
||||
* tab changes.
|
||||
*/
|
||||
public static class TabsAdapter extends FragmentPagerAdapter
|
||||
implements TabHost.OnTabChangeListener, ViewPager.OnPageChangeListener {
|
||||
private final Context mContext;
|
||||
private final TabHost mTabHost;
|
||||
private final ViewPager mViewPager;
|
||||
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
|
||||
|
||||
static final class TabInfo {
|
||||
private final String tag;
|
||||
private final Class<?> clss;
|
||||
private final Bundle args;
|
||||
|
||||
TabInfo(String _tag, Class<?> _class, Bundle _args) {
|
||||
tag = _tag;
|
||||
clss = _class;
|
||||
args = _args;
|
||||
}
|
||||
}
|
||||
|
||||
static class DummyTabFactory implements TabHost.TabContentFactory {
|
||||
private final Context mContext;
|
||||
|
||||
public DummyTabFactory(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View createTabContent(String tag) {
|
||||
View v = new View(mContext);
|
||||
v.setMinimumWidth(0);
|
||||
v.setMinimumHeight(0);
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
public TabsAdapter(FragmentActivity activity, TabHost tabHost, ViewPager pager) {
|
||||
super(activity.getSupportFragmentManager());
|
||||
mContext = activity;
|
||||
mTabHost = tabHost;
|
||||
mViewPager = pager;
|
||||
mTabHost.setOnTabChangedListener(this);
|
||||
mViewPager.setAdapter(this);
|
||||
mViewPager.setOnPageChangeListener(this);
|
||||
}
|
||||
|
||||
public void addTab(TabHost.TabSpec tabSpec, Class<?> clss, Bundle args) {
|
||||
tabSpec.setContent(new DummyTabFactory(mContext));
|
||||
String tag = tabSpec.getTag();
|
||||
|
||||
TabInfo info = new TabInfo(tag, clss, args);
|
||||
mTabs.add(info);
|
||||
mTabHost.addTab(tabSpec);
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mTabs.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
TabInfo info = mTabs.get(position);
|
||||
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTabChanged(String tabId) {
|
||||
int position = mTabHost.getCurrentTab();
|
||||
mViewPager.setCurrentItem(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageSelected(int position) {
|
||||
mTabHost.setCurrentTab(position);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -81,6 +81,9 @@ public class LoaderCursorSupport extends FragmentActivity {
|
||||
new int[] { android.R.id.text1, android.R.id.text2 }, 0);
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// Prepare the loader. Either re-connect with an existing one,
|
||||
// or start a new one.
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
@@ -147,6 +150,13 @@ public class LoaderCursorSupport extends FragmentActivity {
|
||||
// Swap the new cursor in. (The framework will take care of closing the
|
||||
// old cursor once we return.)
|
||||
mAdapter.swapCursor(data);
|
||||
|
||||
// The list should now be shown.
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
|
||||
@@ -0,0 +1,482 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.example.android.supportv4.app;
|
||||
|
||||
import com.example.android.supportv4.R;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.Collator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.ListFragment;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.SearchView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.SearchView.OnQueryTextListener;
|
||||
|
||||
/**
|
||||
* Demonstration of the implementation of a custom Loader.
|
||||
*/
|
||||
public class LoaderCustomSupport extends FragmentActivity {
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
FragmentManager fm = getSupportFragmentManager();
|
||||
|
||||
// Create the list fragment and add it as our sole content.
|
||||
if (fm.findFragmentById(android.R.id.content) == null) {
|
||||
AppListFragment list = new AppListFragment();
|
||||
fm.beginTransaction().add(android.R.id.content, list).commit();
|
||||
}
|
||||
}
|
||||
|
||||
//BEGIN_INCLUDE(loader)
|
||||
/**
|
||||
* This class holds the per-item data in our Loader.
|
||||
*/
|
||||
public static class AppEntry {
|
||||
public AppEntry(AppListLoader loader, ApplicationInfo info) {
|
||||
mLoader = loader;
|
||||
mInfo = info;
|
||||
mApkFile = new File(info.sourceDir);
|
||||
}
|
||||
|
||||
public ApplicationInfo getApplicationInfo() {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public Drawable getIcon() {
|
||||
if (mIcon == null) {
|
||||
if (mApkFile.exists()) {
|
||||
mIcon = mInfo.loadIcon(mLoader.mPm);
|
||||
return mIcon;
|
||||
} else {
|
||||
mMounted = false;
|
||||
}
|
||||
} else if (!mMounted) {
|
||||
// If the app wasn't mounted but is now mounted, reload
|
||||
// its icon.
|
||||
if (mApkFile.exists()) {
|
||||
mMounted = true;
|
||||
mIcon = mInfo.loadIcon(mLoader.mPm);
|
||||
return mIcon;
|
||||
}
|
||||
} else {
|
||||
return mIcon;
|
||||
}
|
||||
|
||||
return mLoader.getContext().getResources().getDrawable(
|
||||
android.R.drawable.sym_def_app_icon);
|
||||
}
|
||||
|
||||
@Override public String toString() {
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
void loadLabel(Context context) {
|
||||
if (mLabel == null || !mMounted) {
|
||||
if (!mApkFile.exists()) {
|
||||
mMounted = false;
|
||||
mLabel = mInfo.packageName;
|
||||
} else {
|
||||
mMounted = true;
|
||||
CharSequence label = mInfo.loadLabel(context.getPackageManager());
|
||||
mLabel = label != null ? label.toString() : mInfo.packageName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final AppListLoader mLoader;
|
||||
private final ApplicationInfo mInfo;
|
||||
private final File mApkFile;
|
||||
private String mLabel;
|
||||
private Drawable mIcon;
|
||||
private boolean mMounted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform alphabetical comparison of application entry objects.
|
||||
*/
|
||||
public static final Comparator<AppEntry> ALPHA_COMPARATOR = new Comparator<AppEntry>() {
|
||||
private final Collator sCollator = Collator.getInstance();
|
||||
@Override
|
||||
public int compare(AppEntry object1, AppEntry object2) {
|
||||
return sCollator.compare(object1.getLabel(), object2.getLabel());
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper for determining if the configuration has changed in an interesting
|
||||
* way so we need to rebuild the app list.
|
||||
*/
|
||||
public static class InterestingConfigChanges {
|
||||
final Configuration mLastConfiguration = new Configuration();
|
||||
int mLastDensity;
|
||||
|
||||
boolean applyNewConfig(Resources res) {
|
||||
int configChanges = mLastConfiguration.updateFrom(res.getConfiguration());
|
||||
boolean densityChanged = mLastDensity != res.getDisplayMetrics().densityDpi;
|
||||
if (densityChanged || (configChanges&(ActivityInfo.CONFIG_LOCALE
|
||||
|ActivityInfo.CONFIG_UI_MODE|ActivityInfo.CONFIG_SCREEN_LAYOUT)) != 0) {
|
||||
mLastDensity = res.getDisplayMetrics().densityDpi;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to look for interesting changes to the installed apps
|
||||
* so that the loader can be updated.
|
||||
*/
|
||||
public static class PackageIntentReceiver extends BroadcastReceiver {
|
||||
final AppListLoader mLoader;
|
||||
|
||||
public PackageIntentReceiver(AppListLoader loader) {
|
||||
mLoader = loader;
|
||||
IntentFilter filter = new IntentFilter(Intent.ACTION_PACKAGE_ADDED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
|
||||
filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
|
||||
filter.addDataScheme("package");
|
||||
mLoader.getContext().registerReceiver(this, filter);
|
||||
// Register for events related to sdcard installation.
|
||||
IntentFilter sdFilter = new IntentFilter();
|
||||
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
|
||||
sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
|
||||
mLoader.getContext().registerReceiver(this, sdFilter);
|
||||
}
|
||||
|
||||
@Override public void onReceive(Context context, Intent intent) {
|
||||
// Tell the loader about the change.
|
||||
mLoader.onContentChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A custom Loader that loads all of the installed applications.
|
||||
*/
|
||||
public static class AppListLoader extends AsyncTaskLoader<List<AppEntry>> {
|
||||
final InterestingConfigChanges mLastConfig = new InterestingConfigChanges();
|
||||
final PackageManager mPm;
|
||||
|
||||
List<AppEntry> mApps;
|
||||
PackageIntentReceiver mPackageObserver;
|
||||
|
||||
public AppListLoader(Context context) {
|
||||
super(context);
|
||||
|
||||
// Retrieve the package manager for later use; note we don't
|
||||
// use 'context' directly but instead the save global application
|
||||
// context returned by getContext().
|
||||
mPm = getContext().getPackageManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* This is where the bulk of our work is done. This function is
|
||||
* called in a background thread and should generate a new set of
|
||||
* data to be published by the loader.
|
||||
*/
|
||||
@Override public List<AppEntry> loadInBackground() {
|
||||
// Retrieve all known applications.
|
||||
List<ApplicationInfo> apps = mPm.getInstalledApplications(
|
||||
PackageManager.GET_UNINSTALLED_PACKAGES |
|
||||
PackageManager.GET_DISABLED_COMPONENTS);
|
||||
if (apps == null) {
|
||||
apps = new ArrayList<ApplicationInfo>();
|
||||
}
|
||||
|
||||
final Context context = getContext();
|
||||
|
||||
// Create corresponding array of entries and load their labels.
|
||||
List<AppEntry> entries = new ArrayList<AppEntry>(apps.size());
|
||||
for (int i=0; i<apps.size(); i++) {
|
||||
AppEntry entry = new AppEntry(this, apps.get(i));
|
||||
entry.loadLabel(context);
|
||||
entries.add(entry);
|
||||
}
|
||||
|
||||
// Sort the list.
|
||||
Collections.sort(entries, ALPHA_COMPARATOR);
|
||||
|
||||
// Done!
|
||||
return entries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when there is new data to deliver to the client. The
|
||||
* super class will take care of delivering it; the implementation
|
||||
* here just adds a little more logic.
|
||||
*/
|
||||
@Override public void deliverResult(List<AppEntry> apps) {
|
||||
if (isReset()) {
|
||||
// An async query came in while the loader is stopped. We
|
||||
// don't need the result.
|
||||
if (apps != null) {
|
||||
onReleaseResources(apps);
|
||||
}
|
||||
}
|
||||
List<AppEntry> oldApps = apps;
|
||||
mApps = apps;
|
||||
|
||||
if (isStarted()) {
|
||||
// If the Loader is currently started, we can immediately
|
||||
// deliver its results.
|
||||
super.deliverResult(apps);
|
||||
}
|
||||
|
||||
// At this point we can release the resources associated with
|
||||
// 'oldApps' if needed; now that the new result is delivered we
|
||||
// know that it is no longer in use.
|
||||
if (oldApps != null) {
|
||||
onReleaseResources(oldApps);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to start the Loader.
|
||||
*/
|
||||
@Override protected void onStartLoading() {
|
||||
if (mApps != null) {
|
||||
// If we currently have a result available, deliver it
|
||||
// immediately.
|
||||
deliverResult(mApps);
|
||||
}
|
||||
|
||||
// Start watching for changes in the app data.
|
||||
if (mPackageObserver == null) {
|
||||
mPackageObserver = new PackageIntentReceiver(this);
|
||||
}
|
||||
|
||||
// Has something interesting in the configuration changed since we
|
||||
// last built the app list?
|
||||
boolean configChange = mLastConfig.applyNewConfig(getContext().getResources());
|
||||
|
||||
if (takeContentChanged() || mApps == null || configChange) {
|
||||
// If the data has changed since the last time it was loaded
|
||||
// or is not currently available, start a load.
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to stop the Loader.
|
||||
*/
|
||||
@Override protected void onStopLoading() {
|
||||
// Attempt to cancel the current load task if possible.
|
||||
cancelLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to cancel a load.
|
||||
*/
|
||||
@Override public void onCanceled(List<AppEntry> apps) {
|
||||
super.onCanceled(apps);
|
||||
|
||||
// At this point we can release the resources associated with 'apps'
|
||||
// if needed.
|
||||
onReleaseResources(apps);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a request to completely reset the Loader.
|
||||
*/
|
||||
@Override protected void onReset() {
|
||||
super.onReset();
|
||||
|
||||
// Ensure the loader is stopped
|
||||
onStopLoading();
|
||||
|
||||
// At this point we can release the resources associated with 'apps'
|
||||
// if needed.
|
||||
if (mApps != null) {
|
||||
onReleaseResources(mApps);
|
||||
mApps = null;
|
||||
}
|
||||
|
||||
// Stop monitoring for changes.
|
||||
if (mPackageObserver != null) {
|
||||
getContext().unregisterReceiver(mPackageObserver);
|
||||
mPackageObserver = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to take care of releasing resources associated
|
||||
* with an actively loaded data set.
|
||||
*/
|
||||
protected void onReleaseResources(List<AppEntry> apps) {
|
||||
// For a simple List<> there is nothing to do. For something
|
||||
// like a Cursor, we would close it here.
|
||||
}
|
||||
}
|
||||
//END_INCLUDE(loader)
|
||||
|
||||
//BEGIN_INCLUDE(fragment)
|
||||
public static class AppListAdapter extends ArrayAdapter<AppEntry> {
|
||||
private final LayoutInflater mInflater;
|
||||
|
||||
public AppListAdapter(Context context) {
|
||||
super(context, android.R.layout.simple_list_item_2);
|
||||
mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
|
||||
}
|
||||
|
||||
public void setData(List<AppEntry> data) {
|
||||
clear();
|
||||
if (data != null) {
|
||||
addAll(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate new items in the list.
|
||||
*/
|
||||
@Override public View getView(int position, View convertView, ViewGroup parent) {
|
||||
View view;
|
||||
|
||||
if (convertView == null) {
|
||||
view = mInflater.inflate(R.layout.list_item_icon_text, parent, false);
|
||||
} else {
|
||||
view = convertView;
|
||||
}
|
||||
|
||||
AppEntry item = getItem(position);
|
||||
((ImageView)view.findViewById(R.id.icon)).setImageDrawable(item.getIcon());
|
||||
((TextView)view.findViewById(R.id.text)).setText(item.getLabel());
|
||||
|
||||
return view;
|
||||
}
|
||||
}
|
||||
|
||||
public static class AppListFragment extends ListFragment
|
||||
implements OnQueryTextListener, LoaderManager.LoaderCallbacks<List<AppEntry>> {
|
||||
|
||||
// This is the Adapter being used to display the list's data.
|
||||
AppListAdapter mAdapter;
|
||||
|
||||
// If non-null, this is the current filter the user has provided.
|
||||
String mCurFilter;
|
||||
|
||||
@Override public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
// Give some text to display if there is no data. In a real
|
||||
// application this would come from a resource.
|
||||
setEmptyText("No applications");
|
||||
|
||||
// We have a menu item to show in action bar.
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
// Create an empty adapter we will use to display the loaded data.
|
||||
mAdapter = new AppListAdapter(getActivity());
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// Prepare the loader. Either re-connect with an existing one,
|
||||
// or start a new one.
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
}
|
||||
|
||||
@Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
// Place an action bar item for searching.
|
||||
MenuItem item = menu.add("Search");
|
||||
item.setIcon(android.R.drawable.ic_menu_search);
|
||||
item.setShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
|
||||
SearchView sv = new SearchView(getActivity());
|
||||
sv.setOnQueryTextListener(this);
|
||||
item.setActionView(sv);
|
||||
}
|
||||
|
||||
@Override public boolean onQueryTextChange(String newText) {
|
||||
// Called when the action bar search text has changed. Since this
|
||||
// is a simple array adapter, we can just have it do the filtering.
|
||||
mCurFilter = !TextUtils.isEmpty(newText) ? newText : null;
|
||||
mAdapter.getFilter().filter(mCurFilter);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public boolean onQueryTextSubmit(String query) {
|
||||
// Don't care about this.
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public void onListItemClick(ListView l, View v, int position, long id) {
|
||||
// Insert desired behavior here.
|
||||
Log.i("LoaderCustom", "Item clicked: " + id);
|
||||
}
|
||||
|
||||
@Override public Loader<List<AppEntry>> onCreateLoader(int id, Bundle args) {
|
||||
// This is called when a new Loader needs to be created. This
|
||||
// sample only has one Loader with no arguments, so it is simple.
|
||||
return new AppListLoader(getActivity());
|
||||
}
|
||||
|
||||
@Override public void onLoadFinished(Loader<List<AppEntry>> loader, List<AppEntry> data) {
|
||||
// Set the new data in the adapter.
|
||||
mAdapter.setData(data);
|
||||
|
||||
// The list should now be shown.
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onLoaderReset(Loader<List<AppEntry>> loader) {
|
||||
// Clear the data in the adapter.
|
||||
mAdapter.setData(null);
|
||||
}
|
||||
}
|
||||
//END_INCLUDE(fragment)
|
||||
}
|
||||
@@ -410,6 +410,9 @@ public class LoaderThrottleSupport extends FragmentActivity {
|
||||
new int[] { android.R.id.text1 }, 0);
|
||||
setListAdapter(mAdapter);
|
||||
|
||||
// Start out with a progress indicator.
|
||||
setListShown(false);
|
||||
|
||||
// Prepare the loader. Either re-connect with an existing one,
|
||||
// or start a new one.
|
||||
getLoaderManager().initLoader(0, null, this);
|
||||
@@ -493,6 +496,13 @@ public class LoaderThrottleSupport extends FragmentActivity {
|
||||
|
||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||
mAdapter.swapCursor(data);
|
||||
|
||||
// The list should now be shown.
|
||||
if (isResumed()) {
|
||||
setListShown(true);
|
||||
} else {
|
||||
setListShownNoAnimation(true);
|
||||
}
|
||||
}
|
||||
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
|
||||
@@ -67,6 +67,15 @@ and loaders.</p>
|
||||
<dd>Demonstrates creating a stack of Fragment instances similar to the
|
||||
traditional stack of activities.</dd>
|
||||
|
||||
<dt><a href="FragmentTabs.html">Fragment Tabs</a></dt>
|
||||
<dd>Demonstrates the use of fragments to implement switching between
|
||||
tabs in a TabHost.</dd>
|
||||
|
||||
<dt><a href="FragmentTabsPager.html">Fragment Tabs Pager</a></dt>
|
||||
<dd>Demonstrates the use of fragments to implement switching between
|
||||
tabs in a TabHost, using a ViewPager to manager the fragments so that
|
||||
the user can also fling left and right to switch tabs.</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
<h3 id="LoaderManager">LoaderManager</h3>
|
||||
@@ -75,6 +84,10 @@ and loaders.</p>
|
||||
<dd>Demonstrates use of LoaderManager to perform a query for a Cursor that
|
||||
populates a ListFragment.</dd>
|
||||
|
||||
<dt><a href="LoaderCustomSupport.html">Loader Custom</a></dt>
|
||||
<dd>Demonstrates implementation and use of a custom Loader class. The
|
||||
custom class here "loads" the currently installed applications.</dd>
|
||||
|
||||
<dt><a href="LoaderThrottleSupport.html">Loader Throttle</a></dt>
|
||||
<dd>Complete end-to-end demonstration of a simple content provider that
|
||||
populates data in a list through a cursor loader. The UI allows the list
|
||||
|
||||
Reference in New Issue
Block a user