Я играю с 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>
Любая помощь приветствуется.
С наилучшими пожеланиями
У меня такая же проблема. Решение, которое я нашел, заключалось в том, чтобы выбрать, какой из переходов:
(в 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();//
});
Таким образом, даже если вы хотите запустить анимацию по умолчанию без нажатия кнопки, этот код необходимо использовать. И это нигде не упоминается в Android Docs.
Это решение также используется в официальных примерах приложений - github.com/android/views-widgets-samples/blob/master/…
Я думаю, что Аба права. У меня также возникла проблема с добавлением нескольких переходов в один файл сцены. Теоретически MotionLayout должен поддерживать это, потому что каждый переход будет иметь отдельный триггер (часто как щелчок или смахивание). Возможно, это ошибка MotionLayout, которую нужно исправить. Исходя из моего опыта, учитывается только первый переход, встречающийся в файле сцены. Итак, в настоящее время я не думаю, что есть способ поддерживать более одного перехода в описании макета (сцене). Говоря более конкретно, все движения должны запускаться один раз одним и тем же триггером.
Еще один ответ котлины:
with(view as MotionLayout) {
setTransition(R.id.startState, R.id.endState)
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, которое я смог придумать.
Разве это не устраняет причину появления ConstraintLayout
?
Поддерживаются множественные переходы.
В коде, которым вы поделились, у вас есть 4 набора ограничений: start_home -> end_home, start_search -> end_search. Вместо этого используйте только 3 набора, один из которых является базовым состоянием, например start -> end_home и start -> end_search. «Начало» здесь представляет собой базовое состояние экрана.
Это происходит потому, что, скажем, вы сначала выполнили домашнее действие, а затем вы выполнили действие поиска, тогда поиск не будет работать, потому что начальные критерии (start_search) не будут соответствовать start_home или end_home (которые были применены последними)
Спасибо за ваш ответ! Я подумал, что это способ заставить его работать, но это разрушает идею наличия всех частей анимации в xml. В основном переходы в xml устарели. Возможно, сейчас просто невозможно иметь более одного Перехода.