android群英传笔记 android动画机制

来源:互联网 发布:蒋欣演技知乎 编辑:程序博客网 时间:2024/05/31 19:37
逐帧动画Frame Animation :其实也可以规划到视图动画的类别,用来一个一个的显示drawable的resources。
视图动画Tween Animation:也叫补间动画,可以在一个视图容器内执行一系列简单变换(位置,大小,旋转,透明度)实现的原理是每次绘制视图时view所在的viewgroup中的drawchild函数获取该viewanimation的transformation值。然后调用canvas.concat()通过矩阵运算完成动画zhen动画帧。如果动画没有完成,就继续调用invalidate函数启动下次绘制来驱动动画,从而完成整个动画的绘制。它有一个缺点,不具备交互性,当某个元素发生视图动画后,其响应事件的位置还依然在动画前的地方,(例如,将一个按钮向右平移10个单位,但是它的点击事件还是在平移之前的那个位置,而不是平移后显示的位置)所以视图动画只能做普通的动画效果,避免交互的发生。但是它的效率高,使用方便。
属性动画Propety Animation:只对android3.0以上的版本才有效,这种动画可以设置给任何object,包括那些还没有渲染到屏幕上的对象,这种动画是可以扩展的,可以让自定义任何类型和属性的动画。
视图动画示例:
public class AnimationActivity extends AppCompatActivity implements View.OnClickListener {    private ImageView ainmationImg;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_animation);        initView();    }    private void initView() {        ainmationImg = ((ImageView) findViewById(R.id.animationImg));        findViewById(R.id.touming).setOnClickListener(this);        findViewById(R.id.xuanzhuan).setOnClickListener(this);        findViewById(R.id.weiyi).setOnClickListener(this);        findViewById(R.id.suofang).setOnClickListener(this);        findViewById(R.id.jihe).setOnClickListener(this);    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.touming:                toumingAnimation();                break;            case R.id.xuanzhuan:                xuanzhuanAnimation();                break;            case R.id.weiyi:                weiyiAnimation();                break;            case R.id.suofang:                soufangAnimation();                break;            case R.id.jihe:                jiheAnimation();                break;        }    }    /**     * 透明动画     */    private void toumingAnimation() {        AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);        alphaAnimation.setDuration(1000);        ainmationImg.startAnimation(alphaAnimation);    }    /**     * 集合动画,添加多种动画效果     */    private void jiheAnimation() {        AnimationSet as = new AnimationSet(true);        as.setDuration(1000);        AlphaAnimation alphaAnimation = new AlphaAnimation(0, 1);        alphaAnimation.setDuration(1000);        as.addAnimation(alphaAnimation);        ScaleAnimation anmation = new ScaleAnimation(0, 2, 0, 2);        anmation.setDuration(1000);        as.addAnimation(anmation);        RotateAnimation animation = new RotateAnimation(0, 360, 100, 100);        animation.setDuration(1000);        as.addAnimation(animation);        ainmationImg.startAnimation(as);    }    /**     * 缩放动画     */    private void soufangAnimation() {        ScaleAnimation anmation = new ScaleAnimation(0, 2, 0, 2);        anmation.setDuration(1000);        ainmationImg.startAnimation(anmation);    }    /**     * 位移动画     */    private void weiyiAnimation() {        TranslateAnimation animation = new TranslateAnimation(0, 200, 0, 300);        animation.setDuration(1000);        ainmationImg.startAnimation(animation);    }    /**     * 旋转动画     */    private void xuanzhuanAnimation() {//        参数:1旋转的起始角度和旋转中心点的坐标        RotateAnimation animation = new RotateAnimation(0, 360, 100, 100);        animation.setDuration(1000);        ainmationImg.startAnimation(animation);    }    private void animationListener(Animation animation) {        //动画的监听        animation.setAnimationListener(new Animation.AnimationListener() {            @Override            public void onAnimationStart(Animation animation) {            }            @Override            public void onAnimationEnd(Animation animation) {            }            @Override            public void onAnimationRepeat(Animation animation) {            }        });    }}
xml布局
<?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:id="@+id/activity_animation"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.lvqueen.qunyinzhuan.day07.AnimationActivity">    <ImageView        android:id="@+id/animationImg"        android:layout_width="100dp"        android:layout_height="100dp"        android:layout_centerInParent="true"        android:scaleType="fitXY"        android:src="@mipmap/shoukuan" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:orientation="vertical">        <LinearLayout            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_alignParentBottom="true"            android:orientation="horizontal">            <Button                android:id="@+id/touming"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="透明" />            <Button                android:id="@+id/xuanzhuan"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="旋转" />            <Button                android:id="@+id/weiyi"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="位移" />            <Button                android:id="@+id/suofang"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="缩放" />        </LinearLayout>        <Button            android:id="@+id/jihe"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:text="集合" />    </LinearLayout></RelativeLayout>
属性动画示例

public class AnimatorActivity extends AppCompatActivity {    private ImageView imgView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_animator);        initView();    }    private void initView() {        imgView = ((ImageView) findViewById(R.id.animatorImg));//        pingyiAnimator();//        jiheAnimator();//        orderManyAnimator();        useXmlAnimator();    }    /**     * 在使用ObjectAnimator的时候,操纵的属性必须具有get和set方法,不然ObjectAnimator就无效。     * 如果没有,可以通过自定义一个属性类或者包装类,来间接的给这个属性增加get,set方法,活着通过ValueAnimator     * 可以直接使用属性动画的属性值     * translationX,translationY:为一种增量来控制view对象从它的布局容器的左上角坐标偏移的位置。     * rotation,rotationX,rotationY:控制view对象围绕它的支点进行2D,3D旋转     * scaleX,scaleY:控制view围绕它的支点进行2D缩放。     * pivotX,pivotY:控制view围绕支点进行旋转和缩放变换处理。默认情况下,支点位置就是view对象的中心点     * x,y:描述了view对象在他的容器中的最终位置,它是最初的左上角坐标和translationX,translationY值的累计和     * alpha:表示view的透明度,默认值为1不透明,0为完全透明。     */    private void pingyiAnimator() {//        参数1:要操纵的view。参数2:操纵的属性。参数三:可变的数组参数        ObjectAnimator animator = ObjectAnimator.ofFloat(imgView, "translationX", 300);//        ObjectAnimator animator = ObjectAnimator.ofFloat(imgView, "translationX", 300);        animator.setDuration(1000);        animator.start();    }    /**     * 添加多种动效PropertyValuesHolder     */    private void jiheAnimator() {        PropertyValuesHolder translationX = PropertyValuesHolder.ofFloat("translationX", 300f);        PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", 300f);        PropertyValuesHolder scaleX = PropertyValuesHolder.ofFloat("scaleX", 1f, 0, 1f);        ObjectAnimator.ofPropertyValuesHolder(imgView, translationX, scaleX, translationY).setDuration(1000).start();    }    /**     * 顺序添加多种动效     */    private void orderManyAnimator() {        ObjectAnimator animator = ObjectAnimator.ofFloat(imgView, "translationX", 100);        ObjectAnimator animator1 = ObjectAnimator.ofFloat(imgView, "translationY", 100);        AnimatorSet animatorSet = new AnimatorSet();        animatorSet.setDuration(1000);        animatorSet.playTogether(animator, animator1);        animatorSet.start();    }    private void useXmlAnimator(){//        Animator animator = AnimatorInflater.loadAnimator(this, R.anim.animator_test);//        animator.setTarget(imgView);//        animator.start();    }//    view 的animate方法添加动画    private void animateUse(){        imgView.animate().alpha(0).y(300).setDuration(1000).withStartAction(new Runnable() {            @Override            public void run() {            }        }).withEndAction(new Runnable() {            @Override            public void run() {                runOnUiThread(new Runnable() {                    @Override                    public void run() {                    }                });            }        }).start();    }    private void valueAnimatorFactory() {        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 100);        valueAnimator.setTarget(imgView);        valueAnimator.setDuration(1000).start();        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                Float value = (Float) valueAnimator.getAnimatedValue();//                TODO use the value//                在这里监听数值的变换,从而完成动画的变换。            }        });    }    /**     * 动效的监听     *     * @param animator     */    private void animationListener(ObjectAnimator animator) {        animator.addListener(new Animator.AnimatorListener() {            @Override            public void onAnimationStart(Animator animator) {            }            @Override            public void onAnimationEnd(Animator animator) {            }            @Override            public void onAnimationCancel(Animator animator) {            }            @Override            public void onAnimationRepeat(Animator animator) {            }        });//        通常情况下我们只关心动画结束时,所以还提供了一个,来选择必要的事件进行监听        animator.addListener(new AnimatorListenerAdapter() {            @Override            public void onAnimationEnd(Animator animation) {                super.onAnimationEnd(animation);            }        });    }}
示例三:布局动画,给子视图出现添加动画

public class BujuActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_buju);        addAnimation();    }    /**     * 给子视图出现添加动画     * 参数1:需要作用的动画,参数2:子view现实的delay时间     * LayoutAnimationController.ORDER_NORMAL:顺序依次出现     * LayoutAnimationController.ORDER_RANDOM :随机出现     * LayoutAnimationController.ORDER_REVERSE:倒序出现     */    private void addAnimation() {        LinearLayout linearLayout = (LinearLayout) findViewById(R.id.activity_buju);        ScaleAnimation scaleAnimation = new ScaleAnimation(0, 1, 0, 1);        scaleAnimation.setDuration(1000);        LayoutAnimationController controller = new LayoutAnimationController(scaleAnimation, 0.5f);        controller.setOrder(LayoutAnimationController.ORDER_REVERSE);        linearLayout.setLayoutAnimation(controller);    }}

插值器Interpolators

插值器可以定义动画变换速率,类似于物理中的加速度,主要控制目标变量的变化值进行对应的变化。同样的,一个动画变换起始值,在不同的插值器作用下,每个单位时间内所达到的变化值也是不一样的。

自定义动画

示例1:模拟电视机关闭的图像

public class CustomTv extends Animation{//    缩放的中心点    private int mCenterWidth;    private int mCenterHeight;    private Camera mcamera = new Camera();    private float mRotateY = 0.0f;    @Override    public void initialize(int width, int height, int parentWidth, int parentHeight) {        super.initialize(width, height, parentWidth, parentHeight);//      设置默认时常        setDuration(1000);//        动画结束后保留状态        setFillAfter(true);//        设置默认插值器        setInterpolator(new AccelerateInterpolator());        mCenterWidth = width/2;        mCenterHeight = height/2;    }    public void setRotateY(float rorateY){        mRotateY = rorateY;    }    @Override    protected void applyTransformation(float interpolatedTime, Transformation t) {//        获得矩阵对象        final Matrix matrix = t.getMatrix();//        通过对矩阵的各种操作来实现动效        matrix.preScale(1,1-interpolatedTime,mCenterWidth,mCenterHeight);    }}
使用:

CustomTv customTv = new CustomTv();customTv.setRotateY(30);imgView.startAnimation(customTv);

android5.x SVG(可伸缩矢量图形)矢量动画机制

可伸缩矢量图形(scalable vector graphics)

定义用于网络的基于矢量的图形

使用XML格式定义图形

图像在放大或者改变尺寸的情况下其图形质量不会有所损失

万维网联盟的标准

与诸如dom 和xsl之类的问c标准是一个整体

与传统bitmap相比,svg是一个绘图标准,它放大不会失真,而bitmap需要为不同分辨率设计多套图标,矢量图不需要。

它是通过<path>标签创建svg,这些指令一时没看懂,没信心看下去了。


动画特效

一个点击一个按钮,发散出四个按钮的动画,类似于菜单demo

public class SupriseAnimationActivity extends AppCompatActivity implements View.OnClickListener {    private int[] mRes = {R.id.imageView_a, R.id.imageView_b, R.id.imageView_c, R.id.imageView_d, R.id.imageView_e,};    private List<ImageView> imageViews = new ArrayList<>();    private boolean mFlag = true;    private ImageView imgview;    private TextView text;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_suprise_animation);        initView();    }    private void initView() {        text = ((TextView) findViewById(R.id.tv_texts));        for (int i = 0; i < mRes.length; i++) {            imgview = ((ImageView) findViewById(mRes[i]));            imgview.setOnClickListener(this);            imageViews.add(imgview);        }    }    private void startAnim() {        ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(0), "alpha", 0.5F, 1F);        ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageViews.get(1), "translationY", -100F);        ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageViews.get(2), "translationX", -100F);        ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageViews.get(3), "translationY", 100F);        ObjectAnimator animator4 = ObjectAnimator.ofFloat(imageViews.get(4), "translationX", 100F);        AnimatorSet animatorSet = new AnimatorSet();        animatorSet.setDuration(1000);        animatorSet.setInterpolator(new BounceInterpolator());        animatorSet.playTogether(animator,animator1,animator2,animator3,animator4);        animatorSet.start();        mFlag=false;    }    private void stopAnim() {        ObjectAnimator animator = ObjectAnimator.ofFloat(imageViews.get(0), "alpha", 0.5F, 1F);        ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageViews.get(1), "translationY", 100F, 0);        ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageViews.get(2), "translationX", 100F, 0);        ObjectAnimator animator3 = ObjectAnimator.ofFloat(imageViews.get(3), "translationY", -100F, 0);        ObjectAnimator animator4 = ObjectAnimator.ofFloat(imageViews.get(4), "translationX", -100F, 0);        AnimatorSet animatorSet = new AnimatorSet();        animatorSet.setDuration(1000);        animatorSet.setInterpolator(new BounceInterpolator());        animatorSet.playTogether(animator,animator1,animator2,animator3,animator4);        animatorSet.start();        mFlag=true;    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.imageView_a:                if (mFlag) {                    startAnim();                } else {                    stopAnim();                }                break;            default:                Toast.makeText(getApplicationContext(), view.getId() + "", Toast.LENGTH_LONG).show();                tvTimer(text);                break;        }    }    private void tvTimer(final TextView view){        final ValueAnimator animator = ValueAnimator.ofInt(0,100);        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {            @Override            public void onAnimationUpdate(ValueAnimator valueAnimator) {                view.setText("$"+(Integer)animator.getAnimatedValue());            }        });        animator.setDuration(3000);        animator.start();    }}
布局文件

<?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:id="@+id/activity_suprise_animation"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context="com.lvqueen.qunyinzhuan.day08.SupriseAnimationActivity">    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView_b"        android:src="@mipmap/b"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true" />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView_c"        android:src="@mipmap/c"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true" />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView_d"        android:src="@mipmap/d"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true" />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView_e"        android:src="@mipmap/e"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true" />    <ImageView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:id="@+id/imageView_a"        android:src="@mipmap/a"        android:layout_centerVertical="true"        android:layout_centerHorizontal="true" />    <TextView        android:id="@+id/tv_texts"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="test"/></RelativeLayout>








0 0
原创粉丝点击