頁籤(TabHost)在行動APP中扮演了很重要的角色,由於手機的畫面比較小,因此如果有很多功能需要提供給使用者,不太可能全部擠在同一個頁面,因此頁籤功能可以讓使用者有比較好的體驗,讓使用者操作起來就像在「同一個頁面」,要切換功能也比較方便。但Google TabHost找到的範例大多是使用TabActivity來操作TabHost,而官網已經明確的指出TabActivity這個類別已經過期(deprecated)。

This class is deprecated.
New applications should use Fragments instead of this class; to continue to run on older devices, you can use the v4 support library which provides a version of the Fragment API that is compatible down to DONUT.

照著上面官網所提到的可以透過Fragments來取代TabActivity的功能。
為了避免「我的股票精算師」往後也會面臨到這種困擾,小蛙開始找有沒有替代方案,既然過期的是TabActivity,TabActivity是繼承ActivityGroup,而ActivityGroup又是繼承Activity,那應該有可能將TabHost放置在Activity中吧?Google上發現的確有高手分享相關文章,小蛙就以「最少修改」的方式進行「我的股票精算師」修改,其實把TabActivity用Activity取代並不難,但是不知道從何修改起,也不知道問題到底在哪,從官方的TabActivity原始碼中應該可以看出一些端倪,看來要增進自己的能力還是必須要多看官方原始碼才行。
不廢話了,直接進程式碼吧!TabHost的使用方法小蛙就不再另外說明了,Google一下就有很多。這裡直接說明要修改的部分。小蛙參考了Stack Overflow這篇文章,建立TabHost的方始與使用TabActivity時完全相同,要修改部分如下(上面是原始版本,下面是修改過後的版本):
1. 把TabActivity改成Activity(廢話 …)

public class MainActivity extends TabActivity
public class MainActivity extends Activity

2. 取得TabHost物件,這裡不能透過像TabActivity一樣直接用getTabHost();。

TabHost tabHost = getTabHost();
TabHost tabHost = (TabHost)findViewById(android.R.id.tabhost);

3. 增加一個LocalActivityManager物件。這幾行是一定不能少,少了對大家都不好DDMS會一直報出大量的錯誤訊息。

LocalActivityManager lam = new LocalActivityManager(MainActivity.this, false);
lam.dispatchCreate(savedInstanceState);
mHost.setup(lam);

4. 最後最重要的重頭戲部份Override onPause及onResume(這個應該是有看過Source的人才知道的吧!小蛙太弱了><),少了這邊的設定,就算上面全部都對,到這邊還是會狂錯(感謝Stack Overflow的dcanh121以及CJ Villa)。

@Override
protected void onPause() {
    lam.dispatchPause(isFinishing());
    super.onPause();
}
@Override
protected void onResume() {
    lam.dispatchResume();
    super.onResume();
}

如果有任何一個步驟漏掉,會得到以下錯誤。

Caused by: java.lang.IllegalStateException: Activities can't be added until the containing group has been created.

到這邊就已經完成囉!其他tabHost.addTab的使用方式一模一樣。接下來會再另一篇說明怎麼在TabHost裡面切換多個Activity,並且讓每個頁籤中的Back Stack可以獨立運作。

One Reply to “Android TabHost Without TabActivity”

發表迴響

你的電子郵件位址並不會被公開。 必要欄位標記為 *