Android tutorial – Screen with tabs and swipe – part I

This is how you can make an app with a main screen using tabs and swipe. For the first part of this tutorial we’ll just create the simple version of the app, in the next parts we’ll see all there is to know about compatibility management, styling and customizing everything. So let’s start.

We’ll use a simple architecture with Fragments to be shown in each tab and a main Activity with a FragmentPagerAdapter to control everything.

First, the layouts – main layout (activity_main.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">

</android.support.v4.view.ViewPager>

As you can see, all we need is the ViewPager filling the screen.

A fragment layout – (fragment_tab1.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ff8433" >

    <TextView android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="Tab 1 content"
        android:textSize="20dp"
        android:textColor="@android:color/black"
        android:layout_centerInParent="true"/>

</RelativeLayout>

The other layouts for fragments keep the same format. You may download all from the attached sources at the end of this post.

For the fragments classes for now we only need to load the layout – (Tab1Frag.java):

package com.indyvision.test.tabswipe.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.indyvision.test.tabswipe.R;

public class Tab1Frag extends Fragment {

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {

		View rootView = inflater.inflate(R.layout.fragment_tab1, container, false);

		return rootView;
	}
}

The adapter for now will only return new fragments for each tab request – (TabsPagerAdapter.java):

package com.indyvision.test.tabswipe.adapters;

import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;

import com.indyvision.test.tabswipe.fragments.Tab1Frag;
import com.indyvision.test.tabswipe.fragments.Tab2Frag;
import com.indyvision.test.tabswipe.fragments.Tab3Frag;
import com.indyvision.test.tabswipe.fragments.Tab4Frag;

public class TabsPagerAdapter extends FragmentPagerAdapter {
	private static final int NO_OF_TABS = 4;

	public TabsPagerAdapter(FragmentManager fm) {
		super(fm);
	}

	@Override
	public Fragment getItem(int index) {

		switch (index) {
		case 0:
			return new Tab1Frag();
		case 1:
			return new Tab2Frag();
		case 2:
			return new Tab3Frag();
		case 3:
			return new Tab4Frag();
		}

		return null;
	}

	@Override
	public int getCount() {
		return NO_OF_TABS;
	}

}

Important here are the getItem() and getCount() methods – the first manages what fragment is given to the ViewPager in the main screen to be displayed, the second one gives the total number of tabs we want to show.

Now let’s put everything togheter in the main Activity – (MainActivity.java):

package com.indyvision.test.tabswipe.activities;

import android.app.ActionBar;
import android.app.ActionBar.Tab;
import android.app.FragmentTransaction;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.view.ViewPager;

import com.indyvision.test.tabswipe.R;
import com.indyvision.test.tabswipe.adapters.TabsPagerAdapter;

public class MainActivity extends FragmentActivity implements
		ActionBar.TabListener {

	private ViewPager viewPager;
	private TabsPagerAdapter adapter;
	private ActionBar actionBar;

	private String[] tabs = { "tab 1", "tab 2", "tab 3", "tab 4" };

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		viewPager = (ViewPager) findViewById(R.id.pager);
		actionBar = getActionBar();
		adapter = new TabsPagerAdapter(getSupportFragmentManager());

		viewPager.setAdapter(adapter);
		actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

		for (String tab_name : tabs) {
			actionBar.addTab(actionBar.newTab().setText(tab_name)
					.setTabListener(this));
		}

		viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

			@Override
			public void onPageSelected(int position) {
				actionBar.setSelectedNavigationItem(position);
			}

			@Override
			public void onPageScrolled(int arg0, float arg1, int arg2) {
			}

			@Override
			public void onPageScrollStateChanged(int arg0) {
			}
		});
	}

	@Override
	public void onTabReselected(Tab tab, FragmentTransaction ft) {
	}

	@Override
	public void onTabSelected(Tab tab, FragmentTransaction ft) {
		viewPager.setCurrentItem(tab.getPosition());
	}

	@Override
	public void onTabUnselected(Tab tab, FragmentTransaction ft) {
	}

}

First of all, here we are using the classic Fragments and ActionBar methods and that makes our app compatible only with devices Android 3.0+. We’ll take care of lower Android versions in the next tutorial.

We need compatibility library v4 for lower Android versions – see this for details. To install – copy the JAR file from your Android SDK installation directory (e.g., /extras/android/support/v4/android-support-v4.jar) into your application’s project libs/ directory. Right click the JAR file and select Build Path > Add to Build Path.

We are using the viewPager to display the fragments and the actionBar for the titles. The tabs variable contains the titles of each tab – in the following tutorials we’ll see how we can fully customize the titles contents. All tabs are initialized in this case in a for loop:

	for (String tab_name : tabs) {
		actionBar.addTab(actionBar.newTab().setText(tab_name)
			.setTabListener(this));
	}

Our Activity implements ActionBar.TabListener in order to be able to process tab selection and switch the viewPager to the corresponding fragment:

viewPager.setCurrentItem(tab.getPosition());

On the other side, when the user switches by slide the current page displayed in the viewPager, we must update the ActionBar with the new situation, thus implementing ViewPager.OnPageChangeListener() with:

@Override
	public void onPageSelected(int position) {
		actionBar.setSelectedNavigationItem(position);
	}

The last thing we need is the manifest file:

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

    <uses-sdk
        android:minSdkVersion="11"
        android:targetSdkVersion="17" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.indyvision.test.tabswipe.activities.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

That’s all, now you have a swipeable main activity for your app. You can download the source code from here. Next time we’ll see how we can modify our code to support older Android versions.

Leave a Reply

You must be logged in to post a comment.