After reading the lessons in this class, you should have a strong understanding of how to implement navigation patterns with tabs, swipe views, and a navigation drawer. You should also understand how to provide proper Up and Back navigation.
Swipe views provide lateral navigation between sibling screens such as tabs with a horizontal finger gesture (a pattern sometimes known as horizontal paging).
> You can create swipe views in your app using the ViewPager
widget, available in the Support Library. The ViewPager
is a layout widget in which each child view is a separate page (a separate tab) in the layout.
To insert child views that represent each page, you need to hook this layout to a PagerAdapter
. There are two kinds of adapter you can use:
- This is best when navigating between sibling screens representing a fixed, small number of pages.
- This is best for paging across a collection of objects for which the number of pages is undetermined. It destroys fragments as the user navigates to other pages, minimizing memory usage.
FragmentPagerAdapter
FragmentStatePagerAdapter
public class CollectionDemoActivity extends FragmentActivity { // When requested, this adapter returns a DemoObjectFragment, // representing an object in the collection. DemoCollectionPagerAdapter mDemoCollectionPagerAdapter; ViewPager mViewPager; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_collection_demo); // ViewPager and its adapters use support library // fragments, so use getSupportFragmentManager. mDemoCollectionPagerAdapter = new DemoCollectionPagerAdapter( getSupportFragmentManager()); mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setAdapter(mDemoCollectionPagerAdapter); } } // Since this is an object collection, use a FragmentStatePagerAdapter, // and NOT a FragmentPagerAdapter. public class DemoCollectionPagerAdapter extends FragmentStatePagerAdapter { public DemoCollectionPagerAdapter(FragmentManager fm) { super(fm); } @Override public Fragment getItem(int i) { Fragment fragment = new DemoObjectFragment(); Bundle args = new Bundle(); // Our object is just an integer :-P args.putInt(DemoObjectFragment.ARG_OBJECT, i + 1); fragment.setArguments(args); return fragment; } @Override public int getCount() { return 100; } @Override public CharSequence getPageTitle(int position) { return "OBJECT " + (position + 1); } } // Instances of this class are fragments representing a single // object in our collection. public static class DemoObjectFragment extends Fragment { public static final String ARG_OBJECT = "object"; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // The last two arguments ensure LayoutParams are inflated // properly. View rootView = inflater.inflate( R.layout.fragment_collection_object, container, false); Bundle args = getArguments(); ((TextView) rootView.findViewById(android.R.id.text1)).setText( Integer.toString(args.getInt(ARG_OBJECT))); return rootView; } }
Action bar tabs offer users a familiar interface for navigating between and identifying sibling screens in your app.
To create tabs using ActionBar
, you need to enable NAVIGATION_MODE_TABS
, then create several instances ofActionBar.Tab
and supply an implementation of the ActionBar.TabListener
interface for each one. For example, in your activity's onCreate()
method, you can use code similar to this:
@Override public void onCreate(Bundle savedInstanceState) { final ActionBar actionBar = getActionBar(); ... // Specify that tabs should be displayed in the action bar. actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); // Create a tab listener that is called when the user changes tabs. ActionBar.TabListener tabListener = new ActionBar.TabListener() { public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { // show the given tab } public void onTabUnselected(ActionBar.Tab tab, FragmentTransaction ft) { // hide the given tab } public void onTabReselected(ActionBar.Tab tab, FragmentTransaction ft) { // probably ignore this event } }; // Add 3 tabs, specifying the tab's text and TabListener for (int i = 0; i < 3; i++) { actionBar.addTab( actionBar.newTab() .setText("Tab " + (i + 1)) .setTabListener(tabListener)); } }
// Create a tab listener that is called when the user changes tabs. ActionBar.TabListener tabListener = new ActionBar.TabListener() { public void onTabSelected(ActionBar.Tab tab, FragmentTransaction ft) { // When the tab is selected, switch to the // corresponding page in the ViewPager. mViewPager.setCurrentItem(tab.getPosition()); }
mViewPager = (ViewPager) findViewById(R.id.pager); mViewPager.setOnPageChangeListener( new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { // When swiping between pages, select the // corresponding tab. getActionBar().setSelectedNavigationItem(position); } });
Below is an example layout XML file for an activity whose entire contents are a ViewPager
and a top-alignedPagerTitleStrip
inside it. Individual pages (provided by the adapter) occupy the remaining space inside theViewPager
.
<android.support.v4.view.ViewPager xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.view.PagerTitleStrip android:id="@+id/pager_title_strip" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" android:background="#33b5e5" android:textColor="#fff" android:paddingTop="4dp" android:paddingBottom="4dp" /> </android.support.v4.view.ViewPager>