实现自定义动画

1.画波浪线

-使用的全局变量

public class PrgsView extends View {
    //private Paint paint;
    //private Paint textPaint;
    private Paint mPaint;
    private Path mpath;
    private int speed;
    float density=getResources().getDisplayMetrics().density;//屏幕密度
    private int waveLength= (int) (100*density);//波长
    private int waveCrest= (int) (50*density);//波峰
    private int lineColor=Color.BLACK;//线条颜色
    private int lineSize=10;//线条尺寸
    private ValueAnimator va;

1.1创建一个类继承与View并且实现它的两个方法

public class PrgsView extends View {
public PrgsView(Context context) {
        super(context);
        init();
    }
    public PrgsView(Context context, AttributeSet attrs) {
        super(context,attrs);
        //从xml中获取自定义属性的值
        initAttr(context,attrs);
        //初始化画笔
        init();
    }

1.2创建一个init方法用于画笔的实现并且作为全局变量

 private void init(){
        //1.1
        mPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(lineColor);
        mPaint.setStrokeWidth(lineSize);
        mPaint.setStyle(Paint.Style.STROKE);
    }

1.3创建一个startWave开始动画和暂停动画stopWave方法

//4.1开始动画
    private void startWave(){
        va=ValueAnimator.ofInt(0,waveLength);
        va.setDuration(500);
        va.setRepeatCount(ValueAnimator.INFINITE);
        va.setRepeatMode(ValueAnimator.RESTART);
        va.setInterpolator(new LinearInterpolator());//匀速
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                //获取当前值
                speed=(int)valueAnimator.getAnimatedValue();
                //刷新
                invalidate();
            }
        });
        va.start();
    }
//4.2暂停动画
    public void stopWave(){
        if (va!=null) {
            va.cancel();
        }
    }

1.4创建一个onSizeChanged的方法用于动画的开始

@Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);

        //开始动画
        startWave();
    }

1.5在xml里面创建一个容器


1.6创建画布onDraw方法和线条的实现方法initPath

//3.1
    @Override
    protected void onDraw(Canvas canvas) {
        initPath();
        canvas.drawPath(mpath,mPaint);
    }
    //3.2
    private void initPath(){
        //3..2.1创建曲线
        mpath=new Path();
        //3.2.3计算有多少个周期(有几个完整的波)
        int count=getWidth()/waveLength;
        //3.2.2设置起始点  距离x左边的一个波长
        mpath.moveTo(-waveLength+speed,getHeight()/2);
        //3.2.4获取垂直中心的坐标
        int centerY= (int) getPivotY();
        //3.2.5确定曲线的路径
        for(int start=-waveLength+speed;start

1.7实现波浪的粗细,波峰,线条的颜色,和大小的set方法

//5.
    public void setWaveLength(int waveLength) {
        this.waveLength = waveLength;
    }

    public void setWaveCrest(int waveCrest) {
        this.waveCrest = waveCrest;
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
        mPaint.setColor(lineColor);
    }

    public void setLineSize(int lineSize) {
        this.lineSize = lineSize;
        mPaint.setStrokeWidth(lineSize);
    }

1.8定义一个initAttr方法实现自定义属性

private void initAttr(Context context,AttributeSet attrs){
        //读取所有自定义属性的值
        TypedArray array=context.obtainStyledAttributes(attrs,R.styleable.PrgsView);
        //读取每一个属性的值
        waveLength=array.getInteger(R.styleable.PrgsView_WaveLength,(int)(100*density));
        waveCrest=array.getInteger(R.styleable.PrgsView_WaveCrest,(int)(50*density));
        lineColor=array.getInteger(R.styleable.PrgsView_LineColor,Color.BLACK);
        lineSize=array.getInteger(R.styleable.PrgsView_LineSize,10);
    }

2.画圆和文本

使用到的全局变量

 private Paint circlePaint;
    private Paint textPaint;
    private int lineSize=10;
    private int textSize=50;
    private int textColor=Color.BLACK;
    private int lineColor=Color.BLACK;
    private float prograss;//进度
    private int centerSpaceY;//和中心线的距离

2.1创建一个类继承与View并且实现它的两个方法

public class CircleView extends View {
public CircleView(Context context) {
        super(context);
        init();
    }
    public CircleView(Context context, AttributeSet attrs){
        super(context,attrs);
        init();
    }

2.2创建一个init方法实现画笔

private void init(){
        circlePaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(lineColor);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(lineSize);

        textPaint=new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(textColor);
        textPaint.setTextSize(textSize);
    }

2.3实现一个onDraw方法实现画布的功能

 @Override
    protected void onDraw(Canvas canvas) {
        //确定半径
        int radius=Math.min(getWidth(),getHeight()/2-lineSize);
        //画圆
        canvas.drawCircle(getPivotX(),getPivotY(),radius,circlePaint);
        //画文本
        String text=(int)(prograss*100)+"%";
        //计算文本宽度
        int width= (int) textPaint.measureText(text);
        //获取文字矩阵
        Paint.FontMetricsInt fo=textPaint.getFontMetricsInt();
        //计算向下移动的距离
        int space=-fo.ascent/2;
        canvas.drawText(text,getPivotX()-width/2,getPivotY()+space+centerSpaceY,textPaint);
    }

2.4在xml文件里面配置一个容器


2.5实现线条的粗细和颜色,文本的大小和颜色以及进度的set方法

 public void setLineSize(int lineSize) {
        this.lineSize = lineSize;
        circlePaint.setStrokeWidth(lineSize);
    }

    public void setLineColor(int lineColor) {
        this.lineColor = lineColor;
        circlePaint.setColor(lineColor);
    }

    public void setTextColor(int textColor) {
        this.textColor = textColor;
        textPaint.setColor(textColor);
    }

    public void setTextSize(int textSize) {
        this.textSize = textSize;
        textPaint.setTextSize(textSize);
    }

    public float getPrograss() {
        return prograss;
    }

    public void setPrograss(float prograss) {
        this.prograss = prograss;
        //重新绘制/刷新
        invalidate();
    }

    public void setCenterSpaceY(int centerSpaceY) {
        this.centerSpaceY = centerSpaceY;

    }
}

3.自定义动画的组合实现

使用到的全局变量

private float progress;//进度
    private CircleView cv;//进度 圆圈视图
    private PrgsView wave;//波浪视图

3.1创建一个新的类继承与ViewGroup实现它的两个方法

public class WaveLodingView extends ViewGroup {
public WaveLodingView(Context context){
        super(context);
    }
    public WaveLodingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

3.2使用onMesure来进行测量

 //1.
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

3.3使用onSizeChanged来改变尺寸

//2.
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
    }

3.4在类提供的这个onLayout方法里面实现需要的结果

@Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        //创建CircleView
        cv=new CircleView(getContext());
        cv.setLineColor(Color.RED);
        cv.setLineSize(20);
        cv.setTextColor(Color.RED);
        cv.setCenterSpaceY(-100);
        //对子视图进行布局
        cv.layout(0,0,getWidth(),getHeight());
        //将子视图添加到容器中
        addView(cv);
        //创建PrgsView
        wave=new PrgsView(getContext());
        wave.setWaveCrest(30);
        wave.setWaveLength(100);
        wave.setLineSize(5);
        wave.setLineColor(Color.YELLOW);
        //布局
        wave.layout(getWidth()/4,getHeight()/2-30,getWidth()*3/4,getHeight()/2+30);
        //添加
        addView(wave);
    }

3.5在xml里面设置一个容器并且设置它的id号


3.6实现进度的get和set方法

public float getProgress() {
        return progress;
    }

    public void setProgress(float progress) {
        this.progress = progress;
        //改变CircleView的进度值
        if (progress<1.01) {
            cv.setPrograss(progress);
        }
        //暂停动画
        if ((int)progress==1){
            wave.stopWave();
        }
    }

3.7在Manactivity里面实现点击事件

public class MainActivity extends AppCompatActivity {
    WaveLodingView lodingView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lodingView=findViewById(R.id.load);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
       /* MeterView mv=findViewById(R.id.meter);
        if (event.getAction()==MotionEvent.ACTION_DOWN){
            //更改角度值:在原有的进度上+0.05
            mv.setProgress((float) (mv.getProgress()+0.05));
        }*/
       if (event.getAction()==MotionEvent.ACTION_DOWN){
           new Timer().schedule(new TimerTask() {
               @Override
               public void run() {
                   runOnUiThread(new Runnable() {
                       @Override
                       public void run() {
                           lodingView.setProgress((float) (lodingView.getProgress()+0.01));
                       }
                   });
               }
           },0,100);
       }
        return true;
    }
}

4.最终结果

1572698001918.gif

你可能感兴趣的:(实现自定义动画)