Как указать TransitionManager.beginDelayedTransition, чтобы повлиять только на прямые дочерние представления - PullRequest
0 голосов
/ 22 мая 2018

Я пытаюсь использовать ConstraintLayout в сочетании с видами, которые скользят вверх и вниз с анимацией.Эти виды организованы вертикально, с RecyclerView вверху и двумя другими представлениями, сложенными под ним:

<constraint layout container>
    [                    ]
    [    recycler view   ] 
    [                    ]
    [48dp height 1st view]
    [48dp height 2nd view]
</constraint layout container>

Анимация очень проста: при нажатии кнопки 1-й вид перемещается снизуконтейнер в положение, которое вы видите выше, при повторном нажатии он перемещается вниз и остается наложенным на 2-й вид.Когда это происходит, RecyclerView в верхней части изменяет высоту, поскольку ограничено этим первым видом, в противном случае он оставит пустое пространство.

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

    java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.

После изучения происходящего я обнаружил, что эта проблема является следствием TransitionManager, который я использую для анимацииизменения.То, что я обнаружил, было интересно, когда кнопка была нажата, чтобы переместить 1-й вид вверх (или вниз, просто представьте себе противоположные шаги), менеджер делал следующее:

  • Исчезает первый / последний видиз RecyclerView (зависит от того, включен ли у вас обратный макет или стек с конца)
  • Удалите это представление из RecyclerView
  • Уменьшите высоту RecyclerView
  • Переместить 1-й вид вверх

Несмотря на то, что я указал во всех местах, я мог представить, что RecyclerView не должен анимировать изменения элемента, TransitionManager переопределяет его иэто означало, что есть окно, в котором тот же самый вид, который собирается удалить из RecyclerView, может быть снова добавлен к тому же родительскому элементу, и это окно - когда представление исчезает из менеджера.

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

Так как это проблема, вызванная внутри RecyclerView, я буду прекрасно работать без анимации внутри, и по этой причине я хотел бы знать, как я могу указать вTransitionManager.beginDelayedTransition только для анимации прямых дочерних представлений ConstraintLayout, таким образом, он не будет анимировать представления внутри RecyclerView.

Соответствующая документация ничего не освещает, поэтому я представляювот этот вопрос;Как я могу ограничить переход к прямым дочерним видам?

В случае, если это может быть полезно, я включу сюда фрагмент менеджера переходов

    final ConstraintSet constraintSet;
    final ConstraintLayout constraintLayout;

    constraintSet = new ConstraintSet();
    constraintLayout = (ConstraintLayout) viewParent;

    TransitionManager.beginDelayedTransition(constraintLayout);

    constraintSet.clone(constraintLayout);
    constraintSet.connect(startId, startSide, endId, endSide, margin);
    constraintSet.applyTo(constraintLayout);

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Я исправил это так:

TransitionManager.beginDelayedTransition(
                        constraintLayout,
                        TransitionSet().apply {
                            ordering = TransitionSet.ORDERING_SEQUENTIAL
                            addTransition(ChangeBounds())
                            addTransition(Fade(Fade.IN))
                        }
                    )

это почти тот же самый код внутри AutoTransition, который является кодом по умолчанию, если мы не пропустили пользовательский переход, но я удалил addTransition(Fade(Fade.OUT)) это, кажется, причина аварии.А анимации выглядят очень похоже на оригинал, по крайней мере, для меня.

0 голосов
/ 26 мая 2018

pskink опубликовал ответ в комментариях, но после того, как дважды попросил его опубликовать ответ в качестве ответа для меня, чтобы я никогда не делал этого, я опубликую его и отмечу это как ответ.

У TransitionManager был метод excludeChildren, который идеально подходит для того, что я искал.Вы можете использовать типы классов, дочерние элементы определенного представления и т. Д.

РЕДАКТИРОВАТЬ: Добавление запрашиваемого примера

    AutoTransition autoTransition = new AutoTransition();
    autoTransition.excludeChildren(R.id.recyclerView, true);
    TransitionManager.beginDelayedTransition(constraintLayout, autoTransition);

с constraintLayout в качестве родителя целевого представления и R.id.recyclerView быть дочерним представлением того родителя, которого я не хочу анимировать, в этом конкретном примере.Вы также можете исключить всех детей определенного класса (например, EditText) и т. Д.

...