如何使用Canvas

时间:2015-10-02 02:16:48

标签: android image canvas bitmap imageview

我在android中做一个绘画应用程序。我能够在画布上展示一幅画,并能够画画。我只需要在图像中绘制,就像市场上的应用程序colorfy,Coloring Bunny,Happy Zoo那样。我不确定如何实现这项任务。需要你的建议。

这是我的代码。

activity_main.xml中

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity"
android:background="#FFF">

<ImageView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:src="@drawable/bug"/>

<code.android.com.kidscolorbook.DrawingPad
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/drawingPad"
    android:textColor="#FFFFFF"
    android:cursorVisible="true"
    />
<Button
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/btnClear"
    android:layout_gravity="bottom|center"
    android:text="Clear Canvas"/>

MainActivity.java

public class MainActivity extends AppCompatActivity {

DrawingPad drawingPad;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Settings.System.putInt(getBaseContext().getContentResolver(),
            "show_touches", 1);
    drawingPad = (DrawingPad) findViewById(R.id.drawingPad);
   // drawingPad.setBackgroundResource(R.drawable.bug);
    Button btnClear = (Button) findViewById(R.id.btnClear);
    btnClear.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            drawingPad.clearCanvas();
        }
    });
}

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

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    // Handle action bar item clicks here. The action bar will
    // automatically handle clicks on the Home/Up button, so long
    // as you specify a parent activity in AndroidManifest.xml.
    int id = item.getItemId();

    //noinspection SimplifiableIfStatement
    if (id == R.id.action_settings) {
        return true;
    }

    return super.onOptionsItemSelected(item);
}

@Override
protected void onPause() {
    super.onPause();
    Settings.System.putInt(getBaseContext().getContentResolver(),
            "show_touches", 0);

}}

Drawingpad.java

public class DrawingPad extends View {

private Context mContext;
private Path mPath;
private Paint mPaint;

private Bitmap mBitmap;
private Canvas mCanvas;

private float mX,mY;
private static final float TOLERANCE = 5;

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

    this.mContext = context;
    mPath = new Path();
    mPaint = new Paint();

    mPaint.setAntiAlias(true);
    mPaint.setColor(Color.RED);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeJoin(Paint.Join.ROUND);
    mPaint.setStrokeWidth(50f);


}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    Resources resources = getResources();
    mBitmap = BitmapFactory.decodeResource(resources, R.drawable.circle);
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas(mBitmap);

}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawPath(mPath, mPaint);

}


@Override
public boolean onTouchEvent(MotionEvent event) {

    float x = event.getX();
    float y = event.getY();


    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN :
            startTouch(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            moveTouch(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            upTouch(mX,mY);
            invalidate();
            break;

    }

    return true;
}

private void startTouch(float x,float y){
    mPath.moveTo(x,y);
    mX = x;
    mY = y;
}

private void moveTouch(float x,float y)
{
    float dx = Math.abs(x - mX);
    float dy = Math.abs(y - mY);
    System.out.print("******"+x+y);
    if(dx >= TOLERANCE || dy>= TOLERANCE){
        mPath.quadTo(mX,mY,(x+mX)/2,(y+mY)/2);

        mX = x;
        mY = y;
    }
}

private void upTouch(float x, float y)
{
    mPath.lineTo(x,y);
}

public void clearCanvas()
{
    mPath.reset();
    invalidate();
}}

我的输出:

enter image description here

我只需要在图像和特定形状上绘制而不会散布颜色。(我知道我们可以减少笔划宽度)但是如果你能看一下上面提到的应用程序,你可能会完全理解这个问题。

需要你的建议,比如我们如何才能实现这种功能。

提前致谢。

1 个答案:

答案 0 :(得分:1)

我有同样的问题,经过长时间的研究,我认为解决方案FloodFill模式的一部分?这意味着什么:这意味着当你在图像的任何一点点击都有相同的颜色(targetColor) - &gt;在我们的例子中是白色,它转换为(replacementColor) - &gt;如果您的情况mPaint中的油漆颜色为红色,则可能需要进行更改的代码

@Override
public boolean onTouchEvent(MotionEvent event) {

    float x = event.getX();
    float y = event.getY();


    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN :
            startTouch(x, y);
            int sourceColor = bgImg.getPixel((int) x, (int) y);
            int desColor = paint.getColor();
            // pass the bitmap you want paint
            FloodFill(  mBitmap , new Point((int) x, (int) y) , sourceColor , desColor  );
            invalidate();
            break;
        case MotionEvent.ACTION_MOVE:
            moveTouch(x, y);
            invalidate();
            break;
        case MotionEvent.ACTION_UP:
            upTouch(mX,mY);
            invalidate();
            break;

    }

    return true;
}



private void FloodFill(Bitmap bmp, Point pt, int targetColor, int replacementColor) {
        Queue<Point> q = new LinkedList<Point>();
        q.add(pt);
        while (q.size() > 0) {
            Point n = q.poll();
            if (bmp.getPixel(n.x, n.y) != targetColor)
                continue;

            Point w = n, e = new Point(n.x + 1, n.y);
            while ((w.x > 0) && (bmp.getPixel(w.x, w.y) == targetColor)) {
                bmp.setPixel(w.x, w.y, replacementColor);
                if ((w.y > 0) && (bmp.getPixel(w.x, w.y - 1) == targetColor))
                    q.add(new Point(w.x, w.y - 1));
                if ((w.y < bmp.getHeight() - 1)
                        && (bmp.getPixel(w.x, w.y + 1) == targetColor))
                    q.add(new Point(w.x, w.y + 1));
                w.x--;
            }
            while ((e.x < bmp.getWidth() - 1)
                    && (bmp.getPixel(e.x, e.y) == targetColor)) {
                bmp.setPixel(e.x, e.y, replacementColor);

                if ((e.y > 0) && (bmp.getPixel(e.x, e.y - 1) == targetColor))
                    q.add(new Point(e.x, e.y - 1));
                if ((e.y < bmp.getHeight() - 1)
                        && (bmp.getPixel(e.x, e.y + 1) == targetColor))
                    q.add(new Point(e.x, e.y + 1));
                e.x++;
            }
        }
    }