进度绘制

进度绘制_第1张图片

这是效果图,自己加了一个渐变的颜色,模仿鸿神做的,自己试了一下,做个笔记。鸿神的文章: Android 自定义View (四) 视频音量调控

当然鸿神里边我认为有一点儿小问题,就是那个mSplitSize我认为应该变换成角度。

自己不做不知道,做的时候还是发现了一些问题,何况多练习一下比较好,比如说那个角度的问题,比如说那个绘制渐变时的问题,只有自己实验了才知道问题。。。

代码如下:

package com.shj.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import com.shj.test.R;


public class CircleVolumeView extends View {
    private int firstColor;
    private int secondColor;
    private int dotCount;
    private int circleWidth;
    private int splitSize;
    private Bitmap mImage;
    private Paint mPaint;
    private Paint gradientPaint;
    private Rect mRect;
    private int mCurrentCount = 4;
    private Matrix matrix;
    int downY = 0;//摁下时Y坐标
    int lastY = 0;//离开屏幕时Y坐标

    public CircleVolumeView(Context context) {
        this(context, null);
    }

    public CircleVolumeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CircleVolumeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initAttrs(context, attrs);
        mPaint = new Paint();
        gradientPaint = new Paint();
        mRect = new Rect();
        matrix = new Matrix();

    }

    /**
     * 一些属性的初始化
     * @param context
     * @param attrs
     */
    private void initAttrs(Context context, AttributeSet attrs) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircleVolumeView);
        firstColor = a.getColor(R.styleable.CircleVolumeView_firstCorlor, Color.parseColor("#dddddd"));
        secondColor = a.getColor(R.styleable.CircleVolumeView_secondColor, Color.parseColor("#00ff00"));
        dotCount = a.getInt(R.styleable.CircleVolumeView_dotCount, 8);
        circleWidth = a.getDimensionPixelSize(R.styleable.CircleVolumeView_circleWidth, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, getResources().getDisplayMetrics()));
        splitSize = a.getDimensionPixelSize(R.styleable.CircleVolumeView_splitSize, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 20, getResources().getDisplayMetrics()));
        mImage = BitmapFactory.decodeResource(getResources(), a.getResourceId(R.styleable.CircleVolumeView_middleImg, R.mipmap.ic_launcher));
        a.recycle();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downY = y;
                break;
            case MotionEvent.ACTION_UP:
                lastY = y;
                if ((lastY - downY) > 50 && (mCurrentCount > 0)) {//一点点小判断
                    mCurrentCount--;
                    postInvalidate();
                } else if((lastY - downY) < -50 && (mCurrentCount < dotCount)) {
                    mCurrentCount++;
                    postInvalidate();
                }
                break;
        }
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(circleWidth);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        mPaint.setStyle(Paint.Style.STROKE);
        gradientPaint.setAntiAlias(true);
        gradientPaint.setStrokeWidth(circleWidth);
        gradientPaint.setStrokeCap(Paint.Cap.ROUND);
        gradientPaint.setStyle(Paint.Style.STROKE);
        int center = getWidth() / 2;
        int radius = center - circleWidth / 2;
        drawOval(canvas, center, radius);

        /**
         * 这块是计算图片摆放位置内切圆的算法,看大神写的算法的时候,也有点儿郁闷,其实这个不用看
         * 自己一画就知道了,鸿神的只是化解了。
         */
        int includeRadius = center - circleWidth;
        mRect.left = (int) (circleWidth + (includeRadius - Math.sqrt(2) * 1.0f / 2 * includeRadius));
        mRect.top = (int) (circleWidth + (includeRadius - Math.sqrt(2) * 1.0f / 2 * includeRadius));
        mRect.right = (int) (getWidth() / 2 + Math.sqrt(2) * 1.0f / 2 * includeRadius);
        mRect.bottom = (int) (getWidth() / 2 + Math.sqrt(2) * 1.0f / 2 * includeRadius);
        canvas.drawBitmap(mImage, null, mRect, mPaint);
    }

    private void drawOval(Canvas canvas, int center, int radius) {
        float spliteDegree = (float) (splitSize * 360 * 1.0f / (2 * radius * Math.PI));//间隔的角度
        float itemSize = (360 * 1.0f - spliteDegree * dotCount) / dotCount;//绘制的角度
        RectF oval = new RectF(center - radius, center - radius, center + radius, center + radius);
        //绘制外边的圆
        mPaint.setColor(firstColor);
        for (int i = 0; i < dotCount; i++) {
            canvas.drawArc(oval, (i * (itemSize + spliteDegree)), itemSize, false, mPaint);
        }

        SweepGradient sweepGradient = new SweepGradient(center, center, new int[]{Color.BLUE, Color.GREEN, Color.RED}, null);//着色器
        matrix.setRotate(-5, center, center);//这个-5的角度偏移量时因为使用的 Paint.Cap.ROUND 时,两边会出现突出的圆弧,不知道有没有准确计算偏移量的算法,这里的-5是个大概的值
        sweepGradient.setLocalMatrix(matrix);
        gradientPaint.setShader(sweepGradient);//为什么要用两个画笔,因为绘制的渐变,不适用两个画笔的话,这个渐变开始的时候就会被绘制完全,是一个完整的渐变环形,无论时多少的进度
        for (int i = 0; i < mCurrentCount; i++) {
            canvas.drawArc(oval, (i * (itemSize + spliteDegree)), itemSize, false, gradientPaint);
        }

    }
}



你可能感兴趣的:(android)