简易的Android绘图程序

因为要保存图片,所以先添加权限。

设计自定义的view:DevinDrawPanle,设计很多的图形和提供调用的方法,所代码比较多

/**
 * 自定义绘图面板
 * Created by Devin Chen on 2016/12/22.
 */

public class DevinDrawPanle extends View {

    private Canvas mCanvas;//画布

    private Paint mPaint;//画笔
    private Paint mBitmapPaint;//专门绘制图片的画笔;

    private Path mPath;//手绘路径

    private Bitmap mBitmap;//图片
    private Bitmap mTempBitmap;//临时图片

    private int shapeStyle = 0;//形状

    private int mWidth, mHeight;//宽高
    private float drawX, drawY;//绘制点
    //绘制幅度,当一个方向上触摸移动等于这个距离就绘制一条线,quadTo是绘制贝塞尔曲线
    private final static int TOUCH_TOLERANCE = 4;

    public DevinDrawPanle(Context context) {
        super(context);
        initView();
    }

    public DevinDrawPanle(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public DevinDrawPanle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView();
    }

    /**
     * 初始化
     */
    private void initView() {
        initPaints();//初始化画笔
        mPath = new Path();//初始化绘图路径
    }

    /**
     * 初始化画笔
     */

    private void initPaints() {
        //绘图画笔
        mPaint = new Paint();//用数组管理画笔
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);
        mPaint.setStrokeWidth(1);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setStrokeJoin(Paint.Join.ROUND);
        mPaint.setStrokeCap(Paint.Cap.ROUND);
        //绘制图片的画笔
        mBitmapPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mWidth = w;
        mHeight = h;
        mBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
        mCanvas = new Canvas(mBitmap);
        //绘制背景
        mCanvas.drawColor(Color.WHITE);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);//使用这一句,每次调用都把画好的图片在此绘制一遍,可保留绘画痕迹
        canvas.drawPath(mPath, mPaint);//不断被调用,不断绘制
    }

    /**
     * 触摸事件
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN://按下
                touchStart(x, y);
                break;
            case MotionEvent.ACTION_MOVE://移动
                touchMove(x, y);
                break;
            case MotionEvent.ACTION_UP://提起
                touchEnd(x, y);
                break;
            default:
                break;
        }
        invalidate();//刷新视图
        return true;
    }

    /**
     * 绘制结束
     *
     * @param x
     * @param y
     */
    private void touchEnd(float x, float y) {
        switch (shapeStyle) {
            case 0:
                drawBezierEnd(x, y);//绘制贝塞尔曲线结束
                break;
            case 1:
                drawLine(x, y);
                break;
            case 2:
                drawRect(x, y);
                break;
            case 3:
                drawCircle(x, y);
                break;
            case 4:
                drawOval(x, y);
                break;
            case 5:
                drawRoundRect(x, y);
                break;
            default:
                break;
        }
    }

    /**
     * 绘制贝塞尔曲线结束
     *
     * @param x
     * @param y
     */
    private void drawBezierEnd(float x, float y) {
        mPath.lineTo(x, y);
        mCanvas.drawPath(mPath, mPaint);//这句必须要,否则绘制的东西立即消失
        mPath.reset();
    }

    /**
     * 绘制path
     *
     * @param x
     * @param y
     */
    private void touchMove(float x, float y) {
        //装载临时图片,不抬起就不会真正画到画布上,画贝塞尔除外
        mCanvas.drawBitmap(mTempBitmap, 0, 0, mBitmapPaint);
        switch (shapeStyle) {
            case 0:
                drawBezier(x, y);//绘制贝塞尔曲线
                break;
            case 1:
                drawLine(x, y);//绘制直线
                break;

            case 2:
                drawRect(x, y);//绘制矩形
                break;
            case 3:
                drawCircle(x, y);//绘制圆
                break;
            case 4:
                drawOval(x, y);//绘制椭圆
                break;
            case 5:
                drawRoundRect(x, y);//绘制圆角矩形,圆角12
                break;
            default:
                break;
        }
    }

    /**
     * 绘制直线
     *
     * @param x
     * @param y
     */
    private void drawLine(float x, float y) {
        mCanvas.drawLine(drawX, drawY, x, y, mPaint);
    }


    /**
     * 绘制矩形
     *
     * @param x
     * @param y
     */
    private void drawRect(float x, float y) {
        mCanvas.drawRect(drawX, drawY, x, y, mPaint);
    }

    /**
     * 绘制圆
     *
     * @param x
     * @param y
     */
    private void drawCircle(float x, float y) {
        //求得圆心位置
        float cx = (drawX + x) / 2;
        float cy = (drawY + y) / 2;
        //求得半径
        float radius = (float) Math.sqrt(Math.pow(x - drawX, 2) + Math.pow(y - drawY, 2)) / 2;//半径等于对角线的一半
        mCanvas.drawCircle(cx, cy, radius, mPaint);
    }

    /**
     * 绘制椭圆
     *
     * @param x
     * @param y
     */
    private void drawOval(float x, float y) {
        RectF rectF = new RectF(drawX, drawY, x, y);
        mCanvas.drawOval(rectF, mPaint);
    }

    /**
     * 绘制圆角矩形
     *
     * @param x
     * @param y
     */
    private void drawRoundRect(float x, float y) {
        RectF rectF = new RectF(drawX, drawY, x, y);
        mCanvas.drawRoundRect(rectF, 12, 12, mPaint);
    }

    /**
     * 绘制贝塞尔曲线
     *
     * @param x
     * @param y
     */
    private void drawBezier(float x, float y) {
        float dx = Math.abs(x - drawX);
        float dy = Math.abs(y - drawY);//计算绘制距离
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            //绘制一阶贝赛尔曲线,前两个参数为控制点,后两个为结束点
            mPath.quadTo((x + drawX) / 2, (y + drawY) / 2, x, y);//这里以中间位置为控制点
            drawX = x;
            drawY = y;//重新记录绘画点
        }
    }

    /**
     * 绘制开始
     *
     * @param x
     * @param y
     */
    private void touchStart(float x, float y) {
        mPath.reset();//路径工具复位
        mPath.moveTo(x, y);//绘制点移动
        drawX = x;
        drawY = y;//记录下来,作为正式绘制的起始点
        mTempBitmap = Bitmap.createBitmap(mBitmap);//保存临时图片
    }

    public void saveBitmap(File file) {
        //如果文件夹不存在则创建
        if (!file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        //如果文件不存在则创建
        if (!file.exists()) {
            try {
                file.createNewFile();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        OutputStream outputStream = null;
        BufferedOutputStream bos=null;
        try {
            outputStream = new FileOutputStream(file);//输出流
            bos = new BufferedOutputStream(outputStream);//缓冲输出流
            mBitmap.compress(Bitmap.CompressFormat.PNG, 100, bos);//压缩图像到输出流
            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 设置画笔颜色
     *
     * @param color
     */
    public void setPaintColor(@ColorInt int color) {
        mPaint.setColor(color);
    }

    /**
     * 设置画笔颜色
     *
     * @param colorID 从资源文件中获取
     */
    public void setPaintColorFromResources(@ColorRes int colorID) {
        mPaint.setColor(getResources().getColor(colorID));
    }

    /**
     * 设置画笔颜色
     *
     * @param color 从字符串解析
     */
    public void setPaintColor(String color) {
        try {
            //有可能解析失败
            mPaint.setColor(Color.parseColor(color));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置画笔粗细
     *
     * @param width
     */
    public void setPaintStrokeWidth(float width) {
        mPaint.setStrokeWidth(width);
    }

    /**
     * 画矩形
     *
     * @param left
     * @param top
     * @param right
     * @param bottom
     */
    public void drawRect(float left, float top, float right, float bottom) {
        mCanvas.drawRect(left, top, right, bottom, mPaint);
    }

    /**
     * 获得画布
     *
     * @return
     */
    public Canvas getCanvas() {
        return mCanvas;
    }

    /**
     * 获得画笔
     *
     * @return
     */
    public Paint getPaint() {
        return mPaint;
    }

    /**
     * 设置绘制形状
     *
     * @param shapeStyle
     */
    public void setShapeStyle(int shapeStyle) {
        this.shapeStyle = shapeStyle;
    }
}

这样就可以调用了。

设计菜单文件:

1.menu_main_option.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/menu_item_save"
        android:title="保存" />

</menu>

2.menu_paint_colors.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@+id/color_red" android:title="红色"/>
    <item android:id="@+id/color_orange" android:title="橙色"/>
    <item android:id="@+id/color_yellow" android:title="黄色"/>
    <item android:id="@+id/color_green" android:title="绿色"/>
    <item android:id="@+id/color_cyan" android:title="青色"/>
    <item android:id="@+id/color_blue" android:title="蓝色"/>
    <item android:id="@+id/color_purple" android:title="紫色"/>
    <item android:id="@+id/color_black" android:title="黑色"/>
    <item android:id="@+id/color_white" android:title="白色"/>
    <item android:id="@+id/color_gray" android:title="灰色"/>
</menu>

3.menu_line_style.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@+id/drawline1" android:title="1"/>
    <item android:id="@+id/drawline2" android:title="2"/>
    <item android:id="@+id/drawline3" android:title="3"/>
    <item android:id="@+id/drawline4" android:title="4"/>
    <item android:id="@+id/drawline5" android:title="5"/>
</menu>

4.menu_shape_style.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:id="@+id/drawbezier" android:title="自由线"/>
    <item android:id="@+id/drawline" android:title="直线"/>
    <item android:id="@+id/drawrect" android:title="矩形"/>
    <item android:id="@+id/drawcircle" android:title="圆形"/>
    <item android:id="@+id/drawoval" android:title="椭圆"/>
    <item android:id="@+id/drawroundrect" android:title="圆角矩形"/>
</menu>


最后是主程序:MainActivity.java

/**
 * 简易绘画程序
 */
public class MainActivity extends AppCompatActivity {
    private DevinDrawPanle drawPanle;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        drawPanle = new DevinDrawPanle(this);
        setContentView(drawPanle);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main_option, menu);
        //添加子菜单
        SubMenu mnLineColor = menu.addSubMenu("颜色");
        SubMenu mnLineStyle = menu.addSubMenu("线型");
        SubMenu mnShapeStyle = menu.addSubMenu("形状");
        //实例化子菜单
        getMenuInflater().inflate(R.menu.menu_paint_colors, mnLineColor);
        getMenuInflater().inflate(R.menu.menu_line_style, mnLineStyle);
        getMenuInflater().inflate(R.menu.menu_shape_style, mnShapeStyle);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case R.id.menu_item_save:
                saveFile();
                break;
            //颜色选择
            case R.id.color_red:
                drawPanle.setPaintColor(Color.RED);
                break;
            case R.id.color_orange:
                drawPanle.setPaintColor("#FF6600");//有重载形式
                break;
            case R.id.color_yellow:
                drawPanle.setPaintColor(Color.YELLOW);
                break;
            case R.id.color_green:
                drawPanle.setPaintColor(Color.GREEN);
                break;
            case R.id.color_cyan:
                drawPanle.setPaintColor("#0055CC");
                break;
            case R.id.color_blue:
                drawPanle.setPaintColor(Color.BLUE);
                break;
            case R.id.color_purple:
                drawPanle.setPaintColor("#8800CC");
                break;
            case R.id.color_black:
                drawPanle.setPaintColor(Color.BLACK);
                break;
            case R.id.color_gray:
                drawPanle.setPaintColor(Color.GRAY);
                break;

            //设置线条粗细
            case R.id.drawline1:
                drawPanle.setPaintStrokeWidth(1);
                break;
            case R.id.drawline2:
                drawPanle.setPaintStrokeWidth(2);
                break;
            case R.id.drawline3:
                drawPanle.setPaintStrokeWidth(3);
                break;
            case R.id.drawline4:
                drawPanle.setPaintStrokeWidth(4);
                break;
            case R.id.drawline5:
                drawPanle.setPaintStrokeWidth(5);
                break;
            //设置形状
            case R.id.drawbezier:
                drawPanle.setShapeStyle(0);
                break;
            case R.id.drawline:
                drawPanle.setShapeStyle(1);
                break;
            case R.id.drawrect:
                drawPanle.setShapeStyle(2);
                break;
            case R.id.drawcircle:
                drawPanle.setShapeStyle(3);
                break;
            case R.id.drawoval:
                drawPanle.setShapeStyle(4);
                break;
            case R.id.drawroundrect:
                drawPanle.setShapeStyle(5);
                break;

            default:
                break;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * 保存文件
     */
    private void saveFile() {
        File saveFile = new File(Environment.getExternalStorageDirectory(), "mybmp2.png");
        drawPanle.saveBitmap(saveFile);
        Toast.makeText(this, "文件保存在:" + saveFile.getAbsolutePath(), Toast.LENGTH_SHORT).show();
    }
}

运行效果:



评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值