在Android中如何向选项卡布局(Tab Layout)添加控件?

13

我正在按照这篇教程 https://developer.android.com/guide/tutorials/views/hello-tabwidget.html 进行操作并且已经完成了。现在我想要向这些选项卡中添加一些控件,比如文本框(文本编辑)。

我该如何做呢?我打开我的 mail.xml 文件,使用 Eclipse 作为我的 IDE 并进入布局视图,但是我现在遇到了 NullPointerException,所以我甚至无法将东西拖放到布局中。

编辑

这是我目前拥有的内容:

<?xml version="1.0" encoding="utf-8"?>
<TabHost xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@android:id/tabhost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <TabWidget
            android:id="@android:id/tabs"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content" />
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
            <LinearLayout
                android:orientation="vertical"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">            
                <TextView 
                android:id="@+id/textview1"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" 
                android:text="this is a tab" />
                <EditText android:text="" android:id="@+id/EditText01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:password="true"></EditText>

            </LinearLayout>

            <TextView 
                android:id="@+id/textview2"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" 
                android:text="this is another tab" />
            <TextView 
                android:id="@+id/textview3"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent" 
                android:text="this is a third tab" />
        </FrameLayout>
    </LinearLayout>
</TabHost>

@chobo2:你看过我给出的答案吗?我认为我对这个问题进行了相当彻底的审查。 - Steve Haley
@Steve:抱歉,我正在参考它,因为我一直在写期末考试。 - chobo2
请注意,HelloTabWidget使用了已经过时的UI组件,并已从Android开发者网站中删除。 - Jeff Axelrod
4个回答

35

一开始要想让选项卡正常工作有点难,因为有很多代码开销,但是一旦你通过了这些难关,它们就不会太难了。为了让选项卡正常工作,首先我们需要改进您的 XML 文件,然后再确保您用来加载选项卡的代码是正确的。

首先,您的 XML 文件。您应该使用 include 功能,而不是直接将所有内容包含在 main.xml 中。正如名称所示,这使您可以在单独的 XML 文件上进行操作,然后使用一行将其包含在主文件中。这样可以使 main.xml 文件更易于阅读。所以我们会修改您的文件,使其看起来像这样:

//No need to change anything above this
<FrameLayout
    android:id="@android:id/tabcontent"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <include layout="@layout/tab1"/>
    <include layout="@layout/tab2"/>
    //and however many other tabs you want to include

</FrameLayout>

接下来,您需要创建tab1.xml、tab2.xml等文件。这些是普通的xml文件,以ViewGroup(即LinearLayout、RelativeLayout)开头,其中包含任意数量的其他小部件。这些小部件可以是EditText、按钮、自定义视图或任何您想要的东西。唯一的规则是父ViewGroup(顶部的那个)必须具有唯一的ID,以如下方式表示:android:id="@+id/someUniqueName"。您将使用该ID在代码中引用特定的布局/选项卡。例如:

tab1.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" 
    android:id="@+id/tab1Layout"
    android:orientation="vertical">

    <TextView ... />
    <EditText ... />
</LinearLayout>

有了这个以后,我们可以查看你的代码。我假设你已经拥有了这个,但是为了确保,以下是你需要的:

public class YourProject extends TabActivity {

    @Override
    public void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        Resources res = getResources();
        TabHost tabHost = getTabHost();

        tabHost.addTab(tabHost.newTabSpec("tab1").setIndicator("Tab1 title",
                res.getDrawable(R.drawable.logo1)).setContent(R.id.tab1Layout));

        (...)

        //You can also fill tabs with a separate activity like so:
        Intent intent = new Intent(this, YourClass.class);
        tabHost.addTab(tabHost.newTabSpec("tab2").setIndicator("Another title",
                res.getDrawable(R.drawable.logo2)).setContent(intent));

        tabHost.setCurrentTab(0);
    }
}

如上所示,您可以将选项卡中的内容设置为单独的活动。在这种情况下,该活动被定义为带有自己的类、布局等的任何其他活动。通常情况下,您不应该这样做,而应该使用不同的视图(例如通过 setContent(R.id.tabXLayout)),但有时需要这样做。例如,如果您想要一个选项卡具有列表,则需要在其中启动一个扩展ListView的活动,并包括所有ListView的样板代码。

希望这有所帮助!


我复制了你的代码,除了Intent部分,因为我不知道(YourClass.class)是干什么用的。它无法运行,我也不确定该如何查找错误,尝试使用调试器进行步进时出现了许多源代码未找到的错误。 - chobo2
好的,关于意图部分不用担心。这只是让您在主选项卡托管活动中使用另一个活动。在Android中进行调试与Eclipse中的普通调试有些不同,因为您没有运行独立程序;就Eclipse而言,它正在运行模拟器,而模拟器并没有崩溃,因此Eclipse没有报告任何易于阅读的内容。您需要做的是使用LogCat。请参见此答案以了解如何执行:https://dev59.com/Z3E85IYBdhLWcg3w6n90#2552801 - Steve Haley
嗯,我还在遇到问题。是否可能发送整个可运行的解决方案给我,以便我可以运行并尝试它? - chobo2
这基本上就是整个解决方案了。当你复制/粘贴时,你是否删除了“tab1.xml”?那只是告诉你那个XML应该放在一个叫做那个的文件中。LogCat消息说了什么? - Steve Haley
嘿,终于搞定了。我只是误读了你的一个步骤。我仍然不确定缩进还有什么作用以及如何设置它。 - chobo2

2
在Eclipse中的布局视图可能会有些不稳定,特别是对于复杂的布局。通过一些试错,你可能会找到它卡住的View节点。
关于进一步开发基于选项卡的布局,你有两个选择,一个是“快速”方式,另一个是“正确”的方式。第一种方法是通过将现有的布局xml替换为一个包含所需内容的LinearLayout(或其他布局)来进行适应。
然而,选项卡通常用于存在复杂内容的情况。为了可扩展性,最好将TabHost定位在布局中,调用newTabSpec(),然后使用setContent()提供一个标识内部Activity的Intent,该Activity提供自己的布局。
原文链接:http://google.com/codesearch/p?hl=en#HQNWZ1u2Pig/trunk/HelloLayoutAndroid/res/layout/tab_widget.xml

嗨。谢谢。我可能会采用快速方式,因为时间不多,这只是一个学习练习,以更熟悉Android。但是,我想知道正确的方法,然而你刚才提到在布局中找到TabHost让我有点晕,因为我只接触Android几个小时。我能看到一个例子吗?谢谢。 - chobo2

1

在解析XML时,include标签经常会出现问题。我尝试过,得到了“无法解析@layout/mylayout”的错误信息。我的代码正确无误,但这是一个常见的问题,特别是如果您需要为布局和其他属性设置ID。 例如:我通过设计模式解决了这个问题。当您将tabhost拖放到布局中时,可以将其放置在任何位置,它会创建3个线性布局(tab1、tab2、tab3)...在XML编辑器中,在每个选项卡(LinearLayout)中插入您需要用作选项卡内容的控件的标记。 然后,在Java文件中进行以下操作:

  TabHost tabHost = (TabHost)findViewById(R.id.tabHost);
    tabHost.setup();
    TabHost.TabSpec tab1 = tabHost.newTabSpec("smil1");
    TabHost.TabSpec tab2 = tabHost.newTabSpec("smil2");
    TabHost.TabSpec tab3 = tabHost.newTabSpec("smil3");
    tab1.setIndicator("#1");//the name will apear on the first tab
    tab1.setContent(R.id.smiles1); // the Id of the control you put in the first LeanerLayout

    tab2.setIndicator("#2"); // the same as abouv but for the second tab
    tab2.setContent(R.id.smiles2);
    tab3.setIndicator("#3"); // the thierd tab
    tab3.setContent(R.id.smiles3);
    // add the tabs
    tabHost.addTab(tab1);
    tabHost.addTab(tab2);
    tabHost.addTab(tab3);

如果在解析XML时包含某些内容导致问题,那么以下方法可以帮助您解决问题。


0

布局编辑器中的NullPointerException是Android开发工具中已知的错误


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