美文网首页Android自定义View
Android自定义View七(复习基本图形的绘制)

Android自定义View七(复习基本图形的绘制)

作者: 赫丹 | 来源:发表于2017-03-17 11:47 被阅读174次

    基本图形的绘制

    
    public class CanvasLearn extends View {
        private Paint mPaint;
    
        public CanvasLearn(Context context) {
            this(context, null);
        }
    
        public CanvasLearn(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CanvasLearn(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initPaint();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            setCanvasColor(canvas);
    //        drawPoint(canvas);
    //        drawLine(canvas);
    //        drawRectOrRectF(canvas);
    //        drawRoundRect(canvas);
    //        drawOval( canvas);
    //        drawCircle(canvas);
    //        drawAre(canvas);
        }
    
        /**
         * 1、初始化画笔
         */
        private void initPaint() {
            mPaint = new Paint();
            mPaint.setStrokeWidth(10);//设置画笔宽度
            mPaint.setColor(Color.RED);//设置画笔颜色
            mPaint.setStyle(Paint.Style.FILL);//设置画布类型(Fill填充STROKE扫边 FILL_AND_STROKE填充和扫边)
    
        }
    
        /**
         * 2、设置画布颜色
         */
        private void setCanvasColor(Canvas canvas) {
            canvas.drawColor(Color.WHITE);
        }
    
        /**
         * 3、绘制点及多个点
         */
        private void drawPoint(Canvas canvas) {
            mPaint.setStrokeCap(Paint.Cap.ROUND);//设置圆角触笔是点变成圆点
            mPaint.setColor(Color.BLUE);
            canvas.drawPoint(100, 100, mPaint);//绘制一个点
            mPaint.setColor(Color.GREEN);//设置画笔颜色区分
            canvas.drawPoints(new float[]{500, 200, 500, 400, 500, 600}, mPaint);//根据多个坐标绘制多个点
        }
    
        /**
         * 4、绘制直线及多个线段
         */
        private void drawLine(Canvas canvas) {
            mPaint.setColor(Color.BLUE);
            canvas.drawLine(100, 100, 300, 100, mPaint);//绘制一条线段(参数是其实点到x、y轴坐标到结束到x、y轴坐标)
            mPaint.setColor(Color.GREEN);//设置画笔颜色区分
            canvas.drawLines(new float[]{200, 200, 300, 200, 200, 400, 500, 400}, mPaint);
        }
    
        /**
         * 5、绘制矩形
         * Rect与RectF的区别是精度不同,Rect是int型,Rect是float型
         */
        private void drawRectOrRectF(Canvas canvas) {
            //第一种
            canvas.drawRect(100, 100, 800, 200, mPaint);
            //第二种
            Rect rect = new Rect(100, 300, 800, 400);
            canvas.drawRect(rect, mPaint);
            //第三种
            RectF rectF = new RectF(100, 500, 800, 600);
            canvas.drawRect(rectF, mPaint);
        }
    
        /**
         * 绘制圆角矩形
         */
        private void drawRoundRect(Canvas canvas) {
            //第一种
            RectF rectF = new RectF(100, 100, 800, 400);
            canvas.drawRoundRect(rectF, 30, 30, mPaint);
            //第二种方法在API21的时候才可以用,建议用第一种
            //设置圆弧角度rx>矩形宽度/2(350)  ry>矩形高度/2 (200)时都可以画成椭圆
            canvas.drawRect(100,600,800,1000,mPaint);
            mPaint.setColor(Color.GRAY);
            canvas.drawRoundRect(100,600,800,1000,350,250,mPaint);
        }
    
        /**
         * 绘制椭圆
         */
        private void drawOval(Canvas canvas){
            //第一种
            RectF rectF=new RectF(100,100,800,400);
            canvas.drawOval(rectF,mPaint);
            //第二种不建议使用21以上才有
            canvas.drawOval(100,500,800,900,mPaint);
        }
    
        /**
         *  绘制一个圆心坐标在(500,500),半径为300 的圆
         */
        private void drawCircle(Canvas canvas){
            canvas.drawCircle(500,500,300,mPaint);
        }
        /**
         * 绘制圆弧
         * 参数介绍startAngle 开始角度 sweepAngle 结束角度  useCenter 是否使用中心
         */
        private void drawAre(Canvas canvas){
            RectF rectF=new RectF(100,100,500,500);
            mPaint.setColor(Color.GRAY);
            canvas.drawRect(rectF,mPaint);
            mPaint.setColor(Color.GREEN);
            canvas.drawArc(rectF,0,90,false,mPaint);
    
            RectF rectF1=new RectF(100,600,500,1100);
            mPaint.setColor(Color.GRAY);
            canvas.drawRect(rectF1,mPaint);
            mPaint.setColor(Color.GREEN);
            canvas.drawArc(rectF1,0,90,true,mPaint);
        }
    

    简单的绘制一个圆饼图

    public class PieView extends View {
        private int[] datas = {20, 60, 80, 10, 50};//数据
        private int[] colors = {Color.BLACK, Color.GREEN, Color.GRAY, Color.RED, Color.BLUE};//颜色
        private int mWidth, mHeight; //宽高
        private float mRadius;    //半径
        private RectF rectF;//圆饼图区域
        private Paint mPaint = new Paint();//画笔
    
        public PieView(Context context) {
            this(context, null);
        }
    
        public PieView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public PieView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setAntiAlias(true);
        }
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mHeight = h;
            mWidth = w;
            mRadius = Math.min(mHeight, mWidth) / 2 * 0.8f;
            rectF = new RectF(-mRadius, -mRadius, mRadius, mRadius);
        }
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.translate(mWidth / 2, mHeight / 2);
            drawPie(canvas);
        }
        /**
         *绘制圆饼图
         */
        private void drawPie(Canvas canvas) {
            float sumValues = 0;
            for (int i = 0; i < datas.length; i++) {
                sumValues += datas[i];
            }
            float startAngle = 0;//初始角度
            for (int i = 0; i < datas.length; i++) {
                mPaint.setColor(colors[i]);
                float percentage = datas[i] / sumValues ;
                float angle=percentage*360;
                canvas.drawArc(rectF,startAngle,angle,true,mPaint);
                startAngle += angle;
            }
        }
    }
    
    Screenshot_1489053291.png

    根据Path图形的绘制

    
    public class PathLearn extends View {
        private Paint mPaint;
        private int mWidth, mHeight;
    
        public PathLearn(Context context) {
            this(context, null);
        }
    
        public PathLearn(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public PathLearn(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
        private void initView() {
            mPaint = new Paint();
            mPaint.setStyle(Paint.Style.FILL);
            mPaint.setColor(Color.GREEN);
            mPaint.setAntiAlias(true);
            mPaint.setStrokeWidth(10);
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = w;
            mHeight = h;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.translate(mWidth / 2, mHeight / 2);
    //        canvas.scale(1,-1);//翻转y轴坐标
            drawAllPoint(canvas);
            drawPathXY(canvas);
    //        drawPathLine(canvas);
    //        drawPathRect(canvas);
    //        drawPathAll(canvas);
    //        drawPathaddArc(canvas);
    
        }
        //------------moveTo、 setLastPoint、 lineTo 和 close-----------------
    
        /**
         * 利用path绘制坐标和箭头
         * moveTo  设置path起点
         * lineTo  path直线到终点
         */
        private void drawPathXY(Canvas canvas) {
            Path mPath = new Path();
            mPaint.setStrokeWidth(1);
            mPaint.setColor(Color.BLACK);
            mPaint.setStyle(Paint.Style.STROKE);
            //x轴与箭头
            mPath.moveTo(-mWidth / 2 * 0.8f, 0);
            mPath.lineTo(mWidth / 2 * 0.8f, 0);
    
            mPath.lineTo(mWidth / 2 * 0.8f * 0.95f, -mWidth / 2 * 0.8f * 0.05f);
            mPath.moveTo(mWidth / 2 * 0.8f, 0);
            mPath.lineTo(mWidth / 2 * 0.8f * 0.95f, mWidth / 2 * 0.8f * 0.05f);
    
            //y轴
            mPath.moveTo(0, -mHeight / 2 * 0.8f);
            mPath.lineTo(0, mHeight / 2 * 0.8f);
            //y轴箭头
            mPath.moveTo(mWidth / 2 * 0.8f * 0.05f, mHeight / 2 * 0.8f - mWidth / 2 * 0.8f * 0.05f);
            mPath.lineTo(0, mHeight / 2 * 0.8f);
            mPath.lineTo(-mWidth / 2 * 0.8f * 0.05f, mHeight / 2 * 0.8f - mWidth / 2 * 0.8f * 0.05f);
            canvas.drawPath(mPath, mPaint);
        }
    
        /**
         * setLastPoint() 重置上一次操作的最后一个点
         * close() 方法用于连接当前最后一个点和最初的一个点
         */
        private void drawPathLine(Canvas canvas) {
            Path mPath = new Path();
            mPaint.setColor(Color.RED);
            mPaint.setStrokeWidth(5);
            mPath.lineTo(200, 200);
    //        mPath.moveTo(200,100);
            mPath.setLastPoint(200, 100);
            mPath.lineTo(200, 0);
            mPath.close();
            canvas.drawPath(mPath, mPaint);
        }
    
        /**
         * 用原点和四个端点
         */
    
        private void drawAllPoint(Canvas canvas) {
            mPaint.setStrokeWidth(20);
            mPaint.setStrokeCap(Paint.Cap.ROUND);
            canvas.drawPoints(new float[]{0, 0, mWidth / 2 * 0.8f, 0, -mWidth / 2 * 0.8f, 0, 0, mHeight / 2 * 0.8f, 0, -mHeight / 2 * 0.8f}, mPaint);
        }
    
        //------------addCircle() addOval() addRect() addRoundRect()  参数Path.Direction  cw  顺时针  ccw 逆时针-----------------
    
        /**
         * path绘制矩形
         * setLastPoint(-300,300)修改最后点的位置
         */
        private void drawPathRect(Canvas canvas) {
            Path path = new Path();
    //        path.addRect(-200, -200, 200, 200, Path.Direction.CW);
            path.addRect(-200, -200, 200, 200, Path.Direction.CCW);
    //        path.setLastPoint(-300,300);
            canvas.drawPath(path, mPaint);
        }
    
        /**
         * patn绘制其他基本图形
         * addPath (Path src)将两个Path合并成为一个
         * addPath (Path src, float dx, float dy) 进行了位移之后再添加进当前path中
         * addPath (Path src, Matrix matrix) 添加到当前path之前先使用Matrix进行变换
         */
        private void drawPathAll(Canvas canvas) {
            Path path = new Path();
            Path path1 = new Path();
            Path path2 = new Path();
    //        mPaint.setStyle(Paint.Style.FILL);
            path.addCircle(0, 0, 200, Path.Direction.CW);
    //        path.setLastPoint(-300,300);
            path1.addOval(-300, -200, 300, 200, Path.Direction.CW);
    //        path.setLastPoint(-300,300);
            path2.addRoundRect(-200, -200, 200, 200, 30, 30, Path.Direction.CW);
    //        path.setLastPoint(-300,300);
            path.addPath(path1, 0, -300);
            path.addPath(path2, 0, 300);
            canvas.drawPath(path, mPaint);
        }
    
        //------------addArc与arcTo-----------------
        /**
         * public void addArc (RectF oval, float startAngle, float sweepAngle)
         * public void arcTo (RectF oval, float startAngle, float sweepAngle)
         * public void arcTo (RectF oval, float startAngle, float sweepAngle, boolean forceMoveTo)
         * oval  圆弧的外切矩形。
         * startAngle 开始角度
         * sweepAngle 扫过角度(-360 <= sweepAngle <360)
         * forceMoveTo  是否强制使用MoveTo
         * addArc  直接添加一个圆弧到path中
         * arcTo  添加一个圆弧到path,如果圆弧的起点和上次最后一个坐标点不相同,就连接两个点
         * forceMoveTo true 将最后一个点移动到圆弧起点,即不连接最后一个点与圆弧起点
         * firceMoveTo false 不移动,而是连接最后一个点与圆弧起点
         */
    
        /**
         * 圆弧
         */
        private void drawPathaddArc(Canvas canvas) {
            Path path = new Path();
            path.lineTo(100, -100);
            RectF rectF = new RectF(0, -200, 200, 0);
    //        path.addArc(rectF,0,280);
    //        path.arcTo(rectF,0,270,false);
            path.arcTo(rectF, 0, 270, true);
            path.offset(0,300,path);
            canvas.drawPath(path, mPaint);
        }
        //------------isEmpty、 isRect、isConvex、 set 和 offset-----------------
        /**
         * isEmpty() 判断path中是否包含内容 true-无内容  false-有内容
         * isRect()  判断path是否是一个矩形,如果是一个矩形的话,会将矩形的信息存放进参数rect中
         * set()     将新的path赋值到现有path
         * offset()  就是对path进行一段平移
         */
    

    雷达图的绘制

    
    public class RadarView extends View {
    
        private int count = 8;//数据个数
        private float angle = (float) (Math.PI * 2 / count);//每个数据的平均弧度
        private float radius;   //网络最大半径
        private int centerX;    //中心X坐标
        private int centerY;    //中心Y坐标
        private String[] titles = {"1", "2", "3", "4", "5", "6","7","8"};
        private double[] data = {20, 30, 40, 50, 60, 70,80,90}; //各维度分值
        private float maxValues = 100;    //数据最大值
        private Paint radarPaint = new Paint();       //雷达图画笔
        private Paint valuePaint = new Paint();       //网格图画笔
        private Paint textPaint = new Paint();        //文本画笔
        private Paint xyPaint = new Paint();           //坐标画笔
        private int mWidth, mHeight;
    
    
    
        public RadarView(Context context) {
            this(context, null);
        }
    
        public RadarView(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public RadarView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            initView();
        }
    
    
        //初始化数据
        private void initView() {
            //设置雷达画笔属性
            radarPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            radarPaint.setColor(Color.GREEN);
            radarPaint.setAntiAlias(true);
            //设置网格图画笔属性
            valuePaint.setStyle(Paint.Style.STROKE);
            valuePaint.setColor(Color.BLUE);
            valuePaint.setAntiAlias(true);
            //设置文本画笔属性
            textPaint.setStyle(Paint.Style.FILL);
            textPaint.setColor(Color.BLACK);
            textPaint.setTextSize(30);
            textPaint.setAntiAlias(true);
            //设置坐标画笔属性
            xyPaint.setColor(Color.RED);
            xyPaint.setAntiAlias(true);
            xyPaint.setStyle(Paint.Style.STROKE);
            xyPaint.setStrokeWidth(4);
    
    
        }
    
        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            mWidth = w;
            mHeight = h;
            radius = Math.min(mWidth, mHeight) / 2 * 0.8f;
            centerY = h / 2;
            centerX = w / 2;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.translate(centerX, centerY);
    //        drawXY(canvas);
            drawValues(canvas);
            drawCover(canvas);
        }
    
        /**
         * 画坐标
         */
        private void drawXY(Canvas canvas) {
            Path mPath = new Path();
            //x轴与箭头
            mPath.moveTo(-mWidth / 2 * 0.95f, 0);
            mPath.lineTo(mWidth / 2 * 0.95f, 0);
    
            mPath.lineTo(mWidth / 2 * 0.95f * 0.95f, -mWidth / 2 * 0.95f * 0.05f);
            mPath.moveTo(mWidth / 2 * 0.95f, 0);
            mPath.lineTo(mWidth / 2 * 0.95f * 0.95f, mWidth / 2 * 0.95f * 0.05f);
    
            //y轴
            mPath.moveTo(0, -mHeight / 2 * 0.95f);
            mPath.lineTo(0, mHeight / 2 * 0.95f);
            //y轴箭头
            mPath.moveTo(mWidth / 2 * 0.95f * 0.05f, mHeight / 2 * 0.95f - mWidth / 2 * 0.95f * 0.05f);
            mPath.lineTo(0, mHeight / 2 * 0.95f);
            mPath.lineTo(-mWidth / 2 * 0.95f * 0.05f, mHeight / 2 * 0.95f - mWidth / 2 * 0.95f * 0.05f);
            canvas.drawPath(mPath, xyPaint);
        }
    
        /**
         * 绘制网格图和文本
         */
        private void drawValues(Canvas canvas) {
            Path path = new Path();//多边形path
            Path linePath = new Path();//直线Path
            float r = radius / count - 1;//设置网格之间的间距
            Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
            float textHeight = (-fontMetrics.ascent - fontMetrics.descent);//文本高度
            for (int j = 0; j < count; j++) {
                float newR = r * j;
                path.reset();
                for (int i = 0; i < count; i++) {
                    float x = (float) (newR * Math.cos(angle * i));
                    float y = (float) (newR * Math.sin(angle * i));
                    if(j==count-1){
                        //绘制直线
                        linePath.reset();
                        linePath.moveTo(0, 0);
                        linePath.lineTo(x, y);
                        canvas.drawPath(linePath, valuePaint);
                    }
                    if (i == 0) {
                        path.moveTo(newR, 0);
                    } else {
                        path.lineTo(x, y);
                    }
                }
                path.close();
                canvas.drawPath(path, valuePaint);
    
                //绘制文本
                float textX = (float) ((radius - r + textHeight / 2) * Math.cos(angle * j));
                float textY = (float) ((radius - r + textHeight / 2) * Math.sin(angle * j));
                float textWidth = textPaint.measureText(titles[j]);//文本长度
    
                if (j == 0) {
                    canvas.drawText(titles[j], textX, textY + textHeight / 2, textPaint);
                } else if (j == 1) {
                    canvas.drawText(titles[j], textX - textWidth / 2, textY + textHeight, textPaint);
                } else if (j == 2) {
                    canvas.drawText(titles[j], textX - textWidth / 2, textY + textHeight, textPaint);
                } else if (j == 3) {
                    canvas.drawText(titles[j], textX - textWidth, textY + textHeight / 2, textPaint);
                } else if (j == 4) {
                    canvas.drawText(titles[j], textX - textWidth / 2, textY, textPaint);
                } else {
                    canvas.drawText(titles[j], textX - textWidth / 2, textY, textPaint);
                }
            }
        }
    
            /**
             * 绘制覆盖区域
             */
    
        private void drawCover(Canvas canvas) {
            Path path=new Path();
            float r = radius / count - 1;//设置网格之间的间距
            for(int i=0;i<count;i++){
                double percent=data[i]/maxValues;
                float x = (float) ((radius-r)*Math.cos(angle*i)*percent);
                float y = (float) ((radius-r)*Math.sin(angle*i)*percent);
                if(i==0){
                    path.moveTo(x,0);
                }else{
                    path.lineTo(x,y);
                }
                //绘制小圆点
                canvas.drawCircle(x,y,5,radarPaint);
    //            canvas.drawPoint(x,y,radarPaint);
            }
            path.close();
            radarPaint.setStyle(Paint.Style.STROKE);
            canvas.drawPath(path,radarPaint);
            //绘制填充区域
            radarPaint.setAlpha(105);
            radarPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            canvas.drawPath(path,radarPaint);
        }
    
    
    }
    
    
    

    效果

    Screenshot_1489048128.png Screenshot_1489049585.png
    /**
         * 根据path绘制饼图
         */
        private void drawPathAcr(Canvas canvas) {
            float outRadius = mRadius;
            outRecF = new RectF(-outRadius, -outRadius, outRadius, outRadius);
            float alphaRadius = mRadius * 0.6f;
            alphaRecf = new RectF(-alphaRadius, -alphaRadius, alphaRadius, alphaRadius);
            float inRadius = mRadius * 0.5f;
            inRecF = new RectF(-inRadius, -inRadius, inRadius, inRadius);
    
            if (mDatas.size() == 0) {
                return;
            }
            canvas.rotate(drawStartAngle);
            canvas.save();
            float startAngle = 0;
            for (PieChartBean ben : mDatas) {
                float sweepAngle = ben.getPercentage();
                outPaht.moveTo(0, 0);
                outPaht.arcTo(outRecF, startAngle, sweepAngle);
                inPaht.moveTo(0, 0);
                inPaht.arcTo(inRecF, startAngle, sweepAngle);
                alphaPaht.moveTo(0, 0);
                alphaPaht.arcTo(alphaRecf, startAngle, sweepAngle);
                pietPaht.op(outPaht, inPaht, Path.Op.DIFFERENCE);
                alphaPiePaht.op(alphaPaht, inPaht, Path.Op.DIFFERENCE);
                arcPaint.setColor(ben.getPieColor());
                canvas.drawPath(pietPaht, arcPaint);
                arcPaint.setAlpha(100);
                arcPaint.setColor(Color.GRAY);
                canvas.drawPath(alphaPiePaht, arcPaint);
                outPaht.reset();
                inPaht.reset();
                alphaPaht.reset();
                startAngle += sweepAngle;
            }
        }
    
    

    相关文章

      网友评论

        本文标题:Android自定义View七(复习基本图形的绘制)

        本文链接:https://www.haomeiwen.com/subject/iexggttx.html