From Activity A to B , I set enter and return transitions.
I want to put a fadein animation after the return transition ( B to A after a back).
Originally , I thought that in Activity's onStart method will a good place.
It turns out I don't see the fadein animation so I suppose the ending of the Return Transition happens after onStart()
I checked with SharedElementCallback but it doesn't tell when the transition ends.
How to catch the moment when the Return Transition ends ?
For Activity you'll need to call overridePendingTransition() in Activity A after calling startActivity() and provide your own animations. You can also override onEnterAnimationComplete() in Activity A so you know when it has been animated on to the screen.
For Fragments, you can do this by adding your own custom animations for the transitions using setCustomAnimations() on the transaction. These will override the default animations for your Fragment transitions.
Related
I have a fragment with list view on it. When the user clicks on any of the list view's items he/she is transferred in an Activity. The default animation of the activity that is started (startActivity from the fragment -> opens this activity) is from the bottom slide to top of the screen. How I can override this animation and create a slide from right animation when the activity is created.
I have tried to override the overridePendingTransition method in the activity but that did not change anything.
#Override
public void overridePendingTransition(int enterAnim, int exitAnim) {
super.overridePendingTransition(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
}
From the Activity.overridePendingTransition documentation :
Call immediately after one of the flavors of startActivity(Intent) or finish() to specify an explicit transition animation to perform next.
In other words, call the method on the current Activity after starting the new Activity, instead of overriding it.
I add a fragment with a shared element transition like so
currentFragment.setEnterTransition(TransitionInflater.from(context).inflateTransition(android.R.transition.fade));
currentFragment.setExitTransition(TransitionInflater.from(context).inflateTransition(android.R.transition.fade));
Transition transition = TransitionInflater.from(context).inflateTransition(android.R.transition.slide_right);
transition.setDuration(context.getResources().getInteger(R.integer.fragment_transition_duration));
and then
targetFragment.setSharedElementEnterTransition(TransitionInflater.from(context).inflateTransition(R.transition.change_image_transform));
targetFragment.setEnterTransition(TransitionInflater.from(context).inflateTransition(android.R.transition.fade));
targetFragment.setReturnTransition(transition);
The issue I'm seeing is that once I've navigated to several of these fragments in a row, if I then tap the back button - calling the default onBackPressed() - repeatedly and very quickly, the activity shows the wrong fragment as visible. When I tap on the screen, the click events go to the correct fragment (maybe beneath the visible fragment), but I cannot see that correct fragment.
If I tap the back button more slowly, I get the correct behavior. Has anyone ran into a scenario like this before?
Edit : this is what FragmentActivity is doing
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
public void onBackPressed() {
if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
supportFinishAfterTransition();
}
}
Another thing to mention is that when I remove the Return Transition I do not have this problem.
Ok, I found the answer if anyone is interested. I don't know why this works, but it seems to fix my issue.
If you have a fragment which has a return transition set on it, then in your onDestroyView() call the method setReturningTransition(null).
I have an activity I animate to with a transition animation, like this:
ActivityOptionsCompat options = ActivityOptionsCompat.makeSceneTransitionAnimation(activity, view, transitionStr);
ActivityCompat.startActivity(activity, intent, options.toBundle());
However, when I go back, I don't want the animation to run in inverse. Is that possible? I'm using AppCompatActivity from appcompat-v7:23.1.1.
If you never want to have that transition back to the parent activity, use
finish();
You can wrap it around a condition if you sometimes want to the transition on the way back to the parent activity. An example use case would be to disable the transition when an interstitial ad was displayed:
if (interstitialAdWasDisplayed) {
finish();
} else {
finishAfterTransition();
}
A possible duplicate of Overriding Transition
finish();
Details.this.overridePendingTransition(R.anim.nothing,R.anim.nothing);
With this piece of code, you can override the finish animation of the current activity.
According to the answers to this question you can't run an animation in inverse. Instead I would create another transition which is basically the inverse of the transition you use when you start the activity and add it to the Activity like this (R.anim.inverseTransition is the Transition you created):
finish();
Details.this.overridePendingTransition(R.anim.inverseTransition,R.anim.inverseTransition);
(see this answer for more information)
I use view animations in a predrawlistener to animate the activity start.
Exist a similar listener to animate my views before my activity is finished?
I know the overridependingtransition method for animations in xml but i want to use ViewPropertyAnimations in a programmatically way for specific views.
I suggest you to override finish() method, then add your animation there:
#Override
public void finish (){
// do your animation
super.finish();
}
You can call YourActivity.finsih(); when you want to finish your activity from code.
I am currently using a custom shared element transition for when I launch Activity B from activity A. Everything works perfectly.
I want to use another custom Transition that doesn't involve any shared elements for the return transition from activity B back to activity A. However, I am having trouble with several parts:
How do I tell the framework that the return transition doesn't involve any shared elements?
What are the start and end values for the transition in a return transition? For the enter transition, I mostly manipulated activity B's views as they are drawn on top of activity A's. What happens in a return transition?
Appreciate any help I can get!
EDIT:
Further investigation revealed that my return transition's createAnimator isn't even being called even though I'm calling setSharedElementReturnTransition. But I know the set call is doing something because it now doesn't try to reverse the original enter animation (default behavior) and instead of just overlaps the two views.
EDIT #2:
After looking at George Mount's answer, I added
#Override
public void captureStartValues(TransitionValues transitionValues) {
transitionValues.view.setVisibility(View.VISIBLE);
}
#Override
public void captureEndValues(TransitionValues transitionValues) {
transitionValues.view.setVisibility(View.INVISIBLE);
}
This is now causing my return transition's createAnimator to at least run albeit the animation is still weird. Why does the visibility matter?
You must set the SharedElementCallback and in onMapSharedElements, clear the shared element map. That will eliminate the shared element from your transition.
This depends on which transition you're talking about. Specifically the return transition's start end end values are View.VISIBLE and View.INVISIBLE. But there are several transitions happening when returning:
Return Transition: non-shared elements are removed from the scene in Activity B by changing their visibility.
Shared Element Return Transition: The shared element in Activity B starts where it is when finishAfterTransition is called and ends where Activity A says the shared element is. This can be adjusted by SharedElementCallback's onSharedElementStart and onSharedElementEnd, which are called in reverse during return.
Reenter Transition: non-shared element views from Activity A change their visibility.
Shared Element Reenter Transition: usually nothing, but the shared element can do something special after it lands in Activity A.
I actually found the culprit that was causing my return transition's createAnimator to not run. Apparently, if the transition framework thinks that the starting and ending states for the transitioning views are the same, it won't create an animator. Therefore, adding some dummy but different values into captureStartState and captureEndState finally caused my return transition to run properly.