[Android][Animation]
来源:互联网 发布:淘宝考试题和答案2017 编辑:程序博客网 时间:2024/06/03 18:28
1.View Animation(Tweened Animation)补间动画
View Animation主要是针对View的,而且它只是让View展示指定动画,但是并不会改变View的属性。也就是说使用tweened动画来实现移动,缩放,旋转,透明度,最后都是没有改变view的位置,大小,角度,透明度,我们看到的只是一个动画效果。
1).创建动画对象
(1)直接new
Android提供了四个类TranslateAnimation,ScaleAnimation,RotateAnimation和AlphaAnimation。我们可以通过这四个类实现移动,缩放,旋转和透明度设置。如果一个View要同时执行多个动画可以使用AnimationSet。
例子一:TranslateAnimation
/** * 确实如果使用TranslateAnimation实现位移动画,如果没有setX,setY,那么view是不会移动到指定位置的, * 而且通过setX,setY移动view到知道位置的时候,view是会闪一下,如果使用tweened动画来实现缩放,旋转,透明度,最后都是没有改变view的,我们看到的只是一个动画效果 */ private void transition() { UiUtil.initialize(this); animation = new TranslateAnimation(0, UiUtil.getScreenWidth() / 2, 0, UiUtil.getScreenHeight() / 2); animation.setDuration(2000); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { Log.i("lgy", "start----x:" + button.getX() + " y:" + button.getY()); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { button.setX(UiUtil.getScreenWidth() / 2); button.setY(UiUtil.getScreenHeight() / 2); Log.i("lgy", "end----x:" + button.getX() + " y:" + button.getY()); } }); button.startAnimation(animation); }
例子二:ScaleAnimation
/** * float fromX 动画起始时 X坐标上的伸缩尺寸 * float toX 动画结束时 X坐标上的伸缩尺寸 * float fromY 动画起始时Y坐标上的伸缩尺寸 * float toY 动画结束时Y坐标上的伸缩尺寸 * int pivotXType 动画在X轴相对于控件位置类型 * float pivotXValue 动画相对于控件的X坐标的开始位置 * int pivotYType 动画在Y轴相对于控件位置类型 * float pivotYValue 动画相对于控件的Y坐标的开始位置 * 1.四个参数的ScaleAnimation默认是动画是从左上角开始, * 所以new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f), * 你会看到的效果是动画会以view的左上角为定点,开始向x轴和y轴慢慢伸长到1.4倍, * 动画结束后,由于tweened动画不改变view的属性,view就会恢复为正常状态 * 2.八个参数的ScaleAnimation可以定义相对于控件位置类型 * (1)RELATIVE_TO_SELF 相对于自己 * (2)RELATIVE_TO_PARENT 相对于父控件 * (3)ABSOLUTE 绝对位置 ,例如Animation.ABSOLUTE, new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.ABSOLUTE, 200f, Animation.ABSOLUTE, 100f)意思是相对于当前位置 x轴增量为200的坐标点,y轴增量为100的坐标点 如果使用的是RELATIVE_TO_SELF,RELATIVE_TO_PARENT类型,那么他的参数表示的的是倍数 如果使用的是ABSOLUTE,那么他表示的就是具体的增量 * */ private void scale() { UiUtil.initialize(this);// scaleAnimation = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f);// scaleAnimation = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, // Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); scaleAnimation = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF, 1f); scaleAnimation.setDuration(2000); scaleAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { } }); button.startAnimation(scaleAnimation); }
例子三:RotateAnimation
/** * float fromDegrees:旋转的开始角度。 * float toDegrees:旋转的结束角度。 * int pivotXType:X轴上旋转点模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。 * float pivotXValue:X轴上旋转点的值。 * int pivotYType:Y轴上旋转点模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。 * float pivotYValue:Y轴上旋转点的值。 */ private void rotate() { UiUtil.initialize(this); rotateAnimation = new RotateAnimation(0f,360f,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f); rotateAnimation.setDuration(2000); rotateAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { } }); button.startAnimation(rotateAnimation); }
例子四:AlphaAnimation
/** * float fromAlpha:开始时候的透明度。 * float toAlpha:结束时候的透明度。 * 这里都是用倍数表示 */ private void alpha() { UiUtil.initialize(this); alphaAnimation = new AlphaAnimation(0f, 1f); alphaAnimation.setDuration(2000); alphaAnimation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { } }); button.startAnimation(alphaAnimation); }
例子五:AnimationSet
/** * 同时执行多个动画 */ private void animSet() { UiUtil.initialize(this); animationSet = new AnimationSet(true); alphaAnimation = new AlphaAnimation(0f, 1f); animationSet.addAnimation(alphaAnimation); rotateAnimation = new RotateAnimation(0f,360f,Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF,0.5f); animationSet.addAnimation(rotateAnimation); scaleAnimation = new ScaleAnimation(0.0f, 1.4f, 0.0f, 1.4f, Animation.RELATIVE_TO_SELF, 1f, Animation.RELATIVE_TO_SELF, 1f); animationSet.addAnimation(scaleAnimation); animation = new TranslateAnimation(0, UiUtil.getScreenWidth() / 2, 0, UiUtil.getScreenHeight() / 2); animationSet.addAnimation(animation); animationSet.setDuration(2000); button.startAnimation(animationSet); }
(2)AnimationUtils.loadAnimation
也就是通过加载定义好的xml文件来实例化动画对象。
步骤一:在res文件夹下新建一个anim文件夹(anim文件夹下放的是Tweened动画,如果想放Property动画,必须要在res下新建一个animator,把Property动画的文件放里边,在Android Studio里是需要这样区分的,Eclipse没有验证,就不清楚了)
步骤二:在anim里可以定义自己Tweened动画xml文件,他们一般是以set为根标签。
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:fromXDelta="-100%" android:toXDelta="0%" android:duration="1000" /></set>
步骤三:加载xml,实例化动画对象
/** * 这里是实现将mContentView从左边移动出现,而mLoadingView向左移动消失的效果 */ private void xmlAnim() { contentViewAnim = AnimationUtils.loadAnimation(this, R.anim.tweened_anim_translation); contentViewAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { mContentView.setVisibility(View.VISIBLE); } }); mContentView.startAnimation(contentViewAnim); loadingViewAnim = AnimationUtils.loadAnimation(this, R.anim.tweened_anim_translation2); loadingViewAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { mLoadingView.setVisibility(View.GONE); } }); mLoadingView.startAnimation(loadingViewAnim); }
2).动画监听setAnimationListener
我们可以对动画的行为进行监听,根据需要执行我们的操作,AnimationListener这个接口可以监听到动画开始,重复,动画结束的动作。
loadingViewAnim.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { mLoadingView.setVisibility(View.GONE); } });
3).插值器Imterpolator
其实插值器就是设置动画改变的速率。
* 1:AccelerateDecelerateInterpolator 加速减速插补器(先慢后快再慢)
* 2:AccelerateInterpolator 加速插补器(先慢后快)
* 3:AnticipateInterpolator 向前插补器(先往回跑一点,再加速向前跑)
* 4:AnticipateOvershootInterpolator 向前向后插补器(先往回跑一点,再向后跑一点,再回到终点)
* 5:BounceInterpolator 反弹插补器(在动画结束的时候回弹几下,如果是竖直向下运动的话,就是玻璃球下掉弹几下的效果)
* 6:CycleInterpolator 循环插补器(按指定的路径以指定时间(或者是偏移量)的1/4、变速地执行一遍,再按指定的轨迹的相反反向走1/2的时间,再按指定的路径方向走完剩余的1/4的时间,最后回到原点。假如:默认是让a从原点往东跑100米。它会先往东跑100米,然后往西跑200米,再往东跑100米回到原点。可在代码中指定循环的次数)
* 7:DecelerateInterpolator 减速插补器(先快后慢)
* 8:LinearInterpolator 直线插补器(匀速)
* 9:OvershootInterpolator 超出插补器(向前跑直到越界一点后,再往回跑)
* 10:FastOutLinearInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果:依次 慢慢快
* 11:FastOutSlowInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果:依次 慢快慢
* 12:LinearOutSlowInInterpolator MaterialDesign基于贝塞尔曲线的插补器 效果:依次 快慢慢
setInterpolator(new LinearOutSlowInInterpolator())
4).改变属性
我们知道Tweened动画只是让View展示指定动画,但是并不会改变View的属性。那么如果我们要改变它的属性可以通过View的set方法
/** * 确实如果使用TranslateAnimation实现位移动画,如果没有setX,setY,那么view是不会移动到指定位置的, * 而且通过setX,setY移动view到知道位置的时候,view是会闪一下,如果使用tweened动画来实现缩放,旋转,透明度,最后都是没有改变view的,我们看到的只是一个动画效果 */ private void transition() { UiUtil.initialize(this); animation = new TranslateAnimation(0, UiUtil.getScreenWidth() / 2, 0, UiUtil.getScreenHeight() / 2); animation.setDuration(2000); animation.setAnimationListener(new AnimationListener() { @Override public void onAnimationStart(Animation animation) { Log.i("lgy", "start----x:" + button.getX() + " y:" + button.getY()); } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animation animation) { button.setX(UiUtil.getScreenWidth() / 2); button.setY(UiUtil.getScreenHeight() / 2);// button.setAlpha(1f);// button.setScaleX(1.4f);// button.setScaleY(1.4f);// button.setRotationX(0);// button.setRotationY(100); Log.i("lgy", "end----x:" + button.getX() + " y:" + button.getY()); } }); button.startAnimation(animation); }
2.Drawable Animation(帧动画)
这个其实就是按顺序一帧一帧的播放图片。
1)使用xml加载
步骤一:在res下的anim文件夹下创建帧动画xml文件,这个文件的根标签是animation-list。
<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android" android:oneshot="false"> <item android:drawable="@drawable/little_gray_01" android:duration="300" /> <item android:drawable="@drawable/little_gray_03" android:duration="300" /> <item android:drawable="@drawable/little_gray_04" android:duration="300" /> <item android:drawable="@drawable/little_gray_05" android:duration="300" /> </animation-list>
步骤二:加载xml,创建对象
/** * ProgressBar可以用下面这个设置 * bar.setIndeterminate(true); bar.setIndeterminateDrawable(getResources().getDrawable(R.anim.frame_anim_list)); */ private void xmlAnimation() { imageView.setBackgroundResource(R.anim.frame_anim_list); AnimationDrawable animation = (AnimationDrawable) imageView.getBackground(); animation.start(); }
2)不使用xml
private void noXmlAnimation() { AnimationDrawable anim = new AnimationDrawable(); Drawable drawable1 = getResources().getDrawable(R.drawable.little_gray_01); Drawable drawable3 = getResources().getDrawable(R.drawable.little_gray_03); Drawable drawable4 = getResources().getDrawable(R.drawable.little_gray_04); Drawable drawable5 = getResources().getDrawable(R.drawable.little_gray_05); anim.addFrame(drawable1, 300); anim.addFrame(drawable3, 300); anim.addFrame(drawable4, 300); anim.addFrame(drawable5, 300); anim.setOneShot(false); imageView.setBackground(anim); anim.start(); }
3.Property Animation
是在Android 3.0中才引进的,它更改的是对象的实际属性,在View Animation(Tween Animation)中,其改变的是View的绘制效果,真正的View的属性保持不变。而且Property Animation不止可以应用于View,还可以应用于任何对象。Property Animation只是表示一个值在一段时间内的改变,当值改变时要做什么事情完全是你自己决定的。
1)ValueAnimator
ValueAnimator包含Property Animation动画的所有核心功能,它是PropertyAnimation动画的基础,ObjectAnimator也是继承了ValueAnimation。
(1)基础用法
这个例子只修改了view的一个属性:x的坐标
/** * 只修改button的x轴动画 */ private void valueAnim() { UiUtil.initialize(this); ValueAnimator animator = ValueAnimator.ofFloat(0f,UiUtil.getScreenWidth()/2); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { button.setTranslationX((Float)animation.getAnimatedValue()); } }); animator.setDuration(2000); animator.start(); }
(2)修改多个属性
下面展示的是同时修改x坐标和y坐标的值,这里用到了PropertyValuesHolder ,可以使用它来同时执行多个动画。
/** * 修改button的x轴和Y轴动画,通过下面的方法可以传多个动画 */ private void valueAnim2() { UiUtil.initialize(this); PropertyValuesHolder xvalue = PropertyValuesHolder.ofFloat("x", 0f,UiUtil.getScreenWidth()/2); PropertyValuesHolder yvalue = PropertyValuesHolder.ofFloat("y", 0f,UiUtil.getScreenHeight()/2); ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(xvalue,yvalue); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { button.setTranslationX((Float)animation.getAnimatedValue("x")); button.setTranslationY((Float)animation.getAnimatedValue("y")); } }); animator.setDuration(2000); animator.start(); }
(3)监听属性的渐变值
可以通过addUpdateListener监听到属性的渐变值,可以看到下面的代码,
我们可以通过PropertyValuesHolder 的ofFloat给某个属性定义一个propertyName,然后在addUpdateListener里的回调方法onAnimationUpdate,可以通过animation.getAnimatedValue(propertyName)获取对于该属性名的渐变值。
private void valueAnim2() { UiUtil.initialize(this); PropertyValuesHolder xvalue = PropertyValuesHolder.ofFloat("x", 0f,UiUtil.getScreenWidth()/2); PropertyValuesHolder yvalue = PropertyValuesHolder.ofFloat("y", 0f,UiUtil.getScreenHeight()/2); ValueAnimator animator = ValueAnimator.ofPropertyValuesHolder(xvalue,yvalue); animator.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { button.setTranslationX((Float)animation.getAnimatedValue("x")); button.setTranslationY((Float)animation.getAnimatedValue("y")); } }); animator.setDuration(2000); animator.start(); }
2)ObjectAnimator
(1)ObjectAnimator的基本用法
也是修改一个属性值。
/** * 修改button的x轴动画 */ private void objectAnim() { UiUtil.initialize(this); ObjectAnimator animator = ObjectAnimator .ofFloat(button, "translationX", 0f,UiUtil.getScreenWidth()/2); animator.setDuration(2000); animator.start(); }
(2)修改多个属性值
/** * 修改button的x轴和Y轴动画,通过下面的方法可以传多个动画 */ private void objectAnim2() { UiUtil.initialize(this); PropertyValuesHolder xvalue = PropertyValuesHolder.ofFloat("x", 0f,UiUtil.getScreenWidth()/2); PropertyValuesHolder yvalue = PropertyValuesHolder.ofFloat("y", 0f,UiUtil.getScreenHeight()/2); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(button, xvalue,yvalue); animator.setDuration(2000); animator.start(); }
(3)加载xml方式执行动画
步骤一:在res的animator目录下创建动画xml文件,这动画很明显,是同时执行将view的x坐标和y坐标都移动到400处。
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2000" android:ordering="together" > <!-- 动画执行顺序 sequentially:顺序执行;together:同时执行。 --> <objectAnimator android:propertyName="translationX" android:duration="2000" android:valueFrom="0" android:valueTo="400" android:valueType="floatType" /> <objectAnimator android:propertyName="translationY" android:valueFrom="0" android:duration="2000" android:valueTo="400" android:valueType="floatType" /> <!-- 动画值的类型 --></set>
步骤二:加载xml文件,执行动画
通过AnimatorInflater.loadAnimator方法可以获得一个Animator 对象。
/** * 修改button的x轴和Y轴动画,通过下面的方法可以传多个动画 */ private void objectAnimByXml() { Animator animator = AnimatorInflater.loadAnimator(this, R.animator.property_tran_x); animator.setTarget(button); animator.start(); }
3)AnimatorSet 和 PropertyValuesHolder
AnimatorSet 和PropertyValuesHolder都是可以执行多个动画的,PropertyValuesHolder的动画是必须全部同时执行的,而AnimatorSet 可以控制动画是同时执行还是先后执行。
/** * AnimatorSet * play和with可以同时播放多个动画 * play,after,before可以设置动画的先后顺序 * 而PropertyValuesHolder是无法设置动画的先后播放顺序,只能同时执行多个动画 */ private void objectAnimSet() { UiUtil.initialize(this); ObjectAnimator animatorx = ObjectAnimator .ofFloat(button, "translationX", 0f,UiUtil.getScreenWidth()/2); ObjectAnimator animatory = ObjectAnimator .ofFloat(button, "translationY", 0f,UiUtil.getScreenHeight()/2); AnimatorSet animatorSet = new AnimatorSet(); animatorSet.play(animatorx).with(animatory); animatorSet.setDuration(2000); animatorSet.start(); }
4)ViewPropertyAnimator
ViewPropertyAnimator也是用于同时执行多个动画的,但是它可以直接从view的animate()方法里获得,如果是对view要执行多个动画的情况下,使用它是十分简便的。
/** * ViewPropertyAnimator * 如果View只用到一两个动画,那么用ObjectAnimatior就好了, * 但是如果一个View同时要执行多个动画ViewPropertyAnimator的方法会更佳 */ private void ViewPropertyAnim() { UiUtil.initialize(this); button.animate() .translationX(UiUtil.getScreenWidth()/2) .translationY(UiUtil.getScreenHeight()/2) .setDuration(2000) .start(); }
5)布局改变的动画(Viewgroup)
API 11后,在ViewGroup中添加或删除view会触发系统提供的布局动画。
(1)在xml代码中的ViewGroup中添加android:animateLayoutChanges=”true”既可触发系统内置的增加删除item view的动画效果。LinearLayout是继承ViewGroup的这个大家都知道的哦。
<?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:id="@+id/body" android:layout_width="match_parent" android:layout_height="match_parent" android:animateLayoutChanges="true" android:layout_weight="1" android:showDividers="middle" android:orientation="vertical" > </LinearLayout> <Button android:id="@+id/add" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:text="ADD" /></LinearLayout>
2)代码中的ViewGroup直接设置setLayoutTransition(new LayoutTransition());即可调用系统提供的默认动画。
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_linearlaout_anim); bodyLayout = (LinearLayout) findViewById(R.id.body); bodyLayout.setLayoutTransition(new LayoutTransition()); add = (Button) findViewById(R.id.add); add.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { addItem(); } }); }
(3)自定义ViewGroup增加和删除item的动画
可以通过自己定义LayoutTransition,然后通过setLayoutTransition来设置自己定义的动画。
/** * 自定义的LayoutTransaction是在API11出现的 * ObjectAnimator outAnimator = new ObjectAnimator().ofFloat(null, "translationX", 0f,UiUtil.getScreenWidth()).setDuration(4000); * 上面这样在结尾设置setDuration(4000)动画时间是没有效果的 * 需要在layoutTransition对象直接设置动画时间才有效果layoutTransition.setDuration(4000) */ private LayoutTransition initCustomLayoutTransition() { UiUtil.initialize(this); LayoutTransition layoutTransition = new LayoutTransition(); ObjectAnimator outAnimator = ObjectAnimator.ofFloat(null, "translationX", 0f,UiUtil.getScreenWidth()).setDuration(3000); layoutTransition.setAnimator(LayoutTransition.DISAPPEARING, outAnimator);// layoutTransition.setDuration(4000); ObjectAnimator intAnimator = ObjectAnimator.ofFloat(null, "translationX", UiUtil.getScreenWidth(),0f); layoutTransition.setAnimator(LayoutTransition.APPEARING, intAnimator); //加了下面两个效果感觉不是很好,而且效果也没出来// ObjectAnimator intOtherAnimator = ObjectAnimator.ofFloat(null, "rotationY", 0,90,0);// layoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, intOtherAnimator);// // ObjectAnimator outOtherAnimator = ObjectAnimator.ofFloat(null, "rotationX", 0,-90,0);// layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, outOtherAnimator); return layoutTransition; }
<1>可以定制dViewGroup的几个动画效果
我们可以定义的动画有一下几种:
*1.LayoutTransition.APPEARING 子View添加到容器中时的过渡动画效果。
*2.LayoutTransition.DISAPPEARING 子View从容器中移除时的过渡动画效果。
*3.LayoutTransition.CHANGE_DISAPPEARING 子View从容器中移除时,其它子view位置改变的过渡动画。
*4.LayoutTransition.CHANGE_APPEARING 子View添加到容器中时,其他子View位置改变的过渡动画。
*5.LayoutTransition.CHANGING 4.1 JellyBean上还有一个增强的功能,可以在容器内的子view的layout发生变化时也播放动画。
下面这段代码就是设置子View从容器中移除时,其它子view位置改变的过渡动画:
layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, outOtherAnimator);
<2>LayoutTransition需要注意的问题
1.LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须要使用PropertyValuesHolder构造的动画才有效
2.在构造PropertyValuesHolder动画时,”left”,”top”,”right”和”bottom”属性至少要写两个,而且如果是两个的时候,必须是左上,左下,右上,右下的模式,不能出现左右,上下的模式
3.对于LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING,在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将被放弃,在此属性值上将不会有效果
/** * http://blog.csdn.net/harvic880925/article/details/50985596 * PropertyValuesHolder是用于同时执行多个动画,没必要像下面这样,只有一个动画就不必使用PropertyValuesHolder * 但是LayoutTransition有几个需要注意的问题: * 1.LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须要使用PropertyValuesHolder构造的动画才有效 * 2.在构造PropertyValuesHolder动画时,"left","top","right"和"bottom"属性至少要写两个,而且如果是两个的时候,必须是左上,左下,右上,右下的模式,不能出现左右,上下的模式 * 3.对于LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING,在构造PropertyValuesHolder时,所使用的ofInt,ofFloat中的参数值,第一个值和最后一个值必须相同,不然此属性所对应的的动画将被放弃,在此属性值上将不会有效果 * @return */ private LayoutTransition initCustomLayoutTransition2() { UiUtil.initialize(this); LayoutTransition layoutTransition = new LayoutTransition(); PropertyValuesHolder outValuesHolder = PropertyValuesHolder.ofFloat("translationX", 0f,UiUtil.getScreenWidth()); PropertyValuesHolder inValuesHolder = PropertyValuesHolder.ofFloat("translationX", UiUtil.getScreenWidth(),0f); ObjectAnimator outAnimator = ObjectAnimator.ofPropertyValuesHolder(bodyLayout,outValuesHolder); layoutTransition.setAnimator(LayoutTransition.DISAPPEARING, outAnimator); ObjectAnimator intAnimator = ObjectAnimator.ofPropertyValuesHolder(bodyLayout,inValuesHolder); layoutTransition.setAnimator(LayoutTransition.APPEARING, intAnimator); PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0); PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 0); PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 0); PropertyValuesHolder outOtherValuesHolder = PropertyValuesHolder.ofFloat("rotationY", 0,180,0); PropertyValuesHolder inOtherValuesHolder = PropertyValuesHolder.ofFloat("rotationX", 0,-180,0); ObjectAnimator intOtherAnimator = ObjectAnimator.ofPropertyValuesHolder(bodyLayout, pvhRight, pvhTop,outOtherValuesHolder); layoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, intOtherAnimator); layoutTransition.setDuration(3000); ObjectAnimator outOtherAnimator = ObjectAnimator.ofPropertyValuesHolder(bodyLayout, pvhRight, pvhTop,inOtherValuesHolder); layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, outOtherAnimator); return layoutTransition; }
4.Viewpager转场动画
Viewpager本来就有转场动画,但是我们还可以通过PageTransformer设置他的转场动画效果。官网的Using ViewPager for Screen Slides也有介绍。
其实我们要做的很简单,只需要自定义一个PageTransformer,然后在通过Viewpager的setPageTransformer方法设置即可。
当我们实现PageTransformer接口的时候,我们需要实现transformPage方法。里面的两个参数很关键:
View view 这个view即我们能看到的界面;
float position 这个是一个动态属性,是用来控制动画的重要参数;
下面我们通过例子来说明这两个参数。
首先,我给Viewpager的几个界面都设置一个id,pager1=111,pager2=222,pager3=333,这样我们就可以知道在切换界面的时候position 参数改变对应的是哪个view。
public class TestViewPagerActivity extends Activity{ private ViewPager viewPager = null; private List<LinearLayout> pagers = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.test_viewpager); viewPager = (ViewPager) findViewById(R.id.view_pager); viewPager.setPageTransformer(true, new DepthPageTransformer()); pagers = new ArrayList<LinearLayout>(); Pager pager1 = new Pager(this); pager1.setId(111); pager1.setText("界面一"); pager1.setBackgroundColor(Color.RED); Pager pager2 = new Pager(this); pager2.setId(222); pager2.setText("界面二"); pager2.setBackgroundColor(Color.YELLOW); Pager pager3 = new Pager(this); pager3.setId(333); pager3.setText("界面三"); pager3.setBackgroundColor(Color.BLUE); pagers.add(pager1); pagers.add(pager2); pagers.add(pager3); MyAdapter adapter = new MyAdapter(); adapter.setList(pagers); viewPager.setAdapter(adapter); } private class MyAdapter extends PagerAdapter { private List<LinearLayout> list = null; public List<LinearLayout> getList() { return list; } public void setList(List<LinearLayout> list) { this.list = list; } @Override public int getCount() { return list!=null?list.size():0; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0==arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { container.removeView(list.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { container.addView(list.get(position)); return list.get(position); } }}
然后实现我们自己的PageTransformer,在里面打个日志
Log.i(“lgy”, “position:”+position+” view:”+view.getId());
/** * @author LGY *View page :这个当然就是我们在ViewPager中滑动的界面。 *float position :这个参数是动态改变的,是一个float类型,而不是平常我们所理解的int位置,只有很好的理解这个参数我们才能设计出我们想要的效果。 *当position=-1时,表示当前页的前一页,此时该页面是看不见的 *当position= 0时,表示当前页,当前显示页 *当position=-1时,表示当前页的下一页 *position取值为 [-Infinity,-1) -> 页面不可见 *position取值为(1,+Infinity] -> 页面不可见 *position取值为[-1,1] -> 于可见状态区间 如果前一页和下一页基本各在屏幕占一半时,前一页的position是-0.5,后一页的posiotn是0.5,所以根据position的值我们就可以自行设置需要的alpha,x/y信息 */public class DepthPageTransformer implements ViewPager.PageTransformer { private static final float MIN_SCALE = 0.75f; public void transformPage(View view, float position) { int pageWidth = view.getWidth(); Log.i("lgy", "position:"+position+" view:"+view.getId()); if (position < -1) { // [-Infinity,-1)[负无穷大,-1) // This page is way off-screen to the left.这一页是屏幕左边 view.setAlpha(0); } else if (position <= 0) { // [-1,0] // Use the default slide transition when moving to the left page //当向左移动页面的时候,使用默认的幻灯片过渡 view.setAlpha(1); view.setTranslationX(0); view.setScaleX(1); view.setScaleY(1); } else if (position <= 1) { // (0,1] // Fade the page out.页面消失了 view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); } else { // (1,+Infinity] // This page is way off-screen to the right. view.setAlpha(0); } }}
结果:当我向左滑动,界面一切换到显示界面二的时候的日志如下:
从结果我们可以看出,在切换过程中界面一和界面二我们都可以看到,所以从日志里我们可以看到界面一和界面二的position参数。我们可以再看下面这个图理解
这个图展示的是当界面一滑动到界面的一半的时候,界面一的拿到的position是-0.5,而界面而的position是0.5。
所以根据这个position参数就可以设置界面二的出现动画,如下的代码,我们知道界面二出现的过程中,position是从1到0这样变化的,所以view.setAlpha(1 - position);透明度是从0-1变化。
else if (position <= 1) { // (0,1] // Fade the page out.页面消失了 view.setAlpha(1 - position); // Counteract the default slide transition view.setTranslationX(pageWidth * -position); // Scale the page down (between MIN_SCALE and 1) float scaleFactor = MIN_SCALE + (1 - MIN_SCALE) * (1 - Math.abs(position)); view.setScaleX(scaleFactor); view.setScaleY(scaleFactor); }
5.总结
其实还有好多细节没有点 出来,由于没有用到,说要就不探究那么仔细了。
6.参考文章
官方介绍动画的使用
Viewpager动画,这篇文章挺好的
http://blog.csdn.net/yegongheng/article/details/38435553
http://blog.csdn.net/javazejian/article/details/52571779
https://developer.android.com/guide/topics/graphics/view-animation.html
https://developer.android.com/guide/topics/graphics/prop-animation.html
https://developer.android.com/guide/topics/graphics/drawable-animation.html
7.源码地址
官方介绍动画的使用Demo
我的例子
- Android -animation-Property Animation
- Android-animation-View Animation
- Android-animation-drawable Animation
- android animation
- Android Animation
- android animation
- android Animation
- Animation Android
- Android Animation
- android animation
- android animation
- android animation
- Android Animation
- Android--Animation
- android animation
- android animation
- android Animation
- Android Animation
- CMAKE_CURRENT_BINARY_DIR
- 剑指offer--python --c++--从尾到头打印链表
- Android各种屏幕分辨率(VGA、HVGA、QVGA、WQVGA、WVGA、FWVGA) 详解
- 5.23 JLL--实习日志--PropertyExtension和string_float问题
- java锁
- [Android][Animation]
- Jquery实现父子类复选框,选择父类子类全选,选择子类父类显示中间状态,并传值到java后台
- vue弹窗组件练习
- 找出数组中重复元素
- python 第三方库的安装
- android开发者选项里的动画的值的获取
- apk文件的内容
- 15、vue.js 之路由与子路由
- dubbo-monitor安装、 监控中心 配置过程