Center elements of HorizontalScrollView when not enough to make it scroll

12,430

Solution 1

I just solved this issue. I ran into it a few hours ago. You need to center the HorizontalScrollView in its parent and set its width/height to wrap_content. The layout you put in the the HSV must have its width/height set to wrap content as well. The important part here is to not set any gravity/layout_gravity on this layout or you may experience (very annoying) clipping issues after inflating your views. Example below is contained in a RelativeLayout.

 <HorizontalScrollView  android:id="@+id/svExample"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true"
    android:layout_below="@id/rlExample">
    <LinearLayout
        android:id="@+id/llExample"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    </LinearLayout>
</HorizontalScrollView >

Solution 2

I had the same problem and finally got it to work. Here is a minimal example:

The main activity layout with the HorizontalScrollView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

        <LinearLayout
            android:id="@+id/container"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >
        </LinearLayout>

    </HorizontalScrollView>

</LinearLayout>

The layout of the elements that will be inflated and put inside the scroll view:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:orientation="horizontal" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="your text" />

</LinearLayout>

And this is an example of the code to inflate and add the elements:

LinearLayout container = (LinearLayout) findViewById(R.id.container);
LayoutParams elementLayoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT, 1f);
int elementCount = 3; // ...or however many you like
for (int i = 0; i < elementCount; i++) {
    LinearLayout element = (LinearLayout) getLayoutInflater().inflate(R.layout.element, null);
    container.addView(element, elementLayoutParams);
}

It's mainly based on a technique for stretching the content of ScrollViews explained in this article by Romain Guy.

However in this case where you are adding contents dynamically, another key point is setting the positive value for the weight (1f in this example) using LayoutParams when adding the elements to the container. If you have a static set of elements that you can include directly in the container and don't need to inflate you can specify the weight of the elements' outer LinearLayout in the XML layout like so:

android:layout_weight="1"

But if you do it dynamically that won't work because the weight will reset to 0 and the elements collapse. Hence you need to set it via the LayoutParams.

Solution 3

Below is the simplest way worked for me.

<HorizontalScrollView
    android:id="@+id/horizontalScrollView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" 
    android:layout_gravity="center">

    <LinearLayout
        android:id="@+id/layout_others"
        android:orientation="horizontal"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</HorizontalScrollView>

Solution 4

managed to get round center-horizontal clipping the left side:

HorizontalScrollView part of layout has been changed to:

<LinearLayout 
    android:id="@+id/footerWrapperLayoutToGetAroundCenteringIssue"
    android:orientation="horizontal" 
    android:layout_width="fill_parent"
    android:layout_height="50dp"
    android:gravity="center_horizontal">

    <HorizontalScrollView 
        android:id="@+id/horizontalScrollView1"
        android:layout_height="fill_parent" 
        android:layout_width="wrap_content">
        <LinearLayout 
            android:id="@+id/footerLayout" 
            android:orientation="horizontal" 
            android:layout_width="fill_parent" 
            android:layout_height="fill_parent">
        </LinearLayout>
    </HorizontalScrollView>
</LinearLayout>

Its just a pity when it centers them they are not evenly distributed.

If anyone has any ideas please let me know.

Share:
12,430

Related videos on Youtube

Alasdair
Author by

Alasdair

Updated on July 24, 2022

Comments

  • Alasdair
    Alasdair almost 2 years

    I have a Layout with a HorizontalScrollView containing a LinearLayout for a Menu where the contents are inflated with the contents of the DB. This works fine however when there are not enough elements to make the HSV scroll this does not fill the width of the screen which ideally should be centered. i.e. Currently:

    | Element 1 Element 2                         | <- edge of screen
    

    Instead of:

    |        Element 1            Element 2       | <- edge of screen
    

    whilst still being able to:

    | Element 1 Element 2 Element 3 Element 4 Elem| <- edge of screen now scrolling
    

    The layout XML is:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/mainLinearLayout"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    
        <TextView 
             android:id="@+id/header"
             android:layout_width="fill_parent"
             android:layout_height="25dp" >
        </TextView>
    
        <ScrollView
             android:id="@+id/scroll1"
             android:layout_width="fill_parent"
             android:layout_height="fill_parent"
             android:layout_weight="1" >
    
            <LinearLayout
                 android:id="@+id/contentLayout"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
                 android:orientation="vertical" >
    
            </LinearLayout>
        </ScrollView>
    
        <HorizontalScrollView
            android:id="@+id/horizontalScrollView1"
            android:layout_width="fill_parent"
            android:layout_height="30dp">
    
            <LinearLayout
                android:id="@+id/footerLayout"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:orientation="horizontal" >
    
            </LinearLayout>
       </HorizontalScrollView>
    </LinearLayout>
    

    With the following XML being inflated inside footerLayout:

    <?xml version="1.0" encoding="utf-8"?>
    
            <TextView
                xmlns:android="http://schemas.android.com/apk/res/android"
                android:id="@+id/footer_content"
                android:textSize="18sp"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:paddingLeft="5dp"
                android:paddingRight="5dp"
                android:text="FOOTER"
                android:singleLine="true" />
    
  • Alasdair
    Alasdair about 12 years
    has no effect, still looks the same
  • Alasdair
    Alasdair about 12 years
    it seems like the LinearLayout footerLayout does not expand to fill the full width if only one or two elements are inside.
  • Aashish Bhatnagar
    Aashish Bhatnagar about 12 years
    try one more thing may be it works assign wieght sum to linearlayout in ur code to whatever number of elements ur inserting and assign the wieght 1 in xml to the textView to be inflated.
  • Tony Chan
    Tony Chan over 9 years
    fillViewport="true" was the missing piece I was looking for to solve my similar problem. For future readers: if you're experiencing really weird left-side clipping of your centered TextView inside the HorizontalScrollView, try tweaking with the fillViewport attribute. It allows weights to be turned on.
  • GFPF
    GFPF about 9 years
    For me it worked correctly the properties: android: layout_centerHorizontal = "true" android: layout_width = "wrap_content"
  • Adrian Buciuman
    Adrian Buciuman over 6 years
    the article by Romain Guy helped me a lot
  • Mike Keskinov
    Mike Keskinov over 3 years
    This is brilliant!