How can one know if an activity is started without a transition?
Asked Answered
I

2

20

I have a use case where I mostly start an activity with a transition, but that's not the case when opening it from the navigation drawer.

To keep the transition smooth I have a Transition.TransitionListener in which I trigger some UI updating when the transition is done.

So I have something like this:

public class SomeActivity extends Activity {

    public void onCreate(Bundle savedInstanceState){ 
        // ...
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
            sharedElementEnterTransition.addListener(new Transition.TransitionListener() {
                // ...
                @Override
                public void onTransitionEnd(Transition transition) {
                    doSomeUiUpdating();
                }
            });
        } else { // Pre-Lollipop
            doSomeUiUpdating();
        }
    }
}

This works well when starting the Activity with the animation, but how can I know if the Activity was started without a transition so that I can call doSomeUiUpdating()?

I'm sure there must be a simple method in Activity, Window, Transition or somewhere that I have overlooked. I don't want to relay on the calling Activity to set some bundle that telling if the animation is showing or not.

Intelligencer answered 22/2, 2016 at 20:27 Comment(13)
i will assume its the same logic as you have (if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { doSomeUiUpdating(); .... ) before the code you have to start an activityEdiva
and transitions were added in API 19 (KITKAT) so you need to check before that not LOLLIPOP -- youtube.com/watch?v=K3yMV5am-XoEdiva
The thing is that - as I try to say in the first line - the activity (even though on Lollipop+) is most often started with the transition, but not when the user starts the activity from the navigation drawer.Intelligencer
not sure what you mean, but you can wait a second until the nav drawer is closed and then do something if that's an issue -- developer.android.com/intl/ru/reference/android/support/v4/…Ediva
When opening the activity from the navigation drawer I don't have the shared element (an ImageView) to animate into the next activity. (I have the shared element when starting the activity from elsewhere.)Intelligencer
Just a dummy thought: maybe you can rely on getTargets() method of Transition (sharedElementEnterTransition.getTargets().isEmpty()) if it is empty or not? It's not null anyway and numbers of TargetViews maybe the solution here..Ammunition
Isn't sharedElementEnterTransition null when there is no transition?Clymer
@Clymer no, it's not null, though it was also my initial thought.Ammunition
The transition itself (windowSharedElementEnterTransition) is described in the theme for the app. From what I've seen so far the objects describing the transition are always the same. I haven't found any info about the shared elements themselves. @KonstantinLoginov: The targets are always empty..Intelligencer
Hi. How about putting a flag into the starting Intent ?Danzig
@Lev: Yes, that's the only solution I have so far. But as I say in question; I ideally don't want to relay on the caller of the activity to set the flags right. However, I might have to go for that way of doing it.Intelligencer
@RoyS I'm sorry, apparently I did not read that last sentence in your post. My apologies :)Danzig
Did you try onTransitionStart of TransitionListener to set some boolean isAnimationStarted.Vichy
V
4

You can try onTransitionStart of TransitionListener to set some boolean isAnimationStarted.

public class SomeActivity extends Activity {

    private boolean isAnimationStarted = false;

    public void onCreate(Bundle savedInstanceState) { 
        // ...
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
            Transition sharedElementEnterTransition = getWindow().getSharedElementEnterTransition();
            sharedElementEnterTransition.addListener(new Transition.TransitionListener() {
                // ...
                @Override
                public void onTransitionEnd(Transition transition) {
                    doSomeUiUpdating();
                }

                @Override
                public void onTransitionStarted(Transition transition) {
                    isAnimationStarted = true;
                }
            });
        }
    }

    public void onStart() {
        if (!isAnimationStarted) {
            doSomeUiUpdating();
        }
    }

}
Vichy answered 22/9, 2016 at 7:33 Comment(4)
Nice and simple solution. :)Intelligencer
But won't this create a possible problem - because the callback implies an async execution, isn't it possible that even if the animation is upcoming, onStart will be called before the onTransitionStarted is called?Cormier
In fact, I just tested it and it was exactly as I said - in my case, onStart was always called before any of the callbacks, so isAnimationStarted was always false there. So, this method certainly doesn't help to determine if the activity was started with/without transition.Cormier
Did you find the right way to do this? As the comment of @Cormier says, this doesn't exactly solve the problem.Leonleona
G
4

Since you are starting an Activity, you'll be making use of an Intent to start it. You can add extras to Intents and check for them in the onCreate() of the called Activity.

Let's assume that we have 2 Activities – ActivityA, and ActivityB.

Now, let's assume that ActivityA is the calling Activity, and that ActivityB is the called Activity.

In ActivityA, let's say you've written some code to start ActivityB with a SharedElementTransition.

@Override
public void onClick(View v) {
    Intent startActivityBIntent = new Intent(getContext(), ActivityB.class);
    startActivityBIntent.putExtra("IS_SHARED_ELEMENT_TRANSITION_ENABLED", true);
    ActivityOptionsCompat activityOptionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(getActivity(), view, ViewCompat.getTransitionName(view));
    startActivity(startActivityBIntent, activityOptionsCompat);
}

Now, if you notice above, I've passed an Intent extra with the putExtra() method. I've passed a Boolean value of true because I intend to start the Activity with a SharedElementTransition.

Now in ActivityB's onCreate() method, you can just check for the boolean value passed to the Intent. If you passed false, then you can add a conditional statement and perform your UI updating there. I've given you a small snippet below to help you get started:

private static final String isSharedElementTransitionEnabled = "IS_SHARED_ELEMENT_TRANSITION_ENABLED";    

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_b);

    // If you are postponing your SharedElementTransition, don't forget to call postponeEnterTransition() and override onPreDraw()

    if (!getIntent().getExtras().getBoolean(isSharedElementTransitionEnabled)) {
        //Do your UI updation here
    }
}

The good thing about doing it this way is that you can then have full control over how your content transitions and your shared element transitions will play out.

Ghana answered 30/3, 2018 at 12:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.