Android UI學習 - Tab的學習和使用

鴨脖發表於2012-07-19

TabActivity

  首先Android裡面有個名為TabActivity來給我們方便使用。其中有以下可以關注的函式:
  public TabHost getTabHost ()  獲得當前TabActivity的TabHost
  public TabWidget getTabWidget () 獲得當前TabActivity的TabWidget
 
  public void setDefaultTab (String tag) 這兩個函式很易懂,就是設定預設的Tab
  public void setDefaultTab (int index)  通過tab名——tag或者index(從0開始)
  
  protected void onRestoreInstanceState (Bundle state) 這兩個函式的介紹可以
  protected void onSaveInstanceState (Bundle outState) 參考 Activity的生命週期
 

TabHost

  那麼我們要用到的Tab載體是TabHost,需要從TabActivity.getTabHost獲取。
  現在看看TabHost類,它有3個內嵌類:1個類TabHost.TabSpec,2個介面TabHost.TabContentFactory和TabHost.OnTabChangeListener。後面會介紹這些類和介面。
 
  TabHost類的一些函式:
  public void addTab (TabHost.TabSpec tabSpec) 新增tab,引數TabHost.TabSpec通過下面的函式返回得到
  public TabHost.TabSpec newTabSpec (String tag) 建立TabHost.TabSpec
  
  public void clearAllTabs () remove所有的Tabs
  public int getCurrentTab ()
  public String getCurrentTabTag ()
  public View getCurrentTabView ()
  public View getCurrentView ()
  public FrameLayout getTabContentView () 返回Tab content的FrameLayout
 
  public TabWidget getTabWidget ()
  public void setCurrentTab (int index)       設定當前的Tab by index
  public void setCurrentTabByTag (String tag) 設定當前的Tab by tag
  public void setOnTabChangedListener (TabHost.OnTabChangeListener l) 設定TabChanged事件的響應處理
  public void setup () 這個函式後面介紹
 

TabHost.TabSpec

  從上面的函式可以知道如何新增tab了,要注意,這裡的Tag(標籤),不是Tab按鈕上的文字。
  而要設定tab的label和content,需要設定TabHost.TabSpec類。 引用SDK裡面的話——“A tab has a tab indicator, content, and a tag that is used to keep track of it.”,TabHost.TabSpec就是管理這3個東西:
  public String getTag ()
  public TabHost.TabSpec setContent
  public TabHost.TabSpec setIndicator
 
  我理解這裡的Indicator就是Tab上的label,它可以
  設定label: setIndicator (CharSequence label)
  或者同時設定label和iconsetIndicator (CharSequence label, Drawable icon)
  或者直接指定某個view: setIndicator (View view)
  
  對於Content,就是Tab裡面的內容,可以
  設定View的id: setContent(int viewId)
  或者TabHost.TabContentFactory的createTabContent(String tag)來處理:setContent(TabHost.TabContentFactory contentFactory)
  或者用new Intent來引入其他Activity的內容:setContent(Intent intent)
  
  現在來看官方的Views/Tabs/Content By Id例子:

TabHost

   程式碼
  1. public class Tabs1 extends TabActivity { 
  2.  
  3.     @Override 
  4.     protected void onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.         TabHost tabHost = getTabHost(); 
  7.          
  8.         LayoutInflater.from(this).inflate(R.layout.tabs1, tabHost.getTabContentView(), true); 
  9.  
  10.         tabHost.addTab(tabHost.newTabSpec("tab1"
  11.                 .setIndicator("tab1"
  12.                 .setContent(R.id.view1)); 
  13.         tabHost.addTab(tabHost.newTabSpec("tab3"
  14.                 .setIndicator("tab2"
  15.                 .setContent(R.id.view2)); 
  16.         tabHost.addTab(tabHost.newTabSpec("tab3"
  17.                 .setIndicator("tab3"
  18.                 .setContent(R.id.view3)); 
  19.     } 
   原來在獲取TabHost後,需要用LayoutInflater來得到Layout,LayoutInflater在後面就詳細介紹。R.layout.tabs1的內容:
  1. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.     android:layout_width="fill_parent" 
  3.     android:layout_height="fill_parent"> 
  4.  
  5.     <TextView android:id="@+id/view1" 
  6.         android:background="@drawable/blue" 
  7.         android:layout_width="fill_parent" 
  8.         android:layout_height="fill_parent" 
  9.         android:text="@string/tabs_1_tab_1"/> 
  10.  
  11.     <TextView android:id="@+id/view2" 
  12.         android:background="@drawable/red" 
  13.         android:layout_width="fill_parent" 
  14.         android:layout_height="fill_parent" 
  15.         android:text="@string/tabs_1_tab_2"/> 
  16.  
  17.     <TextView android:id="@+id/view3" 
  18.         android:background="@drawable/green" 
  19.         android:layout_width="fill_parent" 
  20.         android:layout_height="fill_parent" 
  21.         android:text="@string/tabs_1_tab_3"/> 
  22.  
  23. </FrameLayout> 
  24.  
  25. <! -- strings.xml 
  26.     <string name="tabs_1_tab_1">tab1</string> 
  27.     <string name="tabs_1_tab_2">tab2</string> 
  28.     <string name="tabs_1_tab_3">tab3</string> 
  29. --> 
  原來是用FrameLayout的!
  而讓Tab1的內容顯示tab1且背景為Blue,是setContent(R.id.view1)這裡引用了TextView1。現在就基本明白如何新增tab以及如何設定label和content了。
 
  接下來看看Views/Tabs/Content By Factory的例子:

TabHost2

  程式碼
  1. public class Tabs2 extends TabActivity implements TabHost.TabContentFactory { 
  2.  
  3.     @Override 
  4.     protected void onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.  
  7.         final TabHost tabHost = getTabHost(); 
  8.         tabHost.addTab(tabHost.newTabSpec("tab1"
  9.                 .setIndicator("tab1", getResources().getDrawable(R.drawable.star_big_on)) 
  10.                 .setContent(this)); 
  11.         tabHost.addTab(tabHost.newTabSpec("tab2"
  12.                 .setIndicator("tab2"
  13.                 .setContent(this)); 
  14.         tabHost.addTab(tabHost.newTabSpec("tab3"
  15.                 .setIndicator("tab3"
  16.                 .setContent(this)); 
  17.     } 
  18.  
  19.     public View createTabContent(String tag) { 
  20.         final TextView tv = new TextView(this); 
  21.         tv.setText("Content for tab with tag " + tag); 
  22.         return tv; 
  23.     } 
    可以看到通過override重寫(重新實現)父類TabHost.TabContentFactory中的方法View createTabContent(String tag)來實現不同tab的不同content。同時在setContent的引數設定為相應的TabContentFactory。
   原來createTabContent是在每個tab第一次顯示時才呼叫的,隨後再次顯示該tab就不會再次呼叫的,我自己用Logcat檢視到的!這一點很關鍵,就是說在createTabContent是在tab沒有完全建立前呼叫的,這意味在createTabContent裡面是不能呼叫getCurrentTabView等之類的函式的,否則就出錯!
 
   至於Views/Tabs/Content By Intent例子,就只是貼出程式碼,不給截圖了:
  1. public class Tabs3 extends TabActivity { 
  2.  
  3.     @Override 
  4.     protected void onCreate(Bundle savedInstanceState) { 
  5.         super.onCreate(savedInstanceState); 
  6.  
  7.         final TabHost tabHost = getTabHost(); 
  8.  
  9.         tabHost.addTab(tabHost.newTabSpec("tab1"
  10.                 .setIndicator("list"
  11.                 .setContent(new Intent(this, List1.class))); 
  12.  
  13.         tabHost.addTab(tabHost.newTabSpec("tab2"
  14.                 .setIndicator("photo list"
  15.                 .setContent(new Intent(this, List8.class))); 
  16.          
  17.         // This tab sets the intent flag so that it is recreated each time 
  18.         // the tab is clicked. 
  19.         tabHost.addTab(tabHost.newTabSpec("tab3"
  20.                 .setIndicator("destroy"
  21.                 .setContent(new Intent(this, Controls2.class
  22.                         .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP))); 
  23.     } 
效果:Tab1的內容是List1的Activity,Tab2的是List8的Activity,Tab3的是controls2.Activity。
 

TabHost.OnTabChangeListener

   TabHost.OnTabChangeListener介面只有一個抽象方法onTabChanged(String tagString),明顯地,在onTabChanged(String tagString)方法裡面swtich..case..來判斷tagString分別處理就行了。
 

TabHost.setup()

  在此貼出SDK doc裡面的相關解釋:
public void setup ()         Since: API Level 1
Call setup() before adding tabs if loading TabHost using findViewById(). However,You do not need to call setup() after getTabHost() in TabActivity. Example:
 
     mTabHost = (TabHost)findViewById(R.id.tabhost);
     mTabHost.setup();
     mTabHost.addTab(TAB_TAG_1, "Hello, world!", "Tab 1");
 
//我的理解是,如果要用到findViewById來獲取TabHost,然後add tabs的話,需要在addTab前call setup();
 
public void setup (LocalActivityManager activityGroup)         Since: API Level 1
If you are using setContent(android.content.Intent), this must be called since the activityGroup is needed to launch the local activity. This is done for you if you extend TabActivity.
 
Parameters
activityGroup Used to launch activities for tab content.

本文出自 “學習Android” 部落格,請務必保留此出處http://android.blog.51cto.com/268543/315208

相關文章