Jason Crosby
Jason Crosby

Reputation: 3583

Android OnGlobalLayoutListener, What Is Happening Here

Background:

I have been working on a proof of concept for my work. The requirement being that when the app is first started a welcome screen opens up to introduce the user to the app and new features. All fine and dandy there. The welcome screen is a long scrollable list of sections highlighting new features. When this scrollable list first opens there is to be 2 text sections in the middle of the screen and a text at the bottom of the screen letting the user know to scroll down for more. After that each section should basically just wrap its content. I found a way to get it to work but I'm having a hard time figuring out HOW and WHY it works. Here is the code that works.

Layout:

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        tools:context=".MainActivity" >

<LinearLayout
    android:id="@+id/linlayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- first section -->
    <LinearLayout
        android:id="@+id/f1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv1"
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="top text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:paddingTop="35dp"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="middle text"
            android:layout_gravity="center_horizontal"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="bottom text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:textColor="@android:color/holo_red_dark"/>
    </LinearLayout>

    <!-- second section -->
    <ImageView
        android:id="@+id/f2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff8222"/>

    <!-- third section -->
    <ImageView
        android:id="@+id/f3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@android:color/darker_gray"/>
</LinearLayout>

Java:

final LinearLayout layout = (LinearLayout)findViewById(R.id.linlayout);
final LinearLayout f1=(LinearLayout) findViewById(R.id.f1);
final ImageView f2=(ImageView) findViewById(R.id.f2);
final ImageView f3=(ImageView) findViewById(R.id.f3);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        int width = layout.getMeasuredWidth();
        int height = layout.getMeasuredHeight();
        f1.setLayoutParams(new LinearLayout.LayoutParams(width, height));
        f2.setLayoutParams(new LinearLayout.LayoutParams(width, height));
        f3.setLayoutParams(new LinearLayout.LayoutParams(width, height));
    }
});

The problem:

Following through the code I see that it is setting the width and height of each "section" to be the width and height of the outer linear layout. And since that is match_parent each section is about the same size as the screen. Makes sense so far. Now there are 3 sections in the long scrollable list that match the width and height of the screen. The requirements say only the first section should match the screen width and height. So since the first section height is match_parent and the 2 other sections height are wrap_content. I would think removing these two lines of Java code

f2.setLayoutParams(new LinearLayout.LayoutParams(width, height));
f3.setLayoutParams(new LinearLayout.LayoutParams(width, height));

should make the following 2 sections wrap their content. But it actually results in the first section being shown full screen like it should however scrolling is disabled so I cant scroll down to see the other sections. Can anyone explain what is going on here? And if there is a better way of achieving what I'm trying to do here I'd love to hear about it.

Upvotes: 2

Views: 563

Answers (1)

Jason Crosby
Jason Crosby

Reputation: 3583

I was actually able to get this working properly with the following code. Turns out it was an issue with the ImageView being set to wrap its content but as there was no image just color it must not have know where to wrap at. But this code is working for me.

Layout

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:fillViewport="true"
        tools:context=".MainActivity" >

<LinearLayout
    android:id="@+id/linlayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <LinearLayout
        android:id="@+id/f1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="top text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:paddingTop="35dp"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="middle text"
            android:layout_gravity="center_horizontal"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="0dp"
            android:layout_weight="1"
            android:text="bottom text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:textColor="@android:color/holo_red_dark"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/f2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="middle text"
            android:layout_gravity="center_horizontal"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="bottom text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:textColor="@android:color/holo_red_dark"/>
    </LinearLayout>

    <LinearLayout
        android:id="@+id/f3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="middle text"
            android:layout_gravity="center_horizontal"
            android:textColor="@android:color/holo_red_dark"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="bottom text"
            android:layout_gravity="center_horizontal"
            android:gravity="bottom"
            android:textColor="@android:color/holo_red_dark"/>
    </LinearLayout>
</LinearLayout>

Java

final LinearLayout layout = (LinearLayout)findViewById(R.id.linlayout);
    final LinearLayout f1=(LinearLayout) findViewById(R.id.f1);
    ViewTreeObserver vto = layout.getViewTreeObserver();
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
    {
        @Override
        public void onGlobalLayout()
        {
            layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            int width = layout.getMeasuredWidth();
            int height = layout.getMeasuredHeight();

            f1.setLayoutParams(new LinearLayout.LayoutParams(width, height));
        }
    });

Upvotes: 0

Related Questions