Проблема с несколькими переходами в Android MotionLayout

Я играю с MotionLayout в Android. Я использую альфа 2 версию.

'com.android.support.constraint:constraint-layout:2.0.0-alpha2'

Я хочу реагировать на два разных нажатия кнопок и запускать анимацию для каждого из них. Мой текущий подход состоит в том, чтобы установить два Transitions в MotionScene с триггером OnClick в каждом из них.

Проблема в том, что вроде бы обнаружен только первый переход. Для второго просто ничего не происходит. Я что-то не так делаю или можно просто установить один переход на MotionScene? Если это так, то есть ли другое решение проблемы?

Вот важные части моей сцены движения

<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:motion="http://schemas.android.com/apk/res-auto">

<Transition
    motion:constraintSetStart="@id/startHome"
    motion:constraintSetEnd="@id/endHome"
    motion:duration="300">
    <OnClick
        motion:mode="toggle"
        motion:target="@+id/imageView_bottom_home" />
</Transition>

<Transition
    motion:constraintSetStart="@id/startSearch"
    motion:constraintSetEnd="@id/endSearch"
    motion:duration="300">
    <OnClick
        motion:mode="toggle"
        motion:target="@+id/imageView_bottom_search" />
</Transition>

<ConstraintSet android:id="@+id/startSearch">
    <Constraint
        android:id="@id/imageView_bottom_search"
        ...startConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/endSearch">
    <Constraint
        android:id="@id/imageView_bottom_search"
        ...endConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/startHome">
    <Constraint
        android:id="@id/imageView_bottom_home"
        ...startConstraints... />
</ConstraintSet>

<ConstraintSet android:id="@+id/endHome">
    <Constraint
        android:id="@id/imageView_bottom_home"
        ...endConstraints... />
</ConstraintSet>

Any help appreciated.

С наилучшими пожеланиями


person aba    schedule 25.10.2018    source источник


Ответы (4)


У меня такая же проблема. Решение, которое я нашел, заключалось в том, чтобы выбрать, какой из переходов:

(в java-коде) ...

MotionLayout motionConteiner = findViewById(R.id.motion_container);
button1.setOnClickListener((v) -> {
            motionConteiner.setTransition(R.id.start1, R.id.end1);
            motionConteiner.transitionToEnd();//                
        });
button2.setOnClickListener((v) -> {
            motionConteiner.setTransition(R.id.start2, R.id.end2);
            motionConteiner.transitionToEnd();//                
        });
person close_file    schedule 27.10.2018
comment
Спасибо за ваш ответ! Я подумал, что это способ заставить его работать, но это подрывает идею наличия всех частей анимации в xml. В основном переходы в xml устарели. Возможно, сейчас просто невозможно иметь более одного Перехода. - person aba; 28.10.2018
comment
Таким образом, даже если вы хотите запустить анимацию по умолчанию без нажатия кнопки, этот код необходимо использовать. И это нигде не упоминается в Android Docs. - person Lalit Fauzdar; 20.03.2020
comment
Это решение также используется в официальных примерах приложений - github.com/android/views-widgets-samples/blob/master/ - person frangulyan; 02.04.2020

Я думаю, что Аба права. У меня также возникла проблема с добавлением нескольких переходов в один файл сцены. Теоретически MotionLayout должен поддерживать это, потому что каждый переход будет иметь отдельный триггер (часто как щелчок или смахивание). Возможно, это ошибка MotionLayout, которую нужно исправить. Исходя из моего опыта, учитывается только первый переход, встречающийся в файле сцены. Итак, в настоящее время я не думаю, что есть способ поддерживать более одного перехода в описании макета (сцене). Говоря более конкретно, все движения должны запускаться один раз одним и тем же триггером.

person codezombie    schedule 15.11.2019

Более котлиный ответ:

with(view as MotionLayout) {
    setTransition(R.id.startState, R.id.endState)
    transitionToEnd()
}
person Dambakk    schedule 16.04.2020

Мне кажется, что MotionLayout поддерживает только один Transition, когда вы добавляете второй Transition в MotionScene файл, второй Transition игнорируется. Однако у вас может быть несколько MotionLayout в вашем макете и создать MotionScene для каждого MotionLayout. Это также сделает MotionScene файл более чистым и упростит обслуживание.

В вашем файле макета вам понадобится родительский макет, который может содержать несколько файлов MotionLayout.

<?xml version="1.0" encoding="utf-8"?>
<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">

    <data>
        ...
    </data>

    <!-- [databinding] {"msg":"Only one layout element with 1 view child is allowed. So a Parent Layout is required for Multiple motion layouts. -->
    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.constraintlayout.motion.widget.MotionLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/motion_scene_01"
            tools:context=".menu.contextual.FragmentContextualOne"
            tools:showPath="true">

            <Button
                android:id="@+id/btn_one"
                android:layout_width="64dp"
                android:layout_height="64dp"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="310dp" />
        </androidx.constraintlayout.motion.widget.MotionLayout>

        <androidx.constraintlayout.motion.widget.MotionLayout
            android:id="@+id/m2"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layoutDescription="@xml/motion_scene_02">

            <Button
                android:id="@+id/btn_two"
                android:layout_width="64dp"
                android:layout_height="64dp"
                tools:layout_editor_absoluteX="8dp"
                tools:layout_editor_absoluteY="500dp" />
        </androidx.constraintlayout.motion.widget.MotionLayout>
    </FrameLayout>
</layout>

Сцена движения первая.

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

        <Transition
            android:id="@+id/transition_sine_wave"
            motion:constraintSetStart="@+id/wave_start"  
            motion:constraintSetEnd="@+id/wave_end"
            motion:duration="2000"
            motion:motionInterpolator="linear">
            <OnClick
                motion:touchAnchorId="@+id/btn_one"
                motion:touchAnchorSide="right"
                motion:targetId="@+id/btn_one"/>
        </Transition>

    <ConstraintSet android:id="@+id/wave_start">
        <Constraint
            android:id="@+id/btn_one"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintTop_toTopOf="parent"
            motion:layout_constraintStart_toStartOf="parent"/>

    </ConstraintSet>

    <ConstraintSet android:id="@+id/wave_end">
        <Constraint
            android:id="@+id/btn_one"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent"
            motion:layout_constraintTop_toTopOf="parent" />
    </ConstraintSet>
</MotionScene>

Сцена движения вторая

<?xml version="1.0" encoding="utf-8"?>
<MotionScene xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:motion="http://schemas.android.com/apk/res-auto">

    <Transition
        android:id="@+id/transition_straight"
        motion:constraintSetEnd="@+id/right_end"
        motion:constraintSetStart="@+id/left_start"
        motion:duration="2000"
        motion:motionInterpolator="linear" >
        <OnClick
            motion:targetId="@+id/btn_two"
            motion:clickAction="toggle"/>
    </Transition>

    <ConstraintSet android:id="@+id/left_start">
        <Constraint
            android:id="@+id/btn_two"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginStart="8dp"
            android:layout_marginBottom="100dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintStart_toStartOf="parent" />
    </ConstraintSet>

    <ConstraintSet android:id="@+id/right_end">
        <Constraint
            android:id="@+id/btn_two"
            android:layout_width="64dp"
            android:layout_height="64dp"
            android:layout_marginEnd="8dp"
            motion:layout_constraintBottom_toBottomOf="parent"
            motion:layout_constraintEnd_toEndOf="parent" />
    </ConstraintSet>
</MotionScene>

Это единственное решение XML, которое я смог придумать.

person Shawn    schedule 04.11.2020
comment
Разве это не устраняет причину ConstraintLayout? - person Abbas; 27.02.2021