so I have a canvas, and I would like a certain image (Lets say image.png) to appear where the user touches. What would I use? OnTouch?
Can someone help me out? Here is my canvas class below. Right now I have a few random images and shapes drawn, but they happen right away, not when someone touches like I would like it.
Thanks in advance!
public class MyView extends View
private Canvas canvas;
private Bitmap bitmap;
public MyView(Context context) {
super(context);
}
protected void onSizeChanged(int curw, int curh, int oldw, int oldh) {
if (bitmap != null) {
bitmap .recycle();
}
canvas= new Canvas();
bitmap = Bitmap.createBitmap(curw, curh, Bitmap.Config.ARGB_8888);
canvas.setBitmap(bitmap);
}
public void destroy() {
if (bitmap != null) {
bitmap.recycle();
}
}
public void onTouch(Canvas canvas) {
Bitmap _scratch = BitmapFactory.decodeResource(getResources(), R.drawable.test);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(_scratch, 0, 0, null);
}
public void onDraw(Canvas canvas) {
//draw onto the canvas
Bitmap _scratch1 = BitmapFactory.decodeResource(getResources(), R.drawable.spacecat);
canvas.drawColor(Color.TRANSPARENT);
canvas.drawBitmap(_scratch1, 0, 0, null);
Paint myPaint = new Paint();
myPaint.setStrokeWidth(4);
myPaint.setColor(0xFF097286);
canvas.drawCircle(240, 40, 30, myPaint);
myPaint.setColor(0xFFF07222);
Point p1 = new Point();
Point p2 = new Point();
p1.x = 0;
p1.y = 0;
p2.x = 40;
p2.y = 55;
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, myPaint);
float[] pts = new float[8];
pts[0] = 100;
pts[1] = 5;
pts[2] = 97;
pts[3] = 9;
pts[4] = 90;
pts[5] = 15;
pts[6] = 84;
pts[7] = 20;
myPaint.setColor(0xFF40FF40);
myPaint.setStrokeWidth(9);
myPaint.setAntiAlias(true);
canvas.drawPoints(pts, myPaint);
myPaint.setColor(0xFFF0FF00);
myPaint.setStrokeWidth(4);
myPaint.setStyle(Paint.Style.STROKE);
canvas.drawCircle(110, 150, 100, myPaint);
}}
I wrote an example for you :
public class MyView extends View {
boolean touching = false;
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas); //To change body of overridden methods use File | Settings | File Templates.
if (touching) {
//You can draw other thing here. just draw bitmap for example.
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
Rect source = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
Rect bitmapRect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
canvas.drawBitmap(bitmap, source, bitmapRect, new Paint());
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touching = true;
invalidate();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
touching = false;
invalidate();
break;
}
return super.onTouchEvent(event); //To change body of overridden methods use File | Settings | File Templates.
}
}
Related
I am hand drawing images on a canvas and then converting them to a bitmap. Then, I am dragging this on screen. That's all fine, What I want is onTouchEvent to draw a rectangle round this image/s but NOT the whole canvas. So I'm wondering if I can measure the drawing width and height and subtract this from canvas width and height but I'm struggling and not sure How can I achieve this? Unless there's a better idea someone can suggest.
private static class DrawingView extends View {
float x = 0f,y = 0f;
float dX,dY;
Paint paint;
public DrawingView(Context context){
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.id.main);
paint = new Paint();
}
public boolean onTouchEvent(MotionEvent event){
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
dX = this.getX() - event.getRawX();
dY = this.getY() - event.getRawY();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
this.setX(event.getRawX() + dX);
this.setY(event.getRawY() + dY);
invalidate();
break;
case MotionEvent.ACTION_UP:
invalidate();
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.BLACK);
canvas.drawBitmap(bitmap, x, y, paint);
float left = (x + (bitmap.getWidth()/2));
float top = (y + (bitmap.getHeight()/2));
float right = bitmap.getWidth() - left;
float bottom = bitmap.getHeight() - top;
canvas.drawRect(left, top, right, bottom, paint);
}
}//End of inner class
My drawing class
public class DrawView extends View {
private Paint drawPaint, canvasPaint;
private Canvas drawCanvas;
private Bitmap canvasBitmap;
private SparseArray<Path> paths;
public DrawView(Context context) {
super(context);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public DrawView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setupDrawing();
}
private void setupDrawing() {
paths = new SparseArray<>();
drawPaint = new Paint();
drawPaint.setColor(Color.BLACK);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(9);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#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);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
for (int i = 0; i < paths.size(); i++) {
canvas.drawPath(paths.valueAt(i), drawPaint);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int index = event.getActionIndex();
int id = event.getPointerId(index);
final Point p = new Point();
Path path;
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
path = new Path();
path.moveTo(event.getX(index), event.getY(index));
paths.put(id, path);
break;
case MotionEvent.ACTION_MOVE:
for (int i=0; i<event.getPointerCount(); i++) {
id = event.getPointerId(i);
path = paths.get(id);
if (path != null) path.lineTo(event.getX(i), event.getY(i));
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
path = paths.get(id);
if (path != null) {
drawCanvas.drawPath(path, drawPaint);
paths.remove(id);
}
setPenEnabled(true);
break;
default:
return false;
}
invalidate();
return true;
}
/**
* change path color here
*/
public void setPathColor(int color) {
drawPaint.setColor(color);
}
//Clear screen
public void clear() {
canvasBitmap.eraseColor(Color.TRANSPARENT);
paths.clear();
invalidate();
System.gc();
}
}//End of Class
I have one imageview and i set image for filling the different colors. But when i fill color then other color is not fill on same area on imageview which previous color is filled. I use color pallet button for getting different color for fill on imageview. Below is my code.
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
switch (v.getId()){
case R.id.btn_color_one: {
// do something for button 1 click
initializeMP();
playsound.start();
paint.setColor(DARK_PINK);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStrokeWidth(30);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
// path = new Path();
break;
}
case R.id.btn_color_two: {
// do something for button 1 click
initializeMP();
playsound.start();
paint.setColor(LIGHT_YELLOW);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStrokeWidth(30);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
// paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
break;
}
After getting lots of r&d i got my answer:
private final Paint mPaintSrcIn = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mPaintDstIn = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mPaintColor = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mPaintEraser = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Matrix mMatrix = new Matrix();
private final Canvas mLayerCanvas = new Canvas();
private Bitmap mInnerShape;
private Bitmap mOuterShape;
private Bitmap mLayerBitmap;
private ArrayList<DrawOp> mDrawOps = new ArrayList<DrawOp>();
private DrawOp mCurrentOp = new DrawOp();
private ArrayList<DrawOp> mUndoneOps = new ArrayList<DrawOp>();
public DrawingView(Context context)
{
this(context, null, 0);
}
public DrawingView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public DrawingView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mPaintSrcIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaintDstIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaintColor.setStyle(Paint.Style.STROKE);
mPaintColor.setStrokeJoin(Paint.Join.ROUND);
mPaintColor.setStrokeCap(Paint.Cap.ROUND);
mPaintEraser.set(mPaintColor);
mPaintEraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaintEraser.setMaskFilter(new BlurMaskFilter(getResources()
.getDisplayMetrics().density * 4, BlurMaskFilter.Blur.NORMAL));
}
public void setShape(int inner, int outer)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ALPHA_8;
setShape(BitmapFactory.decodeResource(getResources(), inner, options),
BitmapFactory.decodeResource(getResources(), outer, options));
}
public void setShape(int[] inner, int[] outer){
for(int i=0;i<inner.length;i++){
for(int j=0;j<outer.length;j++){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ALPHA_8;
setShape(BitmapFactory.decodeResource(getResources(), inner[i], options),
BitmapFactory.decodeResource(getResources(), outer[j], options));
}
}
}
public void setShape(Bitmap inner, Bitmap outer)
{
mInnerShape = inner;
mOuterShape = outer;
requestLayout();
invalidate();
}
public void setDrawingColor(int color)
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.PAINT;
mCurrentOp.color = color;
}
public void setDrawingStroke(int stroke)
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.PAINT;
mCurrentOp.stroke = stroke;
}
public void enableEraser()
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.ERASE;
}
public void clearDrawing()
{
mDrawOps.clear();
mUndoneOps.clear();
mCurrentOp.reset();
invalidate();
}
public void undoOperation()
{
if(mDrawOps.size() > 0){
DrawOp last = mDrawOps.remove(mDrawOps.size() - 1);
mUndoneOps.add(last);
invalidate();
}
}
public void redoOperation()
{
if(mUndoneOps.size() > 0){
DrawOp redo = mUndoneOps.remove(mUndoneOps.size() - 1);
mDrawOps.add(redo);
invalidate();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mLayerCanvas.setBitmap(mLayerBitmap);
if(mOuterShape != null){
int dx = (w - mOuterShape.getWidth()) / 2;
int dy = (h - mOuterShape.getHeight()) / 2;
mMatrix.setTranslate(dx, dy);
}
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if(isInEditMode()){
return;
}
// NOTE: Without extra bitmap or layer.. but HW Acceleration does not support setMaskFilter which means
// eraser has strong edges whilst drawing.
// #see http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
/*
canvas.drawBitmap(mOuterShape, 0, 0, null);
canvas.saveLayer(null, mPaint, Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(mInnerShape, 0, 0, null);
canvas.saveLayer(null, mPaintSrcIn, Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
canvas.drawBitmap(mBitmapDraw, 0, 0, null);
canvas.drawPath(mPath, mPaintDraw);
canvas.restore();
canvas.restore();
*/
// Clear software canvas
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
// Draw picture from ops
for(DrawOp op : mDrawOps){
drawOp(mLayerCanvas, op);
}
drawOp(mLayerCanvas, mCurrentOp);
// Mask the drawing to the inner surface area of the shape
mLayerCanvas.drawBitmap(mInnerShape, mMatrix, mPaintDstIn);
// Draw orignal shape to view
canvas.drawBitmap(mOuterShape, mMatrix, null);
// Draw masked image to view
canvas.drawBitmap(mLayerBitmap, 0, 0, null);
}
private void drawOp(Canvas canvas, DrawOp op)
{
if(op.path.isEmpty()){
return;
}
final Paint paint;
if(op.type == DrawOp.Type.PAINT){
paint = mPaintColor;
paint.setColor(op.color);
paint.setStrokeWidth(op.stroke);
}else{
paint = mPaintEraser;
paint.setStrokeWidth(op.stroke);
}
mLayerCanvas.drawPath(op.path, paint);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event)
{
final float x = event.getX();
final float y = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mUndoneOps.clear();
mCurrentOp.path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
for(int i = 0; i < event.getHistorySize(); i++){
mCurrentOp.path.lineTo(event.getHistoricalX(i), event.getHistoricalY(i));
}
mCurrentOp.path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCurrentOp.path.lineTo(x, y);
mDrawOps.add(new DrawOp(mCurrentOp));
mCurrentOp.path.reset();
break;
}
invalidate();
return true;
}
}
I have imageview and i set "A" character for filling the colors.My actual problem is how to fill color over different color on same portion of imageview? Below is my source code for color pallet for changing diferent color on click.
case R.id.btn_color_one: {
// do something for button 1 click
setupDrawing();
paint.setColor(RED);
break;
}
case R.id.btn_color_two: {
// do something for button 1 click
setupDrawing();
paint.setColor(LIGHT_BLUE);
break;
}
And this is a setupDrawing(),
public void setupDrawing(){
initializeMP();
playsound.start();
canvas = new Canvas(bitmap);
paint.setAntiAlias(true);
paint.setDither(true);
paint.setStrokeWidth(30);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
}
Bitmap class has a getPixel(int x, int y) that returns a Color http://developer.android.com/reference/android/graphics/Color.html.
Then you can check the value and setPixel again to a new one. Just run all the bitmap checking for red and set it to blue or whatever.
After doing lots of R&D i got my answer:
private final Paint mPaintSrcIn = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mPaintDstIn = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG | Paint.FILTER_BITMAP_FLAG);
private final Paint mPaintColor = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Paint mPaintEraser = new Paint(Paint.ANTI_ALIAS_FLAG);
private final Matrix mMatrix = new Matrix();
private final Canvas mLayerCanvas = new Canvas();
private Bitmap mInnerShape;
private Bitmap mOuterShape;
private Bitmap mLayerBitmap;
private ArrayList<DrawOp> mDrawOps = new ArrayList<DrawOp>();
private DrawOp mCurrentOp = new DrawOp();
private ArrayList<DrawOp> mUndoneOps = new ArrayList<DrawOp>();
public DrawingView(Context context)
{
this(context, null, 0);
}
public DrawingView(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public DrawingView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
mPaintSrcIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
mPaintDstIn.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaintColor.setStyle(Paint.Style.STROKE);
mPaintColor.setStrokeJoin(Paint.Join.ROUND);
mPaintColor.setStrokeCap(Paint.Cap.ROUND);
mPaintEraser.set(mPaintColor);
mPaintEraser.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
mPaintEraser.setMaskFilter(new BlurMaskFilter(getResources()
.getDisplayMetrics().density * 4, BlurMaskFilter.Blur.NORMAL));
}
public void setShape(int inner, int outer)
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ALPHA_8;
setShape(BitmapFactory.decodeResource(getResources(), inner, options),
BitmapFactory.decodeResource(getResources(), outer, options));
}
public void setShape(int[] inner, int[] outer){
for(int i=0;i<inner.length;i++){
for(int j=0;j<outer.length;j++){
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ALPHA_8;
setShape(BitmapFactory.decodeResource(getResources(), inner[i], options),
BitmapFactory.decodeResource(getResources(), outer[j], options));
}
}
}
public void setShape(Bitmap inner, Bitmap outer)
{
mInnerShape = inner;
mOuterShape = outer;
requestLayout();
invalidate();
}
public void setDrawingColor(int color)
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.PAINT;
mCurrentOp.color = color;
}
public void setDrawingStroke(int stroke)
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.PAINT;
mCurrentOp.stroke = stroke;
}
public void enableEraser()
{
mCurrentOp.reset();
mCurrentOp.type = DrawOp.Type.ERASE;
}
public void clearDrawing()
{
mDrawOps.clear();
mUndoneOps.clear();
mCurrentOp.reset();
invalidate();
}
public void undoOperation()
{
if(mDrawOps.size() > 0){
DrawOp last = mDrawOps.remove(mDrawOps.size() - 1);
mUndoneOps.add(last);
invalidate();
}
}
public void redoOperation()
{
if(mUndoneOps.size() > 0){
DrawOp redo = mUndoneOps.remove(mUndoneOps.size() - 1);
mDrawOps.add(redo);
invalidate();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
mLayerBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mLayerCanvas.setBitmap(mLayerBitmap);
if(mOuterShape != null){
int dx = (w - mOuterShape.getWidth()) / 2;
int dy = (h - mOuterShape.getHeight()) / 2;
mMatrix.setTranslate(dx, dy);
}
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if(isInEditMode()){
return;
}
// NOTE: Without extra bitmap or layer.. but HW Acceleration does not support setMaskFilter which means
// eraser has strong edges whilst drawing.
// #see http://developer.android.com/guide/topics/graphics/hardware-accel.html#unsupported
/*
canvas.drawBitmap(mOuterShape, 0, 0, null);
canvas.saveLayer(null, mPaint, Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
canvas.drawColor(0, PorterDuff.Mode.CLEAR);
canvas.drawBitmap(mInnerShape, 0, 0, null);
canvas.saveLayer(null, mPaintSrcIn, Canvas.FULL_COLOR_LAYER_SAVE_FLAG);
canvas.drawBitmap(mBitmapDraw, 0, 0, null);
canvas.drawPath(mPath, mPaintDraw);
canvas.restore();
canvas.restore();
*/
// Clear software canvas
mLayerCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
// Draw picture from ops
for(DrawOp op : mDrawOps){
drawOp(mLayerCanvas, op);
}
drawOp(mLayerCanvas, mCurrentOp);
// Mask the drawing to the inner surface area of the shape
mLayerCanvas.drawBitmap(mInnerShape, mMatrix, mPaintDstIn);
// Draw orignal shape to view
canvas.drawBitmap(mOuterShape, mMatrix, null);
// Draw masked image to view
canvas.drawBitmap(mLayerBitmap, 0, 0, null);
}
private void drawOp(Canvas canvas, DrawOp op)
{
if(op.path.isEmpty()){
return;
}
final Paint paint;
if(op.type == DrawOp.Type.PAINT){
paint = mPaintColor;
paint.setColor(op.color);
paint.setStrokeWidth(op.stroke);
}else{
paint = mPaintEraser;
paint.setStrokeWidth(op.stroke);
}
mLayerCanvas.drawPath(op.path, paint);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event)
{
final float x = event.getX();
final float y = event.getY();
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
mUndoneOps.clear();
mCurrentOp.path.moveTo(x, y);
break;
case MotionEvent.ACTION_MOVE:
for(int i = 0; i < event.getHistorySize(); i++){
mCurrentOp.path.lineTo(event.getHistoricalX(i), event.getHistoricalY(i));
}
mCurrentOp.path.lineTo(x, y);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mCurrentOp.path.lineTo(x, y);
mDrawOps.add(new DrawOp(mCurrentOp));
mCurrentOp.path.reset();
break;
}
invalidate();
return true;
}
}
I am using below code to erase bitmap from canvas on touch event.
it's working fine in android 2.3 but in 4.0 it show me black spot instead of erasing bitmap.
anyone can help.
public class DemoTouch extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new TouchView(this));
}
class TouchView extends View {
Bitmap bgr;
Bitmap overlayDefault;
Bitmap overlay;
Paint pTouch;
int X = -100;
int Y = -100;
Canvas c2;
public TouchView(Context context) {
super(context);
bgr = BitmapFactory.decodeResource(getResources(), R.drawable.a1);
overlayDefault = BitmapFactory.decodeResource(getResources(),
R.drawable.a2);
overlay = BitmapFactory.decodeResource(getResources(),
R.drawable.a2).copy(Config.ARGB_4444, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
pTouch.setAntiAlias(true);
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_MOVE: {
X = (int) ev.getX();
Y = (int) ev.getY();
invalidate();
break;
}
case MotionEvent.ACTION_UP:
break;
}
return true;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// draw background
canvas.drawBitmap(bgr, 0, 0, null);
// copy the default overlay into temporary overlay and punch a hole
// in it
// c2.drawBitmap(overlayDefault, 0, 0, null); // exclude this line
// to
// show all as you draw
c2.drawCircle(X, Y, 20, pTouch);
// draw the overlay over the background
canvas.drawBitmap(overlay, 0, 0, null);
}
}
}
Have a look at this method of mine. The view EditImageView is a custom ImageView that I also applied that erase function to. I had the same problem until I applied the code below inside the if statement. That fixes the problem for 3.0 and up
/**
* Sets the image to the view in the content view
* #param view
*/
private void setImageView(EditImageView view) {
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
view.setLayoutParams(params);
// #### THIS IS THE IMPORTANT PART ######
if (Build.VERSION.SDK_INT >= 11) {
view.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
LinearLayout main = (LinearLayout) findViewById(R.id.galleryImage);
main.removeAllViews();
main.addView(view);
}
EDIT
You can probably do something like this in your code.
public TouchView(Context context) {
super(context);
// This should fix it from 3.0 and up
if (Build.VERSION.SDK_INT >= 11) {
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}
bgr = BitmapFactory.decodeResource(getResources(), R.drawable.a1);
overlayDefault = BitmapFactory.decodeResource(getResources(),
R.drawable.a2);
overlay = BitmapFactory.decodeResource(getResources(),
R.drawable.a2).copy(Config.ARGB_4444, true);
c2 = new Canvas(overlay);
pTouch = new Paint(Paint.ANTI_ALIAS_FLAG);
pTouch.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
pTouch.setColor(Color.TRANSPARENT);
pTouch.setMaskFilter(new BlurMaskFilter(15, Blur.NORMAL));
pTouch.setAntiAlias(true);
}
Hope this also helps you
I try to erase parts of a bitmap in my Android application by using Porter-Duff Xfermodes.
I have a green background which is overlayed by a blue bitmap. When I touch the screen a "hole" in the overlaying bitmap is supposed to be created making the green background visible. Instead of a hole my current code produces a black dot.
Below is my code. Any ideas, what I am doing wrong here?
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new DrawView(this));
}
public class DrawView extends View implements OnTouchListener {
private int x = 0;
private int y = 0;
Bitmap bitmap;
Canvas bitmapCanvas;
private final Paint paint = new Paint();
private final Paint eraserPaint = new Paint();
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// Set background
this.setBackgroundColor(Color.GREEN);
// Set bitmap
bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.RGB_565);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.drawColor(Color.BLUE);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
eraserPaint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
bitmapCanvas.drawColor(Color.BLUE);
bitmapCanvas.drawCircle(x, y, 10, eraserPaint);
canvas.drawBitmap(bitmap, 0, 0, paint);
}
public boolean onTouch(View view, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
invalidate();
return true;
}
}
Here is working code... may help somebody
public class ImageDemo extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Panel(this));
}
class Panel extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mPaint;
Bitmap bitmap;
Canvas pcanvas;
int x = 0;
int y =0;
int r =0;
public Panel(Context context) {
super(context);
Log.v("Panel", ">>>>>>");
setFocusable(true);
setBackgroundColor(Color.GREEN);
// setting paint
mPaint = new Paint();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setAntiAlias(true);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.mickey);
// converting image bitmap into mutable bitmap
bitmap = bm.createBitmap(295, 260, Config.ARGB_8888);
pcanvas = new Canvas();
pcanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
pcanvas.drawBitmap(bm, 0, 0, null);
}
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
pcanvas.drawCircle(x, y, r, mPaint);
canvas.drawBitmap(bitmap, 0, 0,null);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// set parameter to draw circle on touch event
x = (int) event.getX();
y = (int) event.getY();
r =20;
// At last invalidate canvas
invalidate();
return true;
}
}
}
First thought, I'm not sure if setting alpha to 0 on your erase paint object is a good idea. That might make the whole thing ineffective.
Also, you should always use Bitmap.Config.ARGB_8888 if you're dealing with alphas.
If you're having trouble with the PorterDuff stuff, though, I would suggest simplifying your approach to ONLY do that (temporarily). That will help you narrow down the part which isn't working. Comment out everything to do with touch and view updates.
Then you can single out what part of the drawing isn't working right. Set up your constructor like this:
DrawView()
{
/* Create the background green bitmap */
...
/* Create foreground transparent bitmap */
...
/* Draw a blue circle on the foreground bitmap */
...
/* Apply the foreground to the background bitmap
using a PorterDuff method */
...
}
onDraw()
{
/* Simply draw the background bitmap */
...
}
If you set things up like that, you should be able to tell how your PD method is affecting the green bitmap, and change things accordingly.
Here is another advancement for your solution ... See Demo example
public class MainActivity extends Activity {
Bitmap bp;
Canvas bitmapCanvas;
DrawView drawImg;
LinearLayout ln1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ln1 = (LinearLayout) findViewById(R.id.ln1);
drawImg = new DrawView(this);
ln1.addView(drawImg);
}
public class DrawView extends View implements View.OnTouchListener {
private int x = 0;
private int y = 0;
Bitmap bitmap;
Path circlePath;
Paint circlePaint;
private final Paint paint = new Paint();
private final Paint eraserPaint = new Paint();
public DrawView(Context context){
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
// Set background
this.setBackgroundColor(Color.CYAN);
bp = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
// Set bitmap
bitmap = Bitmap.createBitmap(320, 480, Bitmap.Config.ARGB_8888);
bitmapCanvas = new Canvas();
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.drawColor(Color.TRANSPARENT);
bitmapCanvas.drawBitmap(bp, 0, 0, null);
circlePath = new Path();
circlePaint = new Paint();
circlePaint.setAntiAlias(true);
circlePaint.setColor(Color.BLUE);
circlePaint.setStyle(Paint.Style.STROKE);
circlePaint.setStrokeJoin(Paint.Join.MITER);
circlePaint.setStrokeWidth(4f);
// Set eraser paint properties
eraserPaint.setAlpha(0);
eraserPaint.setStrokeJoin(Paint.Join.ROUND);
eraserPaint.setStrokeCap(Paint.Cap.ROUND);
eraserPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
eraserPaint.setAntiAlias(true);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, paint);
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
canvas.drawPath(circlePath, circlePaint);
}
public boolean onTouch(View view, MotionEvent event) {
x = (int) event.getX();
y = (int) event.getY();
bitmapCanvas.drawCircle(x, y, 30, eraserPaint);
circlePath.reset();
circlePath.addCircle(x, y, 30, Path.Direction.CW);
int ac=event.getAction();
switch(ac){
case MotionEvent.ACTION_UP:
Toast.makeText(MainActivity.this, String.valueOf(x), Toast.LENGTH_SHORT).show();
circlePath.reset();
break;
}
invalidate();
return true;
}
}
}
read more