MotionLayout: несколько кумулятивных переходов

Я использую MotionLayout и пытаюсь применить серию переходов (определено в файле MotionScene). Например, Transition1 изменяет положение View1, а затем Transition2 последовательно меняет положение View2. Проблема, которую я вижу, заключается в том, что Transition2 заставляет View1 вернуться к исходному макету. Я запускаю переходы, используя вызовы transitionToState() (я также пытался явно указать начальное/конечное состояние для перехода, используя setTransition(), а затем вызывая transitionToEnd()).

Я видел комментарий в https://www.raywenderlich.com/8883-motionlayout-tutorial-for-android-getting-started, который

if you don’t provide an end constraint for a view, it will disappear. This happens because the library doesn’t know which constraints it should apply at the end of the animation

Нужно ли также включать информацию о макете View1 в ConstraintSet для Transition2?

В https://github.com/googlesamples/android-ConstraintLayoutExamples/blob/master/README.md есть пример «Многосостояние», но похоже, что все включенные переходы начинаются с одного базового состояния (а не «кумулятивно»)

1
0
2 635
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Переходы не являются дельтой состояния. Они переходят из штата в штат. ConstraintSets определяют эти состояния.

ConstraintSets (в контексте MotionScene) определяют состояние, которое является базовым макетом + вашими изменениями, описанными в теге.

Итак, в моем случае мне также нужно будет определить текущий макет View1 (после Transition1) в ConstraintSet для Transitions2 (а также другой ConstraintSet, если Transitions1 не произошло)? Моя проблема заключается в том, что у нас есть несколько переходов, изменяющих несколько разных представлений... и нет гарантии, что конкретный переход произошел раньше... поэтому перестановки становятся довольно большими (если все комбинации измененных макетов представления должны быть определены для каждого перехода )

John O'Reilly 06.03.2019 17:58
Ответ принят как подходящий

Как сказал @хофорд, наборы ограничений не объединяются при каждом изменении. Судя по всему, это тоже невозможно без использования рефлексии, хотя она точно была бы полезна. Во всяком случае, вот как это сделать с помощью отражения (через несколько функций расширения).

Я создал свой базовый класс собственный TransitionListener для поддержки аннотаций и удобочитаемых имен значений. Функции расширения можно найти здесь.

Что вы можете сделать, так это объединить два ConstraintSets, а затем видоизменить endConstraintSet, который можно получить с помощью TransitionListener#onTransitionChange:

class AccumulativeTransitionListener: TransitionListener() {

        var didApplyConstraintSet = false

        override fun onTransitionChange(view: MotionLayout, @IdRes startConstraintSetId: Int, @IdRes endConstraintSetId: Int, progress: Float) {
            if (!didApplyConstraintSet) {
                // Let's retrieve our ConstraintSets first
                val startConstraintSet = view.getConstraintSet(startConstraintSetId)
                val endConstraintSet = view.getConstraintSet(endConstraintSetId)
                // Merge them (using an extension function)
                val mergedConstraintSet = startConstraintSet + endConstraintSet
                // Clear + Set them
                endConstraintSet.setConstraints(mergedConstraintSet)
                didApplyConstraintSet = true
            }
        }

        override fun onTransitionCompleted(view: MotionLayout, @IdRes constraintSetId: Int) {
            didApplyConstraintSet = false
        }

    }

Чтобы не объединять и не применять ConstraintSets каждый раз, когда вызывается TransitionListener#onTransitionChange, есть простая вспомогательная переменная.

Наконец, вы должны прикрепить слушателя к вашему MotionLayout:

val accumulativeListener = AccumulativeTransitionListener()
motionLayout.setTransitionListener(accumulativeListener)

Дайте мне знать, если это работает или есть какие-либо ошибки!

Другие вопросы по теме