Browse through more Android tutorials. If you'd like to see a tutorial on any particular topic, do leave a comment in the wishlist page. We frequently post new tutorials along with app releases. You may subscribe to our newsletter to get all updates in your inbox.
Now you can get the latest Java source bundled with each app update. Install the app from Google Play and go to Settings > Extras.

«  Create a notepad/to-do list app Create a SMS app  »

Build your first pro Android application with Eclipse

DownloadDownload

Keywords: AppCompat Fragment ActionBar ViewPager Navigation Drawer LoaderManager SQLiteDatabase CursorLoader SimpleCursorAdapter ContentProvider SQLiteOpenHelper ContentResolver ListFragment ListView GridView DialogFragment Volley Library RequestQueue ImageLoader NetworkImageView

Contents

9 « Prev Page

19. View Pager

View Pager ViewPager is available in Android support library that allows user to flip left and right through pages of data.
Let's first see how to add ViewPager to the layout file fragment_item_pager.xml.
	<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" />
					
Fundamentally, view pager implementation is similar to list view or grid view.
	public class ItemPagerFragment extends Fragment implements LoaderManager.LoaderCallbacks<Cursor> {
		
		/**
		 * The pager widget, which handles animation and allows swiping horizontally to access previous
		 * and next wizard steps.
		 */
		private ViewPager mPager;

		/**
		 * The pager adapter, which provides the pages to the view pager widget.
		 */
		private CursorPagerAdapter adapter;

		public ItemPagerFragment() {
			// Required empty public constructor
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			// Inflate the layout for this fragment
			View rootView = inflater.inflate(R.layout.fragment_item_pager, container, false);
			
			// Instantiate a ViewPager and a PagerAdapter.
			mPager = (ViewPager) rootView.findViewById(R.id.pager);
			adapter = new CursorPagerAdapter(getFragmentManager(), null);
			mPager.setAdapter(adapter);
			
			getLoaderManager().initLoader(0, null, this);
			return rootView;
		}
		
		@Override
		public Loader<Cursor> onCreateLoader(int id, Bundle args) {
			CursorLoader loader = new CursorLoader(getActivity(), 
					DataProvider.CONTENT_URI_DATA, 
					new String[]{DataProvider.COL_ID}, 
					null, 
					null, 
					null);
			return loader;
		}

		@Override
		public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
			adapter.swapCursor(data);
		}

		@Override
		public void onLoaderReset(Loader<Cursor> loader) {
			adapter.swapCursor(null);
		}    

	}					
					
We create a custom adapter for view pager and populate it through Loader. Create a nested class inside ItemPagerFragment to implement a custom FragmentStatePagerAdapter.
    /**
     * A simple pager adapter.
     */
    private class CursorPagerAdapter extends FragmentStatePagerAdapter {
    	
    	private Cursor mCursor;
    	
        public CursorPagerAdapter(FragmentManager fm, Cursor c) {
            super(fm);
            mCursor = c;
        }

        @Override
        public Fragment getItem(int position) {
        	if (mCursor.moveToPosition(position)) {
				Bundle arguments = new Bundle();
				arguments.putLong(ItemDetailFragment.ARG_ITEM_ID, mCursor.getLong(mCursor.getColumnIndex(DataProvider.COL_ID)));
				ItemDetailFragment fragment = new ItemDetailFragment();
				fragment.setArguments(arguments);
	            return fragment;
        	}
        	return null;
        }

        @Override
        public int getCount() {
        	if (mCursor != null) {
        		return mCursor.getCount();
        	}
            return 0;
        }
        
        public void swapCursor(Cursor cursor) {
        	mCursor = cursor;
        	notifyDataSetChanged();
        }
    }
					
Each item in adapter is a fragment. So we create ItemDetailFragment class to provide implementation for a page. The major chunk of code is inside onCreateView() method to populate the views with data from cursor.
	public class ItemDetailFragment extends Fragment {
		/**
		 * The fragment argument representing the item ID that this fragment
		 * represents.
		 */
		public static final String ARG_ITEM_ID = "item_id";
		
		private long id;

		/**
		 * Mandatory empty constructor for the fragment manager to instantiate the
		 * fragment (e.g. upon screen orientation changes).
		 */
		public ItemDetailFragment() {
		}

		@Override
		public void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);

			if (getArguments().containsKey(ARG_ITEM_ID)) {
				// Load the dummy content specified by the fragment
				// arguments. In a real-world scenario, use a Loader
				// to load content from a content provider.
				id = getArguments().getLong(ARG_ITEM_ID);
			}
		}

		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
			View rootView = inflater.inflate(R.layout.fragment_item_detail, container, false);

			// Show the dummy content as text in a TextView.
			if (id > 0) {
				Uri contentUri = ContentUris.withAppendedId(DataProvider.CONTENT_URI_DATA, id);
				Cursor c = getActivity().getContentResolver().query(contentUri, null, null, null, null);
				if (c != null) {
					if (c.moveToFirst()) {
						String content = c.getString(c.getColumnIndex(DataProvider.COL_CONTENT));
						Data data = new Data(content);
						
						String title = data.getTitle();
						String desc = data.getDescription();
						String iconUrl = data.getIcon();
						String downloadUrl = data.getDownloadUrl();
						String tutorialUrl = data.getTutorialUrl();
						
						((TextView) rootView.findViewById(R.id.textView1)).setText(title);
						((TextView) rootView.findViewById(R.id.item_detail)).setText(desc);
						
						NetworkImageView iconView = (NetworkImageView) rootView.findViewById(R.id.imageView1);
						iconView.setDefaultImageResId(R.drawable.ic_launcher);
						iconView.setImageUrl(iconUrl, App.getInstance().getImageLoader());
						
						if (!TextUtils.isEmpty(downloadUrl)) {
							TextView downloadLink = (TextView) rootView.findViewById(R.id.downloadLink);
							downloadLink.setMovementMethod(LinkMovementMethod.getInstance());
							downloadLink.setText(Html.fromHtml("<a href='"+downloadUrl+"'>Download</a>"));
						}
						
						if (!TextUtils.isEmpty(tutorialUrl)) {
							TextView tutorialLink = (TextView) rootView.findViewById(R.id.tutorialLink);
							tutorialLink.setMovementMethod(LinkMovementMethod.getInstance());
							tutorialLink.setText(Html.fromHtml("<a href='"+tutorialUrl+"'>Read tutorial</a>"));
						}
					}
					c.close();
				}
			}

			return rootView;
		}
	}
					
We'll reuse this fragment in the next section for implementing detail screen.

20. Detail screen

Detail screen is implemented using an activity that inherits from ActionBarActivity available in Android v7 appcompat library. ActionBarActivity provides action bar to the screen.
Let's first create an activity with help of Eclipse wizard. Go to File > New > Other... and select Android Activity under Android. Click Next and select Blank Activity. Click Next. Enter activity name as DetailActivity and specify Hierarchical Parent as MainActivity. Click Finish. The activity class and layout gets generated as well as the manifest is updated.
	public class DetailActivity extends ActionBarActivity {

		@Override
		protected void onCreate(Bundle savedInstanceState) {
			super.onCreate(savedInstanceState);
			setContentView(R.layout.activity_detail);
			// Show the Up button in the action bar.
			setupActionBar();
			
			if (savedInstanceState == null) {
				// Create the detail fragment and add it to the activity
				// using a fragment transaction.
				Bundle arguments = new Bundle();
				arguments.putLong(ItemDetailFragment.ARG_ITEM_ID, getIntent().getLongExtra(ItemDetailFragment.ARG_ITEM_ID, -1));
				ItemDetailFragment fragment = new ItemDetailFragment();
				fragment.setArguments(arguments);
				getSupportFragmentManager().beginTransaction().add(R.id.item_detail_container, fragment).commit();
			}
		}

		/**
		 * Set up the {@link android.app.ActionBar}, if the API is available.
		 */
		@TargetApi(Build.VERSION_CODES.HONEYCOMB)
		private void setupActionBar() {
			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
				getActionBar().setDisplayHomeAsUpEnabled(true);
			}
		}

		@Override
		public boolean onCreateOptionsMenu(Menu menu) {
			// Inflate the menu; this adds items to the action bar if it is present.
			getMenuInflater().inflate(R.menu.detail, menu);
			return true;
		}

		@Override
		public boolean onOptionsItemSelected(MenuItem item) {
			switch (item.getItemId()) {
			case android.R.id.home:
				NavUtils.navigateUpFromSameTask(this);
				return true;
				
			case R.id.action_delete:
				long id = getIntent().getLongExtra(ItemDetailFragment.ARG_ITEM_ID, -1);
				if(id != -1) {
					getContentResolver().delete(ContentUris.withAppendedId(DataProvider.CONTENT_URI_DATA, id), null, null);
					finish();
				}
				return true;			
			}
			return super.onOptionsItemSelected(item);
		}

	}
					
Most of the code was generated by the wizard including code for handling up navigation in onOptionsItemSelected() method. However, we modified onCreate() method to display ItemDetailFragment, and onOptionsItemSelected() method to add delete functionality.
For adding delete item menu option to the screen you'll need to modify the generated detail.xml file under res/menu directory as follows.
	<menu xmlns:android="http://schemas.android.com/apk/res/android"
		xmlns:myapp="http://schemas.android.com/apk/res-auto" >
		
		<item
			android:id="@+id/action_delete"
			android:showAsAction="always"
			myapp:showAsAction="always"
			android:icon="@android:drawable/ic_menu_delete"
			android:title="@string/action_delete"/>

	</menu>
						
Finally, let's take a look at the activity_detail.xml layout file for this activity.
	<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
		xmlns:tools="http://schemas.android.com/tools"
		android:id="@+id/item_detail_container"
		android:layout_width="match_parent"
		android:layout_height="match_parent"
		tools:context=".DetailActivity"
		tools:ignore="MergeRootFrame" />
						
Since we are using a fragment i.e. ItemDetailFragment for displaying content hence the layout is simply a place holder. Recall that we added the fragment using fragment transaction in onCreate() method of DetailActivity.
Share the love:  

Next Page » 9

App Gen
App Name:
Project Name:
Package:
Screens:
Splash
Login
Help
Main
List  Grid  Pager
Detail
Settings
Options:
Action Bar
Navigation Drawer
Dummy Data
Generate
Free Apps