Android:不使用TabActivity创建TabHost

42

我希望创建选项卡而不需要扩展TabActivity。(原因是TabActivity不能处理自定义标题栏,至少看起来是这样)。 我已经...

public class startTab extends Activity {

 @Override
 public void onCreate(Bundle savedInstanceState) 
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.mylayout);
        Resources res = getResources();
        LocalActivityManager mlam = new LocalActivityManager(this, false);
        TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
        tabHost.setup(mlam);
        TabHost.TabSpec spec;
        Intent intent;

    intent = new Intent().setClass(this, Show1.class);
    spec = tabHost.newTabSpec("Items").setIndicator("Items", res.getDrawable(R.drawable.items32_ldpi)).setContent(intent);
    tabHost.addTab(spec);

    intent = new Intent().setClass(this, Show2.class);
    spec = tabHost.newTabSpec("Users").setIndicator("Users",res.getDrawable(R.drawable.user32_ldpi)).setContent(intent);
    tabHost.addTab(spec);
}

我得到的错误是

    07-02 07:11:12.715: ERROR/AndroidRuntime(411): 
Caused by: java.lang.IllegalStateException: Activities can't be added until the containing group has been created.

视图的XML代码如下:
<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
 android:id="@+id/tabhost" android:orientation="vertical" android:layout_width="fill_parent"
 android:layout_height="fill_parent" >
 <LinearLayout android:orientation="vertical"
  android:layout_width="fill_parent" android:layout_height="fill_parent"
  android:paddingTop="5dip">
  <TabWidget android:id="@android:id/tabs"
   android:layout_width="fill_parent" android:layout_height="fill_parent"></TabWidget>
  <FrameLayout android:id="@android:id/tabcontent"
   android:layout_width="fill_parent" android:layout_height="fill_parent"
   android:paddingTop="5dip">
  </FrameLayout>
 </LinearLayout>
</TabHost>

我在某处读到,需要使用LocalActivityManager,但我猜我可能漏掉了些什么。有没有人知道这是怎么回事呢?

谢谢!


这个教程可能会对你有所帮助:http://learnncode.wordpress.com/2013/12/18/how-to-use-tabwidget-with-fragments/ - Prachi
4个回答

86

在调用 tabHost.setup(mLocalActivityManager) 之前,你需要添加这一行。

mlam.dispatchCreate(savedInstanceState);
tabHost.setup(mlam );

同样地,你需要为onResume添加。

mlam.dispatchResume(); 

onPause()方法,

 mlam.dispatchPause(isFinishing());

4
为什么添加这些dispatchXXX()方法后会起效呢?能否解释一下?非常感谢:) - shihpeng
1
太好了!但是这些额外的行有什么原因吗? - mudit
onStop() 中是否需要使用 dispatchStop(),并在 onDestroy() 中使用 dispatchDestroy() - Someone Somewhere
根据http://alvinalexander.com/java/jwarehouse/android/core/java/android/app/ActivityGroup.java.shtml的说法,这是必需的,但我看到了很多由dispatchDestroy()引起的空指针异常。 - Someone Somewhere
节省了我很多时间,谢谢。 - skryshtafovych
显示剩余4条评论

13

请考虑将Views作为选项卡的内容。这不仅可以减少代码量、堆空间和栈空间的消耗,降低CPU利用率,还可以解决这个问题。这里有两个示例(链接)(链接)展示了这种技术。


1
谢谢。但是如果我不使用意图,我怎么能为每个选项卡拥有不同的菜单? - paradroid666
@paradroid:根据当前活动的选项卡加载不同的菜单。 - CommonsWare
这就是使用活动的全部意义 - 它是更好的功能分离。 - AlikElzin-kilaka
2
@kilaka:并不是。在选项卡中的活动已被弃用,因为Google认为这是一个糟糕的想法。 - CommonsWare

4
public class ScoreboardActivity extends Activity {
    LocalActivityManager mlam;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scoreboard);
        mlam = new LocalActivityManager(this, false);
        mlam.dispatchCreate(savedInstanceState);
        TabHost th = (TabHost) findViewById(android.R.id.tabhost);
        th.setup(mlam);
        th.addTab(th.newTabSpec("Numpad").setIndicator("Numpad").setContent(R.id.tab1));
        th.addTab(th.newTabSpec("CardCount").setIndicator("CardCount").setContent(R.id.tab2));
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_scoreboard, menu);
        return true;


    }
    @Override
    protected void onResume(){
        super.onResume();
        mlam.dispatchResume();
    }

    @Override
    protected void onPause(){
        super.onPause();
        mlam.dispatchPause(isFinishing());
    }

}

1
LocalActivityManager现在已经被弃用。 - Mārtiņš Briedis

1

除了设计考虑之外,以下内容根本不起作用,而API似乎表明setContent(Intent i)是有效的。当活动扩展为TabActivity时,它可以工作,但是,扩展Activity并添加setup()调用会导致exception at android.widget.TabHost$IntentContentStrategy.getContentView(TabHost.java:649)

有趣的是,LogCat建议我忘记调用setup()

mTabHost = (TabHost) findViewById(android.R.id.tabhost);
mTabHost.setup();

Intent tab1Intent = new Intent(this, ActivityOne.class);
Button tab1View = new Button(this);
tab1View.setText("Activity 1");
  mTabHost.addTab(mTabHost.newTabSpec("tab_1").setIndicator(tab1View).setContent(tab1Intent));

这看起来应该是一个单独的问题。你可能遇到的问题是你没有使用TabbedActivity,这意味着你需要像上面建议的那样使用ActivityManager进行设置。除非你正确地将事件分派给ActivityManager,否则这将导致你遇到这个问题。 - shortstuffsushi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接