1

Nested inside my main ConstraintLayout, I have another ConstraintLayout with Id = stripLayout with an ImageView and several Buttons inside. I want to be able to slide the inner ConstraintLayout (image, buttons and all) left and right, and for that I am trying animations as shown in the code below:

The ConstraintLayout slides as expected, but after the animation is complete it resets to the initial position. This is probably related to the fact that the code for the onAnimationEnd() method seems to have no effect on the final position, as I have tried setting params.leftMargin = 0 and other values without noticing any difference in behavior. Apparently this works with views as has been established in other posts (Android translate animation - permanently move View to new position using AnimationListener), but how to do it with a ConstraintLayout?

ConstraintLayout stripImageLayout = findViewById(R.id.stripLayout);

TranslateAnimation anim_to_right = new TranslateAnimation(0, pixToSlide, 0, 0);

anim_to_right.setDuration(1000);

anim_to_right.setAnimationListener(new TranslateAnimation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) { }

            @Override
            public void onAnimationRepeat(Animation animation) { }

            @Override
            public void onAnimationEnd(Animation animation) {
                ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams)stripImageLayout.getLayoutParams();
                params.leftMargin += pixToSlide;
                stripImageLayout.setLayoutParams(params);
            }
        });

stripImageLayout.startAnimation(anim_to_right);

and activity_main.xml:

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:onClick="onBackgroundClick"
    tools:context=".MainActivity">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/outletInfoLayout"
        android:layout_width="151dp"
        android:layout_height="387dp"
        android:layout_marginTop="68dp"
        android:layout_marginEnd="100dp"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <TextView
            android:id="@+id/ThresholdValue"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="8dp"
            android:text="NONE"
            app:layout_constraintBottom_toBottomOf="@+id/textView4"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toEndOf="@+id/textView4"
            app:layout_constraintTop_toTopOf="@+id/textView4"
            app:layout_constraintVertical_bias="1.0" />

        <TextView
            android:id="@+id/textView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="16dp"
            android:text="Threshold:"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/textView2" />

        <TextView
            android:id="@+id/deviceName"
            android:layout_width="136dp"
            android:layout_height="80dp"
            android:textSize="30sp"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginStart="16dp"
            android:layout_marginTop="31dp"
            android:text="Outlet: "
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/deviceName" />

        <TextView
            android:id="@+id/outletNumber"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:layout_constraintBottom_toBottomOf="@+id/textView2"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.0"
            app:layout_constraintStart_toStartOf="@+id/ThresholdValue"
            app:layout_constraintTop_toTopOf="@+id/textView2"
            app:layout_constraintVertical_bias="0.0" />

    </androidx.constraintlayout.widget.ConstraintLayout>

    <androidx.constraintlayout.widget.ConstraintLayout
        android:id="@+id/stripLayout"
        android:layout_width="103dp"
        android:layout_height="475dp"
        android:layout_marginTop="32dp"
        android:layout_marginEnd="80dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintTop_toTopOf="parent">

        <Button
            android:id="@+id/outlet3button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet3ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/outlet2button" />

        <Button
            android:id="@+id/outlet1button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="75dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet1ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="@+id/smartstripImage" />

        <Button
            android:id="@+id/outlet2button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet2ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/outlet1button" />

        <Button
            android:id="@+id/outlet5button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet5ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/outlet4button" />

        <ImageView
            android:id="@+id/smartstripImage"
            android:layout_width="81dp"
            android:layout_height="441dp"
            android:contentDescription="@string/smartstrip_icon"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:srcCompat="@drawable/strip" />

        <Button
            android:id="@+id/outlet4button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet4ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/outlet3button" />

        <Button
            android:id="@+id/outlet6button"
            android:layout_width="60dp"
            android:layout_height="37dp"
            android:layout_marginStart="8dp"
            android:layout_marginTop="15dp"
            android:layout_marginEnd="8dp"
            android:background="@android:color/transparent"
            android:onClick="onOutlet6ButtonClick"
            android:visibility="visible"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/outlet5button" />
    </androidx.constraintlayout.widget.ConstraintLayout>

</androidx.constraintlayout.widget.ConstraintLayout>
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Carlos Vazquez
  • 426
  • 3
  • 9

2 Answers2

0

You'll have to use a ConstraintSet to achieve this. This isn't fully tested so this answer may have to be editied but something like this, make sure you add an id to your parent ConstraintLayout:

ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(R.id.parentLayout);
constraintSet.connect(R.id.outletInfoLayout, ConstraintSet.START, R.id.parentLayout, ConstraintSet.START, startMarginInPixels);
constraintSet.applyTo(R.id.parentLayout);

To make the entire thing easier though, I would use MotionLayout, although it is still in beta.

Charlie Niekirk
  • 1,015
  • 1
  • 10
  • 15
  • Thanks, I will try this... Any theories on why my code doesn't work? Does `stripImageLayout.getLayoutParams()` not return the margins of the inner ConstraintLayout in relation to the outer ConstraintLayout? – Carlos Vazquez Oct 25 '19 at 18:25
0

The left-to-right placement of the ConstaintLayout that you are trying to animate is controlled by its right margin. At the end of the animation, you are trying to shift this layout by setting the left margin: you need to reduce the right margin by the amount of the shift and leave the left margin alone.

I suggest that you change onAnimationEnd() to something like this:

@Override
public void onAnimationEnd(Animation animation) {
    stripImageLayout.clearAnimation(); // Stop jump to start
    ConstraintLayout.LayoutParams params = (ConstraintLayout.LayoutParams) stripImageLayout.getLayoutParams();
    params.rightMargin -= pixToSlide;
    stripImageLayout.setLayoutParams(params);
}

You could also use property animation to save some lines of code as follows:

ObjectAnimator slideAnimator = ObjectAnimator.ofFloat(stripImageLayout, "translationX", pixToSlide)
    .setDuration(1000);
slideAnimator.start();

Since the property animation changes the value of the translationX property, the movement is made post-layout. This means that views whose placement depends upon the moving layout will be laid out according to the original position of the moving layout and not its new position. This may be OK with you, but it is a caveat.

Cheticamp
  • 61,413
  • 10
  • 78
  • 131