Preface As early as Android 4.4, Transition was introduced, but it was not truly implemented until 5.0. What is Transition used for? Next, I will analyze this powerful animation framework of Google through examples and principle analysis. Let's start with a rendering to calm the situation This effect will be described below, but you must first understand some basic concepts of this framework. The core of Transition Framework is to help developers automatically generate animations based on different scenes (explained below). Usually, animations are enabled through the following methods.
Let’s explain each of these situations one by one. TransitionManager.go() First, let's introduce the Scene class and see the official explanation. A scene represents the collection of values that various properties in the View hierarchy will have when the scene is applied. A Scene can be configured to automatically run a Transition when it is applied, which will animate the various property changes that take place during the scene change. The popular explanation is that this class stores the properties of various views under a root view. The instance is usually obtained by getSceneForLayout (ViewGroup sceneRoot, int layoutId, Context context).
The location where the scene changes and the animation is executed
That is the root view mentioned above Maybe this explanation is a bit weak, so let me give you an example.
scene1: scene2: Note that in the two scene layouts, 1 and 4, 2 and 3 have the same ID except for the different positions and sizes of the images. They can be considered as one view because the different creation animations of the starting scene are for the same view. The above simple example triggers the animation through the first method TransitionManager.go(). That is, when entering the Activity, manually set the start scene to scene1 through TransitionManager.go(scene1). Click the button to switch to the end scene state through TransitionManager.go(scene2, new ChangeBounds()): scene2.Transition The framework analyzes the differences between the start scene and the end scene through the ChangeBounds class to create and play animations. Since the ChangeBounds class analyzes and compares the position boundaries of the views in the two scenes to create movement and scaling animations. It is found that from scene1->scene2 is actually 1->4, 2->3. So the corresponding animation is executed, which is the following effect: There are several other classes similar to the ChangeBounds class, all of which inherit the Transiton class.
Detect the view's position boundaries to create moving and scaling animations
Detect the view's scale and rotation to create scaling and rotation animations
Detects the position boundary of the view's clipping area, similar to ChangeBounds. However, ChangeBounds targets the view while ChangeClipBounds targets the view's clipping area (rect in setClipBound(Rect rect)). If not set, there will be no animation effect
Detect the size, position, and ScaleType of ImageView (specifically ImageView) and create corresponding animations.
These three create fade-in, sliding, and explosion animations respectively according to the visibility of the view. The implementation effects of the above animation classes are as follows:
If TransitionManager.go(scene1) does not specify an animation, the default animation is the AutoTransition class. It is actually an animation collection. Looking at the source code, we can see that the Fade and ChangeBounds classes are actually added to the animation collection.
Speaking of animation collections, in fact, animation classes can be created not only through methods like new ChangeBounds(), but also through XML files. And if it is an animation collection, the XML method may be more convenient. It only takes two steps. The first step is to create an XML file in res/transition as follows: res/transition/changebounds_and_fade.xml:
Then call it in the code:
Finally, I would like to add that TransitionManager.go(scene2) actually calls scene1.exit() of the current scene(scene1) and scene2.enter() of the next scene(scene2). They will trigger scene1.setExitAction() and scene1.setEnterAction() respectively. You can customize some special effects in these two methods. beginDelayedTransition() Next, let's introduce the next trigger method. If you understand the above, the following is very simple. The previous TransitionManager.go() has always created the start scene and end scene according to the XML file, which is a bit troublesome. The principle of beginDelayedTransition() is to change the properties of the view through code, and then create the animation by analyzing the differences between the start scene and the end scene through the previously introduced ChangeBounds and other classes. Let’s take an example again:
When a click event is triggered, the current scene status is recorded, and then the size of the clicked view is changed, and the visibility of other views is changed, and then the changed scene status is recorded. In this example, the second parameter of beginDelayedTransition() is a set of ChangeBounds and Explode animations, so the scale animation is executed when the size is changed, and the explosion effect is executed when the visibility is changed. The overall effect is as follows: Interface switching animation After talking so much, we finally come to the highlight: the switching effect between Activity/Fragment. There are two types of interface switching, one is Content Transition without shared elements and the other is Shared Element Transition with shared elements. Content Transition Let me explain a few important concepts first:
The Transition framework will first traverse the A interface to determine the view (non-shared element view) on which the animation is to be executed. Before executing A.exitTransition(), the A interface will obtain the start scene of the interface (the view is in the VISIBLE state), and then set all the views to be animated to INVISIBLE, and obtain the end scene at this time (the view is in the INVISIBLE state). Create execution animations based on the differences in transition analysis.
The Transition framework will first traverse the B interface, determine the view to be animated, and set it to INVISIBLE. Before executing B.enterTransition(), get the start scene at this time (the view is in the INVISIBLE state), then set all the views to be animated to VISIBLE, and get the end scene at this time (the view is in the VISIBLE state). Create execution animations based on the differences in transition analysis. According to the above explanation, the interface transition animation is based on the change of visibility, so the parameters in getWindow().setEnterTransition(transition); are generally instances of the Fade, Slide, and Explode classes (because these three classes create animations by analyzing different visibilities). Usually, writing a complete Activity Content Transiton has the following steps:
Automatically set to true when Material themes are applied.
Of course, you can also set it in the theme
The jump interface here cannot just startActivity(intent), it needs
Ok, now you can run the switching animation between activities. But you will find that when the interface is switched, after a while, B enters after A exits (it's really too much, not showing A the complete ExitTransition). If you want to wait until A completely exits before B enters, you can set setAllowEnterTransitionOverlap(false) (the default is true), which can also be set in xml:
Having said so much, I think I need to give another simple example. A.Activity:
res/translation/slide.xml:
B.Activity:
The achieved effects are as follows: If you look closely at the animation, you can actually find that the status bar of A is also pulled down and up, and there is a certain distance between it and the view below. Virgo said he couldn't stand it. In fact, in principle, the switching animation of Activity targets the visibility of the view of the entire interface, but is there any way to make the Transition framework focus on only a certain view or ignore a certain view? Of course, transition.addTarget() and transition.excludeTarget() can achieve the above functions respectively. Conveniently, this attribute can also be set in XML, so what we need to do now is to exclude the statusBar, which can be written in slide.xml like this:
It's done. I won't post the effect, you can imagine it... Shared Element Transition Content Transition and Shared Element Transition often exist at the same time in interface switching. Different from Content Transition, there are mainly the following differences:
Here pairs is a collection of instances of the Pair<View, String> class, which stores the shared view and name between the two activities. The name here should be consistent with the transitionName of the shared view of interface B. Like this:
If not set, the default is @android:transition/move animation. The defaults for setExitTransition() and setEnterTransition() are null and Fade. In fact, the principle of Shared Element Transition is similar to Content Transition, both of which create animations based on the different status of the scene. The difference is that Content Transition creates animation by changing the visibility of the view to change the state of the scene, while Shared Element Transition creates animation by analyzing the size, position, and style of the shared view of the A and B interfaces. Therefore, the former usually sets Transitions such as Fade, while the latter usually sets Transitions such as ChangeBounds. Finally, let's analyze how to achieve the gif effect at the beginning of the article.
There is actually a pit here. Let's first look at the isTransitionGroup() method:
The return value is true, which means that the ViewGroup executes the Activity Transition as a whole, and false, which means that each subview in the ViewGroup executes its own. If the ViewGroup sets background or TransitionName, or setTransitionGroup(true), the return value is true, which means that the animation is executed as a whole. So it is best to set setTransitionGroup(true) for viewGroup_bottom and viewGroup_top. The effect is as follows, I added some other special effects I won't post the specific code. All the codes in this article have been uploaded to Github (I am the link), including the switching of Fragments which is not introduced in this article but is included in the code. I hope everyone can give me a star. If you still don't understand what it means after reading it once, I strongly recommend that you read it again while running the code. It is actually quite simple once you understand it. Finally, I want to say that there are still some things about this Transition Framework that I haven’t finished talking about. It may take some time to update. Next, I will also write related articles about Dagger 2 and the enhanced version of NavigationBar, so stay tuned. |
<<: The Ultimate Guide to Creating and Publishing Android Libraries
>>: Summary of circular progress bar in Android custom View
Chat Weapon Arsenal,, teach you how to make him/h...
This article is based on answering a question fro...
"Two Weibo and One Douyin" have become ...
Introduction: With the vigorous development of mo...
Preface In e-commerce apps, the focus is on produ...
TikTok has become popular, and many marketers are...
The Tokyo Olympics has been underway for ten days...
Can water be turned into "milk"? Of cou...
Wasn’t there the Luo Zhixiang’s multi-person Qigo...
Advertising is the first impression that consumer...
It has become a consensus that traffic is becomin...
Author: Zhou Paopi You think this is an article a...
In the Internet age, many traditional sales chann...
There are many ways to load the cover (usually ca...
This is the 4402nd article of Da Yi Xiao Hu "...