Android利用Path绘制图形

一、效果图

Android利用Path绘制图形_第1张图片 Android利用Path绘制图形_第2张图片 Android利用Path绘制图形_第3张图片

二、源代码

2.1 第一张效果图

package com.study.yang.drawgraphicaldemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * 绘制圆弧
 */
public class DrawSectorDemo extends View {

    private Paint rectFPaint;

    private Paint circlePaint;

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

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

    public DrawSectorDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        circlePaint = new Paint();
        circlePaint.setColor(Color.RED);
        circlePaint.setAntiAlias(true);
        //设置画笔为空
        circlePaint.setStyle(Paint.Style.STROKE);


        rectFPaint = new Paint();
        rectFPaint.setColor(Color.BLUE);
        rectFPaint.setAntiAlias(true);
        //设置画笔为空
        rectFPaint.setStyle(Paint.Style.STROKE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        RectF rectF = new RectF(0, 0, 800, 800);
        canvas.drawRect(rectF, rectFPaint);
        canvas.drawArc(rectF, -60, 60, false, circlePaint);
        canvas.drawCircle(100, 100, 50, rectFPaint);
    }
}

2.2 第二张效果图

package com.study.yang.drawgraphicaldemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;

/**
 * 绘制内凹图形
 */
public class InternalConcaveDemo extends View {

    private Paint rectFPaint;

    private Paint circlePaint;
    private RectF rectF1;
    private RectF rectF2;
    private RectF rectF3;
    private RectF rectF4;

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

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

    public InternalConcaveDemo(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    private void init(Context context) {
        circlePaint = new Paint();
        circlePaint.setColor(Color.RED);
        circlePaint.setAntiAlias(true);
        circlePaint.setStyle(Paint.Style.STROKE);


        rectFPaint = new Paint();
        rectFPaint.setColor(Color.BLUE);
        rectFPaint.setAntiAlias(true);
        rectFPaint.setStyle(Paint.Style.FILL);

        rectF1 = new RectF(-50, 100, 50, 200);
        rectF2 = new RectF(50, 0, 150, 100);
        rectF3 = new RectF(350, 0, 450, 100);
        rectF4 = new RectF(450, 100, 550, 200);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        userArcToApi(canvas);
        drawRing(canvas);
        drawFanLeaf(canvas);
        drawMoon(canvas);
        drawUnion(canvas);
//        drawXor(canvas);

        Path path = new Path();
        path.moveTo(500, 500);
        path.cubicTo(500, 500, 600, 700, 900, 800);
//        path.lineTo(1100, 1100);
        rectFPaint.setColor(Color.RED);
        canvas.drawPath(path, rectFPaint);
    }

    /**
     * 去除两者之间的图形
     *
     * @param canvas
     */
    private void drawXor(Canvas canvas) {
        Path path1 = new Path();
        path1.addCircle(1200, 1200, 100, Path.Direction.CCW);
        Path path2 = new Path();
        path2.addCircle(1250, 1250, 100, Path.Direction.CCW);
        path1.op(path2, Path.Op.XOR);//去除两者之间的图形
        rectFPaint.setStyle(Paint.Style.STROKE);
        canvas.drawPath(path1, rectFPaint);
    }

    /**
     * 画联合
     *
     * @param canvas
     */
    private void drawUnion(Canvas canvas) {
        Path path1 = new Path();
        path1.addCircle(900, 500, 100, Path.Direction.CCW);
        Path path2 = new Path();
        path2.addCircle(950, 550, 100, Path.Direction.CCW);
        path1.op(path2, Path.Op.UNION);//联结两条路径
        canvas.drawPath(path1, rectFPaint);
    }

    /**
     * 画月亮
     *
     * @param canvas
     */
    private void drawMoon(Canvas canvas) {
        Path path1 = new Path();
        path1.addCircle(900, 900, 100, Path.Direction.CCW);
        Path path2 = new Path();
        path2.addCircle(950, 950, 100, Path.Direction.CCW);
        path1.op(path2, Path.Op.REVERSE_DIFFERENCE);//从第二条路径中减去第一条路径
        canvas.drawPath(path1, rectFPaint);
    }

    /**
     * 画扇叶
     *
     * @param canvas
     */
    private void drawFanLeaf(Canvas canvas) {
        Path path1 = new Path();
        path1.addCircle(600, 600, 100, Path.Direction.CCW);
        Path path2 = new Path();
        path2.addCircle(650, 650, 100, Path.Direction.CCW);
        path1.op(path2, Path.Op.INTERSECT);//两者相交的部分
        canvas.drawPath(path1, rectFPaint);
    }

    /**
     * 画圆环
     *
     * @param canvas
     */
    private void drawRing(Canvas canvas) {
        Path bigPath = new Path();
        bigPath.addCircle(300, 300, 50, Path.Direction.CCW);
        Path smallPath = new Path();
        smallPath.addCircle(300, 300, 25, Path.Direction.CCW);
        bigPath.op(smallPath, Path.Op.DIFFERENCE);  //大减小
        canvas.drawPath(bigPath, rectFPaint);
    }

    /**
     * 用addArc这个API来绘制弧线,这个API更适合来绘制扇形
     *
     * @param canvas
     */
    private void useAddArcApi(Canvas canvas) {
        Path path = new Path();
        path.addArc(rectF1, 90, -90);
        path.lineTo(50, 50);
        path.addArc(rectF2, 180, 90);
        path.lineTo(400, 0);
        path.addArc(rectF3, -90, 90);
        path.lineTo(450, 250);
        path.addArc(rectF4, 180, -90);
        path.lineTo(0, 300);
        canvas.drawPath(path, rectFPaint);
    }

    /**
     * 用arcTo这个API来绘制弧线
     *
     * @param canvas
     */
    private void userArcToApi(Canvas canvas) {
        Path path = new Path();
        //逆时针画弧线
        path.arcTo(rectF1, 90, -90);
        path.lineTo(50, 50);
        //顺时针画弧线
        path.arcTo(rectF2, 180, 90);
        path.lineTo(400, 0);
        //顺时针画弧线
        path.arcTo(rectF3, -90, 90);
        path.lineTo(450, 150);
        //逆时针画曲线
        path.arcTo(rectF4, 180, -90);
        path.lineTo(0, 200);
        canvas.drawPath(path, rectFPaint);
    }

    /**
     * 绘制半角路径
     *
     * @param canvas
     */
    private void drawPath(Canvas canvas) {
        Path path = new Path();
        path.moveTo(50, 0);
        path.lineTo(50, 50);
        path.lineTo(0, 50);
        path.close();
//        canvas.drawPath(path, rectFPaint);

        Path path1 = new Path();
        path1.addArc(rectF1, 0, 90);
//        path.close();
        //path减去path1
        path.op(path1, Path.Op.DIFFERENCE);


        canvas.drawPath(path, rectFPaint);
    }
}

2.3 第三张效果图

package com.study.yang.drawgraphicaldemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

/**
 * 太极View
 */
public class TaiChiView extends View {
    /**
     * 太极矩形外围
     */
    private RectF taiChiRectF;
    /**
     * 白色路径
     */
    private Path whitePath = new Path();
    private Paint whitePaint = new Paint();
    private Region whiteRegion = new Region();
    /**
     * 黑色路径
     */
    private Path blackPath = new Path();
    private Paint blackPaint = new Paint();
    private Region blackRegion = new Region();
    private float radius;

    private final int BLACK_FLAG = 0;
    private final int WRITE_FLAG = 1;
    private int touchFlag = -1;
    private TaiJiListener mListener;

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

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

    public TaiChiView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(context);
    }

    /**
     * 初始化数据
     *
     * @param context
     */
    private void init(Context context) {
        //白色
        whitePaint.setColor(Color.WHITE);
        whitePaint.setAntiAlias(true);
        //黑色
        blackPaint.setColor(Color.BLACK);
        blackPaint.setAntiAlias(true);
    }

    /**
     * 当尺寸改变的时候绘制图形
     *
     * @param w
     * @param h
     * @param oldw
     * @param oldh
     */
    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        int side = w > h ? h : w;
        Region totalRegion = new Region(0, 0, w, h);
        taiChiRectF = new RectF(0, 0, side, side);
        radius = side / 2;
        RectF smallTopRectF = new RectF(radius / 2, 0, radius * 3 / 2, radius);
        RectF smallBottomRectF = new RectF(radius / 2, radius, radius * 3 / 2, side);
        //白色路径添加
        whitePath.addArc(taiChiRectF, 90, 180);
        whitePath.moveTo(radius, 0);
        whitePath.addArc(smallTopRectF, 270, 180);
        whitePath.moveTo(radius, radius);
        //逆时针
        whitePath.arcTo(smallBottomRectF, 270, -180);
        /**
         * 将区域设置为路径和所描述的区域的剪辑。
         * 如果结果区域为非空,则返回true。这就产生了一个区域
         * 这与路径绘制的像素相同(没有抗锯齿)。
         */
        //将白色路径设置
        whiteRegion.setPath(whitePath, totalRegion);
        //黑色路径添加
        blackPath.addArc(taiChiRectF, 270, 180);
        blackPath.moveTo(radius, side);
        blackPath.addArc(smallBottomRectF, 90, 180);
        blackPath.moveTo(radius, radius);
        //逆时针
        blackPath.arcTo(smallTopRectF, 90, -180);
        blackRegion.setPath(blackPath, totalRegion);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //白色
        canvas.drawPath(whitePath, whitePaint);
        canvas.drawCircle(radius, radius / 2, radius / 8, blackPaint);
        //黑色
        canvas.drawPath(blackPath, blackPaint);
        canvas.drawCircle(radius, radius * 3 / 2, radius / 8, whitePaint);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        int currentFlag = -1;
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                touchFlag = getTouchFlag(x, y);
                currentFlag = touchFlag;
                break;
            case MotionEvent.ACTION_MOVE:
                currentFlag = getTouchFlag(x, y);
                break;
            case MotionEvent.ACTION_UP:
                currentFlag = getTouchFlag(x, y);
                if (null != mListener && currentFlag == touchFlag && currentFlag != -1) {
                    if (currentFlag == BLACK_FLAG) {
                        mListener.onBlackClick();
                    } else if (currentFlag == WRITE_FLAG) {
                        mListener.onWriteClick();
                    }
                }
                touchFlag = currentFlag = -1;
                break;
            case MotionEvent.ACTION_CANCEL:
                touchFlag = currentFlag = -1;
                break;
        }
        Log.e("currentFlag", "-->" + currentFlag);
        return true;
    }

    /**
     * 判断落在哪个区域
     */
    private int getTouchFlag(int x, int y) {
        if (blackRegion.contains(x, y)) {
            return BLACK_FLAG;
        } else if (whiteRegion.contains(x, y)) {
            return WRITE_FLAG;
        }
        return -1;
    }

    public void setListener(TaiJiListener mListener) {
        this.mListener = mListener;
    }

    /**
     * 设置触摸监听
     */
    public interface TaiJiListener {
        void onBlackClick();

        void onWriteClick();
    }

}

源代码

推荐文章

Android小练习——Path绘制不规则图形的点击

Android自定义view画五星红旗

Android绘制(二):来用Path绘出想要的图形吧!

你可能感兴趣的:(Android利用Path绘制图形)