A09_Android动画
来源:互联网 发布:无限发短信软件 编辑:程序博客网 时间:2024/06/04 14:58
帧动画FrameAnimation
胶片电影,早期的动画–多张图片快速切换形成动画效果,主要应用在读取界面
帧动画使用XML定义
<?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/g1" android:duration="200" /> <item android:drawable="@drawable/g2" android:duration="200" /> <item android:drawable="@drawable/g3" android:duration="200" /> <item android:drawable="@drawable/g4" android:duration="200" /> <item android:drawable="@drawable/g5" android:duration="200" /> <item android:drawable="@drawable/g6" android:duration="300" /> <item android:drawable="@drawable/g7" android:duration="300" /> <item android:drawable="@drawable/g8" android:duration="300" /> <item android:drawable="@drawable/g9" android:duration="200" /> <item android:drawable="@drawable/g10" android:duration="200" /> <item android:drawable="@drawable/g11" android:duration="200" /></animation-list>
在Activity代码中
ImageView iv = (ImageView) findViewById(R.id.iv);iv.setBackgroundResource(R.drawable.frameanimation);AnimationDrawable ad = (AnimationDrawable)iv.getBackground();ad.start();
补间动画ViewAnimation
组件由原始状态向终极状态转变时,为了让过渡更自然,而自动生成的动画
位移动画TranslateAnimation
TranslateAnimation ta=new TranslateAnimation(10,100,20,100);
- 10:表示x坐标起始位置,不是绝对坐标,是相对的,组件的绝对x+10,下同
- 100:表示x坐标的结束位置
- 20:表示y坐标起始位置
- 100:表示y坐标的结束位置
另一种
ta = new TranslateAnimation( Animation.RELATIVE_TO_SELF, 1, Animation.RELATIVE_TO_SELF, 2, Animation.RELATIVE_TO_SELF, -0.5f, Animation.RELATIVE_TO_SELF, 1.5f);
Animation.RELATIVE_TO_SELF, 1:组件的绝对x坐标+1×组件的宽
//平移动画// TranslateAnimation ta=new TranslateAnimation(0, 50, 0, 50); //相对自己=RELATIVE_TO_SELF,0=控件绝对X+控件宽度*0 //相对父容器=RELATIVE_TO_PARENT,0=控件绝对X+父容器宽度*0 TranslateAnimation ta=new TranslateAnimation(Animation.RELATIVE_TO_PARENT,-1, Animation.RELATIVE_TO_PARENT, 2, Animation.RELATIVE_TO_PARENT, -1, Animation.RELATIVE_TO_PARENT, 2); //设置播放时间 ta.setDuration(1000); //设置重复次数 ta.setRepeatCount(3); //重复模式,默认从头重复 ta.setRepeatMode(Animation.REVERSE); iv.startAnimation(ta);
缩放动画ScaleAnimation
//缩放动画 //缩放点在左上角// ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5); //后两个参数代表缩放的中心点,默认控件左上角// ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5, iv.getWidth()/2, iv.getHeight()/2); ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); sa.setDuration(2000); sa.setRepeatCount(1); sa.setRepeatMode(Animation.REVERSE); //填充动画的结束位置 sa.setFillAfter(true); iv.startAnimation(sa);
透明动画AlphaAnimation
//透明度动画 //起始透明度-结束透明度 0-1 AlphaAnimation aa=new AlphaAnimation(0.1f, 1); aa.setDuration(2000); iv.startAnimation(aa);
旋转动画RotateAnimation
//旋转动画 //以左上角为中心,旋转0-360度// RotateAnimation ra=new RotateAnimation(0, 720);// RotateAnimation ra=new RotateAnimation(0, 360, iv.getWidth()/2, iv.getHeight()/2); RotateAnimation ra=new RotateAnimation(0, 180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); ra.setDuration(2000); ra.setRepeatCount(2); ra.setRepeatMode(Animation.REVERSE); ra.setFillAfter(true); iv.startAnimation(ra);
动画集AnimationSet
将以上四种动画合为一体
注:点击报错,因为空指针,没有对所设置的动画进行初始化
AnimationSet set=new AnimationSet(false); set.addAnimation(ta); set.addAnimation(sa); set.addAnimation(aa); set.addAnimation(ra); iv.startAnimation(set);
属性动画PropertyAnimation
补间动画仅仅改变的是控件在界面上的绘制效果,但实质位置还在原处。
既然是属性动画,所以我们最终操作的属性的改变,在这里,属性需要符合bean规范,大部分控件的setter方法会重绘组件。
平移
这里的ObjectAnimator中只能一次改变一个属性
且,iv.setTranslationX(translationX);中translationX符合并规范,于是平移代码如下
//参数1:哪个控件要执行动画 //参数2:要改变哪个属性 //参数3:改变的过程,左负右正(相对控件本身的坐标点) //这里指,iv的x坐标先从自身(0),移动到100,再移动到50,再移动到150,最后回归 oa1 = ObjectAnimator.ofFloat(iv, "translationX", 0,100,50,150,0); oa1.setDuration(2000); oa1.setRepeatCount(1); oa1.start();
缩放
oa2 = ObjectAnimator.ofFloat(iv,"scaleX",1,2,1,3,4); oa2.setDuration(2000); oa2.start();
透明度
oa3 = ObjectAnimator.ofFloat(iv,"alpha",1,0.5f,1,0.3f,1,0,1); oa3.setDuration(2000); oa3.start();
旋转
oa4 = ObjectAnimator.ofFloat(iv,"rotation",0,180,-180,180); oa4.setDuration(2000); oa4.setRepeatCount(1); oa4.start();
动画集合AnimatorSet
AnimatorSet set=new AnimatorSet(); //按顺序执行 //set.playSequentially(items); //一起执行 set.playTogether(oa1,oa2,oa3,oa4); set.start();
如果所操作的对象的属性方法里,没有调用view的重绘,则需要自己按照下面方式手动调用。
oa1.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { //view.postInvalidate(); //view.invalidate(); } });
如果要执行多种动画,如下代码:
依据addUpdateListener
//2.依照addUpdateListener实现多动画实现ObjectAnimator anim=ObjectAnimator.ofFloat(iv, "abc", 1.0f,0.0f,1.0f).setDuration(1000);anim.start();anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float val=(Float) animation.getAnimatedValue(); iv.setAlpha(val); iv.setScaleX(val); iv.setScaleY(val); iv.setTranslationX(val); iv.setTranslationY(val); }});
依据PropertyValuesHolder
//3.依据PropertyValuesHolder实现多动画处理PropertyValuesHolder pvh1=PropertyValuesHolder.ofFloat("alpha", 1.0f,0.1f,1.0f);PropertyValuesHolder pvh2=PropertyValuesHolder.ofFloat("scaleX", 1,2,1);PropertyValuesHolder pvh3=PropertyValuesHolder.ofFloat("scaleY", 1,2,1);PropertyValuesHolder pvh4=PropertyValuesHolder.ofFloat("translationX", 0,150,0);ObjectAnimator.ofPropertyValuesHolder(iv,pvh1,pvh2,pvh3,pvh4).setDuration(2000).start();
属性动画深入解析
属性动画的出现,解决了补间动画的三种问题
- 解决了补间动画不能对非View进行动画的问题
- 解决了补间动画不能实现颜色背景动画等特殊动画的问题
- 解决了补间动画只是View的显示效果的缺陷
ValueAnimator
核心类
属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等。
比如将一个值从0平滑过渡到1,时长300毫秒,
ValueAnimator anim=ValueAnimator.ofFloat(0f,1f);anim.setDuration(300);anim.start();
运行代码,动画就会执行,但这样并没有任何界面效果,如何得知动画是否运行,就需要设置一个监听器
anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float cVal=(Float) animation.getAnimatedValue(); Log.d("TAG", "current vlaue is "+cVal); } });
日志结果如下:
- 07-25 06:27:58.440: D/TAG(4914): current vlaue is 0.0
- 07-25 06:27:58.460: D/TAG(4914): current vlaue is 0.0070019662
- 07-25 06:27:58.472: D/TAG(4914): current vlaue is 0.029559612
- 07-25 06:27:58.492: D/TAG(4914): current vlaue is 0.066987276
- 07-25 06:27:58.508: D/TAG(4914): current vlaue is 0.11474341
- 07-25 06:27:58.524: D/TAG(4914): current vlaue is 0.17727113
- 07-25 06:27:58.544: D/TAG(4914): current vlaue is 0.25000006
- 07-25 06:27:58.560: D/TAG(4914): current vlaue is 0.32571396
- 07-25 06:27:58.576: D/TAG(4914): current vlaue is 0.41145772
- 07-25 06:27:58.592: D/TAG(4914): current vlaue is 0.5
- 07-25 06:27:58.608: D/TAG(4914): current vlaue is 0.5833843
- 07-25 06:27:58.624: D/TAG(4914): current vlaue is 0.669369
- 07-25 06:27:58.644: D/TAG(4914): current vlaue is 0.7500001
- 07-25 06:27:58.656: D/TAG(4914): current vlaue is 0.818712
- 07-25 06:27:58.672: D/TAG(4914): current vlaue is 0.881898
- 07-25 06:27:58.692: D/TAG(4914): current vlaue is 0.9330126
- 07-25 06:27:58.708: D/TAG(4914): current vlaue is 0.968641
- 07-25 06:27:58.724: D/TAG(4914): current vlaue is 0.99209785
- 07-25 06:27:58.740: D/TAG(4914): current vlaue is 1.0
ObjectAnimator
常用类
ValueAnimator只不过是对值进行了一个平滑的动画过渡,而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的。
但是ObjectAnimator是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator的。
ObjectAnimator moveIn = ObjectAnimator.ofFloat(tv, "translationX", -400f, 0f); ObjectAnimator rotate = ObjectAnimator.ofFloat(tv, "rotation", 0f, 360f); ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(tv, "alpha", 1f, 0f, 1f); AnimatorSet animSet=new AnimatorSet(); animSet.play(rotate).with(fadeInOut).after(moveIn); animSet.setDuration(5000); animSet.start();
Animator监听器
只要继承了Animator,都可包含该方法和监听器
在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。
animSet.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animator animation) { // TODO Auto-generated method stub } @Override public void onAnimationEnd(Animator animation) { // TODO Auto-generated method stub } @Override public void onAnimationCancel(Animator animation) { // TODO Auto-generated method stub } });
- onAnimationStart()方法会在动画开始的时候调用
- onAnimationRepeat()方法会在动画重复执行的时候调用
- onAnimationEnd()方法会在动画结束的时候调用
- onAnimationCancel()方法会在动画被取消的时候调用
也可监听某一动画事件,AnimatorListenerAdapter
animSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { // TODO Auto-generated method stub super.onAnimationEnd(animation); } });
TypeEvaluator的高级用法
TypeEvaluator的作用是什么,就是告诉动画系统如何从初始值过渡到结束值。在ValueAnimator.ofFloat()中就实现了初始值与结束值之间的平滑过渡,那么这个平滑过渡是怎么做到的呢?其实就是系统内置了一个FloatEvaluator,它通过计算告知动画系统如何从初始值过渡到结束值,我们来看一下FloatEvaluator的代码实现:
public class FloatEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { float startFloat = ((Number) startValue).floatValue(); return startFloat + fraction * (((Number) endValue).floatValue() - startFloat); } }
evaluate()方法当中传入了三个参数,第一个参数fraction非常重要,这个参数用于表示动画的完成度的,我们应该根据它来计算当前动画的值应该是多少,第二第三个参数分别表示动画的初始值和结束值。那么上述代码的逻辑就比较清晰了,用结束值减去初始值,算出它们之间的差值,然后乘以fraction这个系数,再加上初始值,那么就得到当前动画的值了。
ValueAnimator包含ofInt和ofFloat方法,分别用于对浮点型和整数型的数据进行动画操作的,但实际上ValueAnimator中还有一个ofObject方法,是用于对任意对象进行动画操作的。但是相比之下,对象的操作明显复杂一些,因为系统将完全无法知道如何从初始对象过渡到结束对象,因此这个时候我们就需要实现一个自己的TypeEvaluator来告知系统如何进行过渡。
先定义一个Point类,x,y表示坐标
public class Point { private float x; private float y; public Point(float x, float y) { super(); this.x = x; this.y = y; } public float getX() { return x; } public void setX(float x) { this.x = x; } public float getY() { return y; } public void setY(float y) { this.y = y; }}
再定义一个TypeEvaluator
public class PointEvaluator implements TypeEvaluator{ @Override public Object evaluate(float fraction, Object startValue, Object endValue) { Point startPoint=(Point) startValue; Point endPoint=(Point) endValue; float x=startPoint.getX()+fraction*(endPoint.getX()-startPoint.getX()); float y=startPoint.getY()+fraction*(endPoint.getX()-startPoint.getX()); Point point=new Point(x, y); return point; }}
接下来让两个Point之间进行平滑过渡
Point p1=new Point(0, 0); Point p2=new Point(300,300); ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), p1,p2); anim.setDuration(5000); anim.start();
但这样依然看不出效果,我们现在自定义一个圆球(View)
public class MyAnimView extends View{ private Point currentPoint; private Paint mPaint; public MyAnimView(Context context, AttributeSet attrs) { super(context, attrs); mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mPaint.setColor(Color.BLUE); } @Override protected void onDraw(Canvas canvas) { //为空,绘制(刚开始) if(currentPoint==null){ currentPoint=new Point(50f, 50f); //画圆 drawCircle(canvas); //开启动画 startAnim(); }else{//不为空,继续绘制(过程中) //继续画 drawCircle(canvas); } } private void startAnim() { //初始点 Point startPoint=new Point(50f, 50f); //结束点 Point endPoint=new Point(getWidth()-50f,getHeight()-50f); ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), startPoint,endPoint); //开始监听动画的更新 anim.addUpdateListener(new AnimatorUpdateListener() { //每次更新,animation.getAnimatedValue()会将PointEvaluator中的evaluate()结果返回 //再进行重绘 @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint=(Point) animation.getAnimatedValue(); invalidate(); } }); anim.setDuration(5000); anim.start(); } private void drawCircle(Canvas canvas) { float x=currentPoint.getX(); float y=currentPoint.getY(); canvas.drawCircle(x, y, 50f, mPaint); }}
ObjectAnimator的高级用法
将ObjectAnimator扩展,能够进行颜色动画效果
因为ObjectAnimator操作的属性需要setter,getter,所以在上述自定义圆球中,加入该属性
public class MyAnimView extends View{ ... private String color; public String getColor() { return color; } public void setColor(String color) { this.color = color; mPaint.setColor(Color.parseColor(color)); invalidate(); } ...}
接下来编写一个用于告知系统如何进行颜色过渡的TypeEvaluator
public class ColorEvaluator implements TypeEvaluator{ private int mCurrentRed=-1; private int mCurrentGreen=-1; private int mCurrentBlue=-1; @Override public Object evaluate(float fraction, Object startValue, Object endValue) { String startColor=(String) startValue; String endColor=(String) endValue; int startRed = Integer.parseInt(startColor.substring(1, 3), 16); int startGreen = Integer.parseInt(startColor.substring(3, 5), 16); int startBlue = Integer.parseInt(startColor.substring(5, 7), 16); int endRed = Integer.parseInt(endColor.substring(1, 3), 16); int endGreen = Integer.parseInt(endColor.substring(3, 5), 16); int endBlue = Integer.parseInt(endColor.substring(5, 7), 16); // 初始化颜色的值 if (mCurrentRed == -1) { mCurrentRed = startRed; } if (mCurrentGreen == -1) { mCurrentGreen = startGreen; } if (mCurrentBlue == -1) { mCurrentBlue = startBlue; } // 计算初始颜色和结束颜色之间的差值 int redDiff = Math.abs(startRed - endRed); int greenDiff = Math.abs(startGreen - endGreen); int blueDiff = Math.abs(startBlue - endBlue); int colorDiff = redDiff + greenDiff + blueDiff; if (mCurrentRed != endRed) { mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0, fraction); } else if (mCurrentGreen != endGreen) { mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff, redDiff, fraction); } else if (mCurrentBlue != endBlue) { mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff, redDiff + greenDiff, fraction); } // 将计算出的当前颜色的值组装返回 String currentColor = "#" + getHexString(mCurrentRed) + getHexString(mCurrentGreen) + getHexString(mCurrentBlue); return currentColor; } /** * 根据fraction值来计算当前的颜色。 */ private int getCurrentColor(int startColor, int endColor, int colorDiff, int offset, float fraction) { int currentColor; if (startColor > endColor) { currentColor = (int) (startColor - (fraction * colorDiff - offset)); if (currentColor < endColor) { currentColor = endColor; } } else { currentColor = (int) (startColor + (fraction * colorDiff - offset)); if (currentColor > endColor) { currentColor = endColor; } } return currentColor; } /** * 将10进制颜色值转换成16进制。 */ private String getHexString(int value) { String hexString = Integer.toHexString(value); if (hexString.length() == 1) { hexString = "0" + hexString; } return hexString; } }
首先在evaluate()方法当中获取到颜色的初始值和结束值,并通过字符串截取的方式将颜色分为RGB三个部分,并将RGB的值转换成十进制数字,那么每个颜色的取值范围就是0-255。接下来计算一下初始颜色值到结束颜色值之间的差值,这个差值很重要,决定着颜色变化的快慢,如果初始颜色值和结束颜色值很相近,那么颜色变化就会比较缓慢,而如果颜色值相差很大,比如说从黑到白,那么就要经历255*3这个幅度的颜色过度,变化就会非常快。
那么控制颜色变化的速度是通过getCurrentColor()这个方法来实现的,这个方法会根据当前的fraction值来计算目前应该过度到什么颜色,并且这里会根据初始和结束的颜色差值来控制变化速度,最终将计算出的颜色进行返回。
最后,由于我们计算出的颜色是十进制数字,这里还需要调用一下getHexString()方法把它们转换成十六进制字符串,再将RGB颜色拼装起来之后作为最终的结果返回。
实现颜色背景动画的过渡
private void startAnim() { //初始点 Point startPoint=new Point(50f, 50f); //结束点 Point endPoint=new Point(getWidth()-50f,getHeight()-50f); ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), startPoint,endPoint); //开始监听动画的更新 anim.addUpdateListener(new AnimatorUpdateListener() { //每次更新,animation.getAnimatedValue()会将PointEvaluator中的evaluate()结果返回 //再进行重绘 @Override public void onAnimationUpdate(ValueAnimator animation) { currentPoint=(Point) animation.getAnimatedValue(); invalidate(); } }); //颜色背景动画 ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),"#0000FF", "#FF0000"); AnimatorSet animSet=new AnimatorSet(); animSet.play(anim).with(anim2); animSet.setDuration(5000); animSet.start(); }
Interpolator的用法
补间器,它的主要作用是可以控制动画的变化速率,比如一些线性/非线性运动。就是说,动画改变的速率不是一成不变的。
Android内置的Interpolator,直接拿来用就好了,setsetInterpolator()。
- AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
- AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
- AnticipateInterpolator 开始的时候向后然后向前甩
- AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
- BounceInterpolator 动画结束的时候弹起
- CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
- DecelerateInterpolator 在动画开始的地方快然后慢
- LinearInterpolator 以常量速率改变
- OvershootInterpolator 向前甩一定值后再回到原来位置
ViewPropertyAnimator的用法
直接在控件后上设置动画
textview.animate().alpha(0f); textview.animate().x(500).y(500); textview.animate().x(500).y(500).setDuration(5000);
注意的地方:
整个ViewPropertyAnimator的功能都是建立在View类新增的animate()方法之上的,这个方法会创建并返回一个ViewPropertyAnimator的实例,之后的调用的所有方法,设置的所有属性都是通过这个实例完成的。
大家注意到,在使用ViewPropertyAnimator时,我们自始至终没有调用过start()方法,这是因为新的接口中使用了隐式启动动画的功能,只要我们将动画定义完成之后,动画就会自动启动。并且这个机制对于组合动画也同样有效,只要我们不断地连缀新的方法,那么动画就不会立刻执行,等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动。当然如果不想使用这一默认机制的话,我们也可以显式地调用start()方法来启动动画。
ViewPropertyAnimator的所有接口都是使用连缀的语法来设计的,每个方法的返回值都是它自身的实例,因此调用完一个方法之后可以直接连缀调用它的另一个方法,这样把所有的功能都串接起来,我们甚至可以仅通过一行代码就完成任意复杂度的动画功能。
布局动画LayoutAnimations
主要使用LayoutTransition为布局的容器设置动画,当容器中的视图层次发生变化时存在过渡的动画效果。
基本你用法如下:
LayoutTransition transition = new LayoutTransition(); transition.setAnimator(LayoutTransition.CHANGE_APPEARING, transition.getAnimator(LayoutTransition.CHANGE_APPEARING)); transition.setAnimator(LayoutTransition.APPEARING, null); transition.setAnimator(LayoutTransition.DISAPPEARING, null); transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, null); mGridLayout.setLayoutTransition(transition);
过渡的类型一共有四种:
- 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设置的动画
还可以自定义动画
mTransition.setAnimator(LayoutTransition.APPEARING, (mAppear .isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 0, 1).setDuration(200) : null));
- A09_Android动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 动画
- 十一、享元Flyweight(结构型)
- css样式表和选择器的优先级以及position元素属性值的区别
- volatile关键字解析&内存模型&并发编程中三概念
- ACM--字母增加--HDOJ 1328--IBM Minus One--字符串
- makefile 文件中 `cat /lib/sysliblist` 意思详解
- A09_Android动画
- Red and Black hd 1312
- 把table中指定数值列的值(NUM),比方说5,转化为生产同记录的5行,方便一些打印软件使用
- LeetCode 147 Insertion Sort List
- MySQL表查询优化(三):有查询条件时的like
- Java三大特征-------多态
- 为什么this super不能用在static方法中??
- IntelliJ IDEA 从零开始创建一个项目
- River Hopscotch(二分)