I have a custom view and I want to get pixel by a given position on ACTION_UP event.
public class MyView extends View
{
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mPaint;
public MyView(Context context)
{
super(context);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
setDrawingCacheEnabled(true);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mPaint = new Paint();
mPaint.setColor(Color.RED);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStrokeWidth(20f);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
switch (event.getAction())
{
case MotionEvent.ACTION_UP:
{
float x = event.getX();
float y = event.getY();
int pixel = mBitmap.getPixel((int) x, (int) y);
Log.i("APP", "Pixel is: " + pixel);
return true;
}
}
return super.onTouchEvent(event);
}
}
I'm getting only 0 when I'm calling mBitmap.getPixel(x, y);
I've marked the ontouch events on the image with black circle
You create a bitmap, and a canvas for that bitmap. But you never draw to it. Since you never draw to it, it will be whatever the default value of a new bitmap is, which is most likely to be either random or 0.
Unless you didn't post the drawing code, in which case we'll need that too.
Related
I am making app which select color from menu activity and then draw drawing on canvas in another activity. If I go to menu activity for changing color and come back canvas is blank.I want it to retain previous drawing. how to save and reload canvas drawing?
public class DrawingView extends View {
private Paint paint = new Paint();
private Path path = new Path();
private Paint canvasPaint = new Paint(Paint.DITHER_FLAG);
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
this.setDrawingCacheEnabled(true);
buildDrawingCache();
canvasBitmap = Bitmap.createBitmap(1440,2560, Bitmap.Config.ARGB_8888);
//canvasBitmap=BitmapFactory.decodeResource(getResources(),R.drawable.images);
drawCanvas = new Canvas(canvasBitmap);
}
public Bitmap getBitmap()
{
//this.measure(100, 100);
//this.layout(0, 0, 100, 100);
this.setDrawingCacheEnabled(true);
this.buildDrawingCache();
Bitmap bmp = Bitmap.createBitmap(this.getDrawingCache());
this.setDrawingCacheEnabled(false);
return bmp;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//canvasBitmap= Bitmap.createBitmap(1440, 2560, Bitmap.Config.ARGB_8888);
//c = new Canvas(b);
//canvas.drawBitmap(canvasBitmap, 1440, 2560, canvasPaint);
canvas.drawBitmap(canvasBitmap, 0, 0, null);
canvas.drawPath(path, paint);
}
//function for drawing on touch
#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;
}
//function to change color of paint
public void setColor(String newcolor) {
// TODO Auto-generated method stub
invalidate();
int paintColor = Color.parseColor(newcolor);
paint.setColor(paintColor);
}
public void clearScreen() {
// TODO Auto-generated method stub
// canvasBitmap.eraseColor(android.graphics.Color.WHITE);
//paint=new Paint();
path=new Path();
paint.setAntiAlias(true);
paint.setStrokeWidth(5f);
//paint.setColor(Color.BLACK);
// int paintColor = Color.parseColor(samecolor);
// paint.setColor(paintColor);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
invalidate();
}
public void setColorint(int i, int j, int k) {
// TODO Auto-generated method stub
invalidate();
int paintColor = Color.rgb(i,j,k);
paint.setColor(paintColor);
}
}
You can make a copy of the current bitmap before leaving the activity. Saving the drawing cache on ACTION_UP event will help you being up to date:
...
switch (event.getAction()) {
...
case MotionEvent.ACTION_UP:
canvasBitmap = getBitmap();
path=new Path(); // If you want a new path with each touch
break;
...
So when you are leaving your activity, you can call your getBitmap method in order to get the current state of the drawing and restore it when you are back to the activity.
As your Bitmap is so big, I guess you cannot keep it using Activity or View states, like explained here. Instead you can keep it in the Application object, explained here.
I am trying to make undo,redo options in custom drawing view app. But it is not working as i want.
I am not good in english. Through picture, let me try to show the working of undo , redo functions. Hope so, this picture will explain my problem.
i want to remove first line on first undo click and second line on second undo click and so on... similarly on redo click draw last line on first click, second last on second click and so on..
Here is my custom view class.
public class DrawingView extends View{
ArrayList<Path> undoPath = new ArrayList<Path>();
ArrayList<Path> paths = new ArrayList<Path>();
private static int pathSize =0;
//draw path
private Path drawPath;
//drawing and canvas point
private Paint drawPaint, canvasPaint;
//initial color
private int paintColor=0xFF660000;
//canvas
private Canvas drawCanvas;
//canvas bitmap
private Bitmap canvasBitmap;
private float brushSize, lastBrushSize;
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
setupDrawing();
}
public void setPattern(String newPattern){
invalidate();
int patternID = getResources().getIdentifier(newPattern, "drawable", "com.faisalahsan.paintingapp");
Bitmap patternBMP = BitmapFactory.decodeResource(getResources(), patternID);
BitmapShader patternBMPShader = new BitmapShader(patternBMP, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
drawPaint.setColor(0xFFFFFFFF);
drawPaint.setShader(patternBMPShader);
}
private void setupDrawing(){
//get drawing area setup for interaction
drawPath = new Path();
drawPaint= new Paint();
paths.add(drawPath);
brushSize = getResources().getInteger(R.integer.medium_size);
lastBrushSize = brushSize;
drawPaint.setColor(paintColor);
drawPaint.setAntiAlias(true);
drawPaint.setStrokeWidth(brushSize);
drawPaint.setStyle(Paint.Style.STROKE);
drawPaint.setStrokeJoin(Paint.Join.ROUND);
drawPaint.setStrokeCap(Paint.Cap.ROUND);
canvasPaint = new Paint(Paint.DITHER_FLAG);
}
#Override
protected void onDraw(Canvas canvas) {
for(Path p: paths){
canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
canvas.drawPath(p, drawPaint);
}
}
#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 onClickUndo () {
if (paths.size()>0) {
undoPath.add(paths.remove(paths.size()-1));
invalidate();
}
}
public void onClickRedo (){
if (undoPath.size()>0) {
paths.add(undoPath.remove(undoPath.size()-1));
invalidate();
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
drawPath.moveTo(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
drawPath.lineTo(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
drawCanvas.drawPath(drawPath, drawPaint);
drawPath.reset();
drawPath = new Path();
paths.add(drawPath);
break;
default:
return false;
}
invalidate();
return true;
}
}
You are not "redrawing" on the canvas when "undo" removes the action from the ArrayList "paths" - in other words, taking it out of the list does not change the image. You have to redraw what was on the canvas before it was drawn in order to "undo" the action.
Save the state of the canvas when "onDraw" starts and then redraw that canvas when undo is called. You need to keep a synchronized stack of canvas states in order to perform a series of "undo" and "redo" calls.
I want to scribble on image with finger(on image not on white background) and I am using this code to draw on image.
it draw on image but when when i release the touch the draw disappear.
i think the problem is in crating canvas.
And also
The image that i load in large so only a portion of image is displayed. So how can i stretch and fit the full image in screen for drawing on it.
public class MyView extends View {
private ImageView image;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
private Paint mPaint;
private float mX, mY;
private final float TOUCH_TOLERANCE = 4;
public MyView(Context c,View v) {
super(c);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(0XFF000000);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
image=(ImageView) v.findViewById(R.id.my_image);
}
#Override
public void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Scribbling on white background
// mBitmap=Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
// mCanvas =new Canvas(mBitmap);
// Scribbling on image
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.batman);
mBitmap= Bitmap.createBitmap( mBitmap.getWidth() ,mBitmap.getHeight(), mBitmap.getConfig());
mCanvas =new Canvas(mBitmap.copy(Bitmap.Config.ARGB_8888, true));
}
#Override
public void onDraw(Canvas c) {
// c.drawBitmap(DrawingActivity.mBitmap, 0, 0, null);
c.drawBitmap(mBitmap, 0, 0,mBitmapPaint);
c.drawPath(mPath, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent e) {
float x=e.getX();
float y=e.getY();
switch(e.getAction()){
case MotionEvent.ACTION_DOWN:
touchStart(x,y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touchMove(x,y);
this.invalidate();
break;
case MotionEvent.ACTION_UP:
touchUp(x,y);
invalidate();
}
return true;
}
private void touchUp(float x, float y) {
mPath.lineTo(mX, mY);
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
private void touchMove(float x, float y) {
float dx= Math.abs(x-mX);
float dy= Math.abs(y-mY);
if(dx>=TOUCH_TOLERANCE && dy>=TOUCH_TOLERANCE){
mPath.quadTo(mX, mY, (x+mX)/2, (y+mY)/2);
mX=x;
mY=y;
}
}
private void touchStart(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX=x;
mY=y;
}
}
please help
I need to implement a grayscale colorpicker that I need to put on the screen alongside the drawing canvas, so that when the user clicks on the grayscale colorpicker he selects a shade of gray.
Please see this example:
Solution found.
To those who might be interested:
public class ColorPickerView extends View {
private OnCustomEventListener mListener;
private Paint mPaint;
private Paint mPaint1;
private Paint mPaint2;
private Bitmap mBitmap;
private Canvas mCanvas;
private Path mPath;
private Paint mBitmapPaint;
public int color;
public ColorPickerView(Context context, AttributeSet attrs) {
super( context, attrs);
mPath = new Path();
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mPaint = new Paint();
mPaint.setAlpha(0x80);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0x44000000);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.BUTT);
mPaint.setStrokeWidth(5);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(0xFFAAAAAA);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
LinearGradient grad = new LinearGradient(0, 0, canvas.getWidth(), 0, Color.WHITE, Color.BLACK, TileMode.CLAMP);
/* Draw your gradient to the top of your bitmap. */
Paint p = new Paint();
p.setStyle(Style.FILL);
p.setShader(grad);
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), p);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setDither(true);
paint.setColor(0xFF00B8F5);
paint.setLinearText(true);
paint.setTextSize(60);
canvas.drawText("SELECT COLOUR", mBitmap.getWidth()/4-40, mBitmap.getHeight()/3*2+5, paint);
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 4;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
color= (int) (x/mBitmap.getWidth()*255);
if(mListener!=null) mListener.onEvent();
}
private void touch_move(MotionEvent event) {
float x = event.getX();
float y = event.getY();
Path npath=new Path();
npath.moveTo(mX, mY);
npath.lineTo( x ,y );
mX=x;
mY=y;
//mCanvas.drawPath(npath, mPaint);
npath.reset();
}
private void touch_up() {
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
touch_move( event);
invalidate();
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();
break;
}
return true;
}
public interface OnCustomEventListener{
public void onEvent();
}
public void setCustomEventListener(OnCustomEventListener eventListener) {
mListener=eventListener;
}
}
i cannot draw a bitmap in android more than once even when my program draws lines multiple times which is included in the same block.
this is my code:
Bitmap cache,backup;
cache = Bitmap.createBitmap(480,800,paint);
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
backup = Bitmap.createBitmap(cache);
return true;
case MotionEvent.ACTION_MOVE:
canvas.drawLine(downX,downY,moveX,moveY,paint);
canvas.drawBitmap(backup,0,0,paint);
return true;
}
In your activity class
public class MyActivity extends Activity
{
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
MyView mv= new MyView(this);
setContentView(mv);
}
}
public class MyView extends View {
private Bitmap mBitmap;
private Canvas mCanvas;
private Paint mBitmapPaint;
private Paint mBitmapPaint;
Context mcontext;
public MyView(Context c) {
super(c);
mcontext=c;
mBitmapPaint = new Paint();
mBitmapPaint.setColor(Color.RED);//paint color set to red
}
// is called when your view is first assigned a size, and again if the size of your view changes for any reason.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
}
//called everytime view is refreshed.
#Override
protected void onDraw(Canvas canvas) {
//do your draw here. draw lines and bitmaps.
Display display = ( (Activity) mcontext).getWindowManager().getDefaultDisplay();
float w = display.getWidth();
float h = display.getHeight();
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
//draw lines as border for the screen
canvas.drawLine(0, 0, w, 0,mBitmapPaint);
canvas.drawLine(0, 0, 0, h,mBitmapPaint);
canvas.drawLine(w,h,w,0,mBitmapPaint);
canvas.drawLine(w, h, 0,h , mBitmapPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touch_start(x, y);
invalidate();//refresh
break;
case MotionEvent.ACTION_MOVE:
touch_move(x, y);
invalidate();//refresh
break;
case MotionEvent.ACTION_UP:
touch_up();
invalidate();//refresh view
break;
}
return true;
}
private void touch_start(float x, float y) {
//do want should be done on touch start
}
private void touch_move(float x, float y) {
//do want should be done on touch move
}
private void touch_up() {
//do want should be done on touch up
}
}
Modify the above according to your needs.More information is available in the androdi developer site. http://developer.android.com/training/custom-views/custom-drawing.html