I\'m trying to make a smoothly-updating display by calling TransitionManager.beginDelayedTransition(viewGroup, new AutoTransition())
before updating the display
I finally found the answer to my question.
I was calling TransitionManager.beginDelayedTransition
on a FrameLayout
which did not have children at the time I called, then I added a child.
This doesn't cause a transition to happen, and no callbacks are called.
I now check if the ViewGroup
I'm calling beginDelayedTransition
on has children before doing the call; if it doesn't, I don't bother trying to animate it.
Upd2:
I think, I got it now. After 2 days of fruitless attempts, I managed to repro the issue.
TransitionManager.beginDelayedTransition()
will fire up something only when there's something to update on the screen.
For example, if you setOnClickListener
with TransitionManager.beginDelayedTransition()
in OnClick
to the button with custom background without selector (android:background="#000"
, instead of the default selector) - nothing will happen, Transition
won't start at all (as you see in your case). At the same time, if you assign same OnClickListener
to the default-styled button (i.e. with selector as a background) - Transition
will start immediately.
Same, if you do some UI-changes after TransitionManager.beginDelayedTransition()
being called:
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);
}
This will code snippet will work, as it should:
But once you remove the setter for Visibility, Transition is adding to the backlog of the TransitionManager
and not executed (the name of the method says - it might be delayed). And it will be executed only during next UI-change:
In this example, I removed the the setVisibility()
- and you can see the result: "animation" (in my case just Toasts) started only after I clicked on the button with Selector as a background (i.e. UI-change happens).
So the fix is going to be - "make sure there's some UI change just after you call TransitionManager.beginDelayedTransition()
".
I hope, it helps
P.S. It's kind of strange though, that TransitionManager.go()
, written after TransitionManager.beginDelayedTransition()
, won't work. The only workaround I found here is to put it inside onTransitionEnd
for the delayed transition.
Upd1:
First thought was that it might be related to Xamarin. Then I found two examples which are using BeginDelayedTransition
in Xamarin.Android: xamarin/monodroid-samples and garuma/Moyeu.
To check if your issue relates to Xamarin.Android or not - I suggest to debug these 2 projects to see if TransitionListener
fires Transition-events.
Both examples uses TransitionManager.beginDelayedTransition()
with one parameter (viewGroup). Checking source code of TransitionManager
shows, that 1-parameter method is is calling beginDelayedTransition(sceneRoot, null);
public static void beginDelayedTransition(final ViewGroup sceneRoot) {
beginDelayedTransition(sceneRoot, null);
}
and null replaces by 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);
}
}
So to debug it, you'll have to get the default TransactionManager.getDefaultTransition()
and add your TransitionListener
into it.
If it works - then we'll have to find the issue in your code. If it doesn't work - well.. Then, presumably, we found a system bug, which we can file.