Draw on Bitmap in dependency to screen size - android

I am working with two other people on a Android project (2.2) for my studies.
We want to show maps of some university buildings so you canf find rooms easier. We use a custom ImageView (TouchImageView).
I make the bitmap mutable with
plant = plant.copy(Bitmap.Config.ARGB_8888, true);
so I can lay the Canvas above it.
Then I draw a red Circle on it with
Paint paint = new Paint();
paint.setColor(Color.RED);
Canvas canvas = new Canvas(plant);
canvas.drawCircle(xFromSearch, yFromSearch, 15, paint);
xFromSearch and yFromSearch are global variables which are already initialised with given values.
It works fine with my Google G1 but with other display sizes (e.g. the AVD or Samsung Galaxy SII) the circle is painted at the wrong place...
May it work when I do something with
Display display = getWindowManager().getDefaultDisplay();
screenWidth = display.getWidth();
screenHeight = display.getHeight();
??
I hope I gave you all the information you need and someone can help...
Thank you very much!!!

try this
int scale = getApplicationContext().getResources().getDisplayMetrics().density;
canvas.drawCircle(xFromSearch*scale , yFromSearch*scale , 15*scale , paint);

Related

Android canvas positioning, and customization

So this is my scenario:
I have an svg image that contains all the music notes on the staff (sort of sprite sheet)
I have two svg image that contains the key (maybe i can merge them together anyway)
All of them are converted to android Vector Drawable.
What i want to do is to select the note from the first svg, select the cleff, and then show them next to each other (the two images should be aligned).
So what i managed to achieve is to select the portion of svg for the note (i need to refine the rect size). But what i'm still having problem is to show both of them on the same line.
public MusicScore(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.BLACK);
Resources res = context.getResources();
musicClef = (VectorDrawable) res.getDrawable(R.drawable.ic_bassclef, null);
musicNotes = (VectorDrawable) res.getDrawable(R.drawable.ic_musicnotes, null);
int width = getWidth();
int height = getHeight();
Log.i("MUSIC", "H: " + musicClef.getMinimumHeight() + " W: " + musicClef.getMinimumWidth());
}
#Override
protected void onDraw(Canvas canvas){
Log.i("MUSIC", "Called");
int left = getWidth()/2;
int top = getHeight()/2;
musicClef.setBounds(0,0,musicClef.getIntrinsicWidth(), musicClef.getIntrinsicHeight() );
Bitmap source = Bitmap.createBitmap(musicNotes.getIntrinsicWidth(), musicNotes.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Bitmap clefSource = Bitmap.createBitmap(musicClef.getIntrinsicWidth(), musicClef.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas newcanvas = new Canvas(source);
Canvas clefCanvas = new Canvas(clefSource);
int notesLeft = musicClef.getIntrinsicWidth();
int notesTop = musicClef.getIntrinsicHeight();
musicNotes.setBounds(0, 0, musicNotes.getIntrinsicWidth(), musicNotes.getIntrinsicHeight());
musicNotes.draw(newcanvas);
musicClef.draw(clefCanvas);
Rect rect = new Rect(1150,0,1700, musicNotes.getIntrinsicHeight());
Rect rect2 = new Rect(notesLeft ,0, notesLeft + 450, musicNotes.getIntrinsicHeight());
Rect clefRect = new Rect(0, 0, musicClef.getIntrinsicWidth(), musicClef.getIntrinsicHeight());
canvas.drawBitmap(clefSource, null, clefRect, null);
canvas.drawBitmap(source, rect, rect2, null);
}
So with that code i can show a portion of the notes drawable, after converting it to a Bitmap. And i can also draw both of them, and the horizontal position is aligned. The problem is that the vertical position is not aligned, what i'm getting is:
So i know that my code is not correct (i'm pretty new to canvas in android and trying to figure out what to do), and what i learned so far is:
that in order to select a portion of the image i need to convert it to the Bitmap (i haven't found any way to do it directly with the VectorDrawable)
While drawing a Bitmap on the canvas with DrawBitmap, the first Rect represents the portion area i want to show, and the second one is the size and position of the area displayed.
In order to have the bitmap displayed on the canvas, i need to create a canvas from the Bitmap and draw it in it, in order to have it displayed. Is that correct?
So i have several questions:
I would like to understand how to vertically align the images, so they have to start from the same y (top).
I'm not sure if the vector image is the best idea, maybe is better to convert it into display dependant pngs? Or anyway the canvas size is relative to the screen? Or maybe i need to make my code screen-independent (i suppose that getIntrinsicWidth/Height are returning the real size of the image, so maybe i need to scale it?)
Why I need to explicitly setBounds of both images to have them displayed?
UPDATE #1
So i understood why probably my images are not aligned on the same line. It looks like that when creating a vector asset, for some reason the sizes are "adapted", not sure if is the android systems doing that or android studio. But anyway what i found after loading two images with the same height in pixels, is that for one i have an height, and for the other i have a different height (nearly double), and that explain why the image is shifted on the bottom.
So what i tried is to make a single image with both the notes, and the clefs, and it sort of works in the emulator. But when testing on a real device i get the error:
W/OpenGLRenderer: Bitmap too large to be uploaded into a texture (11732x1168, max=8192x8192)
Bitmap too large to be uploaded into a texture (11732x1168, max=8192x8192)
i can understand what the error means, but anyway the image size in pixel is: 2933x292 pixels. Why the getIntrinsicWidth and getIntrinsicHeight are returning that dimensions? what is their metrics?
I'm wondering that maybe the vector drawable is not the best choice? Maybe is better to cnvert it into screen-dependant pngs? and use them?

Android Google map circle

I have a map with many markers for places. I want to draw an overlay around all map with a black transparent color, and a circle around those markers which is fully transparent to show them. Like the attached picture.
I know how to add an overlay view, but I don't know how to add the middle circle while keeping the overlay colored.
If I use Circle then only the circle is colored, and not rest of map.
I also tried to draw something like this but yea won't work ^^.
int d = 500; // diameter
Bitmap bm = Bitmap.createBitmap(d, d, Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint p = new Paint();
p.setColor(getResources().getColor(R.color.colorAccent));
c.drawCircle(d / 2, d / 2, d / 2, p);
// generate BitmapDescriptor from circle Bitmap
BitmapDescriptor bmD = BitmapDescriptorFactory.fromBitmap(bm);
// mapView is the GoogleMap
googleMap.addGroundOverlay(new GroundOverlayOptions().
image(bmD).
position(latLng, RADIUS_CIRCLE * 2, RADIUS_CIRCLE * 2).
transparency(0.4f));
I am confused and not sure how to work it out. Any help will be appreciated. Thanks.
Please check Antonio's answer in the comments. I have tested that and works for me.
user1892172 answer but i didn't test it, but seems correct also.
Thanks.

Suggestion for a change of a grid background of graph using an android plot library

I want to make look like grid background as a full screen, .
...by using android plot library. Can anyone suggest a good implementation of that.
I'm going to change bitmapshader by creating bitmap, to pass
RectF rect = plot.getGraph().getGridRect();
BitmapShader myShader = new BitmapShader(
Bitmap.createScaledBitmap(
BitmapFactory.decodeResource(
getResources(),
R.drawable.graph_background),
1,
(int) rect.height(),
false),
Shader.TileMode.REPEAT,
Shader.TileMode.REPEAT);
Matrix m = new Matrix();
m.setTranslate(rect.left, rect.top);
myShader.setLocalMatrix(m);
plot.getGraph().getGridBackgroundPaint().setShader(myShader);
this give error for (int) rect.height(), null pointer exception for this
Without a more precise description of what you're trying to do the best I can do is to provide a general answer to how you accomplish your goal. Here's how you would display a grid of 25x25 px boxes:
plot.setDomainStep(StepMode.INCREMENT_BY_PIXELS, 25);
plot.setRangeStep(StepMode.INCREMENT_BY_PIXELS, 25);
plot.getGraph().getDomainGridLinePaint().setColor(Color.BLUE);
plot.getGraph().getRangeGridLinePaint().setColor(Color.BLUE);
You said in your comments that you wanted to make the boxes as small as possible, so if you really want to do that, you could specify a size of 1 by 1 instead.

Is it necessary to create seperate .xml files rather than using DisplayMetrics?

I am preparing a chess game and I have to declare many ImageViews Buttons dynamically.
However, my friends said that it will not support other screen sizes, but I heard about DisplayMetrics code; we can get the screen width and height through code only.
Well I am using different drawables for different screen sizes. Can I release my application in google playstore like this?
You can do it however you feel better, but using xml files would result in less code to write, to maintain and to execute at runtime.
So, i'd go the standard way (xml files).
You can still use the programmatic way, but then you have to mess with getWidth, getHeight and multiply by the density scale factor, ... you have to do some math!!
This could be done without XML, but i would use a canvas for chess.
Maybe something like this:
private Paint createChessrBoard(int size)
{
Bitmap bitmap = Bitmap.createBitmap(size* 2, size* 2, Bitmap.Config.ARGB_8888);
Paint fill = new Paint(Paint.ANTI_ALIAS_FLAG);
fill.setStyle(Paint.Style.FILL);
fill.setColor(0x22000000);
Canvas canvas = new Canvas(bitmap);
Rect rect = new Rect(0, 0, size, size);
canvas.drawRect(rect, fill);
rect.offset(size, size);
canvas.drawRect(rect, fill);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setShader(new BitmapShader(bitmap, BitmapShader.TileMode.REPEAT, BitmapShader.TileMode.REPEAT));
return paint;
}
You can use this to get the devices DPI
int dpi = getResources().getDisplayMetrics().density;

is canvas in android proportional on different devices

I am trying to make an app using canvas and a surfaceview, and I am worrying that in the future I would have many problems with it because I am not sure if the canvas is proportional with every device. currently I can only use my emulator since my phone's usb cable doesn't work(I know.. I have to get a new one..).
anyways, i would like to know if the canvas would transfer my coordinates and make everything proportional, what I mean by that is that if i have something in point a, lets say (10, 10) on a device that the screen of it is 100 X 100 (this is just an example for easy calculation) it would be on point (1, 1) on a 10 X 10 device.
This is really bothering me...
Thanks!
No, this wouldn't be the case. If you have a coordinate (10,10), it would be the same on all devices. I'd suggest you scale your drawings.
To scale your drawings you simply define a bitmap (that will stay the same) you'd like to draw to (when screen sizes change, that bitmap will be stretched).
Define a constant bitmap:
Bitmap gameScreen = Bitmap.createBitmap(getGameScreenWidth(),
getGameScreenHeight(), Config.RGB_565);
Get the scale for both x and y
width = game.getWindowManager().getDefaultDisplay().getWidth();
height = game.getWindowManager().getDefaultDisplay().getHeight();
scaleXFromVirtualToReal = (float) width/this.gameScreenWidth;
scaleYFromVirtualToreal = (float) height/this.gameScreenHeight;
Define a canvas object based on the bitmap you defined earlier on (allowing you to draw to it eg. canvas.drawRect() [...]):
Canvas canvasGameScreen = new Canvas(gameScreen);
In your rendering Thread you'll have to have a Canvas called frameBuffer, which will render the virtual framebuffer:
frameBuffer.drawBitmap(this.gameScreen, null, new Rect(0, 0, width,
height), null);
No, the unit on the screen (whether you are using canvas or OpenGL) is a pixel. You can get the size of your canvas using Canvas.getWidth() and Canvas.getHeight() if you need relative coordinates, but your Canvas drawing methods are also in Pixels, so I guess you will need to convert coordinates in OpenGL only and not while using Canvas.

Categories

Resources