Проблема с несколькими переходами в 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>
Любая помощь приветствуется.
С наилучшими пожеланиями
6 ответов
У меня такая же проблема. Решение, которое я нашел, состояло в том, чтобы выбрать, какой из переходов:
(в коде 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();//
});
Более котлинный ответ:
with(view as MotionLayout) {
setTransition(R.id.startState, R.id.endState)
transitionToEnd()
}
Поддерживаются множественные переходы.
В коде, которым вы поделились, у вас есть 4 набора ограничений: start_home -> end_home, start_search -> end_search. Вместо этого используйте только 3 набора, один из которых является базовым состоянием, например start -> end_home и start -> end_search. «Начало» здесь представляет собой базовое состояние экрана.
Это происходит потому, что, скажем, вы сначала выполнили домашнее действие, а затем вы выполнили действие поиска, тогда поиск не будет работать, потому что начальные критерии (start_search) не будут соответствовать start_home или end_home (которые были применены последними)
Я думаю, что Аба права. У меня также возникла проблема с добавлением нескольких переходов в один файл сцены. Теоретически MotionLayout должен поддерживать это, потому что каждый переход будет иметь отдельный триггер (часто как щелчок или смахивание). Возможно, это ошибка MotionLayout, которую нужно исправить. Исходя из моего опыта, обрабатывается только первый переход, который встречается в файле сцены. Итак, в настоящее время я не думаю, что есть способ поддерживать более одного перехода в описании макета (сцене). Говоря более конкретно, все движения должны запускаться один раз одним и тем же триггером.
Привет, после некоторого удара и попытки, я нашел хороший способ, и я сделаю все возможное, чтобы сделать его как можно проще. Если у вас все еще есть сомнения, не стесняйтесь спрашивать!
Итак, как вы сказали, вам нужно 2 перехода для 2 кнопок сравнения с помощью onClick
Что вы можете сделать, так это иметь 2 перехода diff с их соответствующим набором ограничений
как например:
<Transition
android:id="@+id/transition_1"
motion:constraintSetEnd="@+id/2"
motion:constraintSetStart="@id/1"
motion:duration="150">
</Transition>
<Transition
android:id="@+id/transition_2"
motion:constraintSetEnd="@+id/4"
motion:constraintSetStart="@id/3"
motion:duration="150">
</Transition>
<ConstraintSet android:id="@+id/1">
<Constraint
android:id="@+id/v1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/v2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/2">
<Constraint
android:id="@+id/v1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/v2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/3">
<Constraint
android:id="@+id/v3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/v4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
<ConstraintSet android:id="@+id/4">
<Constraint
android:id="@+id/v3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
<Constraint
android:id="@+id/v4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
motion:layout_constraintBottom_toBottomOf="parent"
motion:layout_constraintEnd_toEndOf="parent"
motion:layout_constraintStart_toStartOf="parent" />
</ConstraintSet>
Затем добавьте код в onClick, чтобы программно воспроизвести этот переход.
// CODE LIKE THIS IN YOUR ONCLICK BUTTON FUNCTION FOR 1st BUTTON
motionLayoutObject.setTransition(R.id.transition_1)
motionLayoutObject.transitionToEnd()
// CODE LIKE THIS IN YOUR ONCLICK BUTTON FUNCTION FOR 2nd BUTTON
motionLayoutObject.setTransition(R.id.transition_2)
motionLayoutObject.transitionToEnd()
Мне кажется, что
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, которое я мог придумать.