Centering and Autosizing Text in Rect - java

I have a rectangle that I want to draw text inside. I want the text to be centered vertically and horizontally and I need the text size to changed to fit all characters inside the rectangle. Here is my code:
#Override
public void drawFixedText(String text, Rect rect, Paint paint) {
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
int cX = rect.left;
int cY = rect.top;
float textSize = paint.getTextSize();
paint.setTextSize(textSize);
float textWidth = paint.measureText(text);
while (textWidth > rect.width()) {
textSize--;
paint.setTextSize(textSize);
}
//if cX and cY are the origin coordinates of the your rectangle
//cX-(textWidth/2) = The x-coordinate of the origin of the text being drawn
//cY+(textSize/2) = The y-coordinate of the origin of the text being drawn
canvas.drawText(text, cX-(textWidth/2), cY+(textSize/2), paint);
}
I tried to combine the answers from Calculate text size according to width of text area and Android draw text into rectangle on center and crop it if needed
But it didn't work in that the text is placed to the left of the rectangle instead of inside of it. How can I fix this?

First, you need to measure the text width after each time setting its size. Otherwise, you'll end up with an infinite loop if the text starts out wider than the Rect.
while (textWidth > rect.width()) {
textSize--;
paint.setTextSize(textSize);
textWidth = paint.measureText(text);
}
Then, to center the text horizontally, you want to subtract half of the text width from the horizontal midpoint of the Rect, not from its left edge, which is what cX will be in your snippet. That is, replace cX - (textWidth / 2) with rect.centerX() - (textWidth / 2) in the drawText() call.
Furthermore, to center the text vertically, we'll need to do something similar with the y-coordinate. However, using the text size for that will not give the correct result. We need to measure the text's actual height and offset from baseline, which we can do using the Paint#getTextBounds() method.
Altogether, these changes would give something like:
public void drawFixedText(String text, Rect rect, Paint paint) {
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.FILL);
float textSize = paint.getTextSize();
float textWidth = paint.measureText(text);
while (textWidth > rect.width()) {
textSize--;
paint.setTextSize(textSize);
textWidth = paint.measureText(text);
}
Rect bounds = new Rect();
paint.getTextBounds(text, 0, text.length(), bounds);
canvas.drawText(text,
rect.centerX() - textWidth / 2,
rect.centerY() - (bounds.top + bounds.bottom) / 2,
paint);
}
Please note that this assumes a default Paint instance. That is, any properties that affect text alignment have their default values going into this method.

Related

Draw text directly under a specified bitmap

p.setColor(Color.parseColor("#D32F2F"));
RectF background = new RectF((float) itemView.getRight() + dX, (float) itemView.getTop(), (float) itemView.getRight(), (float) itemView.getBottom());
c.drawRect(background, p);
icon = getBitmapFromVectorDrawable(MainActivity.this, R.drawable.ic_clear);
RectF icon_dest = new RectF((float) itemView.getRight() - 2 * width, (float) itemView.getTop() + width, (float) itemView.getRight() - width, (float) itemView.getBot
c.drawBitmap(icon, null, icon_dest, p); //[1]
p.setTextSize(50);
p.setColor(Color.WHITE);
c.drawText("Cancel",*/Insert x and y here*/,p);
So far I have that.
I'm trying to drawText directly under the bitmap I drawed. ([1]). However I'm not sure how to get the coordinates of the bitmap and adjust it so that it's centered below it.
The above image is what I'm trying to achieve. Contents of the app has been censored.
In conclusion, how do I get the coordinates for the text that I'm trying to get?
I'm using onChildDraw method of the ItemTouchHelper for a RecyclerView.
You can use paint.getTextBounds() to get the bounds of the text that you are about to draw on the canvas. Once you get the bounds of the text, you can calculate the position to draw the text based on the icon's position.
Edit:
This aligns the text below the icon at the X position same as the icon:
float textX = icon_dest.left;
float textY = icon_dest.bottom + some_padding;
canvas.drawText("Cancel", textX, textY, textPaint);
This aligns the center of the icon and the center of the text in a same vertical line:
Rect textBounds = new Rect();
textPaint.getTextBounds("Cancel", 0, length, textBounds);
float iconCenterX = icon_dest.left + (icon_dest.width() / 2);
float textHalfWidth = (textBounds.right - textBounds.left) / 2;
float textX = iconCenterX - textHalfWidth;
float textY = icon_dest.bottom + somePadding
canvas.drawText("Cancel", textX, textY, textPaint);

My custom scaling method not working

I've got the following code to display an image/texture in Opengl. The method is supposed to display the image in its correct aspect ratio and zoom in/out.
The image does not seem to maintain its aspect ratio on the horizontal axis. Why?
(NB: The OpenGL viewing width is from -1 to 0 and height from 1 to -1).
private void renderImage(Rectangle dst, float magnification) {
float width, height;
float horizontalOffset, verticalOffset;
// Default: Fill screen horizontally
width = 1f;
height = dst.getHeight()/(float) dst.getWidth();
// magnification
width *= magnification;
height *= magnification;
// Offsets
horizontalOffset = width/2f;
verticalOffset = height/2f;
// Do the actual OpenGL rendering
glBegin (GL_QUADS);
// Right top
glTexCoord2f(0.0f, 0.0f);
glVertex2f(-0.5f + horizontalOffset, verticalOffset);
// Right bottom
glTexCoord2f(0.0f, 1.0f);
glVertex2f(-0.5f + horizontalOffset, -verticalOffset);
// Left bottom
glTexCoord2f(1.0f,1.0f);
glVertex2f(-0.5f - horizontalOffset, -verticalOffset);
// Left top
glTexCoord2f(1.0f, 0.0f);
glVertex2f(-0.5f - horizontalOffset, verticalOffset);
glEnd();
}
I don't have any experience with OpenGL but from looking at your code it seems that there is something fishy about your default fill.
// Default: Fill screen horizontally
width = 1f;
height = dst.getHeight()/(float) dst.getWidth();
This is setting your "width" variable to a constant value of 1 whilst the "height" variable relies on the height and width of the rectangle that you are passing in, which is then being used to calculate the offsets
// Offsets
horizontalOffset = width/2f;
verticalOffset = height/2f;
in my experience this can cause the problems you have stated, first try stepping through this function in the debugger to analyse the values that the width and height variables hold, or try changing
// Default: Fill screen horizontally
width = 1f;
height = dst.getHeight()/(float) dst.getWidth();
to
// Default: Fill screen horizontally
width = 1f;
height = 1f;
and rerun this to see if it has had an effect on your output

Drawing rectangles at an angle

What is a method in Java that draws a rectangle given the following:
The coordinates of the center of the square
The angle of the rectangle from vertical, in degrees
To draw a rectangle in the way you suggest you need to use the class AffineTransform. The class can be used to transform a shape in all manner of ways. To perform a rotation use:
int x = 200;
int y = 100;
int width = 50;
int height = 30;
double theta = Math.toRadians(45);
// create rect centred on the point we want to rotate it about
Rectangle2D rect = new Rectangle2D.Double(-width/2., -height/2., width, height);
AffineTransform transform = new AffineTransform();
transform.rotate(theta);
transform.translate(x, y);
// it's been while, you might have to perform the rotation and translate in the
// opposite order
Shape rotatedRect = transform.createTransformedShape(rect);
Graphics2D graphics = ...; // get it from whatever you're drawing to
graphics.draw(rotatedRect);
For the first point, you can just figure out the coordinates of the center of the square by using a distance formula, (int)Math.sqrt((x1 - x2)*(x1 - x2) + (y1 - y2)*(y1 - y2)); them divide by 2. you can do this for the width and height. I don't know enough about Java draw to give you better answers based on what was in your question but I hope that helps.
For the second, you would need to just create a polygon right?

Align the texts center with the given position

I need to draw a text using
canvas.drawText("1",x,y, paint);
But the problem is that the "text's center" doesn't match with the position I have given,Is there any way I can do the latter.I have done quite a lot of search on the topic,culdn't find any answer.Please help.
Thank You in advance
You'll want to set the alignment on your paint instance:
paint.setTextAlign(Paint.Align.CENTER);
prior to drawing.
See: http://developer.android.com/reference/android/graphics/Paint.html#setTextAlign(android.graphics.Paint.Align)
Edit:
Per your indication that you'd also like it centered vertically, I'd go with an approach similar to this:
paint.setColor(Color.WHITE);
paint.setTextAlign(Align.LEFT);
String text = "Hello";
Rect bounds = new Rect();
float x = 100, y = 100;
paint.getTextBounds(text, 0, text.length(), bounds); // Measure the text
canvas.drawLine(0, y, canvas.getWidth(), y, paint); // Included to show vertical alignment
canvas.drawLine(x, 0, x, canvas.getHeight(), paint); // Included to show horizsontal alignment
canvas.drawText(text, x - bounds.width() * 0.5f, y + bounds.height() * 0.5f, paint); // Draw the text
or, using the center align on the paint:
paint.setColor(Color.WHITE);
paint.setTextAlign(Align.CENTER);
String text = "Hello";
Rect bounds = new Rect();
float x = 100, y = 100;
paint.getTextBounds(text, 0, text.length(), bounds); // Measure the text
canvas.drawLine(0, y, canvas.getWidth(), y, paint); // Included to show vertical alignment
canvas.drawLine(x, 0, x, canvas.getHeight(), paint); // Included to show horizsontal alignment
canvas.drawText(text, x, y + bounds.height() * 0.5f, paint); // Draw the text

Filling the viewport area of a orthographic camera with an image (libgdx)

So im trying to get the whole area of the viewport and then use the coordinates to draw images in the camera's viewport. So if the camera moves I can fill it with one image the length and the width of the viewport:
I just want the take the gray area in the picture (which is the camera's viewport) and fill it with this image.
So no matter what the camera's x and y coordinates are it will continue drawing the bottom image giving the effect of an infinite space and also the effect of moving.
EDIT:
Code I've tried so far
TextureRegion bg = ...;
int imageWidth = bg.getRegionWidth();
int imageHeight = bg.getRegionHeight();
batch.begin();
for (int x = 0;x<(camera.viewportWidth / imageWidth) + 2;x++) {
for (int y = 0;y<(camera.viewportHeight / imageHeight) + 2;y++) {
batch.draw(bg, ((camera.position.x - camera.viewportWidth / 2) + ((x - 1) * imageWidth)), ((camera.position.y - camera.viewportHeight / 2) + ((y - 1) * imageHeight)));
}
}
batch.end();
EDIT 2:
Thinking about getting the viewport area of the camera and adding tiles to a list that are viewable in the viewport area. Then as the camera moves remove the ones out of the list that are out of view and when a new area comes into view add new tiles. Then render all the tiles in the list.

Categories

Resources