用Picture类记录绘制过程,初学者在看了文档后自己试验了一下,不清楚是否能实现效果,且一直出现程序停止运行的错误。
- 功能 点击回放按钮重新绘制过程
【MainActivity】
package painter.com.gangbi;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
private Button btn;
DrawView drawView = (DrawView) findViewById(R.id.draw);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
btn= (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
drawView.mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawView.playBack();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
switch (item.getItemId()) {
// 设置id为menu_exit的菜单子项所要执行的方法。
case R.id.menu1_sub1:
drawView.mOutterPaint.setStrokeWidth(5);
break;
case R.id.menu1_sub2:
drawView.mOutterPaint.setStrokeWidth(10);
break;
case R.id.menu1_sub3:
drawView.mOutterPaint.setStrokeWidth(20);
break;
case R.id.menu1_sub4:
drawView.mOutterPaint.setStrokeWidth(50);
break;
case R.id.menu2:
drawView.mOutterPaint.setColor(Color.BLACK);
break;
case R.id.menu3:
drawView.mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
break;
case R.id.menu4_sub1:
drawView.mOutterPaint.setColor(Color.BLACK);
break;
case R.id.menu4_sub2:
drawView.mOutterPaint.setColor(Color.RED);
break;
case R.id.menu5:
System.exit(0);// 结束程序
break;
}
return true;
}
}
【绘制模块】
package painter.com.gangbi;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Picture;
import android.graphics.drawable.PictureDrawable;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
import java.io.File;
import java.io.FileOutputStream;
/**
* Created by admin on 2017/7/25.
*/
public class DrawView extends View {
public Paint mOutterPaint;
public Path mPath;
public Canvas mCanvas;
private Bitmap mBitmap;
private int mX;
private int mY;
private Bitmap bitmap;
public DrawView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs,0);
}
public DrawView(Context context) {
this(context,null);
}
public DrawView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
//获得宽和高
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width=getMeasuredWidth();
int height=getMeasuredHeight();
//初始化bitmap,有了bitmap在初始化canvas
mBitmap=Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
mCanvas=new Canvas(mBitmap);
setupOutPaint();
}
//设置绘制path画笔的颜色
private void setupOutPaint() {
mOutterPaint.setColor(Color.BLACK);
//(锯齿
mOutterPaint.setAntiAlias(true);
mOutterPaint.setDither(true);
mOutterPaint.setStrokeJoin(Paint.Join.ROUND);
mOutterPaint.setStrokeCap(Paint.Cap.ROUND);
mOutterPaint.setStyle(Paint.Style.STROKE);
mOutterPaint.setStrokeWidth(20);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action =event.getAction();
int x= (int) event.getX();
int y= (int) event.getY();
switch(action)
{
case MotionEvent.ACTION_DOWN:
//用户的手开始的时候
mX=x;
mY=y;
//作为起点
mPath.moveTo(mX,mY);
break;
case MotionEvent.ACTION_MOVE:
//横向移动坐标
int dx=Math.abs(x-mX);
int dy=Math.abs(y-mY);
if(dx>3||dy>3){
//大于3px的变化才开始
mPath.lineTo(x,y);
}
//更新x,y
mX=x;
mY=y;
break;
case MotionEvent.ACTION_UP:
mPath.reset();
break;
default:
break;
}
invalidate();
return true;
}
@Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap,0,0,null);
drawPath();
//在内存中准备好path,用canvas绘制
canvas.drawBitmap(mBitmap,0,0,null);
}
private void drawPath() {
mCanvas.drawPath(mPath,mOutterPaint);
}
/*初始化操作*/
public void init() {
mOutterPaint=new Paint();
//canvas必须得到控件宽高比再创建
mPath=new Path();
bitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.mod);
}
public void playBack()
{
Picture picture = new Picture();
Canvas canvas = picture.beginRecording(300, 500);
canvas.drawPath(mPath,mOutterPaint);
picture.endRecording();
canvas.drawPicture(picture);
}
}
【主要疑惑点】(按照文档根自己的理解写的不知道是否正确)
- 绘制模块中
public void playBack()
{
Picture picture = new Picture();
Canvas canvas = picture.beginRecording(300, 500);
canvas.drawPath(mPath,mOutterPaint);//思路是用画笔把之前的path重绘一次
picture.endRecording();
canvas.drawPicture(picture);//录完后把过程回放
}
- MainActivity中
btn= (Button) findViewById(R.id.btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
drawView.mCanvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
drawView.playBack();
}
});
【程序停止运行】Logcat显示Broken Pipe