Рекурсивно связывающие переходы ConstraintLayout с Runnable останавливается после первого запуска - PullRequest
0 голосов
/ 13 февраля 2019

Я пытаюсь создать переключающую анимацию для пользовательского меню.Есть несколько меню, которые могут быть выбраны разными кнопками.Когда меню не открыто, нажатие на кнопку должно открыть это меню.Если открыто другое меню, открытое закрывается, и после этой анимации следует открыть выбранное.каждое закрывающее / открывающее действие связано с переходом ConstraintLayout.

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

@Override
protected void onCreate(Bundle savedInstanceState) {
    ...
    ConstraintLayout layout_main;
    ConstraintSet l_mh0c = new ConstraintSet();
    ConstraintSet l_mh1o = new ConstraintSet();
    ConstraintSet l_mh1c = new ConstraintSet();

    Button btn;
    btn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            toggleOne();
        }
    });
    layout_main = (ConstraintLayout) findViewById(R.id.constraintMain);
    l_mh1o.clone(this, R.layout.main_menue_header1_open);
    l_mh1c.clone(this, R.layout.main_menue_header1_closed);
    l_mh0c.clone(this, R.layout.activity_main);
    ...
}

int openedMenue = -1;
long animationTime = 1000;
private void toggleOne() {
    TransitionManager.endTransitions(layout_main); //<- makes no difference when commented
    if(openedMenue==1) {              
        System.out.println("sync closing");
        Runnable r = () -> toggleOne();
        closeMenue(1, animationTime, r);
    } else {
        System.out.println("sync opening");
        startMenue(1, animationTime);
    }
}

public void startMenue(Integer index, final Long maxtime) {
    Transition t;
    switch (index) {
        case 1:
            t = new ChangeBounds();
            t.setDuration(0).addListener(new TransitionEndListener() {
                @Override
                public void onTransitionEnd(Transition transition) {
                    Transition t = new ChangeBounds();
                    t.setDuration(maxtime / 2).addListener(new TransitionEndListener() {
                        @Override
                        public void onTransitionEnd(Transition transition) {
                            Transition t = new ChangeBounds();
                            t.setDuration(maxtime / 2);
                            TransitionManager.beginDelayedTransition(layout_main, t);
                            l_mh0o.applyTo(layout_main);
                            openedMenue = 1;
                            System.out.println("sync start finished");
                        }
                    });
                    TransitionManager.beginDelayedTransition(layout_main, t);
                    l_mh1o.applyTo(layout_main);

                }
            });
            TransitionManager.beginDelayedTransition(layout_main, t);
            l_mh1c.applyTo(layout_main);
            // the following does not provoke any changes
            Scene s = new Scene(layout_main); 
            TransitionManager.go(s);
            break;
    }
}

private void closeMenue(int index, final long maxtime, Runnable callback) {
    System.out.println("sync closing menue " + openedMenue);
    Transition t;
    switch (index) {
        case 1:
            t = new ChangeBounds();
            t.setDuration(maxtime/2).addListener(new TransitionEndListener() {
                @Override
                public void onTransitionEnd(Transition transition) {
                    Transition t = new ChangeBounds();
                    t.setDuration(maxtime/2).addListener(new TransitionEndListener() {
                        @Override
                        public void onTransitionEnd(Transition transition) {
                            Transition t = new ChangeBounds();
                            t.setDuration(0);
                            TransitionManager.beginDelayedTransition(layout_main, t);
                            l_mh0c.applyTo(layout_main);
                            openedMenue = -1;
                            try {
                                callback.run();
                            } catch (Exception e) { e.printStackTrace(); }
                        }
                    });
                    TransitionManager.beginDelayedTransition(layout_main, t);
                    l_mh1c.applyTo(layout_main);
                    openedMenue = 1;
                }
            });
            TransitionManager.beginDelayedTransition(layout_main, t);
            l_mh1o.applyTo(layout_main);
            break;
    }
}

Когда я его запускаю, я получаюследующий вывод:

[Button Click]
sync opening
sync start finished
[Button Click]
sync closing
sync closing menue 1
sync opening
sync start finished // problem

Однако последняя строка никогда не печатается;Кажется, как будто (после того, как закрывающее действие снова начинает открывающее действие), первый переход в startMenue () никогда не выполняет обратный вызов к onTransitionEnd ().

Вот TransitionEndListener (просто простая оболочка для интерфейса)

public abstract class TransitionEndListener implements Transition.TransitionListener {

    @Override
    public final void onTransitionStart(Transition transition) {}

    @Override
    public final void onTransitionCancel(Transition transition) {}

    @Override
    public final void onTransitionPause(Transition transition) {}

    @Override
    public final void onTransitionResume(Transition transition) {}
}

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

Не могли бы вы объяснитьпочему это происходит?

ОБНОВЛЕНИЕ

Я нашел этот пост по обратным вызовам TransitionManager ;

Переход от mh0c t0 mh1cявляется переходом ConstraintLayout, потому что ограничения действительно меняются;однако переход не отображается в пользовательском интерфейсе, поскольку ширина переходного элемента равна 0. (Этот переход представляет собой переход от одной точки меню к другой, который не должен быть видимым.)

Может ли это бытьпричина, по которой переход не выполняет обратный вызов?

и если так;как мне обойти это?

ОБНОВЛЕНИЕ 2 Я читал документацию и, возможно, нашел решение, используя TransitionManager.go(scene, transition).

-> К сожалению, это не сработало;см. код startMenue () для изменений

1 Ответ

0 голосов
/ 14 февраля 2019

После все большего количества попыток и рецензирования этих сообщений:

Я выяснил, что вызвало проблему:

В самой внутренней части (самой внутренней функции обратного вызова) closeMenue ()

Transition t = new ChangeBounds();
t.setDuration(0);
TransitionManager.beginDelayedTransition(layout_main, t);
l_mh0c.applyTo(layout_main);
openedMenue = -1;
try {
     callback.run();
} catch (Exception e) { e.printStackTrace(); }

Последовательность команд немного неверна.Это должно выглядеть следующим образом:

Transition t = new ChangeBounds();
t.setDuration(0).addListener(new TransitionEndListener() {
    @Override
    public void onTransitionEnd(Transition transition) {
        try {
            callback.run();
        } catch (Exception e) { e.prtinStackTrace(); }
    }
});
TransitionManager.beginDelayedTransition(layout_main, t);
l_mh0c.applyTo(layout_main);
openedMenue = -1;

Это гарантирует, что сначала завершится закрывающий переход, а затем начнется открывающий переход.

...