In the previous article we learned about the use of ObjectAnimator for property animation. If you don’t understand, you can take a look at ObjectAnimator, one of the Android Property Animation Property Animation series. In this article we are going to learn something new. You should encounter this problem when working on a project: to display or hide a control or layout according to different conditions, the first method we can think of is to call the View.setVisibility() method. Although the display-hiding effect has been achieved, I always feel that the display-hiding process is very stiff and uncomfortable. So is there any way to make this display-hiding transition animation effect? The answer is yes, it goes without saying that it is the LayoutTransition class.
Above rendering
To achieve the above effect, you only need to add the android:animateLayoutChanges="true" attribute to the layout container. If you don’t believe me, look at the
layout file as follows:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="buttonClick" android:text="添加控件" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="buttonClick1" android:text="移除控件" /> </LinearLayout> <LinearLayout android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true" android:orientation="vertical"></LinearLayout></LinearLayout>
If android:animateLayoutChanges="true" is added to the layout container, there will be animation effects by default. This property can only be used in the ViewGroup control, indicating that there will be a default animation effect when the layout in the container is changed. For example, when a control is added or a control is deleted, the default animation effect will be used.
The above animation calling code is as follows:
package com.xjp.animations;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.LinearLayout;/** * Description: * User: xjp * Date: 2015/5/22 * Time: 15:06 */public class LayoutAnimationActivity extends Activity { private LinearLayout parent; private int i = 0; private int j = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout_animation); parent = (LinearLayout) findViewById(R.id.parent); } public void buttonClick(View view) { addButtonView(); } public void buttonClick1(View view) { removeButtonView(); } private void addButtonView() { i++; Button button = new Button(this); button.setText("button" + i); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); parent.addView(button, params); } private void removeButtonView() { if (i > 0) parent.removeViewAt(0); }}
Did you find it very simple? In addition to adding the android:animateLayoutChanges="true" attribute to the layout, there is no need to do any processing in the code to achieve a very comfortable transition animation effect. The main reason is that after adding this attribute, when the layout changes in the container, the system will add a default animation effect to the container by default. If you think the above effect is very nice, then you will be easily satisfied. In addition to using the system's default layout container animation, we can also customize the layout container animation. Now it’s time for the LayoutTransition class to come on stage.
This class is used to define the animation of the layout container itself and the animation of the View when a View is added, deleted, hidden, or displayed in the current layout container. That is to say, when a view is hidden in a LinerLayout, we can customize the animation of the entire LinerLayout container changing because the view is hidden, and we can also customize the animation when the hidden view disappears. You can first create a new LayoutTransition object and set the object into a layout container ViewGroup through the setLayoutTransition() method. The code is as follows:
private LinearLayout container; private LayoutTransition mTransitioner; /** * 初始化容器动画 */ private void initTransition() { mTransitioner = new LayoutTransition(); container.setLayoutTransition(mTransitioner); }
The LayoutTransition class defines the following layout container animation types.
You can customize these animations , set them into a LayoutTransition object through the setAnimator() method.
/** * view出现时 view自身的动画效果 */ ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 0F, 90F, 0F); mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1);
Define a rotating property animation. Leave the animation object blank here, because the system will add it internally The view is set as an animation object. Then call the setAnimator() method to set the animation into the LayoutTransition object mTransitioner.
The complete animation code is as follows, with annotations for specific explanations
package com.xjp.animations;import android.animation.Animator;import android.animation.AnimatorListenerAdapter;import android.animation.Keyframe;import android.animation.LayoutTransition;import android.animation.ObjectAnimator;import android.animation.PropertyValuesHolder;import android.app.Activity;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.LinearLayout;/** * Description:布局动画Demo * User: xjp * Date: 2015/5/22 * Time: 15:06 */public class LayoutAnimationActivity extends Activity { private int i = 0; private LinearLayout container; private LayoutTransition mTransitioner; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_layout_animation); container = (LinearLayout) findViewById(R.id.parent); initTransition(); setTransition(); } /** * 初始化容器动画 */ private void initTransition() { mTransitioner = new LayoutTransition(); container.setLayoutTransition(mTransitioner); } private void setTransition() { /** * view出现时 view自身的动画效果 */ ObjectAnimator animator1 = ObjectAnimator.ofFloat(null, "rotationY", 90F, 0F). setDuration(mTransitioner.getDuration(LayoutTransition.APPEARING)); mTransitioner.setAnimator(LayoutTransition.APPEARING, animator1); /** * view 消失时,view自身的动画效果 */ ObjectAnimator animator2 = ObjectAnimator.ofFloat(null, "rotationX", 0F, 90F, 0F). setDuration(mTransitioner.getDuration(LayoutTransition.DISAPPEARING)); mTransitioner.setAnimator(LayoutTransition.DISAPPEARING, animator2); /** * view 动画改变时,布局中的每个子view动画的时间间隔 */ mTransitioner.setStagger(LayoutTransition.CHANGE_APPEARING, 30); mTransitioner.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 30); /** * 为什么这里要这么写?具体我也不清楚,ViewGroup源码里面是这么写的,我只是模仿而已 * 不这么写貌似就没有动画效果了,所以你懂的! */ PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 1); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 1); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 1); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 1); /** * view出现时,导致整个布局改变的动画 */ PropertyValuesHolder animator3 = PropertyValuesHolder.ofFloat("scaleX", 1F, 2F, 1F); final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder( this, pvhLeft, pvhTop, pvhRight, pvhBottom, animator3). setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_APPEARING)); changeIn.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { View view = (View) ((ObjectAnimator) animation).getTarget(); view.setScaleX(1.0f); } }); mTransitioner.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn); /** * view消失,导致整个布局改变时的动画 */ Keyframe kf0 = Keyframe.ofFloat(0f, 0f); Keyframe kf1 = Keyframe.ofFloat(.5f, 2f); Keyframe kf2 = Keyframe.ofFloat(1f, 0f); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("scaleX", kf0, kf1, kf2); final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder( this, pvhLeft, pvhTop, pvhRight, pvhBottom, pvhRotation). setDuration(mTransitioner.getDuration(LayoutTransition.CHANGE_DISAPPEARING)); changeOut.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { View view = (View) ((ObjectAnimator) animation).getTarget(); view.setScaleX(1.0f); } }); mTransitioner.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut); } public void buttonClick(View view) { addButtonView(); } public void buttonClick1(View view) { removeButtonView(); } private void addButtonView() { i++; Button button = new Button(this); button.setText("button" + i); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); container.addView(button, Math.min(1, container.getChildCount()), params); } private void removeButtonView() { if (i > 0) container.removeViewAt(0); }}
Layout file
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="buttonClick" android:text="添加控件" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:onClick="buttonClick1" android:text="移除控件" /> </LinearLayout> <LinearLayout android:id="@+id/parent" android:layout_width="match_parent" android:layout_height="wrap_content" android:animateLayoutChanges="true" android:orientation="vertical"></LinearLayout></LinearLayout>
Finally, here is a rendering:
Many times we want to have an animation effect when loading ListView or GridView for the first time to achieve a good transition effect. For example, the following effect
To achieve this effect, you only need to add the android:layoutAnimation="@anim/layout" attribute to the layout. Next, let’s take a look at how layout.xml animation is implemented? Create a new layout.xml file in the res/anim directory. The code is as follows:
<?xml version="1.0" encoding="utf-8"?><layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animation="@anim/left" android:animationOrder="normal" android:delay="30%"></layoutAnimation>
android:delay subclass animation time interval (delay) 70%. It can also be a floating point number such as "1.2", etc.
android:animationOrder=”random” The subclass display mode random means random
android:animationOrder’s values are
normal 0 default
reverse 1 reverse order
random 2 random
android:animation =”@anim/left” indicates the specific animation code when the child is displayed
Create a new left.xml file in the res/anim directory, the code is as follows:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="500" android:fromXDelta="100%" android:fromYDelta="0" android:toXDelta="0" android:toYDelta="0" /> <alpha android:duration="500" android:fromAlpha="0" android:toAlpha="1" /></set>
In this way, the above ListView is implemented animation effect.
Of course we can also implement this animation effect in code
private void initAinm() { //通过加载XML动画设置文件来创建一个Animation对象; Animation animation = AnimationUtils.loadAnimation(this, R.anim.left); //得到一个LayoutAnimationController对象; LayoutAnimationController lac = new LayoutAnimationController(animation); //设置控件显示的顺序; lac.setOrder(LayoutAnimationController.ORDER_REVERSE); //设置控件显示间隔时间; lac.setDelay(1); //为ListView设置LayoutAnimationController属性; listView.setLayoutAnimation(lac); }
Load the animation of the item through AnimationUtils.loadAnimation to obtain an Animation object, and then set the Animation object to LayoutAnimationController. Obtain the LayoutAnimationController object and configure some properties of the LayoutAnimationController object. Finally, set the LayoutAnimationController object to the ListView.
layoutAnimation animation is not limited to ListView and GridView, but can also be used in all ViewGroups. How to use it depends on the project requirements.
This is the basic introduction to Android attribute animation. The basic animation usage and examples are also posted, which can basically meet daily development needs. Of course, if you have more exciting animations, you can implement them based on these basics. So, we can no longer use tweening animation in the future? It seems that attribute animation is more reasonable, because this kind of animation changes the attribute and not just the position.