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.
Related
When i choose initially red and draw a line, and then later select blue and draw a line , now the older line is also getting changed to blue instead of red, However i want the red to remain as red, and blue as such can any one help?
I also tried to get this solution online bt not solve my problem.so please help me.
DrawingView.java
public class DrawingView extends View {
Paint mPaint;
Path mpath;
Canvas mCanvas;
Bitmap myBitmap;
//initial color
private int paintColor = 0xFF660000;
private ArrayList<PathWithPaint> _graphics1 = new ArrayList<PathWithPaint>();
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
// private Map<Path,Float> stoWid = new HashMap<Path,Float>();
private Map<Path, Integer> colorsMap = new HashMap<Path, Integer>();
public DrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
Drawingsetup();
}
private void Drawingsetup() {
// TODO Auto-generated method stub
mPaint = new Paint();
mpath = new Path();
mCanvas = new Canvas();
mPaint.setDither(true);
mPaint.setColor(0xFFFFFFFF);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.BEVEL);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(3);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
// TODO Auto-generated method stub
super.onSizeChanged(w, h, oldw, oldh);
myBitmap = Bitmap.createBitmap(820, 480, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(myBitmap);
mCanvas.drawBitmap(myBitmap, 20, 20, mPaint);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
//return super.onTouchEvent(event);
PathWithPaint pp = new PathWithPaint();
//mCanvas.drawPath(path, mPaint);
if (event.getAction() == MotionEvent.ACTION_DOWN) {
undonePaths.clear();
mpath.moveTo(event.getX(), event.getY());
mpath.lineTo(event.getX(), event.getY());
} else if (event.getAction() == MotionEvent.ACTION_MOVE) {
mpath.lineTo(event.getX(), event.getY());
pp.setPath(mpath);
pp.setmPaint(mPaint);
_graphics1.add(pp);
} else if (event.getAction()==MotionEvent.ACTION_UP) {
mpath.lineTo(event.getX(), event.getY());
// commit the path to our offscreen
mCanvas.drawPath(mpath, mPaint);
// kill this so we don't double draw
paths.add(mpath);
mpath = new Path();
colorsMap.put(mpath,paintColor); // store the color of mPath
}
invalidate();
return true;
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//canvas.drawBitmap(myBitmap, 0, 0, mPaint);
for(Path p: paths){
canvas.drawPath(p, mPaint);
mPaint.setColor(colorsMap.get(p));
}
canvas.drawPath(mpath, mPaint);
canvas.setColor(paintColor);
}
public void CurrentDraw(){
}
public void StartNew(){
//colorsMap.clear();
undonePaths.clear();
paths.clear();
myBitmap.eraseColor(Color.TRANSPARENT);
mpath.reset();
invalidate();
_graphics1.clear();
}
public void ColorChanged(String newColor){
//set color
// start by invalidating the View
//parse and set the color for drawing
paintColor = Color.parseColor(newColor);
mPaint.setColor(paintColor);
invalidate();
}
public void onClickUndo()
{
if (paths.size()>0) {
undonePaths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
}
}
public void onClickRedo (){
if (undonePaths.size()>0) {
paths.add(undonePaths.remove(undonePaths.size()-1));
invalidate();
}
else
{
}
}
}
DrawingActivity.java
public class DrwaingActivity extends Activity {
DrawingView drawView;
Bitmap myBitmap;
private ImageButton currentpaint ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_image);
//get drawing view
drawView = (DrawingView)findViewById(R.id.drawing);
// drawView.setOnClickListener(this);
//get the palette and first color button
LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
currentpaint = (ImageButton)paintLayout.getChildAt(0);
currentpaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_item, menu);
return true;
}
public void paintClicked(View view){
if(view!=currentpaint)
{
//update color
// retrieve the tag we set for each button in the layout, representing the chosen color
ImageButton imgView = (ImageButton)view;
String color = view.getTag().toString();
// call the new method on the custom drawing View object
drawView.ColorChanged(color);
// update the UI to reflect the new chosen paint and set the previous one back to normal
imgView.setImageDrawable(getResources().getDrawable(R.drawable.paint_pressed));
currentpaint.setImageDrawable(getResources().getDrawable(R.drawable.paint));
currentpaint=(ImageButton)view;
}
}
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.
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 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
I have a Bitmap object in my main class. I need to send this bitmap to my custom view class to set it as a background for further processing on canvas.
For example, there is a method called setPicture that receives bitmap as a parameter. So, how it is possible to draw this bitmap on the canvas?
Please see the code below:
public class TouchView extends View {
final int MIN_WIDTH = 75;
final int MIN_HEIGHT = 75;
final int DEFAULT_COLOR = Color.RED;
int _color;
final int STROKE_WIDTH = 2;
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float x, y;
private boolean touching = false;
public TouchView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
init();
}
public TouchView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
init();
}
public TouchView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
private void init() {
setMinimumWidth(MIN_WIDTH);
setMinimumHeight(MIN_HEIGHT);
_color = DEFAULT_COLOR;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// TODO Auto-generated method stub
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
if (touching) {
paint.setStrokeWidth(STROKE_WIDTH);
paint.setColor(_color);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(x, y, 75f, paint);
}
}
public void setPicture (Bitmap bitmap) {
///////
This method must receive my bitmap to draw it on canvas!!!!!!!!!!!!!!!
///////
}
public void setColor(int color) {
_color = color;
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
// TODO Auto-generated method stub
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
x = motionEvent.getX();
y = motionEvent.getY();
touching = true;
break;
default:
touching = false;
}
invalidate();
return true;
}
}
How should I send this bitmap to onDraw?
Inside your onDraw() method,
just do
canvas.drawBitmap(myBitmap, 0, 0, null);
myBitmap is your bitmap variable.
0,0 refers to the coordinates to draw at, aka the top left corner.
There are other Apis available, to draw to certain areas etc.
More info can be found here in the api docs.
Alternatively:
extend ImageView instead, and use setImageBitmap(Bitmap src); method to achieve this.
Convert bitmap to drawable and use setBackgroundDrawable method of View class.
public void setPicture (Bitmap bitmap) {
setBackgroundDrawable(new BitmapDrawable(bitmap));
}
decodedString = Base64.decode(datadtlimgsItem.getImageStr(), Base64.DEFAULT);
decodedByte = BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length);
decodedByte = Util.resize(decodedByte, 1500, 1500);
mDrawingView.addBitmap(decodedByte);
public void addBitmap(Bitmap bitmap){
canvasBitmap = bitmap;
invalidate();
}
// set bitmap on draw canvas in your custom view class
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (canvasBitmap == null){
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}
drawCanvas = new Canvas(canvasBitmap);
}