Search code examples
androidandroid-linearlayoutandroid-scrollviewandroid-layout-weight

Android LinearLayout distribution of children


I am trying to create a sliding side-panel that evenly distributes children. The children can be dynamically added to the parent. For mdpi screens, each child is a 32x32 dp ImageButton. I want to achieve the following effect.

Case 1: Few Children. When the layout has few children, I would like the image buttons to be evenly distributed.

Illustration of the panel with few children:

Few Children

XML Layout:

<LinearLayout
    android:id="@+id/toolbar"
    style="@style/TabbedPanelToolbar"
    android:layout_toRightOf="@id/pager"
    android:orientation="vertical" >    
        <ImageButton 
            android:src="@drawable/ic_tab_info"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_tag"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_chat"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_meta"
            style="@style/TabbedPanelToolbarControl" />
</LinearLayout>

Styles:

<style name="TabbedPanelToolbar" parent="android:style/Widget.ListView">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">match_parent</item>
    <item name="android:background">@null</item>
</style>

<style name="TabbedPanelToolbarControl" parent="android:style/Widget.ImageButton">
    <item name="android:background">@null</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:paddingTop">5dp</item>
    <item name="android:paddingBottom">5dp</item>
    <item name="android:layout_weight">1</item>
</style>

Case 2: Many Children. When there are a significant number of children, I would like the layout to condense to a certain point and then start to scroll (no longer distribute children but start overflowing the parent). For this, I had to add ScrollView. The problem is that the LinearLayout with few children stops distributing them evenly.

Illustration of the panel with many children:

Many Children

XML Layout:

<ScrollView
    android:id="@+id/toolbar_container"
    style="@style/TabbedPanelToolbarContainer" >

    <LinearLayout
        android:id="@+id/toolbar"
        style="@style/TabbedPanelToolbar"
        android:layout_toRightOf="@id/pager"
        android:orientation="vertical" >

        <ImageButton 
            android:src="@drawable/ic_tab_info"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_tag"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_chat"
            style="@style/TabbedPanelToolbarControl" />
        <ImageButton
            android:src="@drawable/ic_tab_meta"
            style="@style/TabbedPanelToolbarControl" />
        ...
    </LinearLayout>

</ScrollView>

Styles:

<style name="TabbedPanelToolbarContainer" parent="android:style/Widget.ScrollView">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">match_parent</item>
    <item name="android:scrollbars">none</item>
    <item name="android:scrollbarSize">0dp</item>
    <item name="android:paddingRight">0dp</item>
    <item name="android:scrollbarAlwaysDrawVerticalTrack">false</item>
    <item name="android:scrollbarStyle">insideOverlay</item>
    <item name="android:background">@null</item>
    <item name="android:divider">@null</item>
</style>

<style name="TabbedPanelToolbar" parent="android:style/Widget.ListView">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">match_parent</item>
    <item name="android:background">@null</item>
</style>

<style name="TabbedPanelToolbarControl" parent="android:style/Widget.ImageButton">
    <item name="android:background">@null</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:paddingTop">5dp</item>
    <item name="android:paddingBottom">5dp</item>
    <item name="android:layout_weight">1</item>
</style>

My question is whether it is possible to do the above but with one xml layout declaration - even distribution for few children and scroll for many. If not, is there a non-hacky way to do it with code (considering small and large screen sizes... children grow accordingly from 24dp to 96dp).


Solution

  • Omg, just shows how new I am to Android. So I started to play around with Graphical Layout tool in ADT and clicking random stuff (not really but more like experimenting). Turns out this is achievable by adding android:fillViewport="true" to ScrollView. The final xml layout is as follows:

    <ScrollView
        android:id="@+id/toolbar_container"
        style="@style/TabbedPanelToolbarContainer"
        android:fillViewport="true" >
    
        <LinearLayout
            android:id="@+id/toolbar"
            style="@style/TabbedPanelToolbar"
            android:layout_toRightOf="@id/pager"
            android:orientation="vertical" >
    
            <ImageButton 
                android:src="@drawable/ic_tab_info"
                style="@style/TabbedPanelToolbarControl" />
            <ImageButton
                android:src="@drawable/ic_tab_tag"
                style="@style/TabbedPanelToolbarControl" />
            <ImageButton
                android:src="@drawable/ic_tab_chat"
                style="@style/TabbedPanelToolbarControl" />
            <ImageButton
                android:src="@drawable/ic_tab_meta"
                style="@style/TabbedPanelToolbarControl" />
            ...
        </LinearLayout>
    
    </ScrollView>
    

    I'm glad I found it and sure others will find it useful too :)