Android Development 23

Android ViewPagerIn this part of my Android Development Tutorial I will cover how to use the Android ViewPager. The ViewPager allows you to flip through Fragments sort of like you would do with a book.

I’ll also cover how to connect the ViewPager with a FragmentManager so that we’ll be able to properly display and track the Fragments and make sure they are updated. If you missed previous parts of this tutorial you should start with part 18. The code follows the video.

If you like videos like this it helps to tell Google+ with a click here

Code From the Video

ContactViewPager.java

package com.newthinktank.censusapp;

// ALL 100% NEW

import java.util.ArrayList;
import java.util.UUID;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;

// ViewPager is a layout manager that allows you to flip left 
// and right through pages in your app.

public class ContactViewPager extends FragmentActivity{
	
	private ViewPager theViewPager;
	
	private ArrayList<Contact> contactList;

	@Override
	protected void onCreate(Bundle arg0) {

		super.onCreate(arg0);
		
		theViewPager = new ViewPager(this);
		
		// When using FragmentPagerAdapter the ViewPager must
		// have an id (/res/values/ids.xml)
		
		theViewPager.setId(R.id.viewPager);
		
		// Set the current View for the ViewPager
		
		setContentView(theViewPager);
		
		// Checks if an instance of allContacts exists. If it does
		// the one instance is returned. Otherwise the instance is
		// created. (Remember there is only 1 contact list)
		
		contactList = AllContacts.get(this).getContactList();
		
		// The FragmentManager ads Fragments to Activity views
		
		FragmentManager fragManager = getSupportFragmentManager();
		
		// Just like the AdapterView requires an Adapter like we
		// used in FragmentContactList, a ViewPager requires a
		// PagerAdapter.
		
		// The PagerAdapter provides the Adapter for populating 
		// pages inside of the ViewPager. 
		
		// The FragmentStatePagerAdapter implements the PagerAdapter.
		// It uses a Fragment to manage each page. It also saves
		// and restores each pages state.
		
		theViewPager.setAdapter(new FragmentStatePagerAdapter(fragManager) {
			
			@Override
			public Fragment getItem(int position) {
				
				// Gets the specific Contact from the right position
				// in the ArrayList
				
				Contact theContact = contactList.get(position);
				
				// Return a ContactFragment by retrieving the id 
				// number from the current Contact
				
				return ContactFragment.newContactFragment(theContact.getIdNumber());
				
			}

			// Returns the number of items in the ArrayList
			
			@Override
			public int getCount() {
				return contactList.size();
			}
			
		});
		
		// If you run the app now the pages can be flipped through
		// but if you click on one from the list it will always 
		// display the first. Let's change that by setting the ViewPagers
		// current item to the Contact clicked on
		
		UUID contactId = (UUID) getIntent()
				.getSerializableExtra(ContactFragment.CONTACT_ID);
		
		// Cycle through the Contacts in the ArrayList to find a match
		// Set the current position of the match in setCurrentItem
		
		for(int i = 0; i < contactList.size(); i++){
			
			if(contactList.get(i).getIdNumber().equals(contactId)){
				
				theViewPager.setCurrentItem(i);
				break;
				
			}
			
		}
		
		theViewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
			
			@Override
			public void onPageSelected(int position) {
				
				setTitle("Citizen #" + position);
				
			}
			
			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
				// TODO Auto-generated method stub
				
			}
			
			@Override
			public void onPageScrollStateChanged(int arg0) {
				// TODO Auto-generated method stub
				
			}
		});
		
	}
}

ids.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    
    <!-- Used to define the resource id for your 
    ViewPager. The FragmentManager requires all
    views used as a Fragment container to have
    an id -->
    
    <item type="id" name="viewPager" />
    
</resources>

FragmentContactList.java

package com.newthinktank.censusapp;

import java.util.ArrayList;

import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ListFragment;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.TextView;

// The ListFragment displays a list of items in a 
// ListView, by binding to our ArrayList using an
// ArrayAdapter in this situation.

public class FragmentContactList extends ListFragment {
	
	// Stores the list of Contacts
	
	private ArrayList<Contact> contactList;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		// Change the title for the current Activity
		
		getActivity().setTitle(R.string.fragment_contact_list_title);
		
		// Get the ArrayList from AllContacts
		
		contactList = AllContacts.get(getActivity()).getContactList();
		
		ContactAdapter contactAdapter = new ContactAdapter(contactList);
		
		// Provides the data for the ListView by setting the Adapter 
		
		setListAdapter(contactAdapter);
		
	}
	
	@Override
	public void onListItemClick(ListView l, View v, int position, long id) {
		
		Contact clickedContact = ((ContactAdapter) getListAdapter()).getItem(position);
		
		// NEW
		// We want our ContactViewPager to be called now if they click 
		// on a Contact
		
		// Intent newIntent = new Intent(getActivity(), CensusApp.class);
		
		// startActivityForResult(newIntent, 0);
		
		Intent newIntent = new Intent(getActivity(), ContactViewPager.class);
		
		newIntent.putExtra(ContactFragment.CONTACT_ID, clickedContact.getIdNumber());
		
		startActivity(newIntent);
		
		// END OF NEW
		
	}

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		
		((ContactAdapter) getListAdapter()).notifyDataSetChanged();
		
	}




	private class ContactAdapter extends ArrayAdapter<Contact> {

		public ContactAdapter(ArrayList<Contact> contacts) {
	    	
	    		// An Adapter acts as a bridge between an AdapterView and the 
				// data for that view. The Adapter also makes a View for each 
				// item in the data set. (Each list item in our ListView)
			
				// The constructor gets a Context so it so it can use the 
				// resource being the simple_list_item and the ArrayList
				// android.R.layout.simple_list_item_1 is a predefined 
				// layout provided by Android that stands in as a default
	    	
	            super(getActivity(), android.R.layout.simple_list_item_1, contacts);
	    }
		
		// getView is called each time it needs to display a new list item
		// on the screen because of scrolling for example.
		// The Adapter is asked for the new list row and getView provides
		// it.
		// position represents the position in the Array from which we will 
		// be pulling data.
		// convertView is a pre-created list item that will be reconfigured 
		// in the code that follows.
		// ViewGroup is our ListView
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			
			// Check if this is a recycled list item and if not we inflate it
			
			if(convertView == null){
				
				convertView = getActivity().getLayoutInflater()
						.inflate(R.layout.list_item_contact, null);
				
			}
			
			// Find the right data to put in the list item
			
			Contact theContact = getItem(position);
			
			// Put the right data into the right components
			
			TextView contactNameTextView =
	                (TextView)convertView.findViewById(R.id.contact_name);
			
			contactNameTextView.setText(theContact.getName());
			
	        TextView streetTextView =
	                (TextView)convertView.findViewById(R.id.contact_street);
	        
	        streetTextView.setText(theContact.getStreetAddress());
	        
	        CheckBox contactedCheckBox =
	                (CheckBox)convertView.findViewById(R.id.contact_contacted_checkbox);
	        
	        contactedCheckBox.setChecked(theContact.getContacted());
			
			// Return the finished list item for display
			
	        return convertView;
			
		}
		
	}

}

AndroidManifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.newthinktank.censusapp"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="18" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        
        <activity
            android:name="com.newthinktank.censusapp.ContactListActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        
        <!-- NEW 
        Make ContactViewPager an Activity over CensusApp 
        <activity
            android:name="com.newthinktank.censusapp.CensusApp"
            android:label="@string/app_name" >
        </activity>
        
 END OF NEW -->

<!-- NEW -->
        
       <activity
            android:name="com.newthinktank.censusapp.ContactViewPager"
            android:label="@string/app_name" >
        </activity>

<!-- END OF NEW -->
        
    </application>

</manifest>

4 Responses to “Android Development 23”

  1. Calvin says:

    Hi I have trouble understanding part of the ViewPager adapter code. Can you clarify how ViewPager manages the state of each ContactFragment, when your code returns a new ContactFragment every time getItem() is called? Thanks!

  2. Ronak Lakhwani says:

    Hi,

    First my Question is why we are not using startActivityForResult() method.

    Secondly when I click on a list item and then change the details and then change the page and then again change the details and go back to the list, the name are all set to empty strings.

    • Derek Banas says:

      Hi,

      I cover startActivityForResult later in the tutorial. I’m basically trying to cover most everything in these tutorials. As they continue I start honing them and making more complete apps.

  3. Fernando says:

    Hi Derek!!
    You are awesome! I’m speechless staring to your tutorial!! Thank you very much, really.

    I think, my problem is related with the yun zhou’s comment in the tutorial part 22, I can’t understand that problem with the focus, but yun zhou’s comment fixed it for me. Could you explain it?

    Similar to this problem I have other in this part of the tutorial, I introduced this little change:

    public void onPageScrolled(int i, float v, int i2) { Contact theContact = contactList.get(i);
    setTitle(“Mr: ” + theContact.getName());}

    And everything seems to work fine until I scroll to the first person and the tittle become to “Mr 99999999” (the telephone number). Could you help me?

    Thank you a lot, your work is amazing!!!

Leave a Reply

Your email address will not be published.

Google+