Android _ Tabs

download Android _ Tabs

of 26

  • date post

    27-Dec-2015
  • Category

    Documents

  • view

    71
  • download

    0

Embed Size (px)

Transcript of Android _ Tabs

  • 09/09/13 Android : Tabs. The Fragment Way | I Should Write This $#!T Down

    thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/ 1/26

    I Should Write This $#!T Down

    CLOSE ENCOUNTERS OF THE CODE KIND

    Android : Tabs. The Fragment Way

    04 OCTIf youre the die-hard follower (yes, I said the because the stats says there is) of this blog, you would have probably noticed that Ive been M.I.A for awhile. Well, its mainly been because Ive been working on an Android project with a super-toit deadline which we managed to launch JIT on to the Marketplace.

    Now that the first phase of that project is over, Im now able to reflect a bit on the code that was produced and share here some of my experiences and (source).

    In this first installment, I want to illustrate how to create a Tab activity using Fragments since, going-forward, it is suggested that building on Fragments willensure your app is compatible with pre-Honeycomb, Honeycomb and Ice Cream Sandwich (tablet and phone) OS versions (see this article (http://android-developers.blogspot.com/2011/09/preparing-for-handsets.html)). Remember, in Android 2.x Tabs are presented as classic filing tabs, while on Android 3.xand higher tabs are represented in the ActionBar (http://developer.android.com/guide/topics/ui/actionbar.html) UI component.

    Requirements

    To implement a Tabbed, using fragments on devices running Android 2.1 or higher, youll need to include the Android Compatibility(http://developer.android.com/sdk/compatibility-library.html) library. In my example, Im using Compatibility library v4

    Step-by-Step

    1. Define TabHost layout2. Define Tab fragment layouts3. Define Tab fragments4. Define main fragment activity

    The Code

    Define the TabHost layout

    The tabbed UI layout consists of 4 parts: TabHost, TabWidget, FrameLayout and the content layout. tabs_layout.xml illustrates how they stack up. Youllnotice that the FrameLayout id=realtabcontent is a child of a FrameLayout. Isnt this redundant? The answer is no, be attaching out fragments to thisFrameLayout.

  • 09/09/13 Android : Tabs. The Fragment Way | I Should Write This $#!T Down

    thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/ 2/26

    Define Tab fragment layouts

    Next, we define out fragment layouts (i.e the content layout for each tab). Nothing special hereyoud define your layout as if the layout was for a stand-aloneactivity. Below is tab_frag1_layout.xml (tab_frag2_layout.xml and tab_frag3_layout.xml are exactly the same except the have different colours specified fortheir backgrounds).

    Define Tab fragment classes

    Each tab content fragment needs to extend Fragment and inflate its corresponding layout. As youll see later, each fragment is instantiated by the mainFragmentActivity using the fragment manager. Below is the definition of TabFragment1.java (TabFragment2.java and TabFragment3.java are exactly the same,except they inflate their respective layouts)

  • 09/09/13 Android : Tabs. The Fragment Way | I Should Write This $#!T Down

    thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/ 3/26

    package com.andy.fragments.tabs;

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

    import com.andy.R;

    /** * @author mwho * */public class Tab1Fragment extends Fragment { /** (non-Javadoc) * @see android.support.v4.app.Fragment#onCreateView(android.view.LayoutInflater, android.view.ViewGroup, android.os.Bundle) */ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (container == null) { // We have different layouts, and in one of them this // fragment's containing frame doesn't exist. The fragment // may still be created from its saved state, but there is // no reason to try to create its view hierarchy because it // won't be displayed. Note this is not needed -- we could // just run the code below, where we would create and return // the view hierarchy; it would just never be used. return null; } return (LinearLayout)inflater.inflate(R.layout.tab_frag1_layout, container, false); }}

    Define the main FragmentActivity

    TabsFragmentActivity.java is where everything comes together. Firstly, youll notice that TabsFragmentActivity extends FragementActivity instead ofActivity.

    Next, we look at onCreate(). This is the starting point of our activity. The first step is to inflate the tabbed layout as defined in tabs_layout.xml. In step 2, weinitialise the tabs. This involves invoking setup() on the TabHost view, adding tabs, save some extrinsic tab info (TabInfo) into a map and then setting the firsttab content as active.

    /** * Step 2: Setup TabHost */ private void initialiseTabHost(Bundle args) { mTabHost = (TabHost)findViewById(android.R.id.tabhost); mTabHost.setup(); TabInfo tabInfo = null; TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab1").setIndicator("Tab 1"), ( tabInfo = new TabInfo("Tab1", Tab1Fragment.class, args))); this.mapTabInfo.put(tabInfo.tag, tabInfo); TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab2").setIndicator("Tab 2"), ( tabInfo = new TabInfo("Tab2", Tab2Fragment.class, args))); this.mapTabInfo.put(tabInfo.tag, tabInfo); TabsFragmentActivity.addTab(this, this.mTabHost, this.mTabHost.newTabSpec("Tab3").setIndicator("Tab 3"), ( tabInfo = new TabInfo("Tab3", Tab3Fragment.class, args))); this.mapTabInfo.put(tabInfo.tag, tabInfo); // Default to first tab this.onTabChanged("Tab1"); // mTabHost.setOnTabChangedListener(this); }

    I created a static helper method to add the tabs to the TabHost as defined by an instance of TabHost.TabSpec. Each TabSpec is initialised with an instance ofTabFactory (TabFactory is an inner class that extends TabContentFactory that creates an empty View as a placeholder for our fragments). Next, we detachthe Fragement associated with the tab were trying to add. Then, finally we add the TabSpec to the TabHost.

  • 09/09/13 Android : Tabs. The Fragment Way | I Should Write This $#!T Down

    thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/ 4/26

    private static void addTab(TabsFragmentActivity activity, TabHost tabHost, TabHost.TabSpec tabSpec, TabInfo tabInfo) { // Attach a Tab view factory to the spec tabSpec.setContent(activity.new TabFactory(activity)); String tag = tabSpec.getTag();

    // Check to see if we already have a fragment for this tab, probably // from a previously saved state. If so, deactivate it, because our // initial state is that a tab isn't shown. tabInfo.fragment = activity.getSupportFragmentManager().findFragmentByTag(tag); if (tabInfo.fragment != null && !tabInfo.fragment.isDetached()) { FragmentTransaction ft = activity.getSupportFragmentManager().beginTransaction(); ft.detach(tabInfo.fragment); ft.commit(); activity.getSupportFragmentManager().executePendingTransactions(); }

    tabHost.addTab(tabSpec); }

    Finally, we need to handle the onTabChanged() event handler where well create, attach or detach the fragments when a specific tab is clicked. WhenonTabChanged() is invoked a the tabs tag value is passed as a parameter. We use this tag value to look up the TabInfo instance we storedin initialiseTabHost(), which has a reference to the fragment associated with the implied tab.

    Our responsibility here is to detach the fragment for the tab were moving from, to the fragment for the tab that was clicked and to do nothing if the user clickedthe active tab.

    If the tabs fragment doesnt exist, its created using reflection on fragmentName.class on the FragmentManager by adding the fragment to the FrameLayoutid=realcontent.

    public void onTabChanged(String tag) { TabInfo newTab = this.mapTabInfo.get(tag); if (mLastTab != newTab) { FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction(); if (mLastTab != null) { if (mLastTab.fragment != null) { ft.detach(mLastTab.fragment); } } if (newTab != null) { if (newTab.fragment == null) { newTab.fragment = Fragment.instantiate(this, newTab.clss.getName(), newTab.args); ft.add(R.id.realtabcontent, newTab.fragment, newTab.tag); } else { ft.attach(newTab.fragment); } }

    mLastTab = newTab; ft.commit(); this.getSupportFragmentManager().executePendingTransactions(); } }

    Heres the big picture

    package com.andy.fragments.tabs;

    import java.util.HashMap;

    import android.content.Context;import android.os.Bundle;import android.support.v4.app.Fragment;import android.support.v4.app.FragmentActivity;import android.support.v4.app.FragmentTransaction;import android.view.View;import android.widget.TabHost;import android.widget.TabHost.TabContentFactory;

    import com.andy.R;

    /** * @author mwho

  • 09/09/13 Android : Tabs. The Fragment Way | I Should Write This $#!T Down

    thepseudocoder.wordpress.com/2011/10/04/android-tabs-the-fragment-way/ 5/26

    * */public class TabsFragmentActivity extends FragmentActivity implements TabHost.OnTabChangeListener {

    private TabHost mTabHost; private HashMap mapTabInfo = new HashMap(); private TabInfo mLastTab = nul