2015-12-28 2 views
2

Я пытаюсь сделать плавно обновляющийся дисплей, позвонив TransitionManager.beginDelayedTransition(viewGroup, new AutoTransition()) перед обновлением дисплея. Но я обнаружил, что иногда я быстро обновляю дисплей, и Android запутывается.Почему мой Android-переход игнорирует TransitionListener?

Таким образом, я добавил TransitionListener в AutoTransition, где transitionEnd() перезвонил, заявив, что переход завершен, и в этот момент я оживляю новое состояние экрана. Но я нахожу, что обычно это даже не называется.

Есть ли способ возврата обратного вызова либо когда а) переход заканчивается, либо б) переход никогда не вызван в первую очередь?


Дополнительная информация:

Я использую Xamarin.Android. У меня есть фрагмент кода, который выглядит следующим образом, который инициирует переход:

if (animated && viewGroup != null && Utils.Api19PlusKitkat) { 
    App.Log("** Beginning animation."); 
    var transition = new AutoTransition(); 
    transition.AddListener(new TransitionListener(this)); 
    TransitionManager.BeginDelayedTransition(viewGroup, transition); 
} 

TransitionListener довольно прост:

public class TransitionListener : Java.Lang.Object, Transition.ITransitionListener { 
    readonly TreeNode owner; 

    public TransitionListener(TreeNode owner) 
    { 
     this.owner = owner; 
    } 

    public void OnTransitionEnd(Transition transition) 
    { 
     App.Log("**** TransitionListener: Transition End."); 
     owner.FinishTransition(); 
    } 

    public void OnTransitionCancel(Transition transition) {} 
    public void OnTransitionPause(Transition transition) {} 
    public void OnTransitionResume(Transition transition) {} 
    public void OnTransitionStart(Transition transition) { 
     App.Log("**** TransitionListener: Transition Start."); 
    } 
} 

Когда я смотрю на моем журнале приложений, я вижу кучу случаев " Начало анимации ", но очень редкие случаи" Начало перехода "или" Переходный конец "(в настоящее время я не вижу никаких экземпляров, но иногда видел, как это происходит в журнале).

ответ

2

UPD2:

Я думаю, я получил его. После двух дней бесплодных попыток мне удалось воспроизвести проблему.

TransitionManager.beginDelayedTransition() запустит что-то только, когда есть что-то обновить на экране.

Например, если вы setOnClickListener с TransitionManager.beginDelayedTransition() в OnClick к кнопке с собственным фоном без селектора (android:background="#000", вместо селектора по умолчанию) - ничего не произойдет, Transition не заводится вообще (как вы видите, в вашем случае). В то же время, если вы присвоите тот же OnClickListener кнопке, заданной по умолчанию (т. Е. С селектором в качестве фона) - Transitionбудет немедленно начать.

То же самое, если вы делаете некоторые UI-изменений после TransitionManager.beginDelayedTransition() называют:

public void changeScene(View v){ 
    AutoTransition autoTransition = new AutoTransition(); 
    autoTransition.setDuration(3000); 
    autoTransition.addListener(new Transition.TransitionListener() { 
     @Override 
     public void onTransitionStart(Transition transition) { 
      Toast.makeText(MainActivity.this, "start", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onTransitionEnd(Transition transition) { 
      Toast.makeText(MainActivity.this, "end", Toast.LENGTH_SHORT).show(); 
     } 

     @Override 
     public void onTransitionCancel(Transition transition) {} 

     @Override 
     public void onTransitionPause(Transition transition) {} 

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

    TransitionManager.beginDelayedTransition(container, autoTransition); 
    findViewById(R.id.btn1).setVisibility(
      (findViewById(R.id.btn1).getVisibility()) == View.VISIBLE? 
        View.INVISIBLE : View.VISIBLE); 
} 

Это будет фрагмент кода будет работать, так как он должен:

enter image description here

Но как только вы удалите setter for Visibility, Transition добавляет к backlog из TransitionManager и не исполняется (имя метода говорит - оно может быть de уложенный).И это будет выполняться только во время следующего UI-изменения:

enter image description here

В этом примере я удалил с setVisibility() - и вы можете видеть результат: «анимация» (в моем случае просто Тосты) начали только после того, как я нажал кнопку с Selector в качестве фона (т. е. произойдет изменение пользовательского интерфейса).

Итак, исправление будет - «убедитесь, что есть некоторые изменения пользовательского интерфейса сразу после того, как вы позвоните TransitionManager.beginDelayedTransition()».

Надеюсь, это поможет

P.S. Странно, однако, что TransitionManager.go(), написанный после TransitionManager.beginDelayedTransition(), не будет работать. Единственным обходным решением, которое я нашел здесь, является его размещение в onTransitionEnd для отложенного перехода.

Upd1:

Первая мысль была, что это может быть связано с Xamarin. Затем я нашел два примера, которые используют BeginDelayedTransition в Xamarin.Android: xamarin/monodroid-samples и garuma/Moyeu. Чтобы проверить, относится ли ваша проблема к Xamarin.Android или нет, я предлагаю отладить эти 2 проекта, чтобы увидеть, срабатывает ли TransitionListener Transition-events.

В обоих примерах используется TransitionManager.beginDelayedTransition() с одним параметром (viewGroup). Проверка source code из TransitionManager показывает, что метод 1-параметр призывающего beginDelayedTransition(sceneRoot, null);

public static void beginDelayedTransition(final ViewGroup sceneRoot) { 
    beginDelayedTransition(sceneRoot, null); 
} 

и неопределенные Заменяет по sDefaultTransition:

private static Transition sDefaultTransition = new AutoTransition(); 
.... 
public static void More ...beginDelayedTransition(final ViewGroup sceneRoot, Transition transition) { 
    if (!sPendingTransitions.contains(sceneRoot) && sceneRoot.isLaidOut()) { 
     if (Transition.DBG) { 
      Log.d(LOG_TAG, "beginDelayedTransition: root, transition = " + 
        sceneRoot + ", " + transition); 
     } 
     sPendingTransitions.add(sceneRoot); 
     if (transition == null) { 
      transition = sDefaultTransition; 
     } 
     final Transition transitionClone = transition.clone(); 
     sceneChangeSetup(sceneRoot, transitionClone); 
     Scene.setCurrentScene(sceneRoot, null); 
     sceneChangeRunTransition(sceneRoot, transitionClone); 
    } 
} 

Так отлаживать его, вы должны будете получить по умолчанию TransactionManager.getDefaultTransition() и добавьте свой TransitionListener в него.

Если это сработает - тогда нам нужно будет найти проблему в вашем коде. Если это не сработает - ну .. Тогда, предположительно, мы обнаружили системную ошибку, которую мы можем записать.

+0

Я добавил некоторые дополнительные сведения в свой пост. Не уверен, что это очень полезно. :) –

+0

@ AnthonyMills Я продолжаю действовать как капитан Очевидный, но я нашел два примера, которые используют BeginDelayedTransition в Xamarin.Android: [xamarin/monodroid-samples] (https://github.com/xamarin/monodroid-samples/ blob/7db583176aec6896090ca60e7e075f79d9ad1787/ApiDemo/Animation/Transitions.cs) и [garuma/Moyeu] (https://github.com/garuma/Moyeu/tree/be8b7b369152a3f8707e2ee1ca3fcdcf8dcfbdad) Итак, я предполагаю, что он должен работать в проектах Xamarin. Можете ли вы отлаживать эти примеры на своем устройстве и посмотреть, запущены ли их анимационные слушатели? –

+0

(вам нужно будет сделать 'TransactionManager.getDefaultTransition()' и добавить для него 'TransitionListener', так как оба примера используют' TransitionManager.BeginDelayedTransition() 'с по умолчанию' AutoTransition' в качестве второго параметра - см. Источник код 'TransitionManager': http://grepcode.com/file/repo1.maven.org/maven2/org.robolectric/android-all/4.4_r1-robolectric-0/android/transition/TransitionManager.java#TransitionManager.0sDefaultTransition) Сделав это, мы выясним, является ли это ошибкой в ​​каркасе или что-то не так с вашим приложением, поэтому мы устраним половину гипотезы :-) –

0

Наконец-то я нашел ответ на свой вопрос.

Я звонил TransitionManager.beginDelayedTransition на FrameLayout, у которого не было детей в то время, когда я звонил, затем я добавил ребенка.

Это не вызывает переход, и вызываемые вызовы не вызываются.

Теперь я проверю, есть ли у меня ViewGroupbeginDelayedTransition, у которого есть дети перед выполнением вызова; если это не так, я не пытаюсь его оживить.