LayoutTransition设置动画
使用LayoutTransition可为布局的容器设置动画,当容器中的视图层次发生变化时产生相应的过渡的动画效果 过渡的类型一共有四种:
- LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
- LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
- LayoutTransition.DISAPPEARING 当一个View在ViewGroup中消失时,对此View设置的动画
- LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画
XML中设置属性动画
set标签的orderring属性设置为together表示同时播放,sequentially表示一个接一个播放 缩放、反转等都有中心点或者轴,默认为中心缩放,中间对称线为反转线,通过setPivotX(),setPivotY()可改变中心的位置 Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale); mChangeAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴 mChangeAppear.setPivotY(0); mChangeAppear.invalidate();//设置后要显示的调用invalidate anim.setTarget(mChangeAppear); anim.start();
KeyFrame动画
KeyFrame是一个【时间/值】对,通过它可以定义一个在特定时间的特定状态,即【关键帧】,而且在两个keyFrame之间可以定义不同的【Interpolator】,就好像多个动画的拼接,第一个动画的结束点是第二个动画的开始点。 KeyFrame是抽象类,要通过ofInt(),ofFloat(),ofObject()获得适当的KeyFrame,然后通过PropertyValuesHolder.ofKeyframe获得PropertyValuesHolder对象,然后通过ObjectAnimator.ofPropertyValuesHolder获得一个Animator对象。 Keyframe kf0 = Keyframe.ofInt(0, 300); Keyframe kf1 = Keyframe.ofInt(0.2f, 800);//动画开始1/5时 Width=600 Keyframe kf2 = Keyframe.ofInt(0.4f, 300); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(mDisAppear, pvhRotation); rotationAnim.setDuration(5000).start();
View的animate动画-新API
在SDK11的时候,给View添加了animate方法,可以使用一行代码非常方便的实现动画效果。 此后在SDK12,SDK16又分别添加了withStartAction和withEndAction用于在动画前、动画后执行一些操作,当然也可以.setListener(listener)完成此操作。 如: view.animate().alpha(0.2F).y(1000).setDuration(2000).withStartAction(new Runnable() { @Override public void run() { mChangeDisAppear.setX(200); } }).withEndAction(new Runnable() { @Override public void run() { mChangeDisAppear.setRotation(-30);//是相对初始值转了-30° } }).start();
我们也可以使用PropertyValueHolder实现上面的变化,效果与上面一样 PropertyValuesHolder pvhA = PropertyValuesHolder.ofFloat("alpha", 1f, 0f); PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 0, 200); ObjectAnimator.ofPropertyValuesHolder(iv, pvhA, pvhY).setDuration(1000).start(); 注意,这种动画不再是View动画了,而是属性动画的一种,因为改变了控件的实际属性。
代码
public class MainActivity extends Activity implements OnCheckedChangeListener { private GridLayout gl_container;//放置按钮的父布局 private int mVal;//按钮的编号 private LayoutTransition mTransition;//布局动画,当容器中的视图发生变化时存在过渡的动画效果 private CheckBox mAppear, mChangeAppear, mDisAppear, mChangeDisAppear; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); gl_container = (GridLayout) findViewById(R.id.gl_container); mAppear = (CheckBox) findViewById(R.id.id_appear); mChangeAppear = (CheckBox) findViewById(R.id.id_change_appear); mDisAppear = (CheckBox) findViewById(R.id.id_disappear); mChangeDisAppear = (CheckBox) findViewById(R.id.id_change_disappear); //CheckBox选中状态改变监听,默认全部选中,即动画全部开启 mAppear.setOnCheckedChangeListener(this); mChangeAppear.setOnCheckedChangeListener(this); mDisAppear.setOnCheckedChangeListener(this); mChangeDisAppear.setOnCheckedChangeListener(this); mTransition = new LayoutTransition(); gl_container.setLayoutTransition(mTransition); } @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { mTransition = new LayoutTransition(); //当一个View在ViewGroup中【出现】时,对此【View】设置的动画 mTransition.setAnimator(LayoutTransition.APPEARING, //=2,下面使用的是自定义的动画 (mAppear.isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 0, 1) : null)); //当一个View在ViewGroup中【出现】时,对此View对其他View位置造成影响,对【其他View】设置的动画 mTransition.setAnimator(LayoutTransition.CHANGE_APPEARING,//=0,下面都是使用默认的动画 (mChangeAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.CHANGE_APPEARING) : null)); //当一个View在ViewGroup中【消失】时,对此【View】设置的动画 mTransition.setAnimator(LayoutTransition.DISAPPEARING, //=3 (mDisAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.DISAPPEARING) : null)); //当一个View在ViewGroup中【消失】时,对此View对其他View位置造成影响,对【其他View】设置的动画 mTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,//=1 (mChangeDisAppear.isChecked() ? mTransition.getAnimator(LayoutTransition.CHANGE_DISAPPEARING) : null)); gl_container.setLayoutTransition(mTransition); } // 向GridLayout中添加按钮 public void addBtn(View view) { final Button button = new Button(this); button.setText("" + (++mVal)); gl_container.addView(button, gl_container.getChildCount());//放置在最后那个位置 button.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { gl_container.removeView(button); } }); }
//XML属性动画1,单个动画 public void xmlAnim1(View view) { // 加载动画 Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scalex); mAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴 mAppear.invalidate();//设置后要显示的调用invalidate才能生效 anim.setTarget(mAppear); anim.start(); } //XML属性动画2,多动画 public void xmlAnim2(View view) { Animator anim = AnimatorInflater.loadAnimator(this, R.animator.scale); mChangeAppear.setPivotX(0);//设置缩放、反转时的中心点或者轴 mChangeAppear.setPivotY(0); mChangeAppear.invalidate();//设置后要显示的调用invalidate anim.setTarget(mChangeAppear); anim.start(); }
//Keyframe动画 public void keyframe(View view) { Keyframe kf0 = Keyframe.ofInt(0, 300); Keyframe kf1 = Keyframe.ofInt(0.2f, 800);//动画开始1/5时 Width=600 Keyframe kf2 = Keyframe.ofInt(0.4f, 300); Keyframe kf3 = Keyframe.ofInt(0.6f, 100); Keyframe kf4 = Keyframe.ofInt(0.8f, 50); Keyframe kf5 = Keyframe.ofInt(1f, 500); PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("width", kf0, kf1, kf2, kf3, kf4, kf5); ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(mDisAppear, pvhRotation); rotationAnim.setDuration(5000).start(); }
//新版本View动画 public void viewAnimForNew(View view) { mChangeDisAppear.animate().alpha(0.2F).y(1000).setDuration(2000).withStartAction(new Runnable() { @Override public void run() { mChangeDisAppear.setX(200); mChangeDisAppear.setRotation(180); } }).withEndAction(new Runnable() { @Override public void run() { mChangeDisAppear.setX(200); mChangeDisAppear.setY(300); mChangeDisAppear.setAlpha(1.0f); mChangeDisAppear.setRotation(-30);//是相对初始值转了-30° } }).start(); } }
XML动画
scalex.xml <?xml version="1.0" encoding="utf-8"?> <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:interpolator="@android:anim/accelerate_interpolator" android:propertyName="scaleX" android:repeatCount="1" android:repeatMode="reverse" android:startOffset="1000" android:valueFrom="2.5" android:valueTo="10" android:valueType="floatType" > </objectAnimator>
scale.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:ordering="sequentially" > <objectAnimator android:duration="500" android:propertyName="rotationX" android:startOffset="0" android:valueFrom="0" android:valueTo="360" > </objectAnimator> <objectAnimator android:duration="200" android:propertyName="scaleY" android:startOffset="500" android:valueFrom="1" android:valueTo="1.7" > </objectAnimator> <objectAnimator android:duration="200" android:propertyName="scaleX" android:startOffset="700" android:valueFrom="1" android:valueTo="1.5" > <objectAnimator android:duration="100" android:propertyName="alpha" android:startOffset="900" android:valueFrom="1" android:valueTo="0.2" > </objectAnimator> </objectAnimator> </set>
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/id_container" 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="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xmlAnim1" android:text="XML属性动画1" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="xmlAnim2" android:text="XML属性动画2" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="keyframe" android:text="Keyframe动画" /> <Button android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:onClick="viewAnimForNew" android:text="view的animate动画" /> </LinearLayout> <CheckBox android:id="@+id/id_appear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#200f" android:checked="true" android:text="APPEARING" /> <CheckBox android:id="@+id/id_change_appear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#2ff0" android:checked="true" android:text="CHANGE_APPEARING" /> <CheckBox android:id="@+id/id_disappear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#20f0" android:checked="true" android:text="DISAPPEARING" /> <CheckBox android:id="@+id/id_change_disappear" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#2f00" android:checked="true" android:text="CHANGE_DISAPPEARING " /> <Button android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="10dp" android:onClick="addBtn" android:text="点击添加按钮,点击添加的按钮删除按钮" /> <GridLayout android:id="@+id/gl_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:animateLayoutChanges="false" android:background="#40f0" android:columnCount="5" /> </LinearLayout>
附件列表
时间: 2024-10-24 15:19:59