Можно ли отключить MotionLayout? - PullRequest
4 голосов
/ 12 марта 2019

Я получил Fragment, в котором находится RecyclerView в пределах MotionLayout.На вершине представления переработчика у меня есть представление, которое разрушается и расширяется, и все это сделано в моей сцене движения.Это вызвано щелчком так же как реакцией на перетаскивание представления переработчика.Пока все это работает как задумано.

Теперь самое главное: я хотел бы полностью скрыть сворачивающиеся представления для некоторых состояний в моем приложении.Но если я устанавливаю видимость видов или изменяю их высоту, они все равно возвращаются в вид, когда я перетаскиваю представление переработчика.

Так что возможно полностью отключить MotionLayout (Блокировка ограничений), пока я не включу его снова.Отключить распознаватель перетаскивания также было бы жизнеспособным решением.

Теперь немного упрощенного XML для демонстрации ситуации.

Макет, содержащий макет движения с представлением заголовка и видом переработчика

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.motion.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:id="@+id/favouritesMotionLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layoutDescription="@xml/favourites_motion_scene"
    android:animateLayoutChanges="true">

    <ImageView
        android:id="@+id/headerView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        ...
        />

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/swipeRefreshLayout"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        ...
    >

        <pinch.nrcnext.view.scroll.NRCRecyclerView
            android:id="@+id/favoritesList"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />

    </android.support.v4.widget.SwipeRefreshLayout>

</android.support.constraint.motion.MotionLayout>

Соответствующая сцена движения:

<?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
        motion:constraintSetStart="@id/expanded"
        motion:constraintSetEnd="@id/collapsed"
        motion:duration="300">
        <OnSwipe
            motion:touchAnchorId="@id/swipeRefreshLayout"
            motion:touchAnchorSide="top"
            motion:dragDirection="dragUp" />
    </Transition>

    <ConstraintSet android:id="@+id/expanded">
        ... Constraints for expanded header ...
    </ConstraintSet>

    <ConstraintSet android:id="@+id/collapsed">
        ... ... Constraints for collapsed header ...
    </ConstraintSet>

</MotionScene>

Использование версии макета ограничения "2.0.0-alpha3"

implementation "com.android.support.constraint:constraint-layout:2.0.0-alpha3"

Итак, резюмируя: я хотел бы иметь возможность отключить макет движения, так что яЯ могу прокрутить окно повторного просмотра без расширения заголовка, пока я не скажу, что он снова будет включен.К сожалению, это не так просто, как favouritesMotionLayout.isEnabled = false, но я так думал.

Ответы [ 6 ]

3 голосов
/ 06 апреля 2019

В последнее время я много взламывал MotionLayout, поэтому я нашел свой трюк по отключению MotionLayout, как показано ниже.

layoutContainer.setTransitionListener(object: MotionLayout.TransitionListener {
        override fun onTransitionTrigger(p0: MotionLayout?, p1: Int, p2: Boolean, p3: Float) {}
        override fun onTransitionStarted(p0: MotionLayout?, p1: Int, p2: Int) {}
        override fun onTransitionCompleted(p0: MotionLayout?, p1: Int) {}
        override fun onTransitionChange(p0: MotionLayout?, startedScene: Int, endScene: Int, p3: Float) {
            when(currentFragmentTag) {
                TAG_DEFAULTBACKGROUND ->  {
                    if( startedScene==R.id.halfExpanded ) {
                        layoutContainer.transitionToState(startedScene)
                    }
                }
            }
        }
    })

Так что, в основном, я говорю MotionLayout вернуться к определенным ситуациям. Я чувствую, что onTransitionTrigger или onTransitionStarted должны содержать функцию остановки, но она не будет слушать в эти моменты.

onTransitionChange - то, где это фактически начинает двигаться. Я думаю, что вы поймете смысл этого трюка наоборот.

Удачного кодирования!

2 голосов
/ 02 июля 2019

Обратите внимание, что с последней бета-версии (бета2) можно отключить переход: https://androidstudio.googleblog.com/2019/06/constraintlayout-200-beta-2.html

Пример использования в Kotlin:

(view as? MotionLayout)?.getTransition(R.id.swipe_transition)?.setEnable(false)
1 голос
/ 07 мая 2019

На самом деле, мне удалось заставить его работать, установив начальное состояние моей сцены для начала и конца. В котлине:

motionLayout.setTransition(R.id.start, R.id.start)

И когда мне нужно было включить мой макет:

motionLayout.setTransition(R.id.start, R.id.end)

Не нужно менять свою сцену xml, у меня безупречно сработало в альфа-03

0 голосов
/ 24 июня 2019

у меня работает:

  if (list.isNullOrEmpty()) {
                    //disable
                    motionLayout.apply {
                        setTransition(R.id.expanded, R.id.expanded)
                        setTransitionDuration(0)
                    }
                } else {
                   //enable
                    motionLayout.apply {
                        setTransition(R.id.expanded, R.id.collapsed)
                        setTransitionDuration(200)
                    }
                }





 p.s.: 'androidx.constraintlayout:constraintlayout:2.0.0-beta2'
0 голосов
/ 03 мая 2019

Так что, похоже, есть способ взломать ваше состояние, чтобы отключить переход движения.Он должен быть добавлен после перехода выше в XML-файл.Я добавил еще один переход с тем же начальным и конечным состоянием.В вашем случае:

<Transition
        motion:constraintSetStart="@id/collapsed"
        motion:constraintSetEnd="@id/collapsed"
        motion:duration="0">

и в java / kotlin

motion_layout.setTransition(R.id.collapsed, R.id.collapsed)
0 голосов
/ 18 марта 2019

В данный момент кажется невозможным отключить движения в MotionLayout. Я надеюсь, что это будет добавлено в будущей версии. Чтобы решить мой вариант использования, я использовал немного грязный хак: я удалил представления, составляющие заголовок.

favouritesMotionLayout.removeView(headerView)

Макет был в порядке с этим, и вид исчез, и движение не было запущено. Чтобы вернуть взгляды, я просто заново залил весь макет. (В качестве альтернативы можно добавить программные представления снова с их ограничениями).

Я понимаю, что это не самое красивое решение, и в настоящее время я ищу способы решить весь сценарий использования без макета движения. К сожалению, это было очень полезно для 90% случаев использования.

...