Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ConstraintLayout GONE view occupies space

I have a ViewHolder with the header on top and that header becomes visible in a specific case. In most other cases, the header is set as GONE. The problem is that when a header is set as GONE, its height is still calculated and other views are spread differently (with more space between).

Here is a layout blueprint: blueprint

Blueprint explanation:

  1. The header is constrained to top, left and right.
  2. Two views below are in packed chain, constrained to a header on top, ImageView to the right and parent to the left and bottom.

And here is a screenshot from the layout inspector with highlighted header view which is set as GONE: enter image description here

According to documentation, the header view, when set to GONE should be shrunk to point with constraints from other views still applied to it, but the header should not occupy layout space and affect the height of the ConstraintLayout as it is set as wrap_content.

In this inspector screenshot, it's not clear what happened actually. The header is not visible, a bottom view is obviously constrained to parent top, but the header is still shown in the inspector as full width with specified height.

I'm not sure if this is a bug or I should force ConstraintLayout to re-measure itself.

XML UPDATE:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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:layout_width="match_parent"
    android:layout_height="wrap_content">


    <TextView
        android:id="@+id/list_item_step_conversion_tv_header"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:background="@color/gray_very_light"
        android:padding="@dimen/activity_vertical_margin"
        android:text="@string/favorites"
        android:textColor="@android:color/black"
        android:textSize="@dimen/default_text_size"
        android:textStyle="bold"
        android:visibility="gone"
        tools:visibility="visible"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <TextView
        android:id="@+id/list_item_step_conversion_tv_title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginEnd="16dp"
        android:layout_marginLeft="16dp"
        android:layout_marginRight="16dp"
        android:layout_marginStart="16dp"
        android:layout_marginTop="8dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@color/gray_dark"
        android:textSize="@dimen/medium_text_size"
        app:layout_constraintBottom_toTopOf="@+id/list_item_step_conversion_tv_description"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/list_item_step_conversion_iv_favorite"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_header"
        app:layout_constraintVertical_chainStyle="packed"
        tools:text="Bicycling - light (10-11.9 mph)"/>

    <TextView
        android:id="@+id/list_item_step_conversion_tv_description"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginBottom="8dp"
        android:layout_marginLeft="0dp"
        android:layout_marginRight="16dp"
        android:layout_marginTop="4dp"
        android:ellipsize="end"
        android:maxLines="1"
        android:textColor="@android:color/black"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintHorizontal_bias="0.0"
        app:layout_constraintLeft_toLeftOf="@+id/list_item_step_conversion_tv_title"
        app:layout_constraintRight_toLeftOf="@+id/list_item_step_conversion_iv_favorite"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_title"
        tools:text="182 steps/minute"/>

    <ImageView
        android:id="@+id/list_item_step_conversion_iv_favorite"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="0dp"
        android:layout_marginRight="24dp"
        android:layout_marginTop="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/list_item_step_conversion_tv_header"
        app:srcCompat="@drawable/ic_not_liked"/>    
</android.support.constraint.ConstraintLayout>

UPDATE 2

After additional observations, this problem occurs only after a call to notifyDataSetChanged in RecyclerView.Adapter. Here is a screenshot of layout state before and after the click to the favorite icon to one of the items. enter image description here

Screenshots explanation:

  • On the left side, ViewHolder with visible header view is on position: 2. Items above are displayed correctly.
  • After click on favorite icon (item with value 242), ViewHolder on position: 1 is the one with visible header view, while the ViewHolder on position: 2 have header view set as GONE. I was expecting for ViewHolder height to decrease and have the same height as ViewHolder on position: 0.

Having in mind that this ViewHolder had header set to VISIBLE in previous state, it might have something with recycling, not sure.

like image 467
bajicdusko Avatar asked Apr 28 '17 12:04

bajicdusko


People also ask

What is the difference between ConstraintLayout and LinearLayout?

Following are the differences/advantages: Constraint Layout has dual power of both Relative Layout as well as Linear layout: Set relative positions of views ( like Relative layout ) and also set weights for dynamic UI (which was only possible in Linear Layout).

Is ConstraintLayout a view?

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way. Note: ConstraintLayout is available as a support library that you can use on Android systems starting with API level 9 (Gingerbread).

Which is better RelativeLayout or ConstraintLayout?

ConstraintLayout has flat view hierarchy unlike other layouts, so does a better performance than relative layout. Yes, this is the biggest advantage of Constraint Layout, the only single layout can handle your UI.

How do I get rid of ConstraintLayout?

Is it possible to get rid of this constraint layout? Go to the Text mode for the layout, select the ConstraintLayout root and wipe it.

Is space needed for constraintlayout?

Upon reading my blog, Jorge Aguilar has responded and demonstrate that this could be done using ConstraintLayout, and the good news is, Space is not needed, yet achieve the same result. ConstraintLayout is the newest introduced layout that enable user to define Constraints on the views with other views or it’s parent.

What is constraintlayout in Salesforce?

ConstraintLayout is the newest introduced layout that enable user to define Constraints on the views with other views or it’s parent. The constraint that we will use here is defined as layout_constraint<AnchorX>_to<AnchorY>Of, where Anchor could be either Top, Bottom, Start and End.

How to set the visibility of a view to free space?

What you can do is set an if statement, whenever the condition to set the visibility to "GONE", set the view as wrap content and your space will be free, I did it and it worked for a seekbar Please provide some example. Let take my example for instance.

How to set vertical gravity for labels in a constraintlayout?

A more simple and preferrable way is to wrap both labels into LinearLayout and insert it into parent ConstraintLayout. Then you can set vertical gravity, show or hide labels, hide the LinearLayout itself. If you don't want to have nested layouts, use Barrier s and Group s. It is a difficult task that can waste many hours.


1 Answers

I've solved this issue by calling view.requestLayout()* in the end of my adapter's #getView, after the usual call to binding.executePendingBindings().

*I'm using an old-school Adapter right now, so you should search for the RecyclerView.Adapter's equivalent, probably #onBindViewHolder()

like image 196
Jonas Alves Avatar answered Oct 24 '22 02:10

Jonas Alves