ravi
ravi

Reputation: 1001

VIewpager inside Coordinatorlayout takes extra space on visibility gone

I have a layout whereby I need the an upper section of toolbar and some content and then a lower section of ViewPager which needs to be hidden based on a boolean value.

The skeleton of the XML looks like:

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

        <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="?actionBarSize"/>

        <androidx.coordinatorlayout.widget.CoordinatorLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <com.google.android.material.appbar.AppBarLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content">

                <com.google.android.material.appbar.CollapsingToolbarLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    app:expandedTitleGravity="bottom|center_horizontal"
                    app:layout_scrollFlags="scroll">

                    <androidx.constraintlayout.widget.ConstraintLayout
                        android:layout_width="match_parent"
                        android:layout_height="wrap_content"
                        app:layout_collapseMode="none">

                        <TextView
                            style="@style/Medium.ExtraLarge"
                            android:layout_width="0dp"
                            android:layout_height="wrap_content"
                            tools:text="Title Something" />

                       <!--Other top section content --> 

                    </androidx.constraintlayout.widget.ConstraintLayout>

                </com.google.android.material.appbar.CollapsingToolbarLayout>

            </com.google.android.material.appbar.AppBarLayout>


            <androidx.viewpager.widget.ViewPager
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:visibility="@{(viewModel.isInBusinessManagement &amp;&amp; (viewModel.hasActivePremium || viewModel.hasSuspendedPlan)) ? View.VISIBLE : View.GONE}"
                app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
                app:layout_collapseMode="pin"
                tools:visibility="gone">

                <com.google.android.material.tabs.TabLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:background="@drawable/tab_background_2dp"
                    android:visibility="@{(viewModel.isInBusinessManagement &amp;&amp; (viewModel.hasActivePremium || viewModel.hasSuspendedPlan)) ? View.VISIBLE : View.GONE}"
                    app:layout_collapseMode="pin"
                    app:layout_scrollFlags="scroll|exitUntilCollapsed"
                    app:tabGravity="fill"
                    app:tabMode="fixed"
                    app:tabSelectedTextColor="@color/colorPrimary"
                    app:tabTextAppearance="@style/tab_text"
                    app:tabTextColor="@color/txtColorGrey" />


            </androidx.viewpager.widget.ViewPager>


        </androidx.coordinatorlayout.widget.CoordinatorLayout>
    </LinearLayout>


As you can see I have to control the visibility of the ViewPager and TabLayout based on boolean values, I am using databinding for that.

The layout is all good and I get the expected behavior when it needs to be shown but the issue is that when the conditions mentioned ie. viewModel.isInBusinessManagement &amp;&amp; (viewModel.hasActivePremium || viewModel.hasSuspendedPlan) is false, the Viewpager and TabLayout is invisible but takes up as much space as it did when it was visible.

Now I know that View.INVISIBLE has that behavior but I am clearly using View.GONE for false case.

Also when I put different colors on the root Linearlayout, AppbarLayout and CoordinatorLayout, the extra space on the bottom seems to be coming from CoordinatorLayout.

Could you please help me with this?

Upvotes: 0

Views: 694

Answers (2)

Himanshu Choudhary
Himanshu Choudhary

Reputation: 370

I tried to solve this locally, and the following code worked for me. You can also try this:

  1. Make a binding adapter that will contain the logic for visibility.

@BindingAdapter(value = ["hasActivePremium", "isInBusinessManagement", "hasSuspendedPlan"], requireAll = true)
   fun controlVPVisibility(view: ViewPager, hasActivePremium: Boolean, isInBusinessManagement:Boolean, hasSuspendedPlan:Boolean) {
        view.visibility = if(isInBusinessManagement && (hasActivePremium || hasSuspendedPlan))  View.VISIBLE else View.GONE````<br/>
    }
  1. All the 3 view model variables are mutable live data of type boolean.
    var isInBusinessManagement = MutableLiveData<Boolean>()
    var hasActivePremium = MutableLiveData<Boolean>()
    var hasSuspendedPlan = MutableLiveData<Boolean>()
  1. Since tab layout is in view pager and both have the same visibility logic, so in XML I am only controlling the visibility of the view pager.
    <androidx.viewpager.widget.ViewPager
                android:id="@+id/vpager"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/teal_700"
                isInBusinessManagement="@{viewModel.isInBusinessManagement()}"
                hasActivePremium="@{viewModel.hasActivePremium}"
                hasSuspendedPlan="@{viewModel.hasSuspendedPlan}"          
                app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
                app:layout_collapseMode="pin">

  1. Make sure you have attached a lifecycle owner while using a view model with data binding.
    binding.viewModel = viewModel
    binding.lifecycleOwner = this

  1. And make the height of CoordinatorLayout to wrap_parent

I think only from the 5th step change, you can achieve the result in your existing code. The above 4 steps are to make better use of data binding by writing logic in the binding adapter.

Upvotes: 1

Priyanka
Priyanka

Reputation: 3699

maybe this work for you to stop scrolling toolbar when viewpager visibility is gone

noScroll flag in layout_scrollFlags will stop scrolling CollapsingToolbarLayout

<com.google.android.material.appbar.CollapsingToolbarLayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     app:expandedTitleGravity="bottom|center_horizontal"
     app:layout_scrollFlags="@{(viewModel.isInBusinessManagement &amp;&amp; (viewModel.hasActivePremium || viewModel.hasSuspendedPlan)) ? scroll : noScroll}">

Upvotes: 0

Related Questions