首先感谢您的帮助。 我的应用程序基本上是一个多画布的速写本。在第一个画布上绘制之后,当我单击下一步按钮时,将加载新画布并将前一个画布保存到Bitmap数组中。在绘制已加载的新画布后,当我单击上一个按钮时,当前图形将保存在位图数组中,新画布应将先前绘制的图像加载到画布上。
但是,当我点击上一页按钮时,应用程序崩溃了。
请帮我解决这个问题。
以下是下一步和上一页按钮的代码。
下一步按钮
if(view.getId()==R.id.next){
bitArrayStore(i);
drawView.startNew();
i++;
}
上一页按钮
if(view.getId() == R.id.prev){
bitArrayStore(i);
drawView.startNew();
i--;
drawView.redraw(bits, i);
}
bitArrayStore()
public void bitArrayStore(int k){
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bits[k] = drawView.getDrawingCache();
drawView.destroyDrawingCache();
}
drawView.redraw()
public void redraw(Bitmap[] bits, int i) {
drawCanvas.drawBitmap(bits[i], 0, 0, null);
invalidate();
}
这是我的logcat
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: FATAL EXCEPTION: main
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: Process: com.example.jishnu.notestest, PID: 18856
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: java.lang.RuntimeException: Canvas: trying to use a recycled bitmap android.graphics.Bitmap@c0446aa
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.graphics.Canvas.throwIfCannotDraw(Canvas.java:1282)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.graphics.Canvas.drawBitmap(Canvas.java:1337)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at com.example.jishnu.notestest.DrawingView.redraw(DrawingView.java:136)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at com.example.jishnu.notestest.MainActivity.onClick(MainActivity.java:245)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.view.View.performClick(View.java:4780)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.view.View$PerformClick.run(View.java:19866)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.os.Handler.handleCallback(Handler.java:739)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.os.Handler.dispatchMessage(Handler.java:95)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.os.Looper.loop(Looper.java:135)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at android.app.ActivityThread.main(ActivityThread.java:5254)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at java.lang.reflect.Method.invoke(Native Method)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at java.lang.reflect.Method.invoke(Method.java:372)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
10-16 03:23:45.816 18856-18856/com.example.jishnu.notestest E/AndroidRuntime: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
以下是我参考的其余代码
MainActivity.java
public class MainActivity extends AppCompatActivity implements OnClickListener {
private DrawingView drawView;
private ImageButton currPaint,drawBtn,eraseBtn,newBtn,saveBtn;
private float smallBrush, mediumBrush, largeBrush;
String ucolor;
private Button nextbtn,prevbtn;
int i=0;
Bitmap[] bits;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
drawView = (DrawingView) findViewById(R.id.drawing);
LinearLayout paintLayout = (LinearLayout) findViewById(R.id.paint_colors);
currPaint = (ImageButton) paintLayout.getChildAt(0);
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
smallBrush = getResources().getInteger(R.integer.small_size);
mediumBrush = getResources().getInteger(R.integer.medium_size);
largeBrush = getResources().getInteger(R.integer.large_size);
drawBtn = (ImageButton)findViewById(R.id.draw_btn);
drawBtn.setOnClickListener(this);
drawView.setBrushSize(mediumBrush);
eraseBtn = (ImageButton)findViewById(R.id.erase_btn);
eraseBtn.setOnClickListener(this);
newBtn = (ImageButton)findViewById(R.id.new_btn);
newBtn.setOnClickListener(this);
saveBtn = (ImageButton)findViewById(R.id.save_btn);
saveBtn.setOnClickListener(this);
bits=new Bitmap[40];
nextbtn=(Button)findViewById(R.id.next);
prevbtn=(Button)findViewById(R.id.prev);
nextbtn.setOnClickListener(this);
prevbtn.setOnClickListener(this);
drawView.setDrawingCacheEnabled(true);
}
public void paintClicked(View view) {
//use chosen color
drawView.setErase(false);
drawView.setBrushSize(drawView.getLastBrushSize());
if (view != currPaint) {
ImageButton imgView = (ImageButton)view;
String color = view.getTag().toString();
drawView.setColor(color);
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currPaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currPaint=(ImageButton)view;
}
}
@Override
public void onClick(View view) {
if(view.getId()==R.id.draw_btn){
//draw button clicked
final Dialog brushDialog = new Dialog(this);
brushDialog.setTitle("Brush size:");
brushDialog.setContentView(R.layout.brush_chooser);
ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
smallBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawView.setBrushSize(smallBrush);
drawView.setLastBrushSize(smallBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
mediumBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawView.setBrushSize(mediumBrush);
drawView.setLastBrushSize(mediumBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
largeBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setBrushSize(largeBrush);
drawView.setLastBrushSize(largeBrush);
drawView.setErase(false);
brushDialog.dismiss();
}
});
brushDialog.show();
}
else if(view.getId()==R.id.erase_btn){
//switch to erase - choose size
final Dialog brushDialog = new Dialog(this);
brushDialog.setTitle("Eraser size:");
brushDialog.setContentView(R.layout.brush_chooser);
ImageButton smallBtn = (ImageButton)brushDialog.findViewById(R.id.small_brush);
smallBtn.setOnClickListener(new OnClickListener(){
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(smallBrush);
brushDialog.dismiss();
}
});
ImageButton mediumBtn = (ImageButton)brushDialog.findViewById(R.id.medium_brush);
mediumBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(mediumBrush);
brushDialog.dismiss();
}
});
ImageButton largeBtn = (ImageButton)brushDialog.findViewById(R.id.large_brush);
largeBtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawView.setErase(true);
drawView.setBrushSize(largeBrush);
brushDialog.dismiss();
}
});
brushDialog.show();
}
else if(view.getId()==R.id.new_btn){
//new button
AlertDialog.Builder newDialog = new AlertDialog.Builder(this);
newDialog.setTitle("New drawing");
newDialog.setMessage("Start new drawing (you will lose the current drawing)?");
newDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
drawView.startNew();
dialog.dismiss();
}
});
newDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
newDialog.show();
}
else if(view.getId()==R.id.save_btn){
//save drawing
AlertDialog.Builder saveDialog = new AlertDialog.Builder(this);
saveDialog.setTitle("Save drawing");
saveDialog.setMessage("Save drawing to device Gallery?");
saveDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
//save drawing
drawView.setDrawingCacheEnabled(true);
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
Bitmap bitmap = drawView.getDrawingCache();
String path = Environment.getExternalStorageDirectory().getAbsolutePath();
File file = new File(path+File.separator+"Pictures"+File.separator+"image.png");
FileOutputStream ostream;
try {
file.createNewFile();
ostream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, ostream);
ostream.flush();
ostream.close();
Toast.makeText(getApplicationContext(), "image saved :"+path, Toast.LENGTH_SHORT).show();
} catch (Exception e) {
e.printStackTrace();
Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_SHORT).show();
}
drawView.destroyDrawingCache();
}
});
saveDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener(){
public void onClick(DialogInterface dialog, int which){
dialog.cancel();
}
});
saveDialog.show();
}
if(view.getId()==R.id.next){
bitArrayStore(i);
drawView.startNew();
i++;
}
if(view.getId() == R.id.prev){
bitArrayStore(i);
drawView.startNew();
i--;
drawView.redraw(bits, i);
}
}
public void bitArrayStore(int k){
drawView.buildDrawingCache();
drawView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
bits[k] = drawView.getDrawingCache();
drawView.destroyDrawingCache();
}
}
DrawingView.java
public class DrawingView extends View {
//drawing path
private Path drawPath;
//drawing and canvas paint
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor = 0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
private float brushSize, lastBrushSize;
private boolean erase=false;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
private void setupDrawing() {
//get drawing area setup for interaction
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
drawPath = new Path();
drawPaint = new Paint();
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(brushSize);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//view given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
//draw view
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(drawPath, drawPaint);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//detect user touch
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
break;
default:
return false;
}
invalidate();
return true;
}
public void setColor(String newColor) {
//set color
invalidate();
paintColor = Color.parseColor(newColor);
drawPaint.setColor(paintColor);
}
public void setBrushSize(float newSize) {
//update sizefloat pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
float pixelAmount = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
newSize, getResources().getDisplayMetrics());
brushSize = pixelAmount;
drawPaint.setStrokeWidth(brushSize);
}
public void setLastBrushSize(float lastSize){
lastBrushSize=lastSize;
}
public float getLastBrushSize(){
return lastBrushSize;
}
public void setErase(boolean isErase){
//set erase true or false
erase=isErase;
if(erase) drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
else drawPaint.setXfermode(null);
}
public void startNew(){
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
invalidate();
// Bitmap b= BitmapFactory.decodeFile("/storage/emulated/0/Pictures/image.png");
// drawCanvas.drawBitmap(b, 0, 0, null);
//
// invalidate();
}
public void redraw(Bitmap[] bits, int i) {
drawCanvas.drawBitmap(bits[i], 0, 0, null);
invalidate();
}
}
问题是,当我点击上一页按钮时,应用程序崩溃了。任何人都可以帮我解决这个问题吗?!
答案 0 :(得分:0)
而不是
bits[k] = drawView.getDrawingCache();
bitArrayStore()方法中的
应该是
bits[k] = Bitmap.createBitmap(drawView.getDrawingCache());