Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HorizontalScrollView in TabHost adding extra space on the end

In order to easily switch between fragments, I'm embedding a HorizontalScrollView into my Tab layout like so:

<?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="match_parent"
    android:layout_height="match_parent">
    <LinearLayout
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <HorizontalScrollView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:fillViewport="true"
            android:scrollbars="none" >

            <TabWidget android:id="@android:id/tabs" 
                android:layout_height="wrap_content" 
                android:layout_width="wrap_content">
            </TabWidget>
        </HorizontalScrollView>
        <FrameLayout
            android:id="@android:id/tabcontent"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" />
    </LinearLayout>
</TabHost>

But after adding Fragments in my code (shown below) there suddenly shows up some extra whitespace at the end of the HorizontalScrollView:

Before scrolling

Before scrolling

After scrolling

After scrolling

The code is quite complex but I'll try to show the important parts.

{
    mTabHost = (TabHost) childLayout.findViewById(android.R.id.tabhost);
    mTabHost.setup();
    FrameLayout tabsFL = (FrameLayout) childLayout.findViewById(android.R.id.tabcontent);
    tabsFL.setId(TABS_FRAME_ID);

    for (int i = 0; i < list.size(); i++) {
        mTabHost.addTab(newTab(String.valueOf(i), list.get(i).getTitle(), tabsFL.getId()));
    }

    mTabHost.setOnTabChangedListener(new TabHost.OnTabChangeListener() {
        @Override
        public void onTabChanged(String tabId) {
        updateTab(tabId, Integer.parseInt(tabId), list);
        }
    });

    //manually load first fragment
    mTabHost.setCurrentTab(mCurrentTab);
    updateTab(String.valueOf(mCurrentTab), mCurrentTab, list);
}


private TabSpec newTab(String tag, String tabLabel, int tabContentId) {
    int count = Integer.parseInt(tag);
    count +=1;

    View indicator = inflater.inflate(R.layout.details_tab,
        (ViewGroup) childLayout.findViewById(android.R.id.tabs), false);
    ((TextView) indicator.findViewById(R.id.text)).setText(count + ". " + tabLabel);

    TabSpec tabSpec = mTabHost.newTabSpec(tag);
    tabSpec.setIndicator(indicator);
    tabSpec.setContent(tabContentId);
    return tabSpec;
}

private void updateTab(String tabId, int id, ArrayList<CustomObject> frags) {
    mCurrentTab = id;

    FragmentManager fm = activity.getSupportFragmentManager();
    fm.beginTransaction()
        .replace(TABS_FRAME_ID, DetailsFragment.newInstance(frags.get(id)), tabId)
        .commitAllowingStateLoss();
}

Also unrelated, but I also have a problem where the first tab doesn't load manually (clicking tabs loads the Fragments perfectly, just the very first one doesn't load for some reason).

like image 939
S Fitz Avatar asked Aug 05 '13 09:08

S Fitz


1 Answers

TabWidget has measureWithLargestChild set to true by default, which means it is using the widest of your tabs to calculate the overall width of the internal LinearLayout that TabWidget uses when it measures itself. If your tabs are of different length this will lead to that internal LinearLayout having some extra space on the end from the difference between the shorter tabs and your widest tab. If you add android:measureWithLargestChild="false" to your TabWidget layout it should solve your problem.

tl;dr Change Your layout TabWidget to:

<TabWidget android:id="@android:id/tabs" 
    android:layout_height="wrap_content" 
    android:layout_width="wrap_content"
    android:measureWithLargestChild="false">
</TabWidget>
like image 109
Hans Reichenbach Avatar answered Oct 11 '22 05:10

Hans Reichenbach