H. de Jonge H. de Jonge - 3 months ago 28
Android Question

Viewpager becomes too high

I'm setting up a tabbed Android app. For this I started with the activity created by Android Studio of type Tabbed Activity with the style set to Action Bar Tabs (with ViewPager).

The resulting main activity has a

CoordinatorLayout
, containing the
AppBarLayout
and
ViewPager
(the floating button is not interesting for this case).

Since the
ViewPager
has a height of
match_parent
, I wondered if it would extend beyond the bottom of the screen. To test it, I added a
TextView
to the fragment that is used inside the
ViewPager
and aligned it to the bottom.

When running the app I could not see the extra
TextView
. After I changed the height of the
ViewPager
to 400dp, the
TextView
became visible.

So my assumption is that the
ViewPager
gets the same height as the parent, but the
AppBar
takes up space at the top, so the
ViewPager
is shifted down. Now how should the height of the
ViewPager
be set up properly, so that it takes up all the remaining space under the
AppBar
? The only possible values for the height are
match_parent
,
wrap_content
and a fixed value.

I hope there's an "xml only" solution.

For completeness, here's the layout of the main activity

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="nl.ravelin.so_tabs.MainActivity">

<android.support.design.widget.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/appbar_padding_top"
android:theme="@style/AppTheme.AppBarOverlay">

<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/AppTheme.PopupOverlay">

</android.support.v7.widget.Toolbar>

<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>

</android.support.design.widget.AppBarLayout>

<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</android.support.design.widget.CoordinatorLayout>


and the main fragment

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="nl.ravelin.so_tabs.MainActivity$PlaceholderFragment">

<TextView
android:id="@+id/section_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="How low can you go."/>
</RelativeLayout>

Answer

So my assumption is that the ViewPager gets the same height as the parent, but the AppBar takes up space at the top, so the ViewPager is shifted down.

You are absolutely correct. This was a bit of a surprise to me too.

You have a couple options here.

  • You can move the bottom-anchored view outside the view pager and anchor it to the bottom of the CoordinatorLayout. This way it will always be visible no matter the scroll position of the content inside the view pager.

    When you do this, you do need to offset the view pager with a bottom margin so that when the content is scrolled up, it is entirely visible:

        <android.support.v4.view.ViewPager
            android:id="@+id/container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginBottom="?attr/actionBarSize"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
    
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:text="How low can you go."/>
    

    The downside to this is that the content doesn't move with the view pager. I use this to method anchor buttons to the bottom that apply to the whole screen.

  • If that content absolutely needs to be displayed all the time and paged as well, then perhaps the scrolling app bar isn't the right thing for your UI. Change the CoordinatorLayout to a LinearLayout and use the Toolbar without the AppBarLayout.