0

好的,这是我没有创建位图的完整 CanvasView,我真的不知道该怎么做。如果你理解它,如果你能帮助我,请这样做。先感谢您!保存功能在 FirstActivity 中,它表示位图为空。

public class CanvasView extends View{

private static final float STROKE_WIDTH = 5f;
private static final float HALF_STROKE_WIDTH = STROKE_WIDTH/2;
Paint erasePaint = new Paint();
Paint paint = new Paint();
Path path = new Path();

float lastTouchX,lastTouchY;

AlertDialog.Builder alert;

RectF ovalRectangle = new RectF();
RectF dirtyRect = new RectF();

MyRectangle myRectangle;
MyOval myOval;
MyCircle myCircle;
MyFreehand myFreehand; 
MyLine myLine;
MyEraser myEraser;

List<MyEraser> eraserList = new ArrayList<MyEraser>();
List<MyLine> lineList = new ArrayList<MyLine>();
List<MyFreehand> freehandList  = new ArrayList<MyFreehand>();
List<MyCircle> circleList = new ArrayList<MyCircle>();
List<MyOval> ovalList = new ArrayList<MyOval>();
List<MyRectangle> rectangleList = new ArrayList<MyRectangle>();



public boolean dashedLine = false;
public DashPathEffect dashEffect = new DashPathEffect(new float[]{20,30}, 0);
private Paint mBitmapPaint;
private Bitmap mBitmap; 

public String textValue;

public CanvasView(Context context, AttributeSet attrs) {
    super(context, attrs);
    setBackgroundColor(Color.WHITE);


    if (android.os.Build.VERSION.SDK_INT >= 11) 
    {
        turnOffHardwareAcc();
    }


    erasePaint.setColor(Color.WHITE);
    //erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));

    erasePaint.setAntiAlias(true);
    erasePaint.setStyle(Paint.Style.STROKE);
    erasePaint.setStrokeJoin(Paint.Join.ROUND);
    erasePaint.setStrokeWidth(12);

    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);

    paint.setAntiAlias(true);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
    paint.setTextSize(34);

    setMode(7);//default = 7 - free hand;

    mBitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
    mBitmapPaint = new Paint(Paint.DITHER_FLAG);

    /* input dialog*/

     //setInputDialog();

}
EditText input;
public void setInputDialog(){

    alert = new AlertDialog.Builder(getContext());
    alert.setTitle("Title");
    alert.setMessage("Write text");

    // Set an EditText view to get user input 
    input = new EditText(getContext());
    alert.setView(input);

    alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
         textValue= input.getText().toString();
         Toast.makeText(getContext(), textValue, Toast.LENGTH_SHORT).show();
      // Do something with value!
      }
    });

    alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
      public void onClick(DialogInterface dialog, int whichButton) {
        // Canceled.
      }
    });

    //alert.show();

}

public void setDashLine(){

    dashedLine = true;
    paint = new Paint();
    paint.setPathEffect(dashEffect);
    paint.setStyle(Paint.Style.STROKE);
    paint.setAntiAlias(true);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
}

public void setNormalLine(){
    //paint.setColor(Color.BLACK);
    dashedLine = false;

    paint.setPathEffect(null);
    paint.setStyle(Paint.Style.STROKE);
    paint.setPathEffect(null);
    paint.setAntiAlias(true);
    paint.setStrokeJoin(Paint.Join.ROUND);
    paint.setStrokeWidth(STROKE_WIDTH);
}

@TargetApi(11)
public void turnOffHardwareAcc() // to enable dashed lines
{

    this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

//public void setPaint(int color,)

@TargetApi(11)
protected void onDraw(Canvas canvas) {

    if(dashedLine){
        paint.setPathEffect(dashEffect);
    }
    else {
        paint.setPathEffect(null);
    }

    if(bitmap!=null){

        canvas.drawBitmap(bitmap, 0, 0, paint);
         for(MyCircle circle:circleList){// draw circles

             myCanvas.drawCircle(getCircleMidPointX(circle.firstX, circle.lastX),getCircleMidPointY(circle.firstY, circle.lastY),circle.radius,myPaint);
         }

    }


    for(MyLine line:lineList){ //draw lines
         if(dashedLine)
             line.paint.setPathEffect(dashEffect);
         else
             line.paint.setPathEffect(null);
            canvas.drawLine(line.xStart, line.yStart, line.xEnd, line.yEnd, line.paint);
      }

     for(MyCircle circle:circleList){// draw circles

         canvas.drawCircle(getCircleMidPointX(circle.firstX, circle.lastX),getCircleMidPointY(circle.firstY, circle.lastY),circle.radius,paint);
     }

     for(MyOval oval:ovalList){
         if(dashedLine)
             oval.paint.setPathEffect(dashEffect);
         else oval.paint.setPathEffect(null);

           ovalRectangle.set(oval.getX1(),oval.getY1(),oval.getX2(),oval.getY2());
           canvas.drawOval(ovalRectangle, oval.paint);
     }

     for(MyRectangle rectangle:rectangleList){
         if(dashedLine)
             rectangle.paint.setPathEffect(dashEffect);
         else rectangle.paint.setPathEffect(null);

           canvas.drawRect(rectangle.getX1(),rectangle.getY1(),rectangle.getX2(),rectangle.getY2(),rectangle.paint);
     }  

     for(MyEraser e:eraserList){
            canvas.drawPath(e.p,erasePaint);
            invalidate();
     }
     if(textValue!= null)
         canvas.drawText(textValue, xStart, yStart, paint);
     canvas.drawPath(path, paint);
     //path.reset();

}

final OnTouchListener drawLineListener = new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {

        FirstActivity.ll.setVisibility(LinearLayout.GONE);

        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
              myLine = new MyLine();
              myLine.xStart = event.getX();
              myLine.yStart = event.getY();

            return true;

          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_UP:
            myLine.xEnd = event.getX();
            myLine.yEnd = event.getY();
            invalidate();
            lineList.add(myLine); 
            break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }
        return true;

    }
};

final OnTouchListener drawDashedLineListener = new OnTouchListener() {
    public boolean onTouch(View v, MotionEvent event) {

        FirstActivity.ll.setVisibility(LinearLayout.GONE);

        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
             return true;

          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_UP:

            break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }
        return true;

    }
};

final OnTouchListener drawCircleListener = new OnTouchListener(){

    public boolean onTouch(View v, MotionEvent event) {

        FirstActivity.ll.setVisibility(LinearLayout.GONE);

        float eventX = event.getX();
        float eventY = event.getY();



        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
           //  path.moveTo(eventX, eventY);
              Toast.makeText(getContext(), "action down - circle",Toast.LENGTH_SHORT).show();
              myCircle = new MyCircle();
              myCircle.firstX = eventX;
              myCircle.firstY = eventY;

            // There is no end point yet, so don't waste cycles invalidating.
            return true;

          case MotionEvent.ACTION_MOVE:

          case MotionEvent.ACTION_UP:
            myCircle.lastX = eventX;
            myCircle.lastY = eventY;

            myCircle.radius = getRadius(myCircle.firstX,myCircle.firstY,myCircle.lastX,myCircle.lastY);

            circleList.add(myCircle);

            invalidate();
            break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }
  return true;
    }

};

final OnTouchListener drawOvalListener = new OnTouchListener() {
        public boolean onTouch(View v, MotionEvent event) {

            FirstActivity.ll.setVisibility(LinearLayout.GONE);

            switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN:
                myOval = new MyOval();
                myOval.setX1(event.getX());
                myOval.setY1(event.getY());
                // There is no end point yet, so don't waste cycles invalidating.
                return true;

              case MotionEvent.ACTION_MOVE:
              case MotionEvent.ACTION_UP:

                  myOval.setX2(event.getX());
                  myOval.setY2(event.getY());

                  invalidate();
                  ovalList.add(myOval);

              default:
                Log.d("mock it up", "Unknown touch event  " + event.toString());
                return false;
            }

        }
    };

final OnTouchListener drawRectangleListener = new OnTouchListener() {

        public boolean onTouch(View v, MotionEvent event) {

            FirstActivity.ll.setVisibility(LinearLayout.GONE);

            switch (event.getAction()) {
              case MotionEvent.ACTION_DOWN:
                  myRectangle = new MyRectangle();
                  myRectangle.setX1(event.getX());
                  myRectangle.setY1(event.getY());
                return true;

              case MotionEvent.ACTION_MOVE:

              case MotionEvent.ACTION_UP:

                  myRectangle.setX2(event.getX());
                  myRectangle.setY2(event.getY());
                  invalidate();
                  rectangleList.add(myRectangle);

                break;

              default:
                Log.d("mock it up", "Unknown touch event  " + event.toString());
                return false;
            }


            return true;
        }
};

final OnTouchListener eraseListener = new OnTouchListener() {

    public boolean onTouch(View v, MotionEvent event) {

    //  erasePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        //FirstActivity.ll.setVisibility(LinearLayout.GONE);

        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
             myEraser = new MyEraser();
              lastTouchX = event.getX();
              lastTouchY = event.getY();
              myEraser.mouseDown(event.getX(), event.getY());
              return true;

          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_UP:
              resetDirtyRect(event.getX(),event.getY());
              int historySize = event.getHistorySize();
              for(int i=0;i<historySize;i++){
                  float historicalX = event.getHistoricalX(i);
                  float historicalY = event.getHistoricalY(i);
                  expandDirtyRect(historicalX, historicalY);

                  myEraser.mouseUp(historicalX, historicalY);
            }
              myEraser.mouseUp(event.getX(), event.getY());
              eraserList.add(myEraser);
             break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }



        invalidate(
                (int) (dirtyRect.left - HALF_STROKE_WIDTH),
                (int) (dirtyRect.top - HALF_STROKE_WIDTH),
                (int) (dirtyRect.right + HALF_STROKE_WIDTH),
                (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

            lastTouchX = event.getX();
            lastTouchY = event.getY();
       return true;
    }
};

final OnTouchListener drawFreeHandListener = new OnTouchListener() {

    public boolean onTouch(View v, MotionEvent event) {

        FirstActivity.ll.setVisibility(LinearLayout.GONE);

        float eventX = event.getX();
        float eventY = event.getY();

        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
             // path.reset();
            path.moveTo(eventX, eventY);
            lastTouchX = eventX;
            lastTouchY = eventY;
            // There is no end point yet, so don't waste cycles invalidating.
            return true;

          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_UP:
            // Start tracking the dirty region.
            resetDirtyRect(eventX, eventY);

            // When the hardware tracks events faster than they are delivered, the
            // event will contain a history of those skipped points.
            int historySize = event.getHistorySize();
            for (int i = 0; i < historySize; i++) {
              float historicalX = event.getHistoricalX(i);
              float historicalY = event.getHistoricalY(i);
              expandDirtyRect(historicalX, historicalY);
              path.lineTo(historicalX, historicalY);
            }

            // After replaying history, connect the line to the touch point.
            path.lineTo(eventX, eventY);
            //path.reset();
            break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }

        // Include half the stroke width to avoid clipping.
        invalidate(
            (int) (dirtyRect.left - HALF_STROKE_WIDTH),
            (int) (dirtyRect.top - HALF_STROKE_WIDTH),
            (int) (dirtyRect.right + HALF_STROKE_WIDTH),
            (int) (dirtyRect.bottom + HALF_STROKE_WIDTH));

        lastTouchX = eventX;
        lastTouchY = eventY;

        return true;
    }
};

float xStart,yStart;
final OnTouchListener textListener = new OnTouchListener() {

    public boolean onTouch(View v, MotionEvent event) {
        FirstActivity.ll.setVisibility(LinearLayout.GONE);

    //  Toast.makeText(getContext(), "add some text", Toast.LENGTH_SHORT).show();


        switch (event.getAction()) {
          case MotionEvent.ACTION_DOWN:
              //
              setInputDialog();
              xStart = event.getX();
              yStart = event.getY();
              alert.show();
            break;

          case MotionEvent.ACTION_MOVE:
          case MotionEvent.ACTION_UP:
            //  setInputDialog();
                  break;

          default:
            Log.d("mock it up", "Unknown touch event  " + event.toString());
            return false;
        }


        return true;
    }
};

/**
 * Called when replaying history to ensure the dirty region includes all
 * points.
 */
private void expandDirtyRect(float historicalX, float historicalY) {
  if (historicalX < dirtyRect.left) {
    dirtyRect.left = historicalX;
  } else if (historicalX > dirtyRect.right) {
    dirtyRect.right = historicalX;
  }
  if (historicalY < dirtyRect.top) {
    dirtyRect.top = historicalY;
  } else if (historicalY > dirtyRect.bottom) {
    dirtyRect.bottom = historicalY;
  }
}

/**
 * Resets the dirty region when the motion event occurs.
 */
private void resetDirtyRect(float eventX, float eventY) {

  // The lastTouchX and lastTouchY were set when the ACTION_DOWN
  // motion event occurred.
  dirtyRect.left = Math.min(lastTouchX, eventX);
  dirtyRect.right = Math.max(lastTouchX, eventX);
  dirtyRect.top = Math.min(lastTouchY, eventY);
  dirtyRect.bottom = Math.max(lastTouchY, eventY);
}


public void setMode(int mode){
    switch(mode){
    case 1://draw line
        Toast.makeText(getContext(), "draw line", Toast.LENGTH_SHORT).show();
        setOnTouchListener(drawLineListener);
        break;
    case 2://draw dashed line
        Toast.makeText(getContext(), "dashed line", Toast.LENGTH_SHORT).show();
        break;
    case 3:// draw circle
        setOnTouchListener(drawCircleListener);
        break;
    case 4: //draw oval
        setOnTouchListener(drawOvalListener);
        break;
    case 5: //draw rectangle
        setOnTouchListener(drawRectangleListener);
        break;
    case 6: //erase
        setOnTouchListener(eraseListener);
        break;
    case 7: //free-hand
        setOnTouchListener(drawFreeHandListener);
        break;
    case 8:
        setOnTouchListener(textListener);
        break;
    }
}

private Bitmap bitmap;
private Canvas myCanvas;
public Paint myPaint;

public void setImage(Bitmap b){
    Toast.makeText(getContext(), "set Bitmap",Toast.LENGTH_SHORT).show();
    bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
    myCanvas = new Canvas(bitmap);

    myPaint = new Paint();
    myPaint.setColor(Color.YELLOW);
    myPaint.setAntiAlias(true);
    myPaint.setStrokeWidth(8);

    invalidate();
}

public void changeColor(int color){
    paint = new Paint(paint);
    paint.setColor(color);
    //myPaint.setColor(color);
}

public float getRadius(float x1,float y1,float x2,float y2){
      float r = (float) (Math.sqrt((double)(Math.pow((y2-y1), 2.0)+Math.pow((x2-x1), 2.0)))/2);
      return r;
  }

public float getCircleMidPointX(float x1,float x2){
      return (x1+x2)/2;
  }

public float getCircleMidPointY(float y1,float y2){
      return (y1+y2)/2;
  }

}
4

1 回答 1

1

您必须就地创建位图,就在您将其保存到文件的位置。然后您必须根据位图创建自己的 Canvas 并将其传递给 View 的 draw 方法。像这样的东西:

public boolean onOptionsItemSelected(MenuItem item){
    switch (item.getItemId()) {
    case R.id.tools:
    ll.setVisibility(LinearLayout.VISIBLE);
    return true;
    case R.id.import_pics:
    getPhotos();
    return true;
    case R.id.save:
    {
        Bitmap bitmap = Bitmap.createBitmap(theView.getWidth(),theView.getHeight,Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        theView.draw(canvas);
        storeImage(bitmap);
        bitmap.recycle();
    }
    return true;
    case R.id.trash:
    return true;
    }
    return false;
}

将绘图代码移动到绘图方法。

我想这就是你要问的。这个问题并不是最清楚的。

于 2013-03-27T16:57:26.103 回答