Copy properties from one view in constraint layout to another when it is hidden

constraintlayout
androidx constraintlayout
constraint layout overlapping
missing constraints in constraint layout
constraintset
constraint layout barrier
android constraint layout responsive design
constraint layout guideline

I am beginner in using ConstraintLayout

I have a usecase, when a one TextView is gone in the constraint layout I want to place another TextView to exact same position as the now hidden TextView. In the xml it is easy, is there possibility to achieve the same programmatically?

Here is the layout xml before the changes:

<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:ignore="ContentDescription">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true"
        android:focusable="true">

        <TextView
            android:id="@+id/some_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="20dp"
            android:ellipsize="end"
            android:maxLines="2"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toTopOf="@+id/textView1"
            app:layout_constraintEnd_toStartOf="@+id/textView2"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="SOME TITLE" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="@color/stone"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/textView2"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/some_title"
            tools:text="I WILL BE HIDDEN" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="16dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:enabled="false"
            android:maxLines="2"
            android:maxWidth="88dp"
            android:gravity="end"
            android:paddingTop="32dp"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            tools:text="I WILL CHANGE THE POSITION"
            tools:textColor="@color/green" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</merge>

And here is how it should look after changes:

<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:ignore="ContentDescription">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/card_container"
        android:clickable="true"
        android:focusable="true">

        <TextView
            android:id="@+id/someTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="20dp"
            android:ellipsize="end"
            android:maxLines="2"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toTopOf="@+id/textView2"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="SOME TITLE"  />

        <TextView
            android:id="@+id/textView1"
            android:visibility="gone"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="@color/stone"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toStartOf="@+id/textView1"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/someTitle"
            tools:text="I AM HIDDEN NOW" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="@color/stone"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/someTitle"
            tools:text="I SHOULD REPLACED THE TEXTVIEW1 POSITION!"
            tools:textColor="@color/green" />

    </androidx.constraintlayout.widget.ConstraintLayout>

</merge>

So, as you can see I just copied all of the positioning values from "textView1" to "textView2"(with some adjustments for "someTitle") How can I do it programmatically?


For this I would have 2 approaches, my first choice would be changing the ConstraintSets of the views am interested in like

 ConstraintSet constraintSet = new ConstraintSet();
    constraintSet.clone(constraintLayout);
    constraintSet.connect(textView2.getId(), ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM);
    constraintSet.connect(textView2.getId(), ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START);
    constraintSet.applyTo(constraintLayout);

Of course, this will not be easy.

My 2nd approach easier than option one would be to copy the LayoutParams of TextView1 or view to be GONE then remove it from the layout and replace it with TextView2 like this

  ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) textView1.getLayoutParams();

    constraintLayout.removeView(textView1);
    constraintLayout.removeView(textView2);
    constraintLayout.addView(textView2, params);

For both of these options to work you will need to alter your layout, remove any constraints that connect the views you want to manipulate with those that should remain on screen like

<?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"
xmlns:tools="http://schemas.android.com/tools"
tools:ignore="ContentDescription"

    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/constraintLayout">

<TextView
    android:id="@+id/someTitle"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginTop="20dp"
    android:layout_marginBottom="8dp"
    android:ellipsize="end"
    android:maxLines="2"
    android:text="SOME TITLE"
    android:textColor="@android:color/black"
    app:layout_constrainedWidth="true"
    app:layout_constraintBottom_toTopOf="@+id/textView1"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="16dp"
    android:layout_marginBottom="20dp"
    android:ellipsize="end"
    android:maxLines="1"
    android:text="I WILL BE HIDDEN"
    android:textColor="@android:color/holo_blue_dark"
    app:layout_constrainedWidth="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/someTitle" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="220dp"
        android:background="@android:color/black"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:layout_marginEnd="16dp"
        android:layout_marginStart="16dp"
        android:ellipsize="end"
        android:enabled="false"
        android:maxLines="2"
        android:maxWidth="88dp"
        android:gravity="end"
        android:paddingTop="32dp"
        app:layout_constrainedWidth="true"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        android:text="I WILL CHANGE THE POSITION"
        android:textColor="@android:color/holo_green_dark" />

       </androidx.constraintlayout.widget.ConstraintLayout>

And you will have you result. I got this with option 2

With option 2 you can create method that takes in 2 views, function that you can use to quickly play with the views

   private void changeReplaceViews(View viewToReplace, View viewToTakeOver){
    ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) viewToReplace.getLayoutParams();
    constraintLayout.removeView(viewToReplace);
    constraintLayout.removeView(viewToTakeOver);
    constraintLayout.addView(viewToTakeOver, params);   
}

ConstraintSet, This view is invisible, but it still takes up space for layout purposes. public static final int int rightMargin, float bias). Centers the widget horizontally to the left and right side on another widgets sides. constraintLayout). Copy the layout parameters of a ConstraintLayout. Constraint set, String attributes). Be patience while cloning view from ConstraintLayout. ConstraintLayout.LayoutParams cache its parameters, and is associated with the View you use it on, so you cannot simply pass one widget's LayoutParams to another. You have to instead generate a new LayoutParams for your new View object, and copy the corresponding fields.


I just came up with my own solution, as none of the other fully covered my usecase. So I just introduced a barrier https://developer.android.com/reference/android/support/constraint/Barrier to hold the bottom reference from the bottom some_title TextView to top of the others TextViews. In that case made adjustments in the layout xml:

 <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/card_container"
        android:clickable="true"
        android:focusable="true">

        <TextView
            android:id="@+id/someTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="8dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:layout_marginTop="20dp"
            android:ellipsize="end"
            android:maxLines="2"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toTopOf="@+id/bottomAreaBarrier"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            tools:text="SOME TITLE" />

        <androidx.constraintlayout.widget.Barrier
            android:id="@+id/bottomAreaBarrier"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:barrierDirection="top"
            app:constraint_referenced_ids="textView1,textView2" />

        <TextView
            android:id="@+id/textView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:maxLines="1"
            android:textColor="@color/stone"
            app:layout_constrainedWidth="true"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintHorizontal_bias="0"
            app:layout_constraintStart_toStartOf="parent"
            tools:text="TEXTVIEW TO BE REPLACED SOMETIMES" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_marginBottom="20dp"
            android:layout_marginEnd="16dp"
            android:layout_marginStart="16dp"
            android:ellipsize="end"
            android:enabled="false"
            android:maxLines="2"
            android:maxWidth="88dp"
            android:gravity="end"
            app:layout_constrainedWidth="true"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            tools:text="I WILL CHANGE POSITION FOR TEXTVIEW1 SOMETIMES"
            tools:textColor="@color/green" />

    </androidx.constraintlayout.widget.ConstraintLayout>

In that case, I can just simply change the Gravity of the textView2 whenever should be the case:

  if (textView1.text.isEmpty()) {
      textView2.gravity = Gravity.START
   } else {
      textView2.gravity = Gravity.END
   }

Build a Responsive UI with ConstraintLayout, To see a variety of layouts you can create with ConstraintLayout , check out a connection or alignment to another view, the parent layout, or an invisible guideline. In the Layout section of the Attributes window, click on a constraint anchor, as "match constraints"; or if you want to keep the current size but move the view� This class allows you to define programmatically a set of constraints to be used with ConstraintLayout.. For details about Constraint behaviour see ConstraintLayout.It lets you create and save constraints, and apply them to an existing ConstraintLayout.


That's pretty easy, Android framework supports adding the view by code and xml both way. Check for the view's visibility with help of getVisibility() and isShown(). After determining the visibility state you can create a new view and attach it to the parent ViewGroup container. Consider the creation of TextView here,

RelativeLayout mRelativeLayout = (RelativeLayout)findViewById(R.id.relative_parent_container);
TextView mTextView = new TextView(this); 
RelativeLayout.LayoutParams mParams = new RelativeLayout.LayoutParams((int)LayoutParams.WRAP_CONTENT,(int)LayoutParams.WRAP_CONTENT);
mParams.leftMargin = 50;
mParams.topMargin  = 50;
mTextView.setText("Hello!");
mTextView.setTextSize((float) 20);
mTextView.setPadding(20, 50, 20, 50);
mTextView.setLayoutParams(mParams);
mRelativeLayout.addView(tv[i]);

This is example creation of TextView and attached to the parent RelativeLayout. You can create desired view and attach to the parent container by the same way without worrying about the type of ViewGroup. Here in your case, If you need to attach the View to ConstraintLayout, You'll be needing the ConstraintLayout.LayoutParams for that view.

If you want to copy/clone the existing view,

TextView existingTv = (TextView)findViewById(R.id.existing_tv);
TextView cloned = new TextView(getApplicationContext());
cloned.setText(existingTv.getText());
cloned.setLayoutParams(existingTv.getLayoutParams()); //override anything you want

Be patience while cloning view from ConstraintLayout. ConstraintLayout.LayoutParams cache its parameters, and is associated with the View you use it on, so you cannot simply pass one widget's LayoutParams to another.

You have to instead generate a new LayoutParams for your new View object, and copy the corresponding fields.

For example, if you have something like this,

<?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:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:text="Hello!"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/tv"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginStart="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        android:layout_marginLeft="16dp" />

</android.support.constraint.ConstraintLayout>

Then you can do it as given below,

ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.container);
TextView textView = (TextView) findViewById(R.id.tv);
ConstraintLayout.LayoutParams mParam = 
                (ConstraintLayout.LayoutParams) textView.getLayoutParams();

TextView clonedTextView = new TextView(this);

ConstraintLayout.LayoutParams newParams = new ConstraintLayout.LayoutParams(ConstraintLayout.LayoutParams.WRAP_CONTENT,ConstraintLayout.LayoutParams.WRAP_CONTENT);

newParams.leftToLeft = mParam.leftToLeft;
newParams.topToTop = mParam.topToTop;
newParams.leftMargin = mParam.leftMargin;
newParams.topMargin = mParam.topMargin;

layout.addView(clonedTextView, -1, newParams);

This would put the second TextView exactly in the same position as the one defined in XML layout.

The ultimate view group: ConstraintLayout, Before ConstraintLayout came about, things were a bit tough when it comes Constraints are rules that you set in order to position a view in relative to another or its parent. Now copy and paste the following content into your xml file: Click on the TextView and, in the attributes panel, drag the horizontal� Next, switch to Code view and examine the updated XML for the rocket icon. You have added one new constraint, app:layout_constraintTop_toTopOf="parent", and a top margin attribute for the space between the rocket and the top of the view. Update the code to set the margin to 15dp.


Use ConstraintLayout to design your Android views, A constraint represents a connection or alignment to another view, the parent layout, or an invisible guideline. You will be working primarily with the Layout� In this guide I explained two ways to copy properties from one object to another. If you face a similar situation in your projects, instead of writing multiple lines of code, you can just use these classes or extension methods to copy the needed properties from one object to the other object.


Constructing View Layouts, ConstraintLayout combines the power of LinearLayout and RelativeLayout while Common view attributes you might see used in a LinearLayout: the change causes the second button to expand the width to match that of the first button. two views overlap on screen, that one view will become hidden behind the other. Open the Layer States Manager. Click the N ew button. Enter the desired name (e.g. the same as the layout name) Click the Sa v e button (the current layer state is saved in the layer state) Exit the Layer States Manager. On another layout, repeat the process. Copy the content of the layout in the destination layout.


ConstraintLayout Tutorial for Android: Complex Layouts , ConstraintLayout is a layout on Android that gives you adaptable and After another moment, all your views may just jump into the upper left corner of the layout. and click on the Attributes tab on the right, if it's not already visible. If your layout doesn't match this image, check the Text and Design views. Select the object from which you want to copy properties. If you want to specify which properties are copied, enter s (Settings). In the Property Settings dialog box, clear the properties that you do not want copied, and click OK. Select the objects to which you want to copy the properties, and press Enter.