zoukankan      html  css  js  c++  java
  • 关于ValueAnimation以及Interpolator +Drawable实现的自己定义动画效果

    ValueAnimation :

    Android中的属性动画,他跟objectAnimation是比补间动画拥有更强大的功能,能够操作对象。所以我们能够在自 定义View中通过他们来实现些特别的功能。

    Interpolator: 

    插值器,通过插值器我们能实现比方反弹。重力加速度。等等的效果。

    Android本来就自带了插值器。加速减速等等。并且在最新的v4包中还加入了几个新的插值器,能够上网搜下,看看不同的插值器的效果。

    Drawable :Drawable这个类是能够用来绘制的类


    通过自己定义Drawable 能够实现非常多不通过的功能:


    由于不是动态图片。看不到实际效果。能够下载Demo自己执行下看看。


    关于自己定义Drawable 的步骤:


    1、用一个类继承Drawable

    2、创建一个ValueAnimator 对象。设置他的各种属性以及加入AnimatorUpdateListener。然后通过他的监听器能够设置你控件的动画效果

    3、创建一个画笔,用来进行绘制你所要绘制的东西

    4、绘制的时候按你的需求来计算要绘制的东西(功能不一样计算方式也不一样)


    看上图第一个控件的实现方式:

    package com.example.modifyprogress;
    
    import android.animation.ValueAnimator;
    import android.animation.ValueAnimator.AnimatorUpdateListener;
    import android.annotation.SuppressLint;
    import android.graphics.Canvas;
    import android.graphics.ColorFilter;
    import android.graphics.Path;
    import android.graphics.Rect;
    import android.graphics.RectF;
    import android.graphics.drawable.Drawable;
    import android.view.animation.Animation;
    import app.dinus.com.loadingdrawable.MaterInterpolator;
    
    
    @SuppressLint("NewApi")
    public class LoadingDrawable extends Drawable{
        private Drawable mDrawable;
        private Path mPath = new Path();
        private float mPercent;
        private ValueAnimator mAnimator;
        public LoadingDrawable(Drawable drawable) {
            this.mDrawable = drawable;
          
            mAnimator = ValueAnimator.ofFloat(0.0f,1.0f);
            mAnimator.setDuration(5000);
            mAnimator.setRepeatCount(Animation.INFINITE);
            mAnimator.setRepeatMode(Animation.REVERSE);
            mAnimator.setInterpolator(MaterInterpolator.createInterpolator().setDefault_Type(MaterInterpolator.BOUNCE));
            mAnimator.addUpdateListener(new AnimatorUpdateListener() {
    			
    			@Override
    			public void onAnimationUpdate(ValueAnimator animation) {
    				
    				if (mPercent < 1) {
    					mPercent += (Float)animation.getAnimatedValue()/100;
    	            } else {
    	            	mPercent = 0;
    	            }
    	           invalidateSelf();
    			}
    		});
            mAnimator.start();
        }
        @Override
        public void draw(Canvas canvas) {
            mPath.reset();
            RectF rect = new RectF(getBounds());
            double radius = Math.pow(Math.pow(rect.right, 2) + Math.pow(rect.bottom, 2), 0.5);
            mPath.moveTo(rect.right / 2, rect.bottom / 2);
            mPath.lineTo(rect.right / 2, 0);
            if (mPercent > 0.125f) {
                mPath.lineTo(rect.right, 0);
            }
            if (mPercent > 0.375f) {
                mPath.lineTo(rect.right, rect.bottom);
            }
            if (mPercent > 0.625f) {
                mPath.lineTo(0, rect.bottom);
            }
            if (mPercent > 0.875f) {
                mPath.lineTo(0, 0);
            }
            mPath.lineTo((float) (rect.right / 2 + radius * Math.sin(Math.PI * 2 * mPercent)),
                    (float) (rect.bottom / 2 - radius * Math.cos(Math.PI * 2 * mPercent)));
            mPath.close();
            if (mPercent >= 0 && mPercent <= 1) {
                canvas.save();
                canvas.clipPath(mPath);
                mDrawable.draw(canvas);
                canvas.restore();
            }
        }
    
        @Override
        public void setAlpha(int alpha) {
            mDrawable.setAlpha(alpha);
        }
    
        @Override
        public int getAlpha() {
            return mDrawable.getAlpha();
        }
    
        @Override
        public void setColorFilter(ColorFilter cf) {
            mDrawable.setColorFilter(cf);
        }
    
    
        @Override
        public int getOpacity() {
            // TODO Auto-generated method stub
            return mDrawable.getOpacity();
        }
    
      
    
        @Override
        protected void onBoundsChange(Rect bounds) {
            mDrawable.setBounds(bounds);
        }
    
        @Override
        public int getIntrinsicHeight() {
            return mDrawable.getIntrinsicHeight();
        }
    
        @Override
        public int getIntrinsicWidth() {
            return mDrawable.getIntrinsicWidth();
        }
    
    
        public void setPercent(float percent) {
            if (percent > 1) {
                percent = 1;
            } else if (percent < 0) {
                percent = 0;
            }
            if (percent != mPercent) {
                this.mPercent = percent;
                invalidateSelf();
            }
        }
    
    }


    我自己自己定义了几个插值动画。关于插值动画的測试能够在:http://inloop.github.io/interpolator/

    package app.dinus.com.loadingdrawable;
    
    
    import android.view.animation.Interpolator;
    /**
     *各种插值器效果
     * @author chenpengfei_d
     *能够去这个网址上看效果: http://inloop.github.io/interpolator/
     */
    public class MaterInterpolator implements Interpolator{
    	private int mDefault_Type = LINEAR;
    	private float interpolatorValue;
    	private static MaterInterpolator mInterpolator;
    	public static  MaterInterpolator createInterpolator(){
    		if (mInterpolator == null) {
    			mInterpolator = new MaterInterpolator();
    		}
    		return mInterpolator;
    	}
    	
    	@Override
    	public float getInterpolation(float input) {
    		
    		switch (mDefault_Type) {
    		case LINEAR: //线性
    			interpolatorValue = input;
    			break;
    		case ACCELERATE: //加速
    			float factor = 1.0f;
    			if (factor == 1.0) {
    				factor = input * input;
    			}else {
    				factor = (float)Math.pow(input, factor *2);
    			}
    			interpolatorValue = factor;
    			break;
    		case ACCELERATEDECELERATE://先加速后减速
    			interpolatorValue = (float) ((Math.cos((input + 1) * Math.PI) /2.0) + 0.5F);
    			break;
    		case ANTICIPATE: 
    			
    			float tension = 2.0f;
    			interpolatorValue = input * input *((tension + 1) * input - tension);
    			break;
    		case ANTICIPATEOVERSHOOT:
    			tension = 2.0f * 1.5f;
    			if (input < 0.5){
    				interpolatorValue = (float) (0.5 * (Math.pow(input * 2.0f, 2) * ((tension + 1) * input  - tension)));
    			}else {
    				interpolatorValue = (float) (0.5 *(Math.pow(((input - 1) * 2.0f), 2) *((tension  + 1) *(input - 1) * 2.0f + tension)));
    			}
    			break;
    		case BOUNCE://反弹
    			if (input < 0.3535) {
    				interpolatorValue =	bounce(input);
    			}else if(input < 0.7408){
    				interpolatorValue = bounce(input - 0.54719f) + 0.7f;
    			}else if (input < 0.9644) {
    				interpolatorValue = bounce(input - 0.8526f) + 0.9f;	
    			}else {
    				interpolatorValue = bounce(input - 1.0435f) + 0.95f;  
    			}
    			break;
    		case CUBICHERMITE:
    			interpolatorValue = CubicHermite(input, 0, 1, 4, 4);
    			break;
    		case CYCLE:
    			float cycles = 1.0f;
    			interpolatorValue = (float)Math.sin(2* cycles *Math.PI *input);
    			break;
    		case DECELERATE://减速
    			float divisor = 1.0f;
    			if (divisor == 1.0) {
    				interpolatorValue = (float) (1.0 - (1.0 - input ) * (1.0 - input));
    			}else {
    				interpolatorValue = (float) (1.0 - Math.pow((1.0 - input), 2 * divisor));
    			}
    			break;
    		case OVERSHOOT:
    			tension = 2.0f;
    			input = input - 1.0f;
    			interpolatorValue = (float) (input *input *((tension  + 1) * input  + tension ) +1.0);
    			break;
    		case SMOOTHSTEP:
    			interpolatorValue = input * input * (3 - 2 *input );
    			break;
    		case SPRING://弹簧效果
    			factor = 0.4f;
    			interpolatorValue = (float) (Math.pow(2,  -10 *input) * Math.sin((input - factor /4) *(2 *Math.PI)/factor ) + 1.0);
    			break;
    		default:
    			break;
    		}
    		
    		
    		return  interpolatorValue;
    	}
    
    
    	private float bounce(float input){	
    		return input *input *8;
    	}
    	private float CubicHermite(float t, int p0,int p1,int m0,int m1){
    		float t2 = t* t;
    		float t3 = t2 * t ;
    		return  (2* t3 - 3 * t2 +1) * p0 + (t3 - 2 * t2 + t) * m0 + (-2 * t3 + 3 * t2) * p1 + (t3 - t2) *m1;
    	}
    	public int getDefault_Type() {
    		return mDefault_Type;
    	}
    	public MaterInterpolator setDefault_Type(int default_Type) {
    		mDefault_Type = default_Type;
    		return mInterpolator;
    	}
    	public static final int LINEAR =0 ;
    	public static final int SMOOTHSTEP = 1;
    	public static final int ACCELERATEDECELERATE = 2;
    	public static final int BOUNCE = 3;
    	public static final int ACCELERATE = 4;
    	public static final int ANTICIPATEOVERSHOOT = 5;
    	public static final int CYCLE = 6;
    	public static final int ANTICIPATE = 7;
    	public static final int DECELERATE = 8;
    	public static final int OVERSHOOT = 9;
    	public static final int CUBICHERMITE = 10;
    	public static final int SPRING = 11;
    	public  enum MaterInterPolatorType{
    		LINEAR,SMOOTHSTEP,SPRING,CUBICHERMITE,OVERSHOOT,DECELERATE,ANTICIPATE,CYCLE,ANTICIPATEOVERSHOOT
    		,ACCELERATE,BOUNCE,ACCELERATEDECELERATE
    	}
    }


    还有其它的效果能够看代码里边。下载执行就好,效果还不错,个人感觉。


    Demo:http://download.csdn.net/detail/u012808234/9498353




  • 相关阅读:
    区分浏览器的刷新与关闭(网上查到,记录一下)
    echarts中设置markPoint
    Vue自定义指令,ref ,sync,slot
    手动封装on,emit,off
    数组的一些操作
    ES6-字符串扩展-padStart(),padEnd()
    MongoDB 数据库
    新地方
    使用echarts踩过的一些坑
    IE无法访问vue项目
  • 原文地址:https://www.cnblogs.com/zhchoutai/p/8448185.html
Copyright © 2011-2022 走看看