【安卓】自定义View实现画板涂鸦等功能

news2025/1/16 4:56:05

一、实现效果

画笔测试
开始设计矩形
实现矩形的随笔画
圆形
三角形,还有bug
等腰三角形和塔型
等边三角形
等边三角形计算

二、代码

1、MainActivity.class

package com.lsl.mydrawingboarddemo;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.widget.ImageButton;

import com.lsl.mydrawingboarddemo.view.DrawingBoardView;

import java.io.IOException;

/**
 * author lishilin
 * date 2023/8/9
 * desc 负责画板UI交互
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private ImageButton paintBtn,fillPaintBtn,rubberBtn,rectBtn,circleBtn,ellipticBtn,triangleBtn,triangleTowerBtn,selectedBtn,clearBtn,equilateralBtn,rightAngleBtn;
    private ImageButton blackBtn,whiteBtn,redBtn,blueBtn,grayBtn,cyanBtn,currentColorBtn;
    private DrawingBoardView drawingBoardView;
    private View selectColorBoxView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();
    }

    private void initView(){
        paintBtn = findViewById(R.id.paint);
        fillPaintBtn = findViewById(R.id.fillPaint);
        //rubberBtn = findViewById(R.id.rubber);
        rectBtn = findViewById(R.id.rect);
        circleBtn = findViewById(R.id.circle);
        ellipticBtn = findViewById(R.id.elliptic);
        triangleBtn = findViewById(R.id.triangle);
        triangleTowerBtn = findViewById(R.id.triangleTower);
        clearBtn = findViewById(R.id.clear);
        equilateralBtn = findViewById(R.id.equilateralTriangle);
        drawingBoardView = findViewById(R.id.drawView);
        selectColorBoxView = findViewById(R.id.selectColorBox);
        rightAngleBtn = findViewById(R.id.rightAngle);

        blackBtn = findViewById(R.id.blackBtn);
        whiteBtn = findViewById(R.id.whiteBtn);
        redBtn = findViewById(R.id.redBtn);
        blueBtn = findViewById(R.id.blueBtn);
        grayBtn = findViewById(R.id.grayBtn);
        cyanBtn = findViewById(R.id.cyanBtn);

        paintBtn.setSelected(true);
        selectedBtn = paintBtn;
        blackBtn.setSelected(true);
        currentColorBtn = blackBtn;

        paintBtn.setOnClickListener(this);
        fillPaintBtn.setOnClickListener(this);
        //rubberBtn.setOnClickListener(this);
        rectBtn.setOnClickListener(this);
        circleBtn.setOnClickListener(this);
        ellipticBtn.setOnClickListener(this);
        triangleBtn.setOnClickListener(this);
        triangleTowerBtn.setOnClickListener(this);
        clearBtn.setOnClickListener(this);
        blackBtn.setOnClickListener(this);
        whiteBtn.setOnClickListener(this);
        redBtn.setOnClickListener(this);
        blueBtn.setOnClickListener(this);
        grayBtn.setOnClickListener(this);
        equilateralBtn.setOnClickListener(this);
        rightAngleBtn.setOnClickListener(this);
        cyanBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
            case R.id.paint:
                setSelectBtn(paintBtn);
                drawingBoardView.setPaint("paint");
                selectColorBoxView.setVisibility(View.VISIBLE);
                break;
            case R.id.fillPaint:
                setSelectBtn(fillPaintBtn);
                drawingBoardView.setPaint("fillPaint");
                selectColorBoxView.setVisibility(View.VISIBLE);
                break;
//            case R.id.rubber:
//                setSelectBtn(rubberBtn);
//                drawingBoardView.setEraseMode();
//                selectColorBoxView.setVisibility(View.INVISIBLE);
//                break;
            case R.id.rect:
                setSelectBtn(rectBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("rect");
                break;
            case R.id.circle:
                setSelectBtn(circleBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("drawCircle");
                break;
            case R.id.elliptic:
                setSelectBtn(ellipticBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("drawOval");
                break;
            case R.id.triangle:
                 setSelectBtn(triangleBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                 drawingBoardView.setPaint("drawTriangle");
                 break;
            case R.id.equilateralTriangle:
                setSelectBtn(equilateralBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("drawEquilateral");
                break;
            case R.id.triangleTower:
                setSelectBtn(triangleTowerBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("drawTriangleTower");
                break;
            case R.id.rightAngle:
                setSelectBtn(rightAngleBtn);
                selectColorBoxView.setVisibility(View.VISIBLE);
                drawingBoardView.setPaint("drawRightAngle");
                break;
            case R.id.clear:
                clearStyle();//设置点击清除图标时的背景闪烁
                selectColorBoxView.setVisibility(View.VISIBLE);
                if (drawingBoardView!=null){
                    drawingBoardView.clearBoard();
                }
                break;
            case R.id.blackBtn:
                int blackColor = ContextCompat.getColor(this,R.color.black);
                drawingBoardView.setPaintColor(blackColor);
                setCurrentColorBtn(blackBtn);
                break;
            case R.id.blueBtn:
                int blueColor = ContextCompat.getColor(this,R.color.blue);
                drawingBoardView.setPaintColor(blueColor);
                setCurrentColorBtn(blueBtn);
                break;
            case R.id.whiteBtn:
                int whiteColor = ContextCompat.getColor(this,R.color.white);
                drawingBoardView.setPaintColor(whiteColor);
                setCurrentColorBtn(whiteBtn);
                break;
            case R.id.cyanBtn:
                int cyanColor = ContextCompat.getColor(this,R.color.cyan);
                drawingBoardView.setPaintColor(cyanColor);
                setCurrentColorBtn(cyanBtn);
                break;
            case R.id.grayBtn:
                int grayColor = ContextCompat.getColor(this,R.color.gray);
                drawingBoardView.setPaintColor(grayColor);
                setCurrentColorBtn(grayBtn);
                break;
            case R.id.redBtn:
                int redColor = ContextCompat.getColor(this,R.color.red);
                drawingBoardView.setPaintColor(redColor);
                setCurrentColorBtn(redBtn);
                break;
            default:

                break;
        }
    }

    /**
     * 设置选中的图形button
     * @param selectBtn
     */
    private void setSelectBtn(ImageButton selectBtn){
        if (this.selectedBtn!=null){
            this.selectedBtn.setSelected(false);
        }
        selectBtn.setSelected(true);
        this.selectedBtn = selectBtn;
    }

    private void setCurrentColorBtn(ImageButton currentColorBtn){
        if (this.currentColorBtn!=null){
            this.currentColorBtn.setSelected(false);
        }
        currentColorBtn.setSelected(true);
        this.currentColorBtn = currentColorBtn;
    }
    /**
     * 设置点击清除图标时的样式变化,让其背景变色500毫秒
     */
    private void clearStyle(){
        clearBtn.setSelected(true);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                clearBtn.setSelected(false);
            }
        }, 200);
    }

}

2、布局代码

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/bord_color"
    tools:context=".MainActivity">

    <com.lsl.mydrawingboarddemo.view.DrawingBoardView
        android:id="@+id/drawView"
        android:layout_width="match_parent"
        android:layout_height="650dp"
        android:layout_alignParentTop="true"
        android:background="@color/bord_color" />

    <LinearLayout
        android:layout_width="600dp"
        android:layout_height="80dp"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:background="@drawable/bottom_bg_corner"
        android:gravity="center"
        android:orientation="horizontal">

        <LinearLayout
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:gravity="center">

            <TableLayout
                android:id="@+id/selectColorBox"
                android:layout_width="40dp"
                android:layout_height="100dp"
                android:gravity="center">

                <TableRow>

                    <ImageButton
                        android:id="@+id/blackBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/black" />

                    <ImageButton
                        android:id="@+id/whiteBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/white" />
                </TableRow>

                <TableRow>

                    <ImageButton
                        android:id="@+id/redBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/red_circle" />

                    <ImageButton
                        android:id="@+id/blueBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/blue" />
                </TableRow>

                <TableRow>

                    <ImageButton
                        android:id="@+id/grayBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/gray" />

                    <ImageButton
                        android:id="@+id/cyanBtn"
                        android:background="@drawable/color_select"
                        android:src="@drawable/cyan" />
                </TableRow>

            </TableLayout>
        </LinearLayout>

        <TextView
            android:layout_width="1dp"
            android:layout_height="match_parent"
            android:background="@color/gray" />

        <LinearLayout
            android:layout_width="500dp"
            android:layout_height="match_parent"
            android:gravity="center">

            <ImageButton
                android:id="@+id/paint"
                android:layout_width="28dp"
                android:layout_height="28dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/paint" />

            <ImageButton
                android:id="@+id/fillPaint"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/brush" />
<!--            <ImageButton-->
<!--                android:id="@+id/rubber"-->
<!--                android:layout_width="32dp"-->
<!--                android:layout_height="32dp"-->
<!--                android:scaleType="centerInside"-->
<!--                android:layout_marginLeft="8dp"-->
<!--                android:background="@drawable/shape_selector"-->
<!--                android:src="@drawable/rubber" />-->

            <ImageButton
                android:id="@+id/rect"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:focusable="true"
                android:src="@drawable/rect" />

            <ImageButton
                android:id="@+id/circle"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/circle" />

            <ImageButton
                android:id="@+id/elliptic"
                android:layout_width="35dp"
                android:layout_height="35dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/elliptic" />

            <ImageButton
                android:id="@+id/triangle"
                android:layout_width="38dp"
                android:layout_height="40dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/triangle" />
            <ImageButton
                android:id="@+id/equilateralTriangle"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/equilateral_triangle" />
            <ImageButton
                android:id="@+id/rightAngle"
                android:layout_width="37dp"
                android:layout_height="37dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/plan" />
            <ImageButton
                android:id="@+id/triangleTower"
                android:layout_width="28dp"
                android:layout_height="28dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/tower" />
            <ImageButton
                android:id="@+id/clear"
                android:layout_width="32dp"
                android:layout_height="32dp"
                android:scaleType="centerInside"
                android:layout_marginLeft="8dp"
                android:background="@drawable/shape_selector"
                android:src="@drawable/clear" />
        </LinearLayout>


    </LinearLayout>

</RelativeLayout>

3、自定义View代码

package com.lsl.mydrawingboarddemo.view;


import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;

import androidx.annotation.Nullable;

import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * author lishilin
 * date 2023/8/9
 * desc 自定义View,实现画板功能
 */
public class DrawingBoardView extends SurfaceView {

    private Paint erasePaint, rectPaint, circlePaint;
    private Path erasePath, selectPath, triangleTowerPath, trianglePath, equilateralPath, anglePath;
    private List<Path> paintPaths, fillPaths, triangleTowerPaths, trianglePaths, equilateralPaths, anglePaths;
    private List<Paint> paints, fillPaints, rectPaints, circlePaints, ovalPaints, triangleTowerPaints, trianglePaints, equilateralPaints, anglePaints;
    private String pathType = "paintPath";
    private boolean eraseMode = false;
    private List<Rect> rects;
    private List<Circle> circleList;
    private List<RectF> ovals;
    private RectF rectF;
    private float startX, startY, currentX, currentY;
    private boolean isDrawing, drawPath, drawRect, drawCircle, isDrawingCircle, isDrawingOval, drawOval, drawTriangleTower, isDrawingTriangleTower, drawTriangle, isDrawingTriangle, isDrawingEquilateral, drawEquilateral, isDrawingRightAngle, drawRightAngle;
    private Rect rect;
    private Circle circle;
    private int pointX, pointY, radius;
    private float tipX, tipY, leftX, leftY, rightX, rightY, equilateralX;

    public DrawingBoardView(Context context) {
        super(context);
        init();
    }

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

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

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

    private void init() {
        erasePaint = new Paint();
        circle = new Circle();
        rect = new Rect();
        triangleTowerPaints = new ArrayList<>();
        triangleTowerPaths = new ArrayList<>();
        ovals = new ArrayList<>();
        trianglePaints = new ArrayList<>();
        trianglePaths = new ArrayList<>();
        rectPaints = new ArrayList<>();
        ovalPaints = new ArrayList<>();
        circlePaints = new ArrayList<>();
        circleList = new ArrayList<>();
        anglePaints = new ArrayList<>();
        anglePath = new Path();
        anglePaths = new ArrayList<>();
        equilateralPaths = new ArrayList<>();
        equilateralPaints = new ArrayList<>();
        circlePaint = new Paint();
        triangleTowerPath = new Path();
        circlePaint.setColor(Color.BLACK);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(5);
        erasePath = new Path();
        trianglePath = new Path();
        equilateralPath = new Path();
        triangleTowerPath = new Path();
        paints = new ArrayList<>();
        fillPaints = new ArrayList<>();
        fillPaths = new ArrayList<>();
        paintPaths = new ArrayList<>();
        setPaintColor(Color.BLACK);
        rects = new ArrayList<>();
        rectPaint = new Paint();
        rectPaint.setColor(Color.BLACK);
        rectPaint.setStrokeWidth(5);
        rectPaint.setStyle(Paint.Style.STROKE);
        drawPath = true;
        isDrawing = false;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = paints.get(paints.size() - 1);
        if (isDrawing) {
            int left = (int) Math.min(startX, currentX);
            int right = (int) Math.max(startX, currentX);
            int top = (int) Math.min(startY, currentY);
            int bottom = (int) Math.max(startY, currentY);
            rect.set(left, top, right, bottom);
            canvas.drawRect(rect, paint);
            isDrawing = false;
        }
        if (!isDrawing) {
            for (int i = 0; i < rects.size(); i++) {
                canvas.drawRect(rects.get(i), rectPaints.get(i));
            }
        }

        for (int i = 0; i < paintPaths.size(); i++) {
            canvas.drawPath(paintPaths.get(i), paints.get(i));
        }

        for (int i = 0; i < trianglePaths.size(); i++) {
            canvas.drawPath(trianglePaths.get(i), trianglePaints.get(i));
        }
        if (isDrawingCircle) {
            circle.setPointX(pointX);
            circle.setPointY(pointY);
            circle.setRadius(radius);
            canvas.drawCircle(circle.getPointX(), circle.getPointY(), circle.getRadius(), paint);
            isDrawingCircle = false;
        }
        if (!isDrawingCircle) {
            for (int i = 0; i < circleList.size(); i++) {
                canvas.drawCircle(circleList.get(i).getPointX(), circleList.get(i).getPointY(), circleList.get(i).getRadius(), circlePaints.get(i));
            }
        }
        if (isDrawingOval) {
            int left = (int) Math.min(startX, currentX);
            int right = (int) Math.max(startX, currentX);
            int top = (int) Math.min(startY, currentY);
            int bottom = (int) Math.max(startY, currentY);
            rectF.set(left, top, right, bottom);
            canvas.drawOval(rectF, paint);
            isDrawingOval = false;
        }
        if (!isDrawingOval) {
            for (int i = 0; i < ovals.size(); i++) {
                canvas.drawOval(ovals.get(i), ovalPaints.get(i));
            }
        }
        if (isDrawingTriangleTower) {
            float leftX = currentX - (currentX - startX) * 2;
            float leftY = currentY;
            triangleTowerPath.lineTo(leftX, leftY);
            triangleTowerPath.lineTo(currentX, currentY);
            triangleTowerPath.close();
            canvas.drawPath(triangleTowerPath, paint);
            isDrawingTriangleTower = false;
        }

        if (!isDrawingTriangleTower){
            for (int i = 0; i < triangleTowerPaths.size(); i++) {
                canvas.drawPath(triangleTowerPaths.get(i), triangleTowerPaints.get(i));
            }
        }
        if (isDrawingTriangle) {
            trianglePath.reset();
            trianglePath.moveTo(tipX, tipY);
            trianglePath.lineTo(leftX, leftY);
            trianglePath.lineTo(rightX, rightY);
            trianglePath.close();
            canvas.drawPath(trianglePath, paint);
            isDrawingTriangle = false;
        }
        if (isDrawingEquilateral) {
            equilateralPath.reset();
            equilateralPath.moveTo(equilateralX, startY);
            int x = (int) ((currentY - startY) / Math.sqrt(3));
            int rightX = (int) (equilateralX + x);
            int leftX = (int) (equilateralX - x);
            equilateralPath.lineTo(leftX, currentY);
            equilateralPath.lineTo(rightX, currentY);
            equilateralPath.close();
            canvas.drawPath(equilateralPath, paint);
            isDrawingEquilateral = false;
        }
        if (!isDrawingEquilateral) {
            for (int i = 0; i < equilateralPaths.size(); i++) {
                canvas.drawPath(equilateralPaths.get(i), equilateralPaints.get(i));
            }
        }
        if (isDrawingRightAngle) {
            anglePath.reset();
            anglePath.moveTo(startX, startY);
            anglePath.lineTo(startX, currentY);
            anglePath.lineTo(currentX, currentY);
            anglePath.close();
            canvas.drawPath(anglePath, paint);
            isDrawingRightAngle = false;
        }
        if (!isDrawingRightAngle) {
            for (int i = 0; i < anglePaths.size(); i++) {
                canvas.drawPath(anglePaths.get(i), anglePaints.get(i));
            }
        }

        for (int i = 0; i < fillPaths.size(); i++) {
            canvas.drawPath(fillPaths.get(i), fillPaints.get(i));
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        Paint paint = paints.get(paints.size() - 1);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();
                if (drawPath && selectPath != null) {
                    selectPath.moveTo(x, y);
                }
                if (drawRect) {
                    rect = new Rect();
                    rectPaints.add(paint);
                }
                if (drawCircle) {
                    circle = new Circle();
                    circlePaints.add(paint);
                }
                if (drawOval) {
                    rectF = new RectF();
                    ovalPaints.add(paint);
                }
                if (drawTriangleTower) {
                    triangleTowerPaints.add(paint);
                    triangleTowerPath.moveTo(event.getX(), event.getY());
                }
                if (drawTriangle) {
                    trianglePath = new Path();
                    tipY = startY;
                    leftX = startX;
                    trianglePaints.add(paint);
                }
                if (drawEquilateral) {
                    equilateralPath = new Path();
                    equilateralPaints.add(paint);
                }
                if (drawRightAngle) {
                    anglePath = new Path();
                    anglePaints.add(paint);
                }
                break;
            case MotionEvent.ACTION_MOVE:
                currentX = event.getX();
                currentY = event.getY();
                if (drawPath) {
                    selectPath.lineTo(x, y);
                }
                if (drawRect) {
                    isDrawing = true;
                    invalidate();
                }
                if (drawOval) {
                    isDrawingOval = true;
                    invalidate();
                }
                if (drawCircle) {
                    pointX = (int) (startX + (currentX - startX) / 2);
                    pointY = (int) (startY + (currentY - startY) / 2);
                    radius = (int) Math.abs(currentY - startY);
                    isDrawingCircle = true;
                    invalidate();
                }
                if (drawTriangleTower) {
                    isDrawingTriangleTower = true;
                    invalidate();
                }
                if (drawTriangle) {
                    isDrawingTriangle = true;
                    leftY = currentY;
                    tipX = (currentX - leftX) / 2 + leftX;
                    rightX = currentX;
                    rightY = currentY;
                    invalidate();
                }
                if (drawEquilateral) {
                    equilateralX = startX + (currentX - startX) / 2;
                    isDrawingEquilateral = true;
                    invalidate();
                }
                if (drawRightAngle) {
                    isDrawingRightAngle = true;
                    invalidate();
                }

                break;
            case MotionEvent.ACTION_UP:
                if (drawRect) {
                    rects.add(rect);
                    isDrawing = false;
                }
                if (drawCircle) {
                    circleList.add(circle);
                    isDrawingCircle = false;
                }
                if (drawOval) {
                    ovals.add(rectF);
                    isDrawingOval = false;
                }
                if (drawTriangleTower) {
                    triangleTowerPaths.add(triangleTowerPath);
                    isDrawingTriangleTower = false;
                }
                if (drawTriangle) {
                    trianglePaths.add(trianglePath);
                    isDrawingTriangle = false;
                }
                if (drawEquilateral) {
                    equilateralPaths.add(equilateralPath);
                    isDrawingEquilateral = false;
                }
                if (drawRightAngle) {
                    anglePaths.add(anglePath);
                    isDrawingRightAngle = false;
                }
                break;
        }
        invalidate();
        return true;
    }

    public void clearBoard() {
        for (int i = 0; i < paintPaths.size(); i++) {
            paintPaths.get(i).reset();
        }
        for (int i = 0; i < fillPaths.size(); i++) {
            fillPaths.get(i).reset();
        }
        for (int i = 0; i < triangleTowerPaths.size(); i++) {
            triangleTowerPaths.get(i).reset();
        }
        for (int i = 0; i < trianglePaths.size(); i++) {
            trianglePaths.get(i).reset();
        }
        for (int i = 0; i < equilateralPaths.size(); i++) {
            equilateralPaths.get(i).reset();
        }
        for (Path path : anglePaths) {
            path.reset();
        }
        rects.clear();
        ovals.clear();
        circleList.clear();
        erasePath.reset();
        eraseMode = false;
        invalidate();
    }

    public void setPaint(String type) {
        switch (type) {
            case "paint":
                selectPath = paintPaths.get(paintPaths.size() - 1);
                this.pathType = "paintPath";
                drawPath = true;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangle = false;
                drawTriangleTower = false;
                drawEquilateral = false;
                drawRightAngle = false;
                break;
            case "fillPaint":
                selectPath = fillPaths.get(fillPaths.size() - 1);
                this.pathType = "fillPath";
                drawPath = true;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangle = false;
                drawTriangleTower = false;
                drawEquilateral = false;
                drawRightAngle = false;
                break;
            case "rect":
                drawPath = false;
                drawRect = true;
                drawCircle = false;
                drawOval = false;
                drawTriangle = false;
                drawTriangleTower = false;
                drawRightAngle = false;
                drawEquilateral = false;
                break;
            case "drawCircle":
                drawRect = false;
                drawPath = false;
                drawOval = false;
                drawCircle = true;
                drawTriangle = false;
                drawTriangleTower = false;
                drawEquilateral = false;
                drawRightAngle = false;
                break;
            case "drawOval":
                drawPath = false;
                drawRect = false;
                drawCircle = false;
                drawOval = true;
                drawTriangle = false;
                drawTriangleTower = false;
                drawEquilateral = false;
                drawRightAngle = false;
                break;
            case "drawTriangleTower":
                drawPath = false;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangle = false;
                drawTriangleTower = true;
                drawEquilateral = false;
                drawRightAngle = false;
                break;
            case "drawTriangle":
                drawPath = false;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangleTower = false;
                drawTriangle = true;
                drawRightAngle = false;
                drawEquilateral = false;
                break;
            case "drawEquilateral":
                drawPath = false;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangleTower = false;
                drawTriangle = false;
                drawRightAngle = false;
                drawEquilateral = true;
                break;
            case "drawRightAngle":
                drawPath = false;
                drawRect = false;
                drawCircle = false;
                drawOval = false;
                drawTriangleTower = false;
                drawTriangle = false;
                drawEquilateral = false;
                drawRightAngle = true;
                break;
        }
    }

    public void setPaintColor(int color) {
        Paint paint = new Paint();
        paint.setColor(color);
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setStrokeJoin(Paint.Join.ROUND);
        paint.setStrokeWidth(3);
        paints.add(paint);
        Paint fillPaint = new Paint();
        fillPaint.setColor(color);
        fillPaint.setStyle(Paint.Style.STROKE);
        fillPaint.setStrokeWidth(20);
        fillPaint.setAntiAlias(true);
        fillPaint.setDither(true);
        fillPaint.setAlpha(250);
        fillPaint.setStrokeJoin(Paint.Join.ROUND);
        fillPaint.setStrokeCap(Paint.Cap.ROUND);
        fillPaints.add(fillPaint);
        Path path = new Path();
        Path fillPath = new Path();
        Path triangleTowerPath = new Path();
        this.triangleTowerPath = triangleTowerPath;
        this.triangleTowerPaints.add(paint);
        triangleTowerPaths.add(triangleTowerPath);
        Path trianglePath = new Path();
        trianglePaths.add(trianglePath);
        trianglePaints.add(paint);
        fillPaths.add(fillPath);
        paintPaths.add(path);
        Path anglePath = new Path();
        anglePaths.add(anglePath);
        this.anglePath = anglePath;
        this.anglePaints.add(paint);
        Path equilateralPath = new Path();
        this.equilateralPath = equilateralPath;
        equilateralPaths.add(equilateralPath);
        equilateralPaints.add(paint);
        if (pathType.equals("paintPath")) {
            selectPath = path;
        } else {
            selectPath = fillPath;
        }
    }

    public void setEraseMode() {
        eraseMode = true;
        drawPath = true;
        drawRect = false;
        drawTriangleTower = false;
        drawTriangle = false;
        drawCircle = false;
        drawEquilateral = false;
        drawRightAngle = false;
        erasePath = new Path();
        erasePaint.setAntiAlias(true);
        erasePaint.setDither(true);
        erasePaint.setStrokeWidth(30);
        erasePaint.setStyle(Paint.Style.STROKE);
        erasePaint.setStrokeJoin(Paint.Join.ROUND);
        erasePaint.setStrokeCap(Paint.Cap.SQUARE);
        erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
        selectPath = erasePath;
    }

    private class Circle {
        int pointX;
        int pointY;
        int radius;

        public int getPointX() {
            return pointX;
        }

        public void setPointX(int pointX) {
            this.pointX = pointX;
        }

        public int getPointY() {
            return pointY;
        }

        public void setPointY(int pointY) {
            this.pointY = pointY;
        }

        public int getRadius() {
            return radius;
        }

        public void setRadius(int radius) {
            this.radius = radius;
        }
    }
}

三、总结

绘制主要用到Paint和Path,大体思路都是监听OnTouchEvent事件,绘制路径或者其他图案,开发这个项目用时一周。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/926780.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

目标检测笔记(十一):如何结合特定区域进行目标检测(基于OpenCV的人脸检测实例)

文章目录 背景代码结果 背景 由于我们在做项目的时候可能会涉及到某个指定区域进行目标检测或者人脸识别等任务&#xff0c;所以这篇博客是为了探究如何在传统目标检测的基础上来结合特定区域进行检测&#xff0c;以OpenCV自带的包为例。 一般来说有两种方式实现区域指定&…

【AI模型】gym强化学习仿真平台配置与使用

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍gym强化学习仿真平台配置与使用。 无专精则不能成&#xff0c;无涉猎则不能通。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&…

Spring BeanName自动生成原理

先看代码演示 项目先定义一个User类 public class User {private String name;Overridepublic String toString() {return "User{" "name" name \ };}public String getName() {return name;}public void setName(String name) {this.name name;} }…

ensp启动设备AR1失败,错误代码: 40.详细:启动失败!串口登录端口号2000 冲突请指定新的端口。

1.重新打开ensp,点击注册设备&#xff0c;勾选全部&#xff0c;注册 2.关闭虚拟化&#xff0c;输入cmd,管理员身份运行命令提示符 输入一下代码&#xff0c;回车&#xff0c;然后重启电脑 bcdedit /set hypervisorlaunchtype off 3.重装ensp及其组件 eNSP下载链接&#xff1a…

集成学习:Bagging, Boosting,Stacking

目录 集成学习 一、bagging 二、boosting Bagging VS Boosting 1.1 集成学习是什么&#xff1f; Bagging Boosting Stacking 总结 集成学习 好比人做出一个决策时&#xff0c;会从不同方面&#xff0c;不同角度&#xff0c;不同层次去思考&#xff08;多个自我&am…

常见前端面试之VUE面试题汇总八

22. Vue 子组件和父组件执行顺序 加载渲染过程&#xff1a; 1.父组件 beforeCreate 2.父组件 created 3.父组件 beforeMount 4.子组件 beforeCreate 5.子组件 created 6.子组件 beforeMount 7.子组件 mounted 8.父组件 mounted 更新过程&#xff1a; 1. 父组件 befor…

【LeetCode-中等题】189. 轮转数组

题目 题解一&#xff1a;开辟数组 取模运算寻找位置(ik)mod n 新位置 思路&#xff1a;通过&#xff0c;开辟数组 取模运算寻找新位置------位置(ik)mod n 新位置 int[] newNums new int[nums.length];for(int i 0;i<nums.length;i){newNums[(ik)%nums.length] nums[i…

京东面试题:java中static 应用场景有哪些?

大家好&#xff0c;我是你们的小米&#xff01;今天我要和大家聊一个在Java中非常重要的关键词——static&#xff01;在京东的面试中&#xff0c;经常会遇到与static相关的问题&#xff0c;而我们今天就要揭开它的神秘面纱&#xff0c;深入探讨它在Java中的应用场景。无论你是…

IoTDB 集群环境搭建

什么是IoTDB IoTDB&#xff08;Internet of Things Database&#xff09;是一个专门设计用于存储和管理大规模物联网&#xff08;IoT&#xff09;数据的开源时序数据库系统。它专注于高效地存储、查询和分析时间序列数据&#xff0c;特别适用于物联网应用中的大量实时数据。 Io…

1146:判断字符串是否为回文

#include <iostream> #include <string> using namespace std; int main() {string str;// 输入一个字符串cin>>str;int nstr.length();for(int i0;i<n;i){if(str[i]!str[n-1-i]){cout<<"no"; // 如果发现不对称的字符&#xff0c;则输出…

系统学习Linux-LVS集群

集群概述 负载均衡技术类型 四层负载均衡器 也称为 4 层交换机&#xff0c;主要通过分析 IP 层及 TCP/UDP 层的流量实现基于 IP 加端口的负载均衡&#xff0c;如常见的 LVS、F5 等&#xff1b; 七层负载均衡器 也称为 7 层交换机&#xff0c;位于 OSI 的最高层&#xff0c;即…

第二讲Java基本语法(变量、数据类型、运算符)

一、前言导读 上一讲,我们安装java的开发工具idea,并且简单介绍如何使用,初步认识了Java的helloworld,我们写了第一行代码,有了初步的印象,接下来我们将真正展开对于java的了解,从这一讲开始,请大家做好笔记,改背的背。为什么说Java是一门编程语言呢,主要是他跟英语一…

控制疫情蔓延嵌入式物联网能帮大忙

联合国所订定之永续发展目标之一&#xff0c;便是针对防治传染病的蔓延做好准备。在新型冠状病毒(COVID-19)流行期间&#xff0c;防疫已成为当前最重要目标&#xff0c;科技在对抗传染病方面扮演重要角色&#xff0c;而物联网(IoT)相关技术正是我们重要的防疫武器──降低成本、…

网络渗透day2-Windows服务器服务管理相关

1.在Windows Server中&#xff0c;用于监视网络连接和流量的工具是&#xff1f; A.Event Viewer B.Performance Monitor C.Task Scheduler D.Resource Monitor 正确答案&#xff1a;D 你的答案&#xff1a;B 解析&#xff1a; 答案解析&#xff1a;Resource Monitor用于监…

【Jetpack】Navigation 导航组件 ④ ( Fragment 跳转中使用 safe args 安全传递参数 )

文章目录 一、页面跳转间的传统的数据传递方式1、传统的数据传递方式 - Bundle 传递数据1、Navigation 组件中的 Bundle 数据传递2、传统数据传递实现步骤3、FragmentA 完整代码示例4、FragmentB 完整代码示例5、执行结果 2、使用 Bundle 传递数据安全性差 二、页面跳转间的传统…

Linux详解(包含Linux安装教程)

文章目录 Linux详解一、安装Linux操作系统VMware介绍安装虚拟机VMware下载centos 7系统安装centos 7系统 二、Linux基础命令Linux的目录结构Linux命令入门目录切换相关命令 cd、pwd相对路径、绝对路径和特殊路径符掌握通过mkdir命令创建文件夹文件操作命令touch、cat、more文件…

APT80DQ60BG-ASEMI新能源功率器件APT80DQ60BG

编辑&#xff1a;ll APT80DQ60BG-ASEMI新能源功率器件APT80DQ60BG 型号&#xff1a;APT80DQ60BG 品牌&#xff1a;ASEMI 芯片个数&#xff1a;2 封装&#xff1a;TO-3P 恢复时间&#xff1a;&#xff1e;50ns 工作温度&#xff1a;-55C~150C 浪涌电流&#xff1a;600A …

Python“牵手”易贝(Ebay)商品列表数据,关键词搜索ebayAPI接口数据,ebayAPI接口申请指南

Ebay平台API接口是为开发电商类应用程序而设计的一套完整的、跨浏览器、跨平台的接口规范&#xff0c; EbayAPI接口是指通过编程的方式&#xff0c;让开发者能够通过HTTP协议直接访问Ebay平台的数据&#xff0c;包括商品信息、店铺信息、物流信息等&#xff0c;从而实现Ebay平…

Etsy如何安全养店?7个因素你要知道

Etsy是全球大型的创意市场电商平台&#xff0c;很多跨境玩家在开店之后&#xff0c;兴致冲冲开始上架&#xff0c;结果流量没有不说&#xff0c;很快店铺就被封禁。注意了&#xff01;Etsy也是一个规则比较严格的平台&#xff0c;想要做好Etsy&#xff0c;一定要看好下面这7个因…

【Java 动态数据统计图】前后端对接数据格式(Map返回数组格式数据)六(120)

说明&#xff1a; 前端使用&#xff1a;vue3.0 前后端对接数据格式&#xff1a;无非就是前端把后端返回的数据处理为自己想要的格式&#xff0c;或者&#xff0c;后端给前端处理好想要的格式&#xff1b; 针对前后端的柱状图&#xff0c;趋势图等数据对接&#xff0c;前端一般需…