I am new to 2d graphics..
I create a text using drawText method.
I have to paint over the drawtext area..
how can i clip the area of the text and paint over the surface
package com.example.testingcanvas;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends Activity {
class MyCustomView extends View {
private float x = 0, y = 0;
Path path = new Path();
Paint paint = new Paint();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ii);
private Rect m_ImageRect;
private Rect m_TextRect;
Context m_Context;
// you need these constructor
// you can init paint object or anything on them
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
m_Context = context;
}
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
m_Context = context;
}
public MyCustomView(Context context) {
super(context);
m_Context = context;
}
// then override on draw method
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(3);
paint.setTextSize(100);
// here frist create two rectangle
// one for your image and two for text you want draw on it
m_ImageRect = canvas.getClipBounds();
m_TextRect = canvas.getClipBounds();
// it gives you an area that can draw on it,
// the width and height of your rect depend on your screen size
// device
canvas.save();
canvas.drawBitmap(bm, null, m_ImageRect, paint);
canvas.drawPath(path, paint);
canvas.restore();
canvas.save();
canvas.clipRect(m_TextRect);
canvas.drawText("A", 100, 300, paint);
// canvas.drawText("A", 20, 20,50,50, paint);
// canvas.restore();
}
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_UP: {
}
default:
}
invalidate();
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyCustomView(this));
}
public void onBackPressed() {
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
finish();
onDestroy();
}
}
i am trying to draw over the text area.but i cant get it.
Related
I figured out that the width of the RectF is 0.0 so thats why it is always false. So can I set the width of the RectF width the StrokeWidth?
I have a path. And I want to handle clicks on it.
So I found out I can check that with an onTouchEvent.
So in the OnDraw() Method I draw a path and add the bounds to a rectF where I can get the left, right, top, bottom in the onTouchEvent correctly I guess.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class PathTest extends View {
Paint paint;
Path path;
RectF rectF = new RectF();
public PathTest(Context context) {
super(context);
init();
}
public PathTest(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PathTest(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo((float)getWidth()/2,getHeight()-20);
path.lineTo((float)getWidth()/2,20);
path.close();
path.computeBounds(rectF,true);
canvas.drawPath(path,paint);
}
private void init(){
paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(100);
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
path = new Path();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width,height/2);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if(event.getAction() == MotionEvent.ACTION_DOWN){
if(rectF.contains(event.getX(),event.getY())){
Log.d("HALLO","HI");
}else{
Log.d("HALLO","left"+rectF.left+" top"+rectF.top+" right"+rectF.right+" bottom"+rectF.bottom + " x->"+event.getX()+" y->"+event.getY());
}
}
return super.onTouchEvent(event);
}
}
It is always the else. I don't know why.
So I log the rectF Coordinates and the MotionEvent.ACTION_DOWN event.
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->528.0 y->490.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1047.0 y->1021.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1016.0 y->961.0
D/HALLO: left540.0 top20.0 right540.0 bottom2240.0 x->1059.0 y->1062.0```
I'm trying to make a custom imageview which cuts the image like below.
I checked many solutions but the nearest answer I saw is this link. But its slanting to opposite side and that too from corner. How can I cut the image with other side slanting and starting a little below.
// Custom View
public class SlantView extends View {
private Context mContext;
Paint paint ;
Path path;
public SlantView(Context ctx, AttributeSet attrs) {
super(ctx, attrs);
mContext = ctx;
setWillNotDraw(false);
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
#Override
protected void onDraw(Canvas canvas) {
int w = getWidth(), h = getHeight();
paint.setStrokeWidth(2);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setAntiAlias(true);
path = new Path();
path.setFillType(Path.FillType.EVEN_ODD);
path.moveTo(0,0);
path.lineTo(0,h);
path.lineTo(w,h);
path.close();
canvas.drawPath(path, paint);
}
}
Here i extended the RelativeLayout. (create a java file named cutLayout)
package com.blin.sharedelementtransition;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
import android.os.Build;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.widget.FrameLayout;
import android.widget.RelativeLayout;
/**
* Created by wituser on 12/12/16.
*/
public class cutLayout extends RelativeLayout {
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private Xfermode pdMode = new PorterDuffXfermode(PorterDuff.Mode.CLEAR);
private Path path = new Path();
public cutLayout(Context context) {
super(context);
}
public cutLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public cutLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public cutLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
super.dispatchDraw(canvas);
paint.setXfermode(pdMode);
path.reset();
// path.moveTo(0, getHeight() - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()));
path.moveTo(0, getHeight());
path.lineTo(getWidth(), getHeight());
path.lineTo(getWidth(), getHeight() - TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, getResources().getDisplayMetrics()));
// change value (50) to change the the slope.50 means 50dp.
// path.lineTo(getWidth()/2, getHeight());
// path.moveTo(0,0); // (0,0)
// path.lineTo(getPx(50),0); // (50,0)
// path.lineTo(0,getPx(50)); // (0,50)
//
// path.lineTo(0,getHeight()-getPx(50)); // (0,H-50)
// path.lineTo(getPx(50),getHeight()); // (50,H)
// path.lineTo(0,getHeight()); // (0,H)
//
// path.lineTo(0,0); // (0,0)
// path.lineTo(getWidth()-getPx(50),0); // (W-50,0)
// path.lineTo(getWidth(),getPx(50)); // (W,50)
// path.lineTo(getWidth(),0); // (W,0)
//
// path.lineTo(getWidth(),getHeight()-getPx(50)); // (W,H-50)
// path.lineTo(getWidth()-getPx(50),getHeight()); // (W-50,H)
// path.lineTo(getWidth(),getHeight()); // (W,H)
// path.lineTo(getWidth(),0); // (W,0)
path.close();
canvas.drawPath(path, paint);
canvas.restoreToCount(saveCount);
paint.setXfermode(null);
}
private float getPx(int i) {
return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, i, getResources().getDisplayMetrics());
}
}
and in xml, <your.package.name.cutLayout . cutLayout is the name of the javafile.
<com.blin.sharedelementtransition.cutLayout
android:layout_width="match_parent"
android:layout_height="300dp"
android:layout_margin="8dp">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg2"
android:layout_marginBottom="0.5dp"/>
</com.blin.sharedelementtransition.cutLayout>
There are multiple scribble apps on here that have an undo button. I haven't implemented those because my code is different, but I have looked at the concepts. I.E storing points in an array.
When the program detects touch events:
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX(); //Gets the fingers x position
float touchY = event.getY(); //gets the fingers y position
PointF points = new PointF(); //init a new PointF
points.x = touchX; //store the coordinates in the Point object
points.y = touchY;
_pointList.add(points); //add this to the list of Points (array)
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
_path.moveTo(touchX, touchY); //Set the beginning of the next contour to the point (x,y)
//will start drawing from where the last point was
break;
case MotionEvent.ACTION_MOVE:
_path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
In theory the _pointList Array should capture all the touch inputs in order. And this is evident, since the console displays the size of the array.
In the onDraw method, it should loop through all of the points in the a_pointList List. Since it contains all of the points that the user has interacted on the screen, then in theory it should draw the lines from memory.
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
}
canvas.drawBitmap(_bitmap, 0, 0, _paint);
}
When the application runs I am able to draw on the screen, and due to the clear method the screen clears.
public void clear(){
_pointList.clear();// empty the list that stores the points
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
//empties the screen
invalidate();
}
However, in my undo method, it should drop one of the points (that contains the users X and Y touch inputs) from the _pointList List. After dropping the point, the screen should redraw all of the lines from memory.
public void undo() {
Log.d("Number", "undo:" + _pointList.size() );
if (_pointList.size()>0){
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
_pointList.remove(_pointList.size() - 1);
invalidate();
}
}
This method has the same effect as the 'clear' method and does not redraw the lines,
My other alternatives to the undo button was putting the bitmaps into an array, but I'm sure that would cause memory issues since it's a dynamic program.
Question: Why doesn't the 'invalidate' call from the 'undo' method update the screen?
Update:
The whole code:
--Draw--
package com.example.moynul.myapplication;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* Created by moynu on 10/12/2015.
*/
public class Draw extends View {
private Paint _paint = new Paint();
private Path _path = new Path();
private Bitmap _bitmap;
private Canvas _canvas;
private List<PointF> _pointList = new ArrayList<PointF>();
public Draw(Context context) {
super(context);
init(null, 0);
}
public Draw(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs,0);
}
public Draw(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(attrs, defStyleAttr);
}
private void init(AttributeSet attrs, int defStyleAttr) {
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
_bitmap = Bitmap.createBitmap (1080, 1920, Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX(); //Gets the fingers x position
float touchY = event.getY(); //gets the fingers y position
PointF points = new PointF(); //init a new PointF
points.x = touchX; //store the coordinates in the Point object
points.y = touchY;
_pointList.add(points); //add this to the list of Points (array)
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
_path.moveTo(touchX, touchY); //Set the beginning of the next contour to the point (x,y)
//will start drawing from where the last point was
break;
case MotionEvent.ACTION_MOVE:
_path.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
break;
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
}
canvas.drawBitmap(_bitmap, 0, 0, _paint);
}
public void clear(){
_pointList.clear();// empty the list that stores the points
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
//empties the screen
invalidate();
}
public void undo() {
Log.d("Number", "undo:" + _pointList.size());
if (_pointList.size()>0){
_pointList.remove(_pointList.size() - 1);
_bitmap = Bitmap.createBitmap(1000,1000,
Bitmap.Config.ARGB_8888);
_canvas = new Canvas(_bitmap);
_path = new Path();
_paint = new Paint(Paint.DITHER_FLAG);
//Added later..
_paint.setColor(Color.RED);
_paint.setAntiAlias(true);
_paint.setStyle(Paint.Style.STROKE);
invalidate();
}
}
}
Change following inside onDraw() for loop
canvas.drawPath(_path, _paint);
Hope it will work
You have an issue in your onDraw method, you are always drawing the _bitmap on the same positions (0,0) not on the path. Replace your onDraw code with my code below:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (PointF points : _pointList) {
_path.moveTo(points.x, points.y);
_path.lineTo(points.x, points.y);
_canvas.drawPath(_path, _paint);
canvas.drawBitmap(_bitmap, points.x, points.y, _paint);
}
}
I'm having problem with undo and redo operations on a canvas.
I noticed the below code works if I don't use canvas.drawbitmap in the Ondraw() method but I need to draw to bitmap so I can save canvas image and as well load image. Kindly help me.
Below is my code.
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Cap;
import android.graphics.Paint.Join;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PorterDuff.Mode;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import com.akinslove.drawingapp.activities.DrawingCanvasActivity;
public class DrawView extends View {
// for bitmap
private Bitmap mainBitmap;
private Canvas mainCanvas;
private Paint mainbitmapPaint;
// for canvas
private Path currentPath;
private Paint currentpathPaint;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialiseMyComponents();
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
initialiseMyComponents();
}
public DrawView(Context context) {
super(context);
initialiseMyComponents();
}
private void initialiseMyComponents() {
currentPath = new Path();
currentpathPaint = new Paint();
currentpathPaint.setColor(Color.BLACK);
currentpathPaint.setStrokeWidth(10);
currentpathPaint.setStyle(Style.STROKE);
currentpathPaint.setStrokeJoin(Join.ROUND);
currentpathPaint.setStrokeCap(Cap.ROUND);
currentpathPaint.setAntiAlias(true);
mainbitmapPaint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
for (Path p : paths){
canvas.drawPath(p, currentpathPaint);
}
canvas.drawPath(currentPath, currentpathPaint);
**//I wish to use the below line of code
canvas.drawBitmap(mainBitmap, 0, 0, mainbitmapPaint);**
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
if (mainBitmap == null) {
mainBitmap = Bitmap.createBitmap(w, h, Config.ARGB_8888);
mainCanvas = new Canvas(mainBitmap);
mainCanvas.drawColor(Color.WHITE);
}
}
float lastX;
float lastY;
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
float x = event.getX();
float y = event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
undonePaths.clear();
DrawingCanvasActivity.IMAGEDRAWN = true;
currentPath.moveTo(x, y);
lastX = x;
lastY = y;
invalidate();
break;
case MotionEvent.ACTION_MOVE:
currentPath.quadTo(lastX, lastY, (lastX + x) / 2, (lastY + y) / 2);
mainCanvas.drawPath(currentPath, currentpathPaint);
lastX = x;
lastY = y;
invalidate();
break;
case MotionEvent.ACTION_UP:
currentPath.lineTo(x, y);
mainCanvas.drawPath(currentPath, currentpathPaint);
// kill this so we don't double draw
paths.add(currentPath);
currentPath = new Path();
currentPath.rewind();
invalidate();
break;
}
return true;
}
// method to get bitmap
public Bitmap getMainBitmap() {
return mainBitmap;
}
// method to set bitmap
public void setMainBitmap(Bitmap mpt) {
mainBitmap = mpt;
mainCanvas = new Canvas(mainBitmap);
postInvalidate();
}
public void onClickUndo () {
if (paths.size()>0)
{
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
}
public void onClickRedo (){
if (undonePaths.size()>0)
{
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
}
}
I just found out that the line mainCanvas.drawPath(currentPath, currentpathPaint); at both case MotionEvent.ACTION_UP: and case MotionEvent.ACTION_MOVE: should not be there. It seems to redraw the path to bitmap and onto the canvas. Not sure if I speak the right android terms.
At first my programm looks like this:
But when i am moving the picture around the screen programm turns to:
Red graph is random-generated in onDraw method. So i want to draging picture around and have static background that not inavalidates while im moving picture.
here is my code:
Custom View:
package com.graph.base;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import java.util.Random;
public class CustomView extends View
{
Random random=new Random();
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context) {
super(context);
}
public void onDraw (Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
Path path=new Path();
path.moveTo(10, 10);
for (float i=0.5f; i<=140; i+=10)
{
path.quadTo(10+i*5, 10+random.nextInt(500), 10+(i+10)*5, 10+random.nextInt(500));
}
paint.setDither(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(2);
canvas.drawPath(path, paint);
}
}
MainActivity
package com.graph.base;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends Activity {
FrameLayout frame;
ImageView image;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
frame=(FrameLayout)findViewById(R.id.frameLayout1);
image=(ImageView)findViewById(R.id.imageView1);
image.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.e("TAG", "Touch happend");
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
break;
}
}
return true;
}
});
}
public void invalidateButton_Click (View v)
{
frame.invalidate();
}
}
You're drawing random lines onto your canvas. This code is called each time the screen is invalidated. If you want to keep the drawing from changing, then set a bitmap into a canvas and draw into the bitmap. In your onDraw() method you'll then draw the bitmap onto the canvas.
// Outside of onDraw()
Bitmap bmDest = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas mycanvas = new Canvas(bmDest);
// Do your drawing on the canvas outside of the onDraw() method
In onDraw(), you'll simply do this:
canvas.drawBitmap(bmDest, x, y, null);
Actually, you should not "disable invalidate" but really do call "invalidate"...
In
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
// here call frame.invalidate(Rect dirty), with dirty set to where the image was previously
break;
}
Note that if your custom View draws "Randomly", then you can get a Bitmap with the cached version and draw from that (blit copy)