Как запустить конкретный переход в MotionLayout?

У меня есть MotionScene с 4 ConstraintSets, представляющими 4 состояния экрана (состояния загрузки) и с 3 переходами между ними. Когда состояние моего приложения меняется с, например, загрузка в обработку, я хочу запустить переход 1 (set1 -> set2), когда состояние снова изменится, я хочу запустить переход 2 (set2 -> set3). И я не могу найти способ сделать это.

Я попробовал следующее:

Чтобы установить текущий переход с помощью

     motion_layout.setTransition(R.id.set1, R.id.set2)
     motion_layout.transitionToState(R.id.set2)

Чтобы просто установить переход

motion_layout.setTransition(R.id.set1)

Для перехода в какое-либо состояние:

motion_layout.transitionToState(R.id.set1)

но все вышеперечисленные методы запускают все мои наборы вместе, даже если я использую app: autoTransition = "none".


Я попытался поместить все в один переход и установить app: progress = 0 на, а затем контролировать состояние анимации с прогрессом:

 motion_layout.setProgress(0.25f, 1.0f)

который просто запускает всю анимацию до конца, или я пробовал

motion_layout.progress = 0.25f

которые не анимируются, они просто показывают мне прогресс анимации 0,25 без какого-либо движения.

Как контролировать поток анимации? Как запустить конкретный набор? Было бы лучше использовать прогресс? Как это решить?

P.S. я использую

implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta7'

person StayCool    schedule 16.06.2020    source источник
comment
Привет, обновил свой ответ - впервые не заметил проблемы;)   -  person Mariusz Brona    schedule 16.06.2020


Ответы (3)


Я не уверен, что вы делаете (недостаточно кода), но вот такой простой, насколько я могу, пример с 5 состояниями.

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

<Transition
    motion:constraintSetStart="@id/state1"
    motion:constraintSetEnd="@+id/state2"/>
<Transition
    motion:constraintSetStart="@id/state2"
    motion:constraintSetEnd="@+id/state3"/>

<Transition
    motion:constraintSetStart="@id/state3"
    motion:constraintSetEnd="@+id/state4"/>

<Transition
    motion:constraintSetStart="@id/state4"
    motion:constraintSetEnd="@+id/state5"/>

<Transition
    motion:constraintSetStart="@id/state1"
    motion:constraintSetEnd="@+id/state5"/>

<ConstraintSet android:id="@+id/state1">
    <Constraint         android:id="@+id/view">
    <CustomAttribute motion:attributeName="text" motion:customStringValue="state1" />
    </Constraint>
</ConstraintSet>

<ConstraintSet android:id="@+id/state2">
    <Constraint         android:id="@+id/view">
        <Transform android:translationX="-100dp"/>
        <CustomAttribute motion:attributeName="text" motion:customStringValue="state2" />
    </Constraint>

</ConstraintSet>

<ConstraintSet android:id="@+id/state3">
    <Constraint         android:id="@+id/view">
        <Transform android:translationX="100dp"/>
        <CustomAttribute motion:attributeName="text" motion:customStringValue="state3" />

    </Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/state4">
    <Constraint         android:id="@+id/view">
        <Transform android:translationY="-100dp"/>
        <CustomAttribute motion:attributeName="text" motion:customStringValue="state4" />
    </Constraint>
</ConstraintSet>
<ConstraintSet android:id="@+id/state5">
    <Constraint         android:id="@+id/view">
        <Transform android:translationY="100dp"/>
        <CustomAttribute motion:attributeName="text" motion:customStringValue="state5" />
    </Constraint>
</ConstraintSet>

этот файл сцены работает с этим main_activity.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.motion.widget.MotionLayout 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"
app:layoutDescription="@xml/activity_main_scene"
android:id="@+id/motionlayout"
tools:context=".MainActivity">

<TextView
    android:id="@+id/view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#4DD3D3"
    android:text="Hello World!"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<Button
    android:id="@+id/button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="transition"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    android:onClick="nextState"
    />
 </androidx.constraintlayout.motion.widget.MotionLayout>

и этот MainActivity.kt

package com.example.multistate

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
}

fun nextState(view: View) {
   when (motionlayout.currentState ) {
       R.id.state1 -> motionlayout.transitionToState(R.id.state2)
       R.id.state2 -> motionlayout.transitionToState(R.id.state3)
       R.id.state3 -> motionlayout.transitionToState(R.id.state4)
       R.id.state4 -> motionlayout.transitionToState(R.id.state5)
       R.id.state5 -> motionlayout.transitionToState(R.id.state1)
   }
}
}
person hoford    schedule 28.06.2020
comment
Я протестирую это и вернусь с ответом завтра - person StayCool; 29.06.2020
comment
Прекрасно работает. Теперь надо покопаться и понять, почему у меня не работает макет. - person StayCool; 07.07.2020

Если у вас нет, он должен переходить в состояние, которое вы вызываете, только если вы вызываете ml.transitionToState (R.id.xx);

Удалите все атрибуты autoTransition в motionScene.

person hoford    schedule 17.06.2020
comment
Не работает. Я устанавливаю autoTransition = false для каждого ConstraintSet - person StayCool; 17.06.2020
comment
@StayCool просто добавьте движение: autoTransition = none к транзакциям в описании макета. - person Reza; 24.10.2020

может попробовать что-то вроде этого:

motion_layout.setTransitionListener(
    object : MotionLayout.TransitionListener {
        override fun onTransitionChange(p0: MotionLayout?, p1: Int, p2: Int, p3: Float) {
        }

        override fun onTransitionCompleted(motionLayout: MotionLayout?, currentId: Int) {
            when(currentId) {
                R.id.set1 -> motion_layout.setTransition(currentId, R.id.set2)
                R.id.set2 -> motion_layout.setTransition(currentId, R.id.set3)
                R.id.set3 -> motion_layout.setTransition(currentId, R.id.set4)
                R.id.set4 -> motion_layout.setTransition(currentId, R.id.set1)
        }
    }
)

motion_layout.transitionToEnd()

Затем элемент управления вызывает motion_layout.transitionToEnd () каждый раз, когда вы хотите изменить состояние

person Mariusz Brona    schedule 16.06.2020
comment
На самом деле я просто хочу остановить Переход после его завершения. И запускать следующий через некоторое время. Я попробую этот обратный звонок и скоро вернусь с обратной связью - person StayCool; 16.06.2020
comment
Как я уже сказал, он остановится на R.id.set2, а через некоторое время просто вызовет motion_layout.transitionToEnd, и он перейдет к R.id.set3 - person Mariusz Brona; 16.06.2020
comment
Этот motionLayout такой беспорядочный. На самом деле, я даже не смог попробовать ваше решение. Потому что моя сцена была полностью сломана, и я не мог просто довести ее до конца. Вернусь к этой задаче через несколько дней, и я сначала попробую ваше решение - person StayCool; 18.06.2020