38

I want to center my LinearLayout within ScrollView. When LinearLayout's height is small it's centered alright (see image #1) but when LinearLayout's height is bigger than the screen's height then it behaves strange. I cannot see the top of LinearLayout (see image #2) and at the bottom of ScrollView there's huge padding. I don't know what's happening here. When there are lots of content in LinearLayout the whole screen should look like in image #3.

image #1
image #2
image #3

Here's my layout file:

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

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_margin="28dp"
                    android:background="#ffffff"
                    android:orientation="vertical"
                    android:paddingBottom="40dp"
                    android:paddingLeft="20dp"
                    android:paddingRight="20dp"
                    android:paddingTop="40dp" >

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="16dp"
                        android:src="@drawable/ic_launcher" />

                    <TextView
                        android:id="@+id/tip_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="12dp"
                        android:text="Title"
                        android:textColor="@color/orange_text"
                        android:textSize="@dimen/font_size_medium" />

                    <TextView
                        android:id="@+id/tip_description"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Description description..."
                        android:textSize="@dimen/font_size_small" />
                </LinearLayout>

            </ScrollView>
Egis
  • 5,081
  • 5
  • 39
  • 61

11 Answers11

80

You can use android:fillViewport="true" to center the content. Something like this:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="true">
        <!-- content -->
</ScrollView>
zbr
  • 6,860
  • 4
  • 31
  • 43
yaircarreno
  • 4,002
  • 1
  • 34
  • 32
  • 1
    This is a better solution. It does not involve the creation of a useless LinearLayout in the hierarchy. – Stephane Mathis Oct 13 '16 at 14:15
  • Excellent! `layout_gravity` to center in LinearLayout caused it to hide content below toolbar. This one worked! – kirtan403 Nov 06 '16 at 06:04
  • 1
    This doesn't work. I just did it and buttons align to the left as if nothing happened. – Ren Sep 13 '18 at 01:28
  • 1
    Why would this work? The content still will be out of bounds if the gravity is set to center – Boldijar Paul Dec 30 '20 at 09:58
  • 1
    `android:fillViewport="true"` will just cause your child layout to match size of `ScrollView` (`match_parent` essentially). You would also need to set gravity to your child layout in order for this to work. – Peter Sep 07 '21 at 11:19
  • This solution didn't work for me. Just adding `android:fillViewport` didn't center ScrollView's content and additionally having `android:layout_gravity="center_vertical"` still cut off top views. @Vladimir workaround below worked, thou. – GrzegDev Oct 31 '21 at 06:59
40

You should use an external horizontal LinearLayout. It's working for me in the same situation.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="horizontal" >
    <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >
        <LinearLayout
                android:orientation="vertical"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:gravity="center_horizontal" >
            <TextView
                    android:text="@string/your_text"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content" />
        </LinearLayout>
    </ScrollView>
</LinearLayout>
Vladimir Petrakovich
  • 4,184
  • 1
  • 30
  • 46
15

And this is how you center a view inside a ConstraintLayout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.appcompat.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        android:background="#86c2e1"
        android:elevation="4dp"
        app:layout_constraintTop_toTopOf="parent"
        app:title="Toolbar" />

    <ScrollView
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="#eda200"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHeight_default="wrap"
        app:layout_constraintTop_toBottomOf="@+id/toolbar"
        app:layout_constraintVertical_bias="0.5">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/lorem_ipsum"
            android:textSize="20sp" />
    </ScrollView>

</androidx.constraintlayout.widget.ConstraintLayout>

enter image description here

Egis
  • 5,081
  • 5
  • 39
  • 61
  • Thank you! Very clever and I don't think I would have easily come up with this. I don't have the tool bar (just filling the screen), but this worked exactly as I wanted, centering smaller content and starting longer content at the top, with scrolling enabled. Perfect! – big_m Mar 26 '22 at 04:04
2

Set focus on your top most UI component which you want to see

<ImageView
            android:focusable="true"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:src="@drawable/ic_launcher" />
Jitender Dev
  • 6,907
  • 2
  • 24
  • 35
2
<ScrollView
android:id="@id/scrool_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">

<LinearLayout
    android:id=="@id/direct_child"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <androidx.cardview.widget.CardView
        android:id=="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:visibility="visible"
        app:cardPreventCornerOverlap="true"
        app:cardUseCompatPadding="true"
        card_view:cardCornerRadius="5dp"
        card_view:cardElevation="10dp">

    </androidx.cardview.widget.CardView>
</LinearLayout></ScrollView>

You need to do 3 things:

  1. Set android:fillViewport="true" in ScrollView
  2. The direct child of the ScroolView needs to be a LinearLayout
  3. Your original Content will be under LinearLayout and for the Content set android:layout_gravity="center_vertical"

These 3 things will ensure the following:

  1. When the Content is Small, it will be centered-vertically in ScrollView.
  2. When the Content is Large, it will be scrolled normally.
Md Tarik Mahmud
  • 331
  • 3
  • 8
0

Try this may satisfy your requirement.

   <?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"
    android:background="#cccfff"
    android:gravity="center"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="10dp"
        android:background="#ffffff"
        android:gravity="center_vertical"
        android:orientation="vertical"
        android:paddingBottom="40dp"
        android:paddingLeft="20dp"
        android:paddingRight="20dp"
        android:paddingTop="40dp" >

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="16dp"
            android:src="@drawable/ic_launcher" />

        <TextView
            android:id="@+id/tip_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="12dp"
            android:text="Title" />

        <TextView
            android:id="@+id/tip_description"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="biruDescription description..." />
    </LinearLayout>

</LinearLayout>

One more line in your java code

TextView tip_description = (TextView) findViewById(R.id.tip_description);
        tip_description.setMovementMethod(new ScrollingMovementMethod());

This will scroll your description content rather whole layout.

Biraj Zalavadia
  • 28,348
  • 10
  • 61
  • 77
  • LinearLayout is not centered vertically when tip_description text is short. – Egis Oct 23 '13 at 11:58
  • Well this is the best solution so far but I wish whole LinearLayout is scrollable not just the TextView inside it. I've been googling for an hour and now I'm having an impression that it's not possible to have what I want. Oh well... – Egis Oct 23 '13 at 12:41
0
<?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"
           android:orientation="vertical"
           android:gravity="center"
           android:padding="10dp"
           android:background="#cccfff">

            <ScrollView 
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                 >

                <LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center_vertical"
                    android:layout_margin="28dp"
                    android:background="#ffffff"
                    android:orientation="vertical"
                    android:paddingBottom="40dp"
                    android:paddingLeft="20dp"
                    android:paddingRight="20dp"
                    android:paddingTop="40dp" >

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="16dp"
                        android:src="@drawable/ic_launcher" />

                    <TextView
                        android:id="@+id/tip_title"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginBottom="12dp"
                        android:text="Title"
                        android:textColor="@color/orange_text"
                        android:textSize="@dimen/font_size_medium" />

                    <TextView
                        android:id="@+id/tip_description"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="Description description..."
                        android:textSize="@dimen/font_size_small" />
                </LinearLayout>

            </ScrollView>
</LinearLayout>
Hariharan
  • 24,741
  • 6
  • 50
  • 54
0

Just use my CenteringLinearLayout class below.

import android.content.Context
import android.support.constraint.ConstraintLayout
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout

class CenteringLinearLayout: LinearLayout {

    constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
    constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
    constructor(context: Context) : super(context)

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        val parentView = this.parent as View
        if (h > parentView.height) {
            parentView.post {
                val params = parentView.layoutParams as ConstraintLayout.LayoutParams
                params.height = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT
                parentView.layoutParams = params
            }
        } else {
            val params = parentView.layoutParams
            params.height = ConstraintLayout.LayoutParams.WRAP_CONTENT
            parentView.layoutParams = params
        }
        super.onSizeChanged(w, h, oldw, oldh)
    }
}
Salih
  • 171
  • 1
  • 12
0

I simply did some calculations and added android:layout_marginLeft & android:layout_marginRight and that did the work for me.

  • Doing this will center the content horizontally only. And it will not work always. – Krrishnaaaa Dec 14 '21 at 11:47
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 14 '21 at 11:47
-1

Try putting the margin and paddings to the ScrollView

Day
  • 844
  • 1
  • 9
  • 21
  • That doesn't help. First of all my ScrollView cannot have margins. It has to take the whole screen. Also it cannot have paddings because these paddings are also applied to ScrollView's scroll bar on the right and scroll bar should be able to scroll from top to the bottom of the screen. – Egis Oct 23 '13 at 11:40
-1

Maybe it is unclear how layout works. In your case you need to set an external layout that fills the parent and has gravity set as center, inside have a scroll view with layout height wrap_content and internal layout with layout height wrap_content also. Then External layout will center scroll view if it is smaller.

<LinearLayout
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:gravity="center">

    <ScrollView
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

        <!-- Content here -->

        </LinearLayout>
    </ScrollView>
</LinearLayout>
Borzh
  • 5,069
  • 2
  • 48
  • 64