Android: touch points escaped - android
I am working on some project, in which I have to animate image depending upon the users touch, but the problem is I am not getting all the touch points, therefore I do not get the smooth animation. I am working on Android tablet os 4.0.3.
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
List<Points> points = new ArrayList<Points>();
Paint paint = new Paint();
Button button = null;
int movement = 0;
int[] imageIds = {R.drawable.zero,R.drawable.one,R.drawable.two,R.drawable.three,R.drawable.four,
R.drawable.five,R.drawable.six,R.drawable.seven,R.drawable.eight,R.drawable.ninie,R.drawable.ten,
R.drawable.eleven,R.drawable.twelve,R.drawable.thirteen,R.drawable.fourteen,R.drawable.fifteen,
R.drawable.sixteen,R.drawable.seventeen,R.drawable.eighteen,R.drawable.ninteen,R.drawable.twenty,
R.drawable.twentyone,R.drawable.twentytwo,R.drawable.twentythree,R.drawable.twentyfour,
R.drawable.twentyfive,R.drawable.twentysix,R.drawable.twentyseven,R.drawable.twentyeight,
R.drawable.twentynine,R.drawable.thirty,R.drawable.thirtyone,R.drawable.thirtytwo,
R.drawable.thirtythree,R.drawable.thirtyfour,R.drawable.thirtyfive,R.drawable.thirtysix,
R.drawable.thirtyseven,R.drawable.thirtyeight,R.drawable.thirtynine,R.drawable.fortyone,
R.drawable.fortytwo,R.drawable.fortytwo,R.drawable.fortyfour,R.drawable.fortyfive,
R.drawable.fortysix,R.drawable.fortyseven,R.drawable.fortyeight,R.drawable.fortynine,
R.drawable.fifty,R.drawable.fiftyone,R.drawable.fiftyone,R.drawable.fiftythree,R.drawable.fiftyfour,
R.drawable.fiftyfive,R.drawable.fiftysix,R.drawable.fiftyseven,R.drawable.fiftyeight,
R.drawable.fiftynine,R.drawable.sixty,R.drawable.sixtyone,R.drawable.sixtytwo,
R.drawable.sixtythree,R.drawable.sixtyfour,R.drawable.sixtyfive,R.drawable.sixtysix,
R.drawable.sixtyseven,R.drawable.sixtyeight,R.drawable.sixtynine,R.drawable.seventy,
R.drawable.seventyone,R.drawable.seventytwo,R.drawable.seventythree,R.drawable.seventyfour,
R.drawable.seventyfive,R.drawable.seventysix,R.drawable.seventyseven,R.drawable.seventyeight,
R.drawable.seventynine,R.drawable.eighty,R.drawable.eightyone,R.drawable.eightytwo,R.drawable.thirtythree,
R.drawable.eightyfour,R.drawable.eightyfive,R.drawable.eightysix,R.drawable.eightyseven,
R.drawable.seventyeight,R.drawable.eightynine,R.drawable.ninty,R.drawable.nintyone,
R.drawable.nintytwo,R.drawable.nintythree,R.drawable.nintyfour,R.drawable.nintyfive,
R.drawable.nintysix,R.drawable.nintyseven,R.drawable.nintyeight,R.drawable.nintynine,
R.drawable.hundred
};
int touchPoint=0,currentImage=0;
float previousX = 0, starting = 0, difference = 0, remaining=0;
RelativeLayout relativeLayout;
Boolean update = false;
int changeImageFrequency = 4;
ImageView image;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
}
#SuppressLint("DrawAllocation")
#TargetApi(11)
#Override
public void onDraw(Canvas canvas) {
Log.i("testing", "i am in draw");
if (movement==0) {
Bitmap bimap = BitmapFactory.decodeResource(getResources(), imageIds[currentImage]);
canvas.drawBitmap(bimap, 0, 0,null);
invalidate();
}
else if (movement==1) {
if (currentImage+changeImageFrequency<100) {
currentImage+=changeImageFrequency;
Bitmap bimap = BitmapFactory.decodeResource(getResources(), imageIds[currentImage]);
canvas.drawBitmap(bimap, 0, 0,null);
invalidate();
}
else {
Bitmap bimap = BitmapFactory.decodeResource(getResources(), imageIds[currentImage]);
canvas.drawBitmap(bimap, 0, 0,null);
currentImage=0;
}
movement=0;
invalidate();
}
else if (movement==2) {
if (currentImage-changeImageFrequency>=0) {
currentImage-=changeImageFrequency;
Bitmap bimap = BitmapFactory.decodeResource(getResources(), imageIds[currentImage]);
canvas.drawBitmap(bimap, 0, 0,null);
invalidate();
}
else {
Bitmap bimap = BitmapFactory.decodeResource(getResources(), imageIds[currentImage]);
canvas.drawBitmap(bimap, 0, 0,null);
currentImage=99;
}
movement=0;
invalidate();
}
}
public boolean onTouch(View view, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
starting = event.getX();
invalidate();
break;
case MotionEvent.ACTION_MOVE:
difference = event.getX()-starting;
if (difference>0)
movement = 1;
else if (difference<0)
movement = 2;
invalidate();
break;
case MotionEvent.ACTION_UP:
invalidate();
break;
}
return true;
}
If your images are of average resolution, then loading them (BitmapFactory.decodeResource) in the Main thread will block the UI, causing some touch events to be skipped untill the loading is performed. A better implementation is to use SurfaceView instead of View since it performs its drawing in a separate thread. Check this link for more details on using SurfaceView.
Related
canvas draw bitmap overrides drawn path
I have a problem with canvas I have two options either to draw with a paint or to add an image but when I choose to add an image after drawing the drawing is gone but when I choose drawing again and start to draw the previous drawing show up and remove the image. public class DrawCanvas extends View { Bitmap bitmap; private Paint paint = new Paint(); private Path path; ArrayList<Path> paths = new ArrayList<>(); ArrayList<Path> undo = new ArrayList<>(); final Paint mBackgroundPaint; ArrayList<Emotion> emotions; private boolean mDrawingEnabled = true; float currentX = 0, currentY = 0; public DrawCanvas(Context context, #Nullable AttributeSet attrs) { super(context, attrs); bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.launcher); paint.setAntiAlias(false); paint.setColor(Color.BLACK); paint.setStrokeJoin(Paint.Join.MITER); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(30f); emotions = new ArrayList<>(); path = new Path(); mBackgroundPaint = new Paint(); mBackgroundPaint.setColor(Color.WHITE); } #Override protected void onDraw(Canvas canvas){ if (mDrawingEnabled ) { canvas.drawPath(path, paint); } else{ canvas.drawBitmap(bitmap, currentX, currentY, null); } } #Override public boolean onTouchEvent(MotionEvent motionEvent){ int xPos =(int) motionEvent.getX(), yPos =(int) motionEvent.getY(); final int action = motionEvent.getAction(); if (mDrawingEnabled){ switch (action) { case MotionEvent.ACTION_DOWN: path.moveTo(xPos, yPos); return true; case MotionEvent.ACTION_MOVE: path.lineTo(xPos, yPos); break; case MotionEvent.ACTION_UP: paths.add(path); break; default: return false; } } else { final float me_x = motionEvent.getX(); final float me_y = motionEvent.getY(); switch ( action ) { case MotionEvent.ACTION_DOWN: case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: currentX = me_x; currentY = me_y; break; } } invalidate(); return true; } public void undo(){ if (paths.size()>0){ undo.add(paths.remove(paths.size()-1)); } } public void redo(){ if (undo.size()>0){ paths.add(undo.remove(undo.size()-1)); } } final void enableDrawing() { mDrawingEnabled = true; } final void disableDrawing() { mDrawingEnabled = false; } public void changeBrushColor(int color){ paint.setColor(color); } public void changeBrushSize(int size){ paint.setStrokeWidth(size); } } here is the drawing and when I add image clears the drawing I want to keep the drawn path alongside the image.
SurfaceView canvas drawing path with transparency
I have problems with my drawing application. I need to catch the correct touch screen and draw them to the canvas. Changing the size of the brush is working properly. But when I change the transparency setting, the program does not work correctly. It imposes a new path on top of the previous one, and the transparency is lost. Screenshot. Where could I go wrong? I need your help. Thank you. This is my SurfaceView code: public class PainterView extends SurfaceView implements SurfaceHolder.Callback { private PainterThread painterThread; private BrushParameters brushParameters; private Bitmap bitmap; public PainterView(Context context, AttributeSet attrs) { super(context, attrs); SurfaceHolder holder = getHolder(); holder.addCallback(this); brushParameters = new BrushParameters(); } #Override public void surfaceCreated(SurfaceHolder surfaceHolder) { setWillNotDraw(false); getThread().setRunning(true); getThread().start(); } #Override public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int width, int height) { if (bitmap == null) { bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); getThread().setBitmap(bitmap, true); } else { getThread().setBitmap(bitmap, false); } } #Override public void surfaceDestroyed(SurfaceHolder surfaceHolder) { getThread().setRunning(false); boolean retry = true; while (retry) { try { getThread().join(); retry = false; } catch (InterruptedException e) { e.printStackTrace(); } } painterThread = null; } #Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: painterThread.startDraw(x, y); break; case MotionEvent.ACTION_MOVE: painterThread.continueDraw(x, y); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: painterThread.finishDraw(x, y); break; } return true; } #Override protected void onDraw(Canvas canvas) { canvas.drawBitmap(bitmap, 0, 0, null); } public BrushParameters getBrushParameters() { return brushParameters; } public void setBrushColor(int color) { brushParameters.setColor(color); getThread().setBrushParameters(brushParameters); } public void setBrushSize(int size) { brushParameters.setSize(size); getThread().setBrushParameters(brushParameters); } public void setBrushAlpha(int alpha) { brushParameters.setAlpha(alpha); getThread().setBrushParameters(brushParameters); } public PainterThread getThread() { if (painterThread == null) { painterThread = new PainterThread(getHolder(), this); } return painterThread; } } And my Thread class: public class PainterThread extends Thread { private SurfaceHolder surfaceHolder; private PainterView painterView; private boolean running = false; private Paint paint; private Path path; private Bitmap mBitmap; private Canvas mCanvas; private float lastX, lastY; private static float TOUCH_TOLERANCE = 4; public PainterThread(SurfaceHolder surfaceHolder, PainterView painterView) { this.surfaceHolder = surfaceHolder; this.painterView = painterView; path = new Path(); paint = new Paint(); paint.setAntiAlias(true); paint.setDither(true); paint.setColor(Color.BLACK); paint.setAlpha(255); paint.setStyle(Paint.Style.STROKE); paint.setStrokeWidth(5); paint.setStrokeJoin(Paint.Join.ROUND); paint.setStrokeCap(Paint.Cap.ROUND); } public void setRunning(boolean running) { this.running = running; } #Override public void run() { Canvas mCanvas; while (running) { mCanvas = null; try { mCanvas = surfaceHolder.lockCanvas(null); synchronized (surfaceHolder) { if (mCanvas != null) { mCanvas.drawBitmap(mBitmap, 0, 0, paint); painterView.postInvalidate(); } } } finally { if (mCanvas != null) { surfaceHolder.unlockCanvasAndPost(mCanvas); } } } } public void setBitmap(Bitmap bitmap, boolean clear) { mBitmap = bitmap; if (clear) { mBitmap.eraseColor(Color.WHITE); } mCanvas = new Canvas(mBitmap); } public void setBrushParameters(BrushParameters brushParameters) { paint.setColor(brushParameters.getColor()); paint.setAlpha(brushParameters.getAlpha()); paint.setStrokeWidth(brushParameters.getSize()); } public void startDraw(float x, float y) { path.reset(); path.moveTo(x, y); lastX = x; lastY = y; } public void continueDraw(float x, float y) { float dx = Math.abs(x - lastX); float dy = Math.abs(y - lastY); if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) { path.quadTo(lastX, lastY, (x + lastX) / 2, (y + lastY) / 2); mCanvas.drawPath(path, paint); lastX = x; lastY = y; } } public void finishDraw(float x, float y) { path.moveTo(x, y); mCanvas.drawPath(path, paint); } } Thanks for help. I lost fiew days for find a cause of the problem...
I recommend getting rid of SurfaceView. You've got some confused-looking code (e.g. setBitmap() sets mCanvas, but that's getting overwritten in a loop by run()), and I think you're just making life harder on yourself. SurfaceViews have two parts, the Surface and the View. The Surface is a separate layer that (by default) sits behind the View layer. The View part of the SurfaceView is normally just a transparent hole that lets you "see through" to the Surface layer behind. In your case, you've overridden onDraw() in the View object, so you're actually drawing in the View. Over in your other thread you're drawing that same Bitmap onto the Surface. Even if your Bitmap has transparent pixels, you'll be seeing two identical Bitmaps layered on top of each other. It looks like you're sharing a Bitmap and possibly a Canvas between two simultaneously-executing threads, which is a recipe for unhappiness. If you get rid of the SurfaceView, and just use a custom View, I think everything will make more sense. The other approach is to get rid of onDraw() and the call to postInvalidate() and do everything on the Surface, but to take advantage of hardware-accelerated rendering it's better to use the custom View.
canvas erase bitmap code android
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
Make new bitmap on the canvas from resource
I think that my problem is minor but I can't find solution. I am trying to make application which will help me to make WEB pages and I want to make application which will put graphic element on the screen. I made drawable png images of rectangles and I can put them on the screen where I want, no problem, but I can not make new graphic/bitmap. How I can put new graphics object on the screen when I press in meni DIV or iFrame? public class Objects extends View { private float X; private float Y; private Paint myPaint; final String C_DIV = "DIV"; final String C_TABLE = "Table"; final String C_IFRAME = "iFrame"; final String C_LIST = "List"; Canvas canvas; Bitmap divimg = BitmapFactory.decodeResource(getResources(), R.drawable.div); Bitmap iframeimg = BitmapFactory.decodeResource(getResources(), R.drawable.iframe); Bitmap img = null; String objectname = " "; public Objects(Context context) { super(context); myPaint = new Paint(); } public void HTMLObjects(String object) { Log.d(object, "see"); if (object.equals(C_DIV)) { myPaint.setColor(Color.GREEN); img = Bitmap.createBitmap(divimg); objectname = "DIV"; } if (object.equals(C_IFRAME)) { myPaint.setColor(Color.BLUE); img = Bitmap.createBitmap(iframeimg); objectname = "iFrame"; } } public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: X = (int) event.getX(); Y = (int) event.getY(); break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: X = (int) event.getX(); Y = (int) event.getY(); break; } return true; } public void onDraw(Canvas canvas) { if (img != null) { canvas.drawBitmap(img, X - 50, Y - 50, myPaint); canvas.drawText(objectname, X, Y - 50, myPaint); } invalidate(); } } This is a class which I am calling from the activity Workspace with ob.HTMLObjects((String) item.getTitle()); and I am sending information which menu is pressed. I do not know how to make new/different object/bitmap when I pressed DIV or iFrame.
Try these version. I replaces x,y,img,objectname with according lists: public class Objects extends View { private Paint myPaint; public final String C_DIV="DIV"; public final String C_TABLE="Table"; public final String C_IFRAME="iFrame"; public final String C_LIST="List"; private Canvas canvas; private Bitmap divimg= BitmapFactory.decodeResource(getResources(), R.drawable.div); private Bitmap iframeimg=BitmapFactory.decodeResource(getResources(), R.drawable.iframe); private List<Bitmap> images; private List<Float> xs; private List<Float> ys; private List<String> objectNames; public Objects(Context context) { super(context); myPaint = new Paint(); images = new ArrayList<Bitmap>(); xs = new ArrayList<Float>(); ys = new ArrayList<Float>(); objectNames = new ArrayList<String>(); } public void HTMLObjects(String object){ Log.d(object, "see"); if (object.equals(C_DIV)) { myPaint.setColor(Color.GREEN); images.add(Bitmap.createBitmap(divimg)); objectNames.add("DIV"); xs.add(0F); ys.add(0F); } if (object.equals(C_IFRAME)){ myPaint.setColor(Color.BLUE); images.add(Bitmap.createBitmap(iframeimg)); objectNames.add("iFrame"); xs.add(0F); ys.add(0F); } } public boolean onTouchEvent(MotionEvent event) { int action=event.getAction(); if (xs.isEmpty()) { return true; } int pos = xs.size() - 1; switch(action) { case MotionEvent.ACTION_DOWN: xs.set(pos, event.getX()); ys.set(pos, event.getY()); break; case MotionEvent.ACTION_MOVE: case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: xs.set(pos, event.getX()); ys.set(pos, event.getY()); break; } return true; } public void onDraw(Canvas canvas){ for (int i = 0; i < images.size(); i++) { float x = xs.get(i); float y = ys.get(i); canvas.drawBitmap(images.get(i), x-50, y-50, myPaint); canvas.drawText(objectNames.get(i), x, y-50, myPaint); } invalidate(); } }
How to redraw the Android Canvas
Can anyone help me on how to redraw the canvas. I tried many examples and source code from the internet, but it still didn't work on my PC like the invalidate func, canvas.save, canvas.restore, etc. I want to do some translation and scaling for the canvas, but when I follow the step on the internet it shows nothing. This is my source code. (I'm still new to Java/Android programming.) #Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); drawMaps.j=1; resources = this.getResources(); try { GetAttributes("path"); } catch (XmlPullParserException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } SeekBar seekBar = (SeekBar)findViewById(R.id.seekBar1); panel = new Panel(this); setContentView(R.layout.main); panel.onDraw(canvas2); ImageView image = (ImageView) findViewById(R.id.mapImage); image.setImageBitmap(bufMaps); } class Panel extends View{ Paint paint = new Paint(); public Panel(Context context) { super(context); setFocusable(true); } public Bitmap quicky_XY(Bitmap bitmap,int pos_x,int pos_y){ Bitmap bufMap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); Canvas canvas = new Canvas(bufMap); canvas.save(); final Paint paint = new Paint(); width = canvas.getWidth();//start height = canvas.getHeight();//end drawMaps.xpos = width / 30; drawMaps.ypos = height/ 20; paint.setStrokeWidth(0); for (int i = 0; i < 30; i++) { paint.setColor(Color.DKGRAY); canvas.drawLine(drawMaps.xpos +(drawMaps.xpos*i), 0, drawMaps.xpos +(drawMaps.xpos*i), height, paint); //canvas.drawLine(startX, startY, stopX, stopY, paint) } for (int i = 0; i < 20; i++) { paint.setColor(Color.DKGRAY); canvas.drawLine(0, drawMaps.ypos+(drawMaps.ypos*i), width, drawMaps.ypos+(drawMaps.ypos*i), paint); } canvas.translate(pos_x,pos_y); drawMaps.addPath(canvas); canvas.restore(); invalidate(); return bufMap; } #Override public void onDraw(Canvas canvas) { canvas.save(); bufMaps = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); bufMaps = quicky_XY(emptyBmap,positionX,positionY); } } #Override public boolean onTouchEvent(MotionEvent event) { positionX = (int)event.getRawX(); positionY = (int)event.getRawY(); switch(event.getAction()) { case MotionEvent.ACTION_DOWN: { prevX = positionX; prevY = positionY; } break; case MotionEvent.ACTION_MOVE: { final int distY = Math.abs(positionY - prevY); final int distX = Math.abs(positionX - prevX); if (distX > mTouchSlop || distY > mTouchSlop){ panel.getDrawingCache(); panel.invalidate(); } Log.e("LSDEBUG", "touch X, " + positionX); } break; } return true; }
You do not call onDraw() yourself. Instead, you call to invalidate() and it will make sure onDraw() is called as soon as the it can. Also, if you are trying to draw on the canvas from outside the onDraw() method, you need to get a reference to the canvas. Inside your onDraw() the canvas is not being changed. only saved (again, called on invalidate() or whenever the system needs to redraw this View): #Override public void onDraw(Canvas canvas) { canvas.save(); bufMaps = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888); bufMaps = quicky_XY(emptyBmap,positionX,positionY); } Accessing the canvas from outside the onDraw() is done using a Holder().lockCanvas() to get reference to the canvas. After drawing, you unlock it again, using unlockAndPost() and that's it. You will also need to implement the Callback.surfaceCreated interface to find out when the Surface is available to use. Take a look at the android reference for SurfaceHolder. This post explains it pretty well.