Android动画属性一

Android动画属性一

标签: Android 动画属性


1. 控件添加动画属性

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/content_layout">
    <ImageView
        android:id="@+id/image_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/back2"
        android:scaleType="centerCrop"
        android:onClick="rotateAnimation"/>
</RelativeLayout>

其中ImageView添加了一个属性 android:onClick="rotateAnimation"
点击时会执行rotateAnimation
rotateAnimation并不是系统给的,是自己实现的。rotateAnimation只是一个名字,要实现这个名字的方法。
如下:

public class ScrollingActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);
    }
    public void rotateAnimation(View view){
       //具体动画
    }
}

2. ObjectAnimator 动画效果

1、ofFloat实现旋转

如下:

public class ScrollingActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scrolling);
    }
    public void rotateAnimation(View view){
        /**
         * rotationX 绕着X轴旋转
         * 从初始夹角180度开始旋转到10度
         * 最后显示10度的状态
         */
        ObjectAnimator.ofFloat(view,"rotationX",180.0f,10.0f).setDuration(500).start();
    }
}

使用了ObjectAnimator动画效果

rotationX 绕着X轴旋转
ofFloat(控件对象,方向,起始角度,终止角度);
或者 ofFloat(控件对象,方向,终止角度);
setDuration(动画持续时间);
start()开始;

对于ObjectAnimator
1、提供了ofInt、ofFloat、ofObject,这几个方法都是设置动画作用的元素、作用的属性、动画开始、结束、以及中间的任意个属性值。
当对于属性值,只设置一个的时候,会认为当然对象该属性的值为开始(getPropName反射获取),然后设置的值为终点。如果设置两个,则一个为开始、一个为结束~~~
动画更新的过程中,会不断调用setPropName更新元素的属性,所有使用ObjectAnimator更新某个属性,必须得有getter(设置一个属性值的时候)和setter方法~
2、如果你操作对象的该属性方法里面,比如上例的setRotationX如果内部没有调用view的重绘,则你需要自己按照下面方式手动调用。

anim.addUpdateListener(new AnimatorUpdateListener()  
        {  
            @Override  
            public void onAnimationUpdate(ValueAnimator animation)  
            {  
//              view.postInvalidate();  
//              view.invalidate();  
            }  
        });  

2、实现缩放和淡出

方法一

public void rotateAnimation(final View view){
        ObjectAnimator animator = ObjectAnimator.ofFloat(view,"xyz",1.0f,0.0f).setDuration(500);
        animator.start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (float) animation.getAnimatedValue();
                view.setAlpha(cVal);    //设置控件透明度
                view.setScaleY(cVal);   //设置控件x轴宽度
                view.setScaleX(cVal);   //设置控件Y轴宽度
            }
        });

这里设置了变化量为“xyz”就是一个没有的量,初始值为1,终值为0,点击时变化。
这样就获得了1-0的渐变量,然后设置监听器,变化更新时:

view.setAlpha(cVal); 设置当前渐变量为当前透明度。
view.setScaleX(cVal); 设置当前渐变量为当前View的宽度。
view.setScaleY(cVal); 设置当前渐变量为当前View的高度。

方法二

使用 propertyValuesHolder 同时设置多个变化属性。

public void propertyValuesHolder(View view)  
    {  
        PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("alpha", 1f,  
                0f, 1f);  
        PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("scaleX", 1f,  
                0, 1f);  
        PropertyValuesHolder pvhZ = PropertyValuesHolder.ofFloat("scaleY", 1f,  
                0, 1f);  
        ObjectAnimator.ofPropertyValuesHolder(view, pvhX, pvhY,pvhZ).setDuration(1000).start();  
    }  

3、ValueAnimator属性动画

先是布局代码:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.valueanimatortest.MainActivity">

   <ImageButton
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:src="@drawable/redball"
       android:id="@+id/red_ball"/>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal">
        <Button
            android:id="@+id/line"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="LineRun"
            android:text="垂直"/>
        <Button
            android:id="@+id/not_line"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="NotLineRun"
            android:text="抛物线"/>
    </LinearLayout>
</RelativeLayout>

一个ImageView是一个红球,两个按键分别实现两种动画。

下面是主活动

public class MainActivity extends Activity {
    private ImageView mRedBall;
    private int mScreenHeight;

    public int getScreenHeight(){
        Display mDisplay = getWindowManager().getDefaultDisplay();
        Point mPoint = new Point();
        mDisplay.getSize(mPoint);
        return mPoint.y;
    }
    public int getScreemWidth(){
        Display mDisplay = getWindowManager().getDefaultDisplay();
        Point mPoint = new Point();
        mDisplay.getSize(mPoint);
        return mPoint.x;
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        mRedBall = (ImageView) findViewById(R.id.red_ball);
        mScreenHeight = getScreenHeight();
    }
    public void LineRun(View view){
    //设置一个变量,大小从0到屏幕长度
        ValueAnimator animator = ValueAnimator.ofFloat(0,mScreenHeight-mRedBall.getHeight());
        animator.setTarget(mRedBall);
        animator.setDuration(2000);
        animator.start();
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
            //不断的改变红球的Y坐标
                mRedBall.setTranslationY((Float) animation.getAnimatedValue());
            }
        });
    }
    //抛物线运动
    public void NotLineRun(View view){
        ValueAnimator animator = new ValueAnimator();
        animator.setDuration(2000);

        //设置初始值
        animator.setObjectValues(new PointF(0, 0));
        animator.setInterpolator(new LinearInterpolator()); //时间差值 线性变化

        //自定义数值如何变化
        animator.setEvaluator(new TypeEvaluator<PointF>() {
            @Override
            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
                float x = 200 * fraction * 3;
                float y = 0.5f * 200 * fraction * 3 * fraction * 3;
                PointF pointF = new PointF(x, y);
                return pointF;
            }
        });
        animator.start();
        //监听数值变化,不断改变X,Y坐标
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF pointF = (PointF) animation.getAnimatedValue();
                mRedBall.setTranslationX(pointF.x);
                mRedBall.setTranslationY(pointF.y);
            }
        });
    }
}

animator.setInterpolator(new LinearInterpolator());
setInterpolator表示设置变化速率。LinearInterpolator为匀速效果,Accelerateinterpolator为加速效果、DecelerateInterpolator为减速效果。

这里有几种X的值:
TranslationX 控件坐标(是TranslationX坐标,和X的左标不同)
RotationX 翻转角度(和基点对比)
PivotX 基线(旋转中心的X坐标)
ScaleX 控件宽度
X 控件坐标(应该是布局文件中定义的位置坐标)

动画监听

可以在动画的不同阶段设置监听器。
比如我要删除个元素,我可能希望是个淡出的效果,但是最终还是要删掉,并不是你透明度没有了,还占着位置,所以我们需要知道动画如何结束。

public void fadeOut(View view)  
    {  
        ObjectAnimator anim = ObjectAnimator.ofFloat(mBlueBall, "alpha", 0.5f);  

        anim.addListener(new AnimatorListener()  
        {  

            @Override  
            public void onAnimationStart(Animator animation)  
            {  
                Log.e(TAG, "onAnimationStart");  
            }  

            @Override  
            public void onAnimationRepeat(Animator animation)  
            {  
                // TODO Auto-generated method stub  
                Log.e(TAG, "onAnimationRepeat");  
            }  

            @Override  
            public void onAnimationEnd(Animator animation)  
            {  
                Log.e(TAG, "onAnimationEnd");  
                ViewGroup parent = (ViewGroup) mBlueBall.getParent();  
                if (parent != null)  
                    parent.removeView(mBlueBall);  
            }  

            @Override  
            public void onAnimationCancel(Animator animation)  
            {  
                // TODO Auto-generated method stub  
                Log.e(TAG, "onAnimationCancel");  
            }  
        });  
        anim.start();  
    }  

3、多动画的运行次序

//多动画一起执行
    public void togetherRun(View view)  
    {  
        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",  
                1.0f, 2f);  
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",  
                1.0f, 2f);  
        AnimatorSet animSet = new AnimatorSet();  
        animSet.setDuration(2000);  
        animSet.setInterpolator(new LinearInterpolator());  
        //两个动画同时执行  
        animSet.playTogether(anim1, anim2);  //一起执行
        animSet.start();  
    }  

    public void playWithAfter(View view)  
    {  
        float cx = mBlueBall.getX();  

        ObjectAnimator anim1 = ObjectAnimator.ofFloat(mBlueBall, "scaleX",  
                1.0f, 2f);  
        ObjectAnimator anim2 = ObjectAnimator.ofFloat(mBlueBall, "scaleY",  
                1.0f, 2f);  
        ObjectAnimator anim3 = ObjectAnimator.ofFloat(mBlueBall,  
                "x",  cx ,  0f);  
        ObjectAnimator anim4 = ObjectAnimator.ofFloat(mBlueBall,  
                "x", cx);  

        /** 
         * anim1,anim2,anim3同时执行 
         * anim4接着执行 
         */  
        AnimatorSet animSet = new AnimatorSet();  
        animSet.play(anim1).with(anim2);  
        animSet.play(anim2).with(anim3);  
        animSet.play(anim4).after(anim3);  
        animSet.setDuration(1000);  
        animSet.start();  
    }  

第一:使用playTogether两个动画同时执行,当然还有playSequentially依次执行~~
第二:如果我们有一堆动画,如何使用代码控制顺序,比如1,2同时;3在2后面;4在1之前等~就是效果2了
有一点注意:animSet.play().with();也是支持链式编程的,但是不要想着狂点,比如 animSet.play(anim1).with(anim2).before(anim3).before(anim5); 这样是不行的,系统不会根据你写的这一长串来决定先后的顺序,所以按照上面例子的写法,多写几行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值