用手指在安卓画布上绘制

4

我在当前工作中的某个项目中遇到了一些非常棘手的问题,要么没有可用的好信息,要么好信息被埋藏在海量的坏信息下面。

我已经解决了这些问题,并计划与所有开发人员分享一个简单的示例,以获取手指的触摸和运动事件,并进行绘制**。


1
请查看这篇博客文章:http://corner.squareup.com/2012/07/smoother-signatures.html - Gabe Sechan
这个回答解决了你的问题吗?在Android上通过手指在画布上绘制 - SebasSBM
我投票关闭此问题,因为它似乎并没有提出一个问题。 - TylerH
2个回答

13

按照以下步骤操作:

1) 创建一个视图类,继承View,并创建构造函数

覆盖 onDraw() 方法。你需要添加手指触碰和移动的路径。为此目的,你需要重写onTouch()方法。在你的onDraw()方法中,使用自己选择的画笔绘制路径。你应该调用invalidate()来刷新视图。

//drawing path
    static Path drawPath;
    //drawing and canvas paint
    private Paint drawPaint, canvasPaint;
    //initial color
    static int paintColor = 0xFFFF0000; 
    //stroke width
    private  float STROKE_WIDTH = 5f;
    //canvas
    private Canvas drawCanvas;
    //canvas bitmap
    private Bitmap canvasBitmap;
    //eraser mode
    private boolean erase=false;

    //constructor
    public DrawingView(Context context, AttributeSet attrs){
        super(context, attrs);
        setupDrawing();
        setErase(erase);
    }


        private void setupDrawing(){
            drawPath = new Path();
            drawPaint = new Paint();
            drawPaint.setColor(paintColor);
            drawPaint.setAntiAlias(true);
            drawPaint.setStrokeWidth(STROKE_WIDTH);
            drawPaint.setStyle(Paint.Style.STROKE);
            drawPaint.setStrokeJoin(Paint.Join.ROUND);
            drawPaint.setStrokeCap(Paint.Cap.ROUND);
            canvasPaint = new Paint(Paint.DITHER_FLAG);
        }

        //*************************************** View assigned size  ****************************************************

        @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            super.onSizeChanged(w, h, oldw, oldh);
            canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
            drawCanvas = new Canvas(canvasBitmap);
        }

        public void setErase(boolean isErase){
            erase=isErase;
        drawPaint = new Paint();
        if(erase) { 
            setupDrawing();
            int srcColor= 0x00000000;

            PorterDuff.Mode mode = PorterDuff.Mode.CLEAR;
            PorterDuffColorFilter porterDuffColorFilter = new PorterDuffColorFilter(srcColor, mode);

            drawPaint.setColorFilter(porterDuffColorFilter);

            drawPaint.setColor(srcColor);
            drawPaint.setXfermode(new PorterDuffXfermode(mode));

        }
        else {

            setupDrawing();

        }
        }

        //************************************   draw view  *************************************************************

        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
            canvas.drawPath(drawPath, drawPaint);
        }

        //***************************   respond to touch interaction   **************************************************

        @Override
        public boolean onTouchEvent(MotionEvent event) {

            canvasPaint.setColor(paintColor);
            float touchX = event.getX();
            float touchY = event.getY();
            //respond to down, move and up events

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawPath.lineTo(touchX, touchY);
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;
            default:
                return false;
            }
            //redraw
            invalidate();
            return true;
        }

        //***********************************   return current alpha   ***********************************************
        public int getPaintAlpha(){
            return Math.round((float)STROKE_WIDTH/255*100);
        }

        //**************************************  set alpha   ******************************************************
        public void setPaintAlpha(int newAlpha){
            STROKE_WIDTH=Math.round((float)newAlpha/100*255);
            drawPaint.setStrokeWidth(newAlpha);
    }
        }

2) 你的活动:

SeekBar mThickness;
private DrawingView mDrawLayout;
Button erase, draw;
private Paint drawPaint = new Paint();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mThickness = (SeekBar) findViewById(R.id.thickness);
    mDrawLayout = (DrawingView) findViewById(R.id.viewDraw);
    erase = (Button) findViewById(R.id.erase);
    draw= (Button) findViewById(R.id.draw);

    mDrawLayout.setVisibility(View.VISIBLE);
    mDrawLayout.setDrawingCacheEnabled(true);
    mDrawLayout.setEnabled(true);
    mThickness.setMax(50);
    mThickness.setProgress(10);
    mDrawLayout.setPaintAlpha(mThickness.getProgress());
    int currLevel = mDrawLayout.getPaintAlpha();
    mThickness.setProgress(currLevel);
    mDrawLayout.invalidate();

    erase.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            drawPaint.setColor(Color.TRANSPARENT);
            mDrawLayout.setErase(true);

        }
    });

    draw.setOnClickListener(new OnClickListener() {

        @Override
        public void onClick(View v) {
            mDrawLayout.setErase(false);

        }
    });

    mThickness.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
        }

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            mDrawLayout.setPaintAlpha(mThickness.getProgress());
        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

3) XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    tools:context=".MainActivity" >

    <com.example.drawdemo.DrawingView
        android:id="@+id/viewDraw"
        android:layout_width="wrap_content"
        android:layout_height="200dp"
        android:layout_marginTop="20dp"
        android:scaleType="fitXY" />

    <SeekBar
        android:id="@+id/thickness"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/viewDraw"
        android:layout_marginTop="25dp" />

    <Button
        android:id="@+id/erase"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/thickness"
        android:text="erase" />

    <Button
        android:id="@+id/draw"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/erase"
        android:text="draw" />

</RelativeLayout>

2
创建一个继承自View的类,将下面的代码粘贴到该类中。
public class CustomClass extends View {

  private Paint paint = new Paint();
  private Path path = new Path();

  public CustomClass(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    paint.setAntiAlias(true);
    paint.setStrokeWidth(5 f);
    paint.setColor(Color.BLACK);
    paint.setStyle(Paint.Style.STROKE);
    paint.setStrokeJoin(Paint.Join.ROUND);
  }

  @Override protected void onDraw(Canvas canvas) {
    canvas.drawPath(path, paint);
  }

  @Override public boolean onTouchEvent(MotionEvent event) {
    // Get the coordinates of the touch event.
    float eventX = event.getX();
    float eventY = event.getY();

    switch (event.getAction()) {
      case MotionEvent.ACTION_DOWN:
        // Set a new starting point
        path.moveTo(eventX, eventY);
        return true;
      case MotionEvent.ACTION_MOVE:
        // Connect the points
        path.lineTo(eventX, eventY);
        break;
      default:
        return false;
    }

    // Makes our view repaint and call onDraw
    invalidate();
    return true;
  }

}

在XML中,粘贴以下代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff">

    <!-- This is the view on which we will draw. -->
    <view
        android:layout_width="match_parent"
        android:layout_height="200sp"
        class="com.example.gopal.drawing.MainDrawingView"
        android:id="@+id/custom_view"
        android:layout_gravity="left|top"
        android:background="#ffffff" />

    <View
        android:id="@+id/boundary"
        android:layout_width="match_parent"
        android:layout_height="2sp"
        android:background="@color/colorAccent"
        android:layout_below="@id/custom_view"/>

    <ImageView
        android:id="@+id/image"
        android:layout_width="300sp"
        android:layout_height="300sp"
        android:src="@drawable/ic_launcher_background"
        android:layout_below="@id/boundary"
        android:layout_marginTop="6sp"
        android:layout_centerHorizontal="true"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="save"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:onClick="saveImage"/>

</RelativeLayout>

您的MainActivity

public class MainActivity extends AppCompatActivity {

  ImageView imageView;
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    imageView = findViewById(R.id.image);
  }

  public void saveImage(View view) {
    View v = findViewById(R.id.custom_view);
    int canvasWidth = v.getWidth();
    int canvasHeight = v.getHeight();
    Bitmap bitmap = Bitmap.createBitmap(canvasWidth, canvasHeight, Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    v.draw(canvas);
    imageView.setImageBitmap(bitmap);

  }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接