views:

819

answers:

1

Hi all,

This is what i'm trying to achieve:

  1. Use a TextView in a TabWidget (i.e. call TabHost.TabSpec.setIndicator(View) instead of TabHost.TabSpec.setIndicator(String)).

  2. And i want to configure that TextView in XML instead of building it programatically.

So initially, in my layout XML, i had:

<TabHost
    android:id="@+id/mainTabHost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="30px"/>
    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingTop="30px">
    </FrameLayout>
</TabHost>

Now i want to put in the TextView configuration somewhere. It does not actually "belong" nested anywhere within the layout hierarchy. But, since the layout XML have to be a valid XML of course, it can't have more than one root element. So i'm forced to nest the TextView somewhere. Hence i just put it one level below the root (TabHost):

<TabHost
    android:id="@+id/mainTabHost"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android"&gt;
    <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="30px"/>
    <TextView
        android:id="@+id/tvTabIndicatorPreferences"
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:text="@string/tab_name_preferences"/>
    <FrameLayout
        android:id="@android:id/tabcontent"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:paddingTop="30px">
    </FrameLayout>
</TabHost>

And in my code i do:

final TabHost mainTabHost = (TabHost) this.findViewById(R.id.mainTabHost);
mainTabHost.setup();
final TextView tvTabIndicatorPreferences = (TextView) this.findViewById(R.id.tvTabIndicatorPreferences);
final TabHost.TabSpec tabSpecPreferences = mainTabHost.newTabSpec("tabPreferences");
tabSpecPreferences.setIndicator(tvTabIndicatorPreferences);
tabSpecPreferences.setContent(R.id.scrlTblPreferences);
mainTabHost.addTab(tabSpecPreferences);

but there's a problem here. When i try to run the application, i get an exception which says

Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

which is by all means logical and reasonable. The TextView is already a child of the TabHost. i can't just set it as the child of another element. (Note: Putting the TextView nested under the TabWidget yields the same thing.)

so i'm forced to call mainTabHost.removeView(tvTabIndicatorPreferences) before calling the setIndicator.

It works actually, but this way of doing feels very wrong to me. Firstly, i have to put the TextView in the XML where it didn't belong, then in the code remove it from where it didn't belong before using it.

In such a scenario, what's the Right Way to achieve this?

+2  A: 

Step #1: Pull the TextView out into a separate layout file (e.g., res/layout/indicator.xml).

Step #2: Call tabSpecPreferences.setIndicator(getLayoutInflater().inflate(R.layout.indicator, null));

Step #3: There is no Step #3.

CommonsWare
Thank you! Previously, i did do what you say in step #1, but in #2, what i did was to try and call directly findViewById(...) which gave me a NPE. Hence i had thought that all related view elements have to be in the same layout file.
Edwin Lee
oh, i also found that doing it this way, i can actually "reuse" the TextView in the layout XML for BOTH tabs. How is it so? i mean, won't it be the case that the TextView would have 2 parents? (or does inflate() create different instances of the view from the same config?)
Edwin Lee
Each call to inflate creates a new Java object tree.
CommonsWare
Thanks! i was about to post another question about how to dynamically create N number of a view element configured via XML. But now i know!
Edwin Lee