In a previous post I wrote an example of Layout Tab using a TabActivity class that it is deprecated since version 3.0 Honeycomb of Android.
In this post I develop the same interface using ActionBar and Fragment, and I tried wherever possible to limit the changes to the files *.xml.
- create an Android project called TabActionBar, a package eu.lucazanini and an activity TabActionBarActivity.java
- edit the file AndroidManifest.xml, it should be the default one
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="eu.lucazanini" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".TabActionBarActivity" 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>
- edit the file /res/values/strings.xml, to manage the labels
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">TabActionBar</string> <string name="label1">one</string> <string name="label2">two</string> <string name="body1"> body one</string> <string name="body2">body two</string> </resources>
- edit the file res/layout/main.xml, it should be the default one (this file is not used, so you can skip this step, see the comments below)
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > </LinearLayout>
- create the files res/layout/tab1.xml and res/layout/tab2.xml, representing the contents of 2 tabs
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tab1" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/body1" /> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tab2" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:gravity="center"> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:text="@string/body2" /> </LinearLayout>
- edit the class TabActionBarActivity.java, note that the labels of the tabs will be capitalized and that eventually you can put an icon or a view with the methods setIcon or setCustomView
package eu.lucazanini; 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; public class TabActionBarActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar actionBar = getActionBar(); actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); String label1 = getResources().getString(R.string.label1); Tab tab = actionBar.newTab(); tab.setText(label1); TabListener<Tab1Fragment> tl = new TabListener<Tab1Fragment>(this, label1, Tab1Fragment.class); tab.setTabListener(tl); actionBar.addTab(tab); String label2 = getResources().getString(R.string.label2); tab = actionBar.newTab(); tab.setText(label2); TabListener<Tab2Fragment> tl2 = new TabListener<Tab2Fragment>(this, label2, Tab2Fragment.class); tab.setTabListener(tl2); actionBar.addTab(tab); } private class TabListener<T extends Fragment> implements ActionBar.TabListener { private Fragment mFragment; private final Activity mActivity; private final String mTag; private final Class<T> mClass; /** * Constructor used each time a new tab is created. * * @param activity * The host Activity, used to instantiate the fragment * @param tag * The identifier tag for the fragment * @param clz * The fragment's Class, used to instantiate the fragment */ public TabListener(Activity activity, String tag, Class<T> clz) { mActivity = activity; mTag = tag; mClass = clz; } public void onTabSelected(Tab tab, FragmentTransaction ft) { // Check if the fragment is already initialized if (mFragment == null) { // If not, instantiate and add it to the activity mFragment = Fragment.instantiate(mActivity, mClass.getName()); ft.add(android.R.id.content, mFragment, mTag); } else { // If it exists, simply attach it in order to show it ft.attach(mFragment); } } public void onTabUnselected(Tab tab, FragmentTransaction ft) { if (mFragment != null) { // Detach the fragment, because another one is being attached ft.detach(mFragment); } } public void onTabReselected(Tab tab, FragmentTransaction ft) { // User selected the already selected tab. Usually do nothing. } } }
- create the classes Tab1Fragment.java and Tab2Fragment.java
package eu.lucazanini; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; public class Tab1Fragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return (LinearLayout) inflater.inflate(R.layout.tab1, container, false); } }
package eu.lucazanini; import android.app.Fragment; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; public class Tab2Fragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return (LinearLayout) inflater.inflate(R.layout.tab2, container, false); } }
- launch the app
Leave a Reply