自定义的画画板

//自定义的画画板,需要在代码中添加,与他的父控件大小一样

public class TuyaView extends View {  
    private Context context;  
    private Bitmap mBitmap;  
    private Canvas mCanvas;  
    private Path mPath;  
    private Paint mBitmapPaint;// 画布的画笔  
    private Paint mPaint;// 真实的画笔  
    private float mX, mY;// 临时点坐标  
    private static final float TOUCH_TOLERANCE = 4;  
    // 保存Path路径的集合  
    private static List<DrawPath> savePath;  
    // 保存已删除Path路径的集合  
    private static List<DrawPath> deletePath;  
    // 记录Path路径的对象  
    private DrawPath dp;  
    private int screenWidth, screenHeight;  
    private int currentColor = Color.RED;  
    private int currentSize = 5;  
    private int currentStyle = 1;  
    private int[] paintColor;//颜色集合  
    private class DrawPath {  
        public Path path;// 路径  
        public Paint paint;// 画笔  
    }  
    public TuyaView(Context context, int w, int h) {  
        super(context);  
        this.context = context;  
        screenWidth = w;  
        screenHeight = h;  
        paintColor = new int[]{  
                Color.RED, Color.BLUE, Color.GREEN, Color.YELLOW, Color.BLACK, Color.GRAY, Color.CYAN  
        };  
        setLayerType(LAYER_TYPE_SOFTWARE,null);//设置默认样式,去除dis-in的黑色方框以及clear模式的黑线效果  
        initCanvas();  
        savePath = new ArrayList<DrawPath>();  
        deletePath = new ArrayList<DrawPath>();  
    }  
    public void initCanvas() {  
        setPaintStyle();  
        mBitmapPaint = new Paint(Paint.DITHER_FLAG); //抗抖动  
        //画布大小  
        mBitmap = Bitmap.createBitmap(screenWidth, screenHeight, Bitmap.Config.ARGB_8888);  
        mBitmap.eraseColor(Color.argb(0, 0, 0, 0)); //Bitmap的背景颜色  
        mCanvas = new Canvas(mBitmap);  //所有mCanvas画的东西都被保存在了mBitmap中  
        mCanvas.drawColor(Color.TRANSPARENT);  
    }  
    //初始化画笔样式  
    private void setPaintStyle() {  
        mPaint = new Paint();  
        mPaint.setStyle(Paint.Style.STROKE);  
        mPaint.setStrokeJoin(Paint.Join.ROUND);// 设置外边缘  
        mPaint.setStrokeCap(Paint.Cap.ROUND);// 形状  
        mPaint.setAntiAlias(true); // 抗锯齿  
        mPaint.setDither(true); // 防抖动  
        if (currentStyle == 1) {  
            mPaint.setStrokeWidth(currentSize);    //线宽  
            mPaint.setColor(currentColor);        //颜色  
        } else {   //橡皮擦  
            mPaint.setAlpha(0);  
            mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));  
            mPaint.setColor(Color.TRANSPARENT);  
            mPaint.setStrokeWidth(50);  
        }  
    }  
    @Override  
    public void onDraw(Canvas canvas) {  
        //canvas.drawColor(0xFFAAAAAA);  
        // 将前面已经画过得显示出来  
        canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);  
        if (mPath != null) {  
            // 实时的显示  
            canvas.drawPath(mPath, mPaint);  
        }  
    }  
    private void touch_start(float x, float y) {  
        mPath.moveTo(x, y);  
        mX = x;  
        mY = y;  
    }  
    private void touch_move(float x, float y) {  
        float dx = Math.abs(x - mX);  
        float dy = Math.abs(mY - y);  
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {  
            // 从x1,y1到x2,y2画一条贝塞尔曲线,更平滑(直接用mPath.lineTo也可以)  
            mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);  
            //mPath.lineTo(mX,mY);  
            mX = x;  
            mY = y;  
        }  
    }  
    private void touch_up() {  
        mPath.lineTo(mX, mY);  
        mCanvas.drawPath(mPath, mPaint);  
        //将一条完整的路径保存下来   保存路径和画笔  
        savePath.add(dp);  
        mPath = null;// 重新置空  
    }  
    /**  
     * 撤销  
     * 撤销的核心思想就是将画布清空,  
     * 将保存下来的Path路径最后一个移除掉,  
     * 重新将路径画在画布上面。  
     */  
    public void undo() {  
        if (savePath != null && savePath.size() > 0) {  
            DrawPath drawPath = savePath.get(savePath.size() - 1);  
            deletePath.add(drawPath);  
            savePath.remove(savePath.size() - 1);  
            redrawOnBitmap();  
        }  
    }  
    /**  
     * 重做  
     */  
    public void redo() {  
        if (savePath != null && savePath.size() > 0) {  
            savePath.clear();  
            redrawOnBitmap();  
        }  
    }  
    private void redrawOnBitmap() {  
        /*mBitmap = Bitmap.createBitmap(screenWidth, screenHeight,  
                Bitmap.Config.RGB_565);  
        mCanvas.setBitmap(mBitmap);// 重新设置画布,相当于清空画布*/  
        initCanvas();  
        Iterator<DrawPath> iter = savePath.iterator();  
        while (iter.hasNext()) {  
            DrawPath drawPath = iter.next();  
            mCanvas.drawPath(drawPath.path, drawPath.paint);  
        }  
        invalidate();// 刷新  
    }  
    /**  
     * 恢复,恢复的核心就是将删除的那条路径重新添加到savapath中重新绘画即可  
     */  
    public void recover() {  
        if (deletePath.size() > 0) {  
            //将删除的路径列表中的最后一个,也就是最顶端路径取出(栈),并加入路径保存列表中  
            DrawPath dp = deletePath.get(deletePath.size() - 1);  
            savePath.add(dp);  
            //将取出的路径重绘在画布上  
            mCanvas.drawPath(dp.path, dp.paint);  
            //将该路径从删除的路径列表中去除  
            deletePath.remove(deletePath.size() - 1);  
            invalidate();  
        }  
    }  
    @Override  
    public boolean onTouchEvent(MotionEvent event) {  
        float x = event.getX();  
        float y = event.getY();  
        switch (event.getAction()) {  
            case MotionEvent.ACTION_DOWN:  
                // 每次down下去重新new一个Path  
                mPath = new Path();  
                //每一次记录的路径对象是不一样的  
                dp = new DrawPath();  
                dp.path = mPath;  
                dp.paint = mPaint;  
                touch_start(x, y);  
                invalidate();  
                break;  
            case MotionEvent.ACTION_MOVE:  
                touch_move(x, y);  
                invalidate();  
                break;  
            case MotionEvent.ACTION_UP:  
                touch_up();  
                invalidate();  
                break;  
        }  
        return true;  
    }  
    //保存到sd卡  
    public void saveToSDCard() {  
//        public static final String LOAD_TASK_PATH = "/mnt/sdcard/Navpad/airport/飞行卡片";  
        //获得系统当前时间,并以该时间作为文件名  
        SimpleDateFormat formatter = new SimpleDateFormat("yyyyMMddHHmmss");  
        Date curDate = new Date(System.currentTimeMillis());//获取当前时间  
        String str = formatter.format(curDate) + "paint.png";  
        File file = new File("sdcard/picture");  
        file.mkdirs();  
        FileOutputStream fos = null;  
        if (file.exists()){  
        }else {  
            try {  
                file.createNewFile();  
            } catch (IOException e) {  
                e.printStackTrace();  
                Toast.makeText(context,"不存在",Toast.LENGTH_SHORT).show();  
            }  
        }  
        if (file.exists()){  
            try {  
                fos = new FileOutputStream(file.getAbsolutePath()+"/"+str);  
                mBitmap.compress(CompressFormat.PNG, 100, fos);  
                //发送Sd卡的就绪广播,要不然在手机图库中不存在  
//                Intent intent = new Intent(Intent.ACTION_MEDIA_MOUNTED);  
//                intent.setData(Uri.fromFile(Environment.getExternalStorageDirectory()));  
//                context.sendBroadcast(intent);  
                redo();  
                Toast.makeText(context,"图片已保存",Toast.LENGTH_SHORT).show();  
            } catch (Exception e) {  
                e.printStackTrace();  
                Toast.makeText(context,"保存失败",Toast.LENGTH_SHORT).show();  
            }  
        }else {  
            Toast.makeText(context,"保存失败2",Toast.LENGTH_SHORT).show();  
        }  
  
  
    }  
    //以下为样式修改内容  
    //设置画笔样式  
    public void selectPaintStyle(int which) {  
        if (which == 0) {  
            currentStyle = 1;  
            setPaintStyle();  
        }  
        //当选择的是橡皮擦时,设置颜色为白色  
        if (which == 1) {  
            currentStyle = 2;  
            setPaintStyle();  
        }  
    }  
    //选择画笔大小  
    public void selectPaintSize(int which) {  
        //int size = Integer.parseInt(this.getResources().getStringArray(R.array.paintsize)[which]);  
        currentSize = which;  
        setPaintStyle();  
    }  
    //设置画笔颜色  
    public void selectPaintColor(int which) {  
        currentColor = paintColor[which];  
        setPaintStyle();  
    }  
}  

// 主要的activity,需要加载,向framLayout中添加TuyaView,需要获取屏幕的宽高,实际涂鸦宽高是控件的

自定义涂鸦板 
public class MainActivity extends AppCompatActivity implements View.OnClickListener{  
    private String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};  
    private FrameLayout frameLayout;  
    private Button btn_undo;  
    private Button btn_redo;  
    private Button btn_save;  
    private Button btn_recover;  
    private TuyaView tuyaView;//自定义涂鸦板  
    private Button btn_paintcolor;  
    private Button btn_paintsize;  
    private Button btn_paintstyle;  
    private SeekBar sb_size;  
    @Override  
    protected void onCreate(Bundle savedInstanceState) {  
        super.onCreate(savedInstanceState);  
        setContentView(R.layout.activity_main);  
        frameLayout = (FrameLayout) findViewById(R.id.fl_container);  
        initView();  
        initData();  
        initListener();  
    }  
    private void initView() {  
        btn_undo = (Button) findViewById(R.id.btn_last);  
        btn_redo = (Button) findViewById(R.id.btn_redo);  
        btn_save = (Button) findViewById(R.id.btn_savesd);  
        btn_recover = (Button) findViewById(R.id.btn_recover);  
        btn_paintcolor = (Button) findViewById(R.id.btn_paintcolor);  
        btn_paintsize = (Button) findViewById(R.id.btn_paintsize);  
        btn_paintstyle = (Button) findViewById(R.id.btn_paintstyle);  
        sb_size = (SeekBar) findViewById(R.id.sb_size);  
    }  
  
    private void initData() {   //虽然此时获取的是屏幕宽高,但是我们可以通过控制framlayout来实现控制涂鸦板大小  
        Display defaultDisplay = getWindowManager().getDefaultDisplay();  
        int screenWidth = defaultDisplay.getWidth();  
        int screenHeight = defaultDisplay.getHeight();  
        tuyaView = new TuyaView(this,screenWidth,screenHeight);  
        frameLayout.addView(tuyaView);  
        tuyaView.requestFocus();  
        tuyaView.selectPaintSize(30);  
        sb_size.setProgress(30);  
    }  
    private void initListener() {  
        btn_undo.setOnClickListener(this);  
        btn_redo.setOnClickListener(this);  
        btn_save.setOnClickListener(this);  
        btn_recover.setOnClickListener(this);  
        btn_paintcolor.setOnClickListener(this);  
        btn_paintsize.setOnClickListener(this);  
        btn_paintstyle.setOnClickListener(this);  
        sb_size.setOnSeekBarChangeListener(new MySeekChangeListener());  
    }  
    class MySeekChangeListener implements SeekBar.OnSeekBarChangeListener {  
        @Override  
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {  
            tuyaView.selectPaintSize(seekBar.getProgress());  
            //Toast.makeText(MainActivity.this,"当前画笔尺寸为"+seekBar.getProgress(),Toast.LENGTH_SHORT ).show();  
        }  
        @Override  
        public void onStartTrackingTouch(SeekBar seekBar) {  
            tuyaView.selectPaintSize(seekBar.getProgress());  
            //Toast.makeText(MainActivity.this,"当前画笔尺寸为"+seekBar.getProgress(),Toast.LENGTH_SHORT ).show();  
        }  
        @Override  
        public void onStopTrackingTouch(SeekBar seekBar) {}  
    }  
    @Override  
    public void onClick(View v) {  
        switch (v.getId()){  
            case R.id.btn_last://撤销  
                tuyaView.undo();  
                break;  
            case R.id.btn_redo://重做  
                tuyaView.redo();  
                break;  
            case R.id.btn_recover://恢  
                tuyaView.recover();  
                break;  
            case R.id.btn_savesd://保存  
                tuyaView.saveToSDCard();  
                break;  
            case R.id.btn_paintcolor:  
                sb_size.setVisibility(View.GONE);  
                showPaintColorDialog(v);  
                break;  
            case R.id.btn_paintsize:  
                sb_size.setVisibility(View.VISIBLE);  
                break;  
            case R.id.btn_paintstyle:  
                sb_size.setVisibility(View.GONE);  
                showMoreDialog(v);  
                break;  
        }  
    }  
    private int select_paint_color_index = 0;  
    private int select_paint_style_index = 0;  
    //private int select_paint_size_index = 0;  
    public void showPaintColorDialog(View parent){  
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);  
        alertDialogBuilder.setTitle("选择画笔颜色:");  
        alertDialogBuilder.setSingleChoiceItems(R.array.paintcolor, select_paint_color_index, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                select_paint_color_index = which;  
                tuyaView.selectPaintColor(which);  
                dialog.dismiss();  
            }  
        });  
        alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                dialog.dismiss();  
            }  
        });  
        alertDialogBuilder.create().show();  
    }  
    /*  
    //弹出画笔大小选项对话框  
        public void showPaintSizeDialog(View parent){  
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);  
            alertDialogBuilder.setTitle("选择画笔大小:");  
            alertDialogBuilder.setSingleChoiceItems(R.array.paintsize, select_paint_size_index, new DialogInterface.OnClickListener() {  
                @Override  
                public void onClick(DialogInterface dialog, int which) {  
                    select_paint_size_index = which;  
                    tuyaView.selectPaintSize(which);  
                    dialog.dismiss();  
                }  
            });  
            alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
                @Override  
                public void onClick(DialogInterface dialog, int which) {  
                    dialog.dismiss();  
                }  
            });  
            alertDialogBuilder.create().show();  
        }  
    */  
//弹出选择画笔或橡皮擦的对话框  
    public void showMoreDialog(View parent){  
        AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(this);  
        alertDialogBuilder.setTitle("选择画笔或橡皮擦:");  
        alertDialogBuilder.setSingleChoiceItems(R.array.paintstyle, select_paint_style_index, new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                select_paint_style_index = which;  
                tuyaView.selectPaintStyle(which);  
                dialog.dismiss();  
            }  
        });  
        alertDialogBuilder.setNegativeButton("取消", new DialogInterface.OnClickListener() {  
            @Override  
            public void onClick(DialogInterface dialog, int which) {  
                dialog.dismiss();  
            }  
        });  
        alertDialogBuilder.create().show();  
    }  
} 
// 

//array

<string-array name="paintcolor">  
       <item>红</item>  
       <item>蓝</item>  
       <item>绿</item>  
       <item>黄</item>  
       <item>黑</item>  
       <item>灰</item>  
       <item>青</item>  
   </string-array >  
  
   <string-array name="paintstyle" >  
       <item>画笔</item>  
       <item>橡皮擦</item>  
   </string-array>  
//layout.xml
<?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"  
    tools:context="com.example.administrator.myapplication.MainActivity">  
  
  
   <FrameLayout  
       android:id="@+id/fl_container"  
       android:layout_width="match_parent"  
       android:layout_height="match_parent"  
       >  
  
   </FrameLayout>  
   <LinearLayout  
       android:id="@+id/ll_right"  
       android:layout_width="80dp"  
       android:layout_height="wrap_content"  
       android:layout_alignParentRight="true"  
       android:orientation="vertical">  
      <Button  
          android:text="保存"  
          android:id="@+id/btn_savesd"  
          style="@style/MyButton"/>  
      <Button  
          android:text="撤销"  
          android:id="@+id/btn_last"  
          style="@style/MyButton"/>  
      <Button  
          android:text="恢复"  
          android:id="@+id/btn_recover"  
          style="@style/MyButton"/>  
      <Button  
          android:text="重做"  
          android:id="@+id/btn_redo"  
          style="@style/MyButton"/>  
   </LinearLayout>  
   <SeekBar  
       android:layout_above="@id/ll_bottom"  
       android:id="@+id/sb_size"  
       android:layout_width="match_parent"  
       android:layout_height="wrap_content" />  
   <LinearLayout  
       android:id="@+id/ll_bottom"  
       android:layout_alignParentBottom="true"  
       android:layout_width="match_parent"  
       android:layout_height="80dp"  
       android:gravity="center">  
      <Button  
          android:text="画笔样式"  
          android:id="@+id/btn_paintstyle"  
          android:layout_width="0dp"  
          android:layout_height="60dp"  
          android:layout_weight="1"/>  
      <Button  
          android:text="画笔颜色"  
          android:id="@+id/btn_paintcolor"  
          android:layout_width="0dp"  
          android:layout_height="60dp"  
          android:layout_weight="1"/>  
      <Button  
          android:text="画笔尺寸"  
          android:id="@+id/btn_paintsize"  
          android:layout_width="0dp"  
          android:layout_height="60dp"  
          android:layout_weight="1"/>  
   </LinearLayout>  
</RelativeLayout>  

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值