Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using MotionLayout and setting visibility using Databinding fails [duplicate]

I'm using implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta1', and have databinding enabled.

When my view

<ImageView
            android:id="@+id/im_lightning"
            android:layout_width="24dp"
            android:layout_height="24dp"
            android:layout_marginTop="24dp"
            android:layout_marginEnd="4dp"
            android:contentDescription="@string/charging"
            android:src="@drawable/ic_lightning"
            android:visibility="@{batteryViewModel.liveData.charging ? View.VISIBLE : View.GONE}"
            app:layout_constraintBottom_toBottomOf="@id/tv_percent"
            app:layout_constraintRight_toLeftOf="@id/tv_percent"
            app:layout_constraintTop_toTopOf="@id/tv_percent"
            app:layout_constraintVertical_bias="1.0" />

is wrapped around a coordinator layout, its visibility changes occur as expected. As soon as I wrap it in a MotionLayout, the visibility changes don't work as before. To be precise, the view isn't visible when it should be. It becomes visible for a second upon triggering an event and then goes back to invisible. Is this a known bug?

The code in case it's needed:

Coordinator Layout:

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorBackground">
        <ImageView (same as above) />
</androidx.constraintlayout.widget.ConstraintLayout>

Motion Layout:

<layout 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:context=".ui.MainActivity">

    <androidx.constraintlayout.motion.widget.MotionLayout
        android:id="@+id/motion_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/colorBackground"
        app:layoutDescription="@xml/home_scene_0"
        app:showPaths="true">

        <ImageView (same as above) />
    </androidx.constraintlayout.motion.widget.MotionLayout>
    <data>
        <import type="android.view.View" />
        <variable
            name="batteryViewModel"
            type="rish.crearo.minimalphone.viewmodels.BatteryViewModel" />
    </data>
</layout>
like image 883
Crearo Rotar Avatar asked Sep 01 '19 17:09

Crearo Rotar


1 Answers

I encounter the same problem. Its seem that if you are manipulating the same view's attributes (in this case the visibility) in the databinding & motion scene, the motion scene is superior to the binded value, so you need to bind the value on the scene.

TL;DR Bind the view's attribute motion scene's constraintSet (and not the layout.xml)

I used @BindingAdapter in order to achieve this.

@BindingAdapter("goneUnlessOnMotionLayout")
public static void goneUnlessOnMotionLayout(View view, boolean visible) {
  if (view.getParent() instanceof MotionLayout) {
        final MotionLayout layout = (MotionLayout) view.getParent();
        final int setToVisibility = visible ? View.VISIBLE : View.GONE;
        final float setToAlpha = visible ? 1f : 0f;

        for (int constraintId : layout.getConstraintSetIds()) {
            final ConstraintSet constraint = layout.getConstraintSet(constraintId);
            if (constraint != null) {
                constraint.setVisibility(view.getId(), setToVisibility);
                constraint.setAlpha(view.getId(), setToAlpha);
            }
        }
    }
}

pay attention not to notifyPropertyChanged in your view model while motionLayout is in progress i.e motionLayout.progress != 0 or 1, it will cause a break of the natural motion between the constraints

like image 154
Idan Avatar answered Nov 07 '22 18:11

Idan