Android的学习与实践11(波浪线与进度的结合,利用图片来进行“加载”的实现)

1 收获

说实话今天没有多少的新知识点,但是今天做的东西是在昨天做的东西之上又实现了一些功能,昨天最后的波浪时静态的,而今天我们将昨天做的最后一个静态的波浪线是实现了动态,就在这里我们又重复用到了昨天学到的知识和以前学过的知识,包括自定义属性,ObjectAnimator,ValueAnimator,RotateAnimation三种动画,这又给我们进行复习的机会,说实话我对于这些动画没有了多大印象,除了ValueAnimator因为昨天才学的,今天他们又出现在了我的眼前,我一定要好好的把握住他们,不让他们从我的手指间跑掉。这周又这样结束了,时间转瞬即逝,好好珍惜眼下吧!!!

2.技术

(1)ValueAnimator动画实现波浪线的动画
(2)利用画笔绘制体格圆形和文本
(3)利用继承ViewGroup实现布局和一些动画的组合
(4)利用ValueAnimator和RotateAnimation实现加载动画

3.技术实践及其应用

(1)ValueAnimator动画实现波浪线的动画
在利用ValueAnimator动画实现波浪线的动画之前为我们必须要做一些准备工作
设置一些私有变量以及写出它们对应的构造方法,有利于外部对他们进行设置

private ValueAnimator va;//动画
    private Paint paint;//画笔
    private Path path;//路径

    float density=getResources().getDisplayMetrics().density;//密度
    private int wavelength= (int) (100*density);//波长
    private int wavecrest= (int) (100*density);//波峰

    private int speed;//变化动画的速度

    private int lineColor=Color.BLACK;//线条颜色
    private int linesize=20 ;//线条粗细

构造方法

  //通过set方法来实现外部对属性值的设置
    public void setWavelength(int wavelength) {
        this.wavelength = wavelength;
    }

    public void setWavecrest(int wavecrest) {
        this.wavecrest = wavecrest;
    }

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

    public void setLinesize(int linesize) {
        this.linesize = linesize;
        paint.setStrokeWidth(linesize);
    }

接下来就是在外部的设置(通过自定义属性)
首先我们先要自定义属性


image.png

image.png

我们属性定义完后我们可以在xml中进行设置值


当外部传来值时,内部就要进行对值进行处理

private void initAttr(Context context, AttributeSet attrs){
        //读取所有自定义属性的值
        TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.Waveview);
        //读取每一个属性的值
        wavelength=typedArray.getInteger(R.styleable.Waveview_wavelength, (int) (100*density));
        wavecrest=typedArray.getInteger(R.styleable.Waveview_wavecrest,(int) (100*density));
        linesize=typedArray.getInteger(R.styleable.Waveview_linesize,10);
        lineColor=typedArray.getInteger(R.styleable.Waveview_linecolor,Color.BLACK);
    }

接下来就是进行绘制图形了,首先我们还是要进行对画笔进行初始化

 private void inite(){
        paint=new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(lineColor);
        paint.setStrokeWidth(linesize);
        paint.setStyle(Paint.Style.STROKE);
    }

由于这个绘制的图形并不是规则的,所以我们要明确绘制的路径,我们要对路径进行初始化

private void initpath() {
        //创造曲线
        path=new Path();
        //计算多少个周期(有几个完整的波)
        int count=getWidth()/wavelength;
        //移动设置起始点 距离x左边的一个波长
        path.moveTo(-wavelength+speed,getHeight()/2);
        //获取中心的坐标
        int ceterY= (int) getPivotY();
        //却确定曲线的路径
        for(int start=-wavelength+speed;start

现在笔有了,路径有了,接下来我们就是进行绘制了

@Override
    protected void onDraw(Canvas canvas) {
        //开始绘制
        initpath();
        canvas.drawPath(path,paint);
    }

但是当我们运行后发现这个波浪时静态的,所以我们想到用一个动画来实现

//开始动画
    public void startWave(){
        va=ValueAnimator.ofInt(0,wavelength);
        va.setDuration(400);//动画间隔时间
        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();//开始动画
    }

但是我们又发现当我们我们进度满后,动画并没有结束,所以我们写了一一个专门用来结束动画的函数

 //暂停动画
    public void stopWave(){
        if(va!=null){
            va.cancel();
        }
    

效果:

录制_2019_10_28_00_00_24_864.gif

(2)利用画笔绘制体格圆形和文本
在这里并没有什么新的知识和技术,都是在昨天的讲过的,不知道的可以看上一篇推文,那片推文中有详细的介绍。
首先我们还是要一些我们需要的属性以及他们的set方法,方便外部对这些属性进行设置值

Paint circlepaint;//画圆的画笔
    Paint textcircle;//绘制文本的画笔
    private int centerYSpace;//和中心线的距离
    private int linesize=20;//线条粗细
    private int linecolor=Color.BLACK;//线条颜色
    private int textcolor=Color.BLACK;//文本颜色
    private int textsize=50;//文本大小

    private float progress;//进度

set方法

ublic 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;
        textcircle.setColor(textcolor);
    }

    public void setTextsize(int textsize) {
        this.textsize = textsize;
        textcircle.setTextSize(textsize);
    }

    public void setProgress(float progress) {
        this.progress = progress;
        //刷新
        invalidate();
    }

    public void setCenterYSpace(int centerYSpace) {
        this.centerYSpace = centerYSpace;
    }

然后对两种画笔进行初始化

 private void inite() {
        circlepaint=new Paint(Paint.ANTI_ALIAS_FLAG);//创建画笔
        circlepaint.setStrokeWidth(linesize);//画笔的粗细
        circlepaint.setColor(linecolor);//画笔的颜色
        circlepaint.setStyle(Paint.Style.STROKE);//画笔的风格(空心,实心)

        textcircle=new Paint(Paint.ANTI_ALIAS_FLAG);//创建画笔
        textcircle.setStyle(Paint.Style.FILL);//画笔的风格(空心,实心)
        textcircle.setColor(textcolor);//画笔的颜色
        textcircle.setTextSize(textsize);//画笔的粗细

    }

在onDraw方法中进行一些位置的设置,然后开始进行绘制

protected void onDraw(Canvas canvas) {
        //确定半径
        int radius=Math.min(getWidth(),getHeight());
        //画圆
        canvas.drawCircle(getPivotX(),getPivotX(),radius/2-linesize,circlepaint);
        //画文本
        String text=(int)(progress*100)+"%";
        //计算文本宽度
        int width= (int) textcircle.measureText(text);
        //获取文字矩阵fontMetrics
        Paint.FontMetricsInt fm=textcircle.getFontMetricsInt();
        //开始绘制
        canvas.drawText(text,getPivotX()-width/2,getPivotY()+(-fm.ascent)/2+centerYSpace,textcircle);
    }

效果:

image.png

(3)利用继承ViewGroup实现布局和一些动画的组合
首先我们要先创建一个类,这个类继承于ViewGroup
image.png

image.png

创建后我们要实现ViewGroup里面的抽象方法
和自己的构造方法(得到外部给自己的值)

//抽象方法
 @Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
   
    }
//构造方法
 public WaveLoadingView(Context context) {
        super(context);
    }

    public WaveLoadingView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
public float getProgress() {
        return progress;
    }

然后我们需要创建两个视图类(动画)的对象和一个进度属性

 private Waveview wv;
    private float progress;
    private cricleview cv;

我们要实现具体类的,对类的属性进行设置以及实现具体的布局
所以我们要在 onLayout() 抽象方法中去实现。

@Override
    protected void onLayout(boolean b, int i, int i1, int i2, int i3) {
        //创建原视图
        cv=new cricleview(getContext());
        cv.setLinecolor(Color.RED);
        cv.setLinesize(50);
        cv.setTextcolor(Color.RED);
        cv.setTextsize(60);
        cv.setCenterYSpace(-50);
        //对子视图进行布局
        cv.layout(0,0,getWidth(),getHeight());
        //将子视图添加到容器中
        addView(cv);

        //创建Waveview
        wv=new Waveview(getContext());
        wv.setLineColor(Color.RED);
        wv.setLinesize(5);
        wv.setWavecrest(30);
        wv.setWavelength(100);
        //布局
        wv.layout(getWidth()/4,getHeight()/2-30,getWidth()*3/4,getHeight()+30);
        //添加视图
        addView(wv);
    }

效果:


录制_2019_10_28_13_04_44_375.gif

(4)利用ValueAnimator和RotateAnimation实现加载动画
首先我们需要两张图片,我们将看两张图片引到在

image.png

然后我们对两张图片添加到容器中去

private void inite() {
        ImageView inner=new ImageView(getContext());
        inner.setImageResource(R.drawable.m);
        addView(inner);

        outer=new ImageView(getContext());
        outer.setImageResource(R.drawable.y);
        addView(outer);
    }

然后我们对里面的图片进行设置动画(两种方式ValueAnimator和RotateAnimation)

 @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        /*
        RotateAnimation ra=new RotateAnimation(0,720,outer.getPivotX(),outer.getPivotY());
        ra.setDuration(300);
        ra.setRepeatCount(Animation.INFINITE);
        ra.setRepeatMode(Animation.RESTART);
        ra.setInterpolator(new LinearInterpolator());
        outer.startAnimation(ra);
        */
        ObjectAnimator oa=ObjectAnimator.ofFloat(outer,"rotation",0,360);
        oa.setDuration(1000);
        oa.setRepeatMode(ObjectAnimator.RESTART);
        oa.setRepeatCount(ObjectAnimator.INFINITE);
        oa.setInterpolator(new LinearInterpolator());
        oa.start();
    }

效果:


录制_2019_10_28_00_40_45_649.gif

你可能感兴趣的:(Android的学习与实践11(波浪线与进度的结合,利用图片来进行“加载”的实现))