一个揭露动画的的折线图

就是上面的这个折线图,加载的时候有揭露动画,gif图就不录制了,直接上代码,代码注释写的很详细了,自定义属性没有加,为了方便直接拿来用

package com.oneweone.momocamera.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by fanday on 2017/11/1.
 */

public class LineChart extends View {

    //圆点的数据
    private float[] dots = {1.2f,2.4f,3.2f,0.9f,1.1f,2.3f,4.0f};
    //数据对应的日期
    private String[] days = {"21","22","23","24","25","26","27"};
    //圆点的半径
    private float circleRadius = 12f;
    //每段线在x轴上的投影
    private float lineLen = 0f;
    //y轴对应的分度值
    private float hAverage = 0f;
    //下方文字的总高度
    private float textHeight = 60;
    public LineChart(Context context) {
        this(context,null,0);
    }

    public LineChart(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public LineChart(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private Paint paint;
    private Paint bgPaint;
    private Paint circlePaint;
    private Paint vLinePaint;
    private Paint textPaint;
    //距离最左边的偏移量  防止圆点和文字过于靠左
    private float xOffset = 20;
    //初始化各种画笔
    private void init() {
        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(4);

        bgPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        bgPaint.setColor(Color.GRAY);
        bgPaint.setStyle(Paint.Style.FILL);
        bgPaint.setStrokeWidth(0.0f);

        circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        circlePaint.setColor(Color.WHITE);
        circlePaint.setStyle(Paint.Style.FILL);
        circlePaint.setStrokeWidth(0.0f);

        vLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        vLinePaint.setColor(Color.RED);
        vLinePaint.setStyle(Paint.Style.STROKE);
        vLinePaint.setStrokeWidth(2.0f);


        textPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        textPaint.setColor(Color.BLACK);
        textPaint.setStyle(Paint.Style.STROKE);
        textPaint.setTextSize(30);
        textPaint.setStrokeWidth(2.0f);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        lineLen = (w - dots.length*2*circleRadius-circleRadius-xOffset)*1.0f/6;
        float maxH = getMaxHPoint();
        hAverage = (h-circleRadius-textHeight-2)*1.0f/maxH;
    }

    /**
     * 拿到数据中的最大值  以便于计算y轴的分度值
     * @return
     */
    private float getMaxHPoint() {
        float max = 0f;
        for (Float f :dots){
            max = max>f?max:f;
        }
        return max;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //画垂直x轴的线段
        drawVLine(canvas);
        //画折线图
        drawChart(canvas);
        //画日期文字
        drawText(canvas);


    }

    private void drawText(Canvas canvas) {
        for (int i = 0;i<dots.length;i++){
            float x = 2*circleRadius*i+lineLen*i+circleRadius;
            float y = getHeight()-textHeight/2;
            canvas.drawText(days[i],x,y,textPaint);
        }
    }

    private void drawVLine(Canvas canvas) {
        for (int i = 0;i<dots.length;i++){
            float y = getHeight() - textHeight;
            float x = 2*circleRadius*i+lineLen*i+circleRadius+xOffset;
            canvas.drawLine(x,0,x,y,vLinePaint);
        }
    }


    private void drawChart(Canvas canvas) {
        //画布平移缩放,调整坐标原点
        canvas.save();
        canvas.translate(0,getHeight());
        canvas.scale(1,-1);
        //画布裁剪实现折线图动画
        canvas.clipRect(0,getHeight(),clipWidth,0);
        //背景path
        canvas.drawPath(getBGPath(),bgPaint);
        //折线图path
        canvas.drawPath(getPath(),paint);
        //折线图圆点填充颜色重置
        canvas.drawPath(getCirclePath(),circlePaint);
        //折线图圆点边线重置
        canvas.drawPath(getCirclePath(),paint);
        canvas.restore();
    }

    private float clipWidth;


    public void anim(){
        this.postDelayed(new Runnable() {
            @Override
            public void run() {
                start();
            }
        },100);
    }

    public void start(){
        float width = getWidth();
        ValueAnimator va = ValueAnimator.ofFloat(0,width);
        va.setDuration(2000);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                clipWidth = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        va.start();
    }

    private Path getPath() {
        Path path = new Path();
        for (int i = 0;i<dots.length;i++){
            float y = dots[i]*hAverage+textHeight;
            float x = 2*circleRadius*i+lineLen*i+circleRadius+xOffset;
            if(i==0)
                path.moveTo(x,y);
            path.lineTo(x,y);
        }
        return path;
    }
    private Path getCirclePath() {
        Path path = new Path();
        for (int i = 0;i<dots.length;i++){
            float cy = dots[i]*hAverage+textHeight;
            float cx = 2*circleRadius*i+lineLen*i+circleRadius+xOffset;
            path.addCircle(cx,cy,circleRadius,Path.Direction.CW);
        }
        return path;
    }
    private Path getBGPath() {
        Path path = new Path();
        float y = 0f;
        float x = 0f;
        for (int i = 0;i<dots.length;i++){
            y = dots[i]*hAverage+textHeight;
            x = 2*circleRadius*i+lineLen*i+circleRadius+xOffset;
            if(i==0)
                path.moveTo(x,textHeight);
            path.lineTo(x,y);
        }
        path.lineTo(x,y);
        path.lineTo(x,textHeight);
        path.close();
        return path;
    }


}

复制之后就可以用了,布局文件
    <com.oneweone.momocamera.widget.LineChart
        android:layout_width="260dp"
        android:id="@+id/line"
        android:layout_height="140dp" />
代码中调用

        LineChart view = (LineChart) findViewById(R.id.line);
        view.anim();

再贴上仪表盘的代码
package com.oneweone.momocamera.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;

/**
 * Created by fanday on 2017/11/2.
 */

public class CompassView extends View {
    public CompassView(Context context) {
        super(context);
        init();
    }

    public CompassView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public CompassView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private Paint dashPaint;
    private Paint outerPaint;
    private Paint grayDashPaint;
    private Paint grayOuterPaint;
    private Paint pointPaint;
    //边缘的距离  防止绘制圆球超出
    private float outOffset = 20f;
    //两个圆弧之间的距离
    private float outInnerOffset = 40f;
    //当前的动画加载到的角度
    private float currentRadius = 120f;
    //小圆点的半径
    private float circleRadius = 15f;
    //内圆弧的宽度
    private float innerPaintWidth = 6.0f;
    //外圆弧的宽度
    private float outerPaintWidth = 8.0f;
    //内指示器的宽度
    private float pointPaintWidth = 2f;
    private void init() {
        dashPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        dashPaint.setColor(Color.WHITE);
        dashPaint.setStyle(Paint.Style.STROKE);
        dashPaint.setStrokeWidth(innerPaintWidth);
        dashPaint.setPathEffect(new DashPathEffect(new float[] {15, 15}, 0));

        outerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        outerPaint.setColor(Color.WHITE);
        outerPaint.setStyle(Paint.Style.STROKE);
        outerPaint.setStrokeWidth(outerPaintWidth);

        grayDashPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        grayDashPaint.setColor(Color.GRAY);
        grayDashPaint.setStyle(Paint.Style.STROKE);
        grayDashPaint.setStrokeWidth(innerPaintWidth);
        grayDashPaint.setPathEffect(new DashPathEffect(new float[] {15, 15}, 0));

        grayOuterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        grayOuterPaint.setColor(Color.GRAY);
        grayOuterPaint.setStyle(Paint.Style.STROKE);
        grayOuterPaint.setStrokeWidth(outerPaintWidth);

        pointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        pointPaint.setColor(Color.WHITE);
        pointPaint.setStyle(Paint.Style.FILL);
        pointPaint.setStrokeWidth(pointPaintWidth);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //关闭硬件加速
        setLayerType(LAYER_TYPE_SOFTWARE, null);
        drawCircle(canvas);
        drawPoint(canvas);
    }


    private void drawPoint(Canvas canvas) {
        //旋转画布让指示器和和圆点始终在y轴上面
        canvas.save();
        canvas.translate(getWidth()/2,getHeight()/2);
        canvas.rotate(60f,0,0);
        canvas.rotate(currentRadius,0,0);
        float cx = 0;
        float cy = getWidth()/2-outOffset-4;
        canvas.drawCircle(cx,cy,circleRadius,pointPaint);

        float y1 = getWidth()/2-outOffset-outInnerOffset-outerPaintWidth-innerPaintWidth-5;
        float y2 = getWidth()/2-outOffset-outInnerOffset-outerPaintWidth-innerPaintWidth-55;
        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStrokeWidth(14);
        paint.setColor(Color.WHITE);

        canvas.drawLine(0,y1,0,y2,paint);
        canvas.restore();
    }

    private void drawCircle(Canvas canvas) {
        RectF rect = new RectF(outOffset+outInnerOffset,outOffset+outInnerOffset,
                getWidth()-outOffset-outInnerOffset,getHeight()-outOffset-outInnerOffset);
        RectF outRect = new RectF(outOffset,outOffset,getWidth()-outOffset,
                getHeight()-outOffset);

        //灰色带圆弧
        canvas.drawArc(rect,-210,240f,false,grayDashPaint);
        canvas.drawArc(outRect,-210,240,false,grayOuterPaint);


        //动画控制的
        canvas.drawArc(rect,-210,currentRadius,false,dashPaint);
        canvas.drawArc(outRect,-210,currentRadius,false,outerPaint);
    }

    public void start(){
        ValueAnimator va = ValueAnimator.ofFloat(0,180);
        va.setDuration(2000);
        va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                currentRadius = (float) animation.getAnimatedValue();
                invalidate();
            }
        });
        va.start();
    }
}

布局使用

    <com.oneweone.momocamera.widget.CompassView
        android:visibility="gone"
        android:layout_width="200dp"
        android:id="@+id/compass"
        android:layout_height="200dp" />
代码中启动

        final CompassView campassView = (CompassView) findViewById(R.id.compass);
        campassView.postDelayed(new Runnable() {
            @Override
            public void run() {
                campassView.start();
            }
        },100);



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值