1

我正在开发一个 Android 数字签名应用程序,用户可以在其中签名,我必须将此文件保存为图像。我正在使用 SurfaceView 进行绘图。DigitalSignatureActivity 有两个按钮保存,清除。1.Save 按钮将文件保存为图像 2.Clear 按钮清除表面。但我无法清除表面。我尝试了 drawingSurface.setBackgroundColor(Color.BLACK); 仍然保留以前的标志和 canvas.drawColor(Color.BLACK); 没有效果,我可以保存文件,但它不能完美地存储签名(一些内容丢失)请帮忙。我的代码是:DigitalSignatureActivity.java

package com.pop.digitalsign;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Bundle;
import android.os.Environment;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

public class DigitalSignatureActivity extends Activity implements
        View.OnTouchListener {

    private DrawingSurface drawingSurface;
    private DrawingPath currentDrawingPath;
    private Paint currentPaint;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        setCurrentPaint();
        drawingSurface = (DrawingSurface) findViewById(R.id.drawingSurface);
        drawingSurface.setOnTouchListener(this);

    }

    private void setCurrentPaint() {
        currentPaint = new Paint();
        currentPaint.setDither(true);
        currentPaint.setColor(Color.WHITE);
        currentPaint.setStyle(Paint.Style.STROKE);
        currentPaint.setStrokeJoin(Paint.Join.ROUND);
        currentPaint.setStrokeCap(Paint.Cap.ROUND);
        currentPaint.setStrokeWidth(2);

    }

    public boolean onTouch(View view, MotionEvent motionEvent) {
        if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {

            drawingSurface.setBackgroundColor(0);
            currentDrawingPath = new DrawingPath();
            currentDrawingPath.paint = currentPaint;
            currentDrawingPath.path = new Path();
            currentDrawingPath.path.moveTo(motionEvent.getX(),
                    motionEvent.getY());
            currentDrawingPath.path.lineTo(motionEvent.getX(),
                    motionEvent.getY());

        } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
            currentDrawingPath.path.lineTo(motionEvent.getX(),motionEvent.getY());
            drawingSurface.addDrawingPath(currentDrawingPath);

        } else if (motionEvent.getAction() == MotionEvent.ACTION_UP) {
            currentDrawingPath.path.lineTo(motionEvent.getX(),motionEvent.getY());
        }

        return true;
    }
    //To save file as  Image
    public void saveDrawing(View v) throws IOException {

        File mediaStorageDir = new File(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "MySignatures");

        Bitmap nBitmap = drawingSurface.getBitmap();
        try {
            if (!mediaStorageDir.exists()) {
                mediaStorageDir.mkdirs();
            }
            String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
                    .format(new Date());
            File mediaFile = new File(mediaStorageDir.getPath()
                    + File.separator + "SIGN_" + timeStamp + ".png");
            FileOutputStream out = new FileOutputStream(mediaFile);

            nBitmap.compress(Bitmap.CompressFormat.PNG, 90, out);
            out.flush();
            out.close();
            Toast.makeText(this, "Signature saved  to " + mediaFile,
                    Toast.LENGTH_LONG).show();
        } catch (Exception e) {
            e.printStackTrace();
            Toast.makeText(getApplicationContext(), "Not saved",
                    Toast.LENGTH_SHORT).show();
        }

    }

    //To clear Surface
    public void clearScreen(View v) {
        //drawingSurface.setBackgroundColor(Color.BLACK);
        drawingSurface.clear();
    }
}

绘图表面.java

package com.pop.digitalsign;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;


public class DrawingSurface extends SurfaceView implements SurfaceHolder.Callback {
    private Boolean _run;
    protected DrawThread thread;
    private Bitmap mBitmap;
    Canvas canvas;


    private CommandManager commandManager;

    public DrawingSurface(Context context, AttributeSet attrs) {
        super(context, attrs);

        getHolder().addCallback(this);
        commandManager = new CommandManager();
        thread = new DrawThread(getHolder());
    }


    class DrawThread extends  Thread{

         public SurfaceHolder mSurfaceHolder;

        public DrawThread(SurfaceHolder surfaceHolder){
            mSurfaceHolder = surfaceHolder;

        }
        public DrawThread() {
            // TODO Auto-generated constructor stub
        }

        public void setRunning(boolean run) {
            _run = run;
        }


        @Override
        public void run() {
            canvas = null;
            while (_run){
                try{
                    canvas = mSurfaceHolder.lockCanvas(null);
                    //canvas.drawColor(Color.WHITE);
                    if(mBitmap == null){
                        mBitmap =  Bitmap.createBitmap (1, 1, Bitmap.Config.ARGB_8888);;
                    }
                    final Canvas c = new Canvas (mBitmap);
                    c.drawColor(0, PorterDuff.Mode.CLEAR);
                    commandManager.executeAll(c);
                    canvas.drawBitmap (mBitmap, 0,  0,null);
                } finally {
                    if(canvas!=null){
                        mSurfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
        }
    }


    public void addDrawingPath (DrawingPath drawingPath){
        commandManager.addCommand(drawingPath);
    }


    public void clear(){
        //Here i want to clear surface
         canvas.drawColor(Color.BLACK);//it has no effect
    }

    public boolean hasMoreUndo(){
        return commandManager.hasMoreUndo();
    }

    public Bitmap getBitmap(){
        return mBitmap;
    }


    public void surfaceChanged(SurfaceHolder holder, int format, int width,  int height) {
        mBitmap =  Bitmap.createBitmap (width, height, Bitmap.Config.ARGB_8888);;
    }


    public void surfaceCreated(SurfaceHolder holder) {
        thread.setRunning(true);
        thread.start();
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        thread.setRunning(false);
        while (retry) {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
            }
        }
    }

}

命令管理器.java

package com.pop.digitalsign;

import android.graphics.Canvas;

import java.util.Iterator;
import java.util.List;
import java.util.Collections;
import java.util.ArrayList;


public class CommandManager {
    private List<DrawingPath> currentStack;

    public  CommandManager(){
        currentStack = Collections.synchronizedList(new ArrayList<DrawingPath>());
    }

    public void addCommand(DrawingPath command){
        currentStack.add(command);
    }

    public void undo (){
        final int length = currentStackLength();
        if ( length > 0) {
            final DrawingPath undoCommand = currentStack.get(  length - 1  );
            currentStack.remove( length - 1 );
            undoCommand.undo();
        }
    }

    public int currentStackLength(){
        final int length = currentStack.toArray().length;
        return length;
    }


    public void executeAll( Canvas canvas){
        if( currentStack != null ){
            synchronized( currentStack ) {
                final Iterator<?> i = currentStack.iterator();
                while ( i.hasNext() ){
                    final DrawingPath drawingPath = (DrawingPath) i.next();
                    drawingPath.draw( canvas );
                }
            }
        }
    }

    public boolean hasMoreUndo(){
        return  currentStack.toArray().length > 0;
    }
}

绘图路径.java

package com.pop.digitalsign;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;

public class DrawingPath {
    public Path path;
    public Paint paint;

    public void draw(Canvas canvas) {
        canvas.drawPath( path, paint );
    }

    public void undo() {
    }
}

主要的.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    android:background="@android:color/white" >

     <com.pop.digitalsign.DrawingSurface
        android:id="@+id/drawingSurface"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

      <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center" >

      <Button
            android:id="@+id/saveBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="saveDrawing"
            android:text="@string/save" />
       <Button
            android:id="@+id/clearBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:onClick="clearScreen"
            android:text="@string/clear" />
       </LinearLayout>

</RelativeLayout>
4

3 回答 3

1

我最好的建议是使用这个

if (surfaceHolder.getSurface().isValid()) {
                    Canvas c = surfaceHolder.lockCanvas();
                    if (first >= 0) {
                        c.drawARGB(255, 255, 255, 255);
                        first--;
                    }

first 的值是 2 你可以使用你想要的每个名字。原因是画布是双缓冲的,因此您需要通过将其涂成白色来清除两个屏幕。这停止了​​闪烁

于 2013-01-06T03:52:14.463 回答
0
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)
于 2017-11-10T15:27:27.960 回答
-1

DrawingSurface添加此方法

public void resetCanvas(){ commandManager.clearAllPath(); }

并调用此方法,当您需要采取行动清除..

objectNameofDrawingSurefaceClass.resetCanvas();

将代码添加到CommandManager

public void clearAllPath(){currentStack.clear();  }

好的..

于 2012-04-09T10:49:01.140 回答