Bitmap画板

又是一天。

1.根据我看比别人软件的习惯,是先看xml的再看MainActivity,先写XML


<span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/frameLayout_1"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
<com.example.hejingzhou.drawdemo.DrawActivity
    android:id="@+id/drawActivity_1"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />
</FrameLayout></span>

2.MainActivity   主要是菜单的Select


2.1.再写MainActivity前需要写一个菜单

记住这个菜单名别在后边读代码的时候不知道从哪里来的



<?xml version="1.0" encoding="utf-8"?>
<span style="font-size:14px;color:#990000;"><menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:title="画笔颜色">
        <menu>
            <!--定义一组单选菜单项-->
            <group android:checkableBehavior="single">
                <item android:id="@+id/red" android:title="红色"/>
                <item android:id="@+id/green" android:title="绿色"/>
                <item android:id="@+id/blue" android:title="蓝色"/>
            </group>
        </menu>
    </item>
    <item android:title="画笔宽度">
        <menu>
            <group>
                <item android:id="@+id/width_1" android:title="1像素"/>
                <item android:id="@+id/width_5" android:title="5像素"/>
                <item android:id="@+id/width_10" android:title="10像素"/>
            </group>
        </menu>
    </item>
    <item android:id="@+id/clear" android:title="擦除绘画"/>
    <item android:id="@+id/save" android:title="保存绘画"/>
    <item android:id="@+id/fullClear" android:title="清空画板"/>
</menu></span>




<span style="color:#ff6600;"><span style="font-size:18px;">package com.example.hejingzhou.drawdemo;

import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.FrameLayout;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    //创建菜单
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater inflator = new MenuInflater(this);//实例化一个MenuInflater对象 菜单填充器
        inflator.inflate(R.menu.tools, menu);
        return super.onCreateOptionsMenu(menu);
    }
    //重写菜单方法
    public boolean onOptionsItemSelected(MenuItem item) {
        DrawActivity drawActivity = (DrawActivity)findViewById(R.id.drawActivity_1);
        drawActivity.paint.setXfermode(null);//取消擦出效果
        drawActivity.paint.setStrokeWidth(1);//初始化画笔的宽度

        switch (item.getItemId())//返回菜单项的标识符
        {
            /***
             * 设置paint颜色
             */
            case R.id.red:
                drawActivity.paint.setColor(Color.RED);
                item.setChecked(true);
                break;
            case R.id.blue:
                drawActivity.paint.setColor(Color.BLUE);
                item.setChecked(true);
                break;
            case R.id.green:
                drawActivity.paint.setColor(Color.GREEN);
                item.setChecked(true);
                break;
            /***
             * 设置笔宽
             */
            case R.id.width_1:
                drawActivity.paint.setStrokeWidth(1);
                item.setChecked(true);
                break;
            case R.id.width_5:
                drawActivity.paint.setStrokeWidth(5);
                item.setChecked(true);
                break;
            case R.id.width_10:
                drawActivity.paint.setStrokeWidth(10);
                item.setChecked(true);
                break;
            case R.id.clear:
                drawActivity.clear();
                break;
            case R.id.fullClear:
                Toast.makeText(MainActivity.this,"Sorry  不知道咋弄了  用橡皮擦大宽度重写笔按说可以,肯定有清空Bitmap的方法",Toast.LENGTH_SHORT).show();
                //drawActivity.fillClear();
                break;
            case  R.id.save:
                drawActivity.save();
                Toast.makeText(MainActivity.this,"貌似有错",Toast.LENGTH_SHORT).show();
                break;
        }
            return true;
    }
}</span>
</span>


3.画图的主类 命名是Activity结尾的,并不继承Activity思路别误会了 

<span style="font-size:18px;"><span style="color:#666600;">package com.example.hejingzhou.drawdemo;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

/**
 * Created by Hejingzhou on 2015/12/12.
 */
public class DrawActivity extends View {
    private int view_width = 0;//屏幕宽度
    private int view_height = 0;//屏幕高度
    private float preX;//起始点的X坐标
    private float preY;//起始点的Y坐标
    private Path path;
    public Paint paint = null;
    Bitmap cacheBitmap = null;//定义一个内存中的图片,该图片将作为缓冲区
    Canvas cacheCanvas = null;//定义一个画布

    public DrawActivity(Context context,AttributeSet attributeSet)//写一个构造方法初始化类
    {
        super(context, attributeSet);
        view_width = context.getResources().getDisplayMetrics().widthPixels;//获取屏幕的宽度   /*显示度量标准*宽像素
        view_height = context.getResources().getDisplayMetrics().heightPixels;//获取屏幕的高度

        //创建一个与该View相同大小的缓冲区
        cacheBitmap = Bitmap.createBitmap(view_width,view_height, Bitmap.Config.ARGB_8888);
        /***
         * Bitmap.Config 	ALPHA_8 	Each pixel is stored as a single translucency (alpha) channel.
         Bitmap.Config 	ARGB_4444 	This field was deprecated in API level 13. Because of the poor quality of this configuration, it is advised to use ARGB_8888 instead.
         Bitmap.Config 	ARGB_8888 	Each pixel is stored on 4 bytes.
         Bitmap.Config 	RGB_565 	Each pixel is stored on 2 bytes and only the RGB channels are encoded: red is stored with 5 bits of precision (32 possible values), green is stored with 6 bits of precision (64 possible values) and blue is stored with 5 bits of precision.
         可以参考  http://blog.csdn.net/wulongtiantang/article/details/8481077
         */
        cacheCanvas = new Canvas();
        path = new Path();
        cacheCanvas.setBitmap(cacheBitmap);//在cache的上边绘制cacheBitmap
        paint = new Paint(Paint.DITHER_FLAG);//抗抖动
        /**Paint flag that enables dithering when blitting.
         Enabling this flag applies a dither to any blit operation
         where the target's colour space is more constrained than the source.*/
        paint.setColor(Color.RED);
        //设置画笔风格
        paint.setStyle(Paint.Style.STROKE);//填充轮廓
        paint.setStrokeJoin(Paint.Join.ROUND);//??????????????????????????????????????????
        paint.setStrokeCap(Paint.Cap.BUTT);//?????????????????????????????????
        paint.setStrokeWidth(8);//设置笔触宽度
        paint.setAntiAlias(true);//设置抗锯齿功能,稍微耗费内存
        paint.setDither(true);//使用抖动效果对手抖动结果进行处理
    }
    @Override
    public void onDraw(Canvas canvas) {//重写绘制方法
        canvas.drawColor(0xFFFFFFFF);//设置背景色
        Paint bmpPaint = new Paint();
        canvas.drawBitmap(cacheBitmap, 0, 0, bmpPaint);//绘制cacheBitmap   //注释掉后画完一笔后不保留绘图
        /**   drawBitmap_API
         bitmap	The bitmap to be drawn
         left	The position of the left side of the bitmap being drawn
         top	The position of the top side of the bitmap being drawn
         paint	The paint used to draw the bitmap (may be null)*/
        canvas.drawPath(path, paint);
        canvas.save(Canvas.ALL_SAVE_FLAG);//保存Canvas的状态
        canvas.restore();//恢复canver之前保存的状态 ,防止保存后对canver执行的操作对后续的绘制有影响
        //super.onDraw(canvas);
    }
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getRawX();
        float y = event.getRawY();
        switch (event.getAction())
        {
            case MotionEvent.ACTION_DOWN://按下时  只是将该点坐标设置为起点坐标
                path.moveTo(x,y);//将这个点设置为路径的起点
                preX = x;//将x值赋给 起始X坐标
                preY = y;
                break;
            case MotionEvent.ACTION_MOVE://手势(ACTION_DOWN和ACTION_UP之间)。包含最近点的运动,以及任何中间点自上一下按下或移动事件。
                float dx = Math.abs(x-preX);//取绝对值赋给dx
                float dy = Math.abs(y-preY);
                if(dx >= 5 || dy>=5)//判断是否在允许的范围内
                {
                    path.quadTo(preX,preY,(x+preX)/2,(y+preY)/2);
                    /***添加一种二次贝塞尔曲线,从过去点,逼近控制点(x1,y1)和结束(x2,y2)。
                     * 如果没有moveTo()调用了这个轮廓,首先自动设置为(00)*/
                    preX = x;
                    preY = y;
                }
                break;
            case MotionEvent.ACTION_UP://位置以及任何中间点从过去或移动事件后,一个按下的动作完成了。
                cacheCanvas.drawPath(path,paint);//绘制路径
                path.reset();//复位
                break;
        }
        invalidate();//整个视图无效。 如果视图可见,onDraw(android.graphics.Canvas)将在未来某个时候调用。
        return true;//返回ture 表明处理方法已经处理该事件
    }
    /**Clear方法实现橡皮擦功能*/
    public void clear()
    {                         // 波特-达夫相交    相交模式       清理
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));//设置图形重叠时的处理方式
        paint.setStrokeWidth(30);//相交宽度
    }
    /*public void fillClear()
    {
           啥时候学会了就把这个洞补起来
    }*/
    public void save()
    {
        try {
            saveBitmap("myPicture");
        }catch (IOException e)
        {
            e.printStackTrace();
        }
    }
    public void saveBitmap(String fileName)throws IOException
    {
       File file = new File("/data/NewFile/"+fileName+".png");//创建文件对象   //如果需要写入SD卡中那么需要添加加权限
       file.createNewFile();//创建一个新文件
        FileOutputStream fileOS = new FileOutputStream(file);
       //将绘图内容压缩为Png格式输出到输出流的对象中
        cacheBitmap.compress(Bitmap.CompressFormat.PNG, 100, fileOS);
        /**@param format   The format of the compressed image
         * @param quality  Hint to the compressor, 0-100. 0 meaning compress for
         *                 small size, 100 meaning compress for max quality. Some
         *                 formats, like PNG which is lossless, will ignore the
         *                 quality setting   为0?100?null?
         * @param stream   The outputstream to write the compressed data.
         * */
        fileOS.flush();  //将缓冲区中的数据全部写出到输出流中
        fileOS.close();  //关闭文件输出流对象
    }
}</span><span style="color:#ff0000;">
</span></span>




4.个别参数方法的值变化带来的变化






5.橡皮擦擦的过程 黑色线条



6.橡皮擦擦完



源码:http://download.csdn.net/detail/csdnhejingzhou/9350383

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值