我正在使用 SurfaceView 开发绘画应用程序。我在我的应用程序中发现了一些问题:
1.当我接到电话或转到其他应用程序并返回我的应用程序时,我的应用程序出现运行时错误。
2.绘制时我收到闪烁效果,之后只有我得到颜色
3.我无法在 DrawingSurface.java 中将位图设置到画布中
//绘图活动.java
import android.R.string;
import android.app.Activity;`
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PixelFormat;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.almondmendoza.Main;
import com.almondmendoza.R;
import com.almondmendoza.drawings.brush.Brush;
import com.almondmendoza.drawings.brush.CircleBrush;
import com.almondmendoza.drawings.brush.PenBrush;
import java.io.File;
import java.io.FileOutputStream;
public class DrawingActivity extends Activity implements View.OnTouchListener{
private DrawingSurface drawingSurface;
private DrawingPath currentDrawingPath;
private Paint currentPaint;
private Button redbtn,bluebtn,greenbtn,undobtn,redobtn,savebtn,pathbtn,circlebtn;
private Brush currentBrush;
private File APP_FILE_PATH = new File("/sdcard/TutorialForAndroidDrawings");
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.drawing_activity);
final LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//RelativeLayout b = (RelativeLayout)inflater.inflate(R.layout.drawing_activity,
// null);
/* LayoutParams layoutParamsControl1 = new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
this.addContentView(b, layoutParamsControl1);*/
setCurrentPaint();
currentBrush = new PenBrush();
drawingSurface = (DrawingSurface) findViewById(R.id.drawingSurface);
drawingSurface.setOnTouchListener(this);
drawingSurface.previewPath = new DrawingPath();
drawingSurface.previewPath.path = new Path();
drawingSurface.previewPath.paint = getPreviewPaint();
redbtn = (Button) findViewById(R.id.colorRedBtn);
redbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFFFF0000);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setAntiAlias(true);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
}
});
greenbtn = (Button) findViewById(R.id.colorGreenBtn);
greenbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00FF00);
currentPaint.setAntiAlias(true);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(10);
}
});
bluebtn = (Button) findViewById(R.id.colorBlueBtn);
bluebtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor( 0xFF0000FF);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
}
});
undobtn = (Button) findViewById(R.id.undoBtn);
undobtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawingSurface.undo();
if( drawingSurface.hasMoreUndo() == false ){
undobtn.setEnabled( false );
}
redobtn.setEnabled( true );
}
});
redobtn = (Button) findViewById(R.id.redoBtn);
redobtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
drawingSurface.redo();
if( drawingSurface.hasMoreRedo() == false ){
redobtn.setEnabled( false );
}
undobtn.setEnabled( true );
}
});
savebtn = (Button) findViewById(R.id.saveBtn);
savebtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final Activity currentActivity = DrawingActivity.this;
Handler saveHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
final AlertDialog alertDialog = new AlertDialog.Builder(currentActivity).create();
alertDialog.setTitle("Saved 1");
alertDialog.setMessage("Your drawing had been saved :)");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
} ;
// new ExportBitmapToFile(DrawingActivity.this,saveHandler, drawingSurface.getBitmap()).execute();
}
});
pathbtn = (Button) findViewById(R.id.pathBtn);
pathbtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
currentBrush = new PenBrush();
}
});
circlebtn = (Button) findViewById(R.id.circleBtn);
circlebtn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
currentBrush = new CircleBrush();
}
});
redobtn.setEnabled(false);
undobtn.setEnabled(false);
}
private void setCurrentPaint(){
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFFFFFF00);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setAntiAlias(true);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
}
private Paint getPreviewPaint(){
final Paint previewPaint = new Paint();
previewPaint.setColor(Color.GREEN);
previewPaint.setStyle(Paint.Style.STROKE);
previewPaint.setAntiAlias(true);
previewPaint.setStrokeJoin(Paint.Join.ROUND);
previewPaint.setStrokeCap(Paint.Cap.ROUND);
previewPaint.setStrokeWidth(10);
return previewPaint;
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
public boolean onTouch(View view, MotionEvent motionEvent) {
if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
drawingSurface.isDrawing = true;
currentDrawingPath = new DrawingPath();
currentDrawingPath.paint = currentPaint;
currentDrawingPath.path = new Path();
currentBrush.mouseDown(currentDrawingPath.path, motionEvent.getX(), motionEvent.getY());
currentBrush.mouseDown(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
}else if(motionEvent.getAction() == MotionEvent.ACTION_MOVE){
drawingSurface.isDrawing = true;
currentBrush.mouseMove( currentDrawingPath.path, motionEvent.getX(), motionEvent.getY() );
currentBrush.mouseMove(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
}else if(motionEvent.getAction() == MotionEvent.ACTION_UP){
currentBrush.mouseUp(drawingSurface.previewPath.path, motionEvent.getX(), motionEvent.getY());
drawingSurface.previewPath.path = new Path();
drawingSurface.addDrawingPath(currentDrawingPath);
currentBrush.mouseUp( currentDrawingPath.path, motionEvent.getX(), motionEvent.getY() );
undobtn.setEnabled(true);
redobtn.setEnabled(false);
}
return true;
}
/* public void onClick(View view){
switch (view.getId()){
case R.id.colorRedBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFFFF0000);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.colorBlueBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00FF00);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.colorGreenBtn:
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF0000FF);
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(3);
break;
case R.id.undoBtn:
drawingSurface.undo();
if( drawingSurface.hasMoreUndo() == false ){
undoBtn.setEnabled( false );
}
redoBtn.setEnabled( true );
break;
case R.id.redoBtn:
drawingSurface.redo();
if( drawingSurface.hasMoreRedo() == false ){
redoBtn.setEnabled( false );
}
undoBtn.setEnabled( true );
break;
case R.id.saveBtn:
final Activity currentActivity = this;
Handler saveHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
final AlertDialog alertDialog = new AlertDialog.Builder(currentActivity).create();
alertDialog.setTitle("Saved 1");
alertDialog.setMessage("Your drawing had been saved :)");
alertDialog.setButton("OK", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
return;
}
});
alertDialog.show();
}
} ;
new ExportBitmapToFile(this,saveHandler, drawingSurface.getBitmap()).execute();
break;
case R.id.circleBtn:
currentBrush = new CircleBrush();
break;
case R.id.pathBtn:
currentBrush = new PenBrush();
break;
}
}*/
//new ExportBitmapToFile(DrawingActivity.this,saveHandler, drawingSurface.getBitmap()).execute();
/*private class ExportBitmapToFile extends AsyncTask<Intent,Void,Boolean> {
private Context mContext;
private Handler mHandler;
private Bitmap nBitmap;
public ExportBitmapToFile(Context context,Handler handler,Bitmap bitmap) {
mContext = context;
nBitmap = bitmap;
mHandler = handler;
}
@Override
protected Boolean doInBackground(Intent... arg0) {
try {
if (!APP_FILE_PATH.exists()) {
APP_FILE_PATH.mkdirs();
}
final FileOutputStream out = new FileOutputStream(new File(APP_FILE_PATH + "/myAwesomeDrawing.png"));
nBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
out.flush();
out.close();
return true;
}catch (Exception e) {
e.printStackTrace();
}
//mHandler.post(completeRunnable);
return false;
}
@Override
protected void onPostExecute(Boolean bool) {
super.onPostExecute(bool);
if ( bool ){
mHandler.sendEmptyMessage(1);
}
}
}*/
}
//DrawingSurface.java
import android.R;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.*;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
private Boolean _run;
protected DrawThread thread;
private Bitmap mBitmap;
public boolean isDrawing = true;
public DrawingPath previewPath;
private CommandManager commandManager;
public DrawingSurface(Context context, AttributeSet attrs) {
super(context, attrs);
getHolder().addCallback(this);
commandManager = new CommandManager();
thread = new DrawThread(getHolder());
}
private Handler previewDoneHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
isDrawing = false;
}
};
class DrawThread extends Thread{
private SurfaceHolder mSurfaceHolder;
public DrawThread(SurfaceHolder surfaceHolder){
mSurfaceHolder = surfaceHolder;
}
public void setRunning(boolean run) {
_run = run;
}
@Override
public void run() {
Canvas canvas = null;
while (_run){
if(isDrawing == true){
try{
canvas = mSurfaceHolder.lockCanvas(null);
if(mBitmap == null){
mBitmap = Bitmap.createBitmap (1, 1, Bitmap.Config.ALPHA_8);
}
final Canvas c = new Canvas (mBitmap);
c.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawColor(Color.WHITE);
commandManager.executeAll(c,previewDoneHandler);
previewPath.draw(c);
canvas.drawBitmap (mBitmap, 0, 0,null);
} finally {
mSurfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
public void addDrawingPath (DrawingPath drawingPath){
commandManager.addCommand(drawingPath);
}
public boolean hasMoreRedo(){
return commandManager.hasMoreRedo();
}
public void redo(){
isDrawing = true;
commandManager.redo();
}
public void undo(){
isDrawing = true;
commandManager.undo();
}
public boolean hasMoreUndo(){
return commandManager.hasMoreUndo();
}
public Bitmap getBitmap(){
return mBitmap;
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
mBitmap = Bitmap.createBitmap (width, height, Bitmap.Config.ARGB_8888);;
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
//Logcat 报告
): java.lang.IllegalThreadStateException: Thread already
at java.lang.Thread.start
com.almondmendoza.drawings.DrawingSurface.surfaceCreated(DrawingSurface.java:154)
android.view.SurfaceView.updateWindow(SurfaceView.java:552)
android.view.SurfaceView.onWindowVisibilityChanged
android.view.View.dispatchWindowVisibilityChanged
android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
android.view.ViewGroup.dispatchWindowVisibilityChanged(ViewGroup.java:720)
android.view.ViewRoot.performTraversals(ViewRoot.java:788)
android.view.ViewRoot.handleMessage(ViewRoot.java:1865)
android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
at dalvik.system.NativeStart.main(Native Method)
//错误在以下方法的 DrawingSurface.java 类中显示
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
thread.setRunning(true);
thread.start();
}