I'm developing an painting app at the moment for the first time. I can draw and such things.
But everytime the orientation changes, everything is lost. How can i fix this? I have been searching on the internet for solution but dont seem to find one. I know it has to to with the onSizeChanged event from the view class. I have overriden that event and changed a lot to make it work with the orientation change but i cant get it to work.
Here is the code from the onSizeChanged event:
private Canvas drawCanvas;
private Bitmap canvasBitmap;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//View given size
super.onSizeChanged(w, h, oldw, oldh);
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
drawCanvas = new Canvas(canvasBitmap);
}
I have already tryed android:configChanges. But it doesnt seem to work.
I have found an solution for this problem. Everytime the screen orientation changed the event was being called. So the bitmap was recreated everytime. I have fixed this by scaling the bitmap before recreation and then setting it as new bitmap. This way it is automatticly scaled and nothing is lost.
This is the full code now:
private Canvas drawCanvas;
private Bitmap canvasBitmap;
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
//View given size
super.onSizeChanged(w, h, oldw, oldh);
if(canvasBitmap == null){
canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
}else{
Bitmap temporary = Bitmap.createScaledBitmap(canvasBitmap, w, h, true);
canvasBitmap = temporary;
}
drawCanvas = new Canvas(canvasBitmap);
}
Related
I have created a class that extends View. I am drawing on it. It works as expected. Now I wanna select an image from Gallery and set it to draw above it.
I am setting the image to the bitmap of the canvas once it is selected.
Bitmap bitmap= BitmapFactory.decodeStream(inputStream);
mdb.mExtraBitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
mdb is the object of the that custom View.
Here is the onSizeChanged method of the View.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mExtraBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mExtraCanvas = new Canvas(mExtraBitmap);
mExtraCanvas.drawColor(WHITE);
}
And here is the code inside onDraw method
super.onDraw(canvas);
canvas.drawBitmap(mExtraBitmap, 0, 0, null);
In the onTouchEvent method drawing paths on the mExtraCanvas.
The problem are.
1. The image is set but cannot draw on it.
2. Scale the image to cover.
Thanks!
You just need to draw the selected image on mExtraCanvas
mdb.mExtraCanvas.drawBitmap(image, 0, 0, null)
And for the scaled part create a scaled bitmap like.
Bitmap.createScaledBitmap(image,
mdb.mExtraBitmap.getWidth(),
mdb.mExtraBitmap.getHeight(), false);
Not Tested. But should be work.
Actually What happen, After set mdb.mExtraBitmap , onSizeChanged called. And new bitmap created by Bitmap.createBitmap.
change onSizeChanged() method by below.
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mExtraBitmap = Bitmap.createScaledBitmap(mExtraBitmap,w, h,false);
mExtraCanvas = new Canvas(mExtraBitmap);
}
And no need to draw bitmap again since you are making canvas from Bitmap.
Use mExtraCanvas for every drawing instead of other canvas.
I created a function to draw a text on a path:
public void drawText(float x, float y, String text) {
Log.i("DRAWING", "drawText");Typeface.BOLD);
mPath.reset();
mPath.moveTo(x, y);
mPath.lineTo(x+200,y);
Paint textPaint = new Paint();
textPaint.setColor(Color.RED);
textPaint.setTextSize(20f);
textPaint.setAntiAlias(true);
textPaint.setStrokeWidth(5f);
textPaint.setStyle(Paint.Style.FILL);
mCanvas.drawTextOnPath(text, mPath, 0, 0, textPaint);
setLayerType(View.LAYER_TYPE_SOFTWARE, null);
paths.add(mPath);
invalidate();
}
I set a Bitmap like this:
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas();
mCanvas.setBitmap(mBitmap);
reset();
}
Question:
When I set a bitmap, it works fine and the text appears on the ImageView, but when I don't, just a white line appears and not the text.
Do I have to use a Bitmap to draw text on path with drawTextOnPath ? Because I want to use only paths (all works fine except text, like it needed a Bitmap).
So a Bitmap is mandatory to draw text with drawTextOnPath.
The text won't appear if there is no Bitmap.
For those who, like me, implemented a Undo/Redo functionnality, I guess you have to save both paths and bitmaps to allow user to go back and forward.
I got a picture of a sun, 860x860 pixels.
I want to rotate the sun with the anchor-point being center of the screen.
This is what I got so far:
class GraphicalMenu extends View{
int screenH;
int screenW;
int angle;
Bitmap sun, monster;
public GraphicalMenu(Context context){
super(context);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
sun = BitmapFactory.decodeResource(getResources(),R.drawable.sun,options);
monster = BitmapFactory.decodeResource(getResources(),R.drawable.monster,options);
}
#Override
public void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
screenH = h;
screenW = w;
sun = Bitmap.createScaledBitmap(sun, w, h, true);
monster = Bitmap.createScaledBitmap(monster, w, h, true);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
//Increase rotating angle.
if (angle++ >360)
angle =0;
Matrix matrix = new Matrix();
matrix.setRotate(angle , getWidth()/2, getHeight()/2);
canvas.drawBitmap(sun, matrix, new Paint());
//Call the next frame.
canvas.drawBitmap(monster,0 , 0, null);
invalidate();
}
}
I've tried to change this line:
sun = Bitmap.createScaledBitmap(sun, w, h, true);
to:
sun = Bitmap.createScaledBitmap(sun, h, h, true);
but then the sun leaves the center of the screen and rotates far out to the right.
How can I fit the sun to the screen?
And how can I make it keep its ratio?
edit
Screenshot from running it on my N5 and the picture of the sun.
If I understand correctly, you have several problems with your code:
If you're making multiple calls to onSizeChanged() then you'll want to keep the original bitmap (pre-scaled) otherwise when you upscale the bitmaps again, they will look pixelated because every time you downscale them, you're losing information.
When you provide a matrix through which to transform your bitmap for drawing onto the canvas, that matrix will apply to the bitmap itself, not the screen as a whole. So when you make the drawBitmap() call, what you are actually requesting is for the bitmap to be rotated around the local point (getWidth()/2, getHeight()/2), not the screen point.
You're not actually rotating around the screen centre, you're rotating around the View's centre. Unless the View takes up the entire screen, you won't get the intended effect.
I can't pinpoint exactly what your problem is, but uploading some images would likely clarify what you're trying to achieve and what your current situation is.
I need a little help with the application that I'm working. I'm trying to create an application for painting and there is one problem which I noticed a few days ago and now I decide to make some research to solve it. When I use PorterDuff.Mode.CLEAR to use my brush as eraser it's working as it should be while my background is white. But if I set my background in other color ( for example Black like : mCanvas.drawColor(Color.BLACK); ) and after I use the eraser, the places where I use the eraser are painted with white color.
Here is how I'm setting the variables for my eraser :
erase.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
stamp=false;
MODE = ERASER_MODE;
mPaint.setColorFilter(null);
mPaint.setShader(null);
mPaint.setMaskFilter(null);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
});
So any ideas why it's happening and how can I fix that problem?
Thanks in advance!
Actually I find where were my problem. In my Custom View that I was using for drawing and etc I was doing this
#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);
mCanvas.drawColor(parentColor); //parentColor = currentBackgroundColor
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
canvas.drawPath(mPath, mPaint);
}
and I had to change only on my
I want to set an image from gallery as a background to the canvas in fingerpaint (api demo sample). I can retrieve the image from gallery but not able to set that as a background. One guess is I can open the image as a input stream, convert that as a array and pass it for bitmap - but I am not sure whether it will work or not and i don't have any clue for how the code will be. Can somebody help me?
You can modify the onSizeChanged() function to,
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
BitmapFactory.Options decode_options = new BitmapFactory.Options();
decode_options.inMutable = true;
mBitmap = BitmapFactory.decodeFile(<file_path>,decode_options);
mCanvas = new Canvas(mBitmap);
mBitmapPaint.setXfermode(new PorterDuffXfermode (SRC_IN));
}