Android canvas draw multiple rectangles of equal distance - android

I have 4 Strings. I'd like to draw a rectangle around each, and have them be equal distance to each other. I have code that "works" but I need 3 spaces for my last rectangle to make the distance equal, and I don't understand why. I am using an LG G Watch R, in case it is relevant.
private void drawDate(Canvas canvas, float centerX, float centerY)
{
float x = centerX + 75f;
float y = centerY + 50f;
String dayOfWeek = daysOfWeek[mTime.weekDay] + ",";
String month = months[mTime.month];
String monthDay = mTime.monthDay + ",";
String year = Integer.toString(mTime.year);
float height = outLinePaint.getTextSize();
float totalWidth = outLinePaint.measureText(String.format("%s %s %s %s", dayOfWeek, month, monthDay, year));
final float spaceWidth = outLinePaint.measureText(" ");
x -= totalWidth/2f;
outLinePaint.setStyle(Paint.Style.FILL);
float halfWidth = outLinePaint.measureText(dayOfWeek)/2f;
canvas.drawRect(x - halfWidth, y - height, x + halfWidth, y + height /2f , whitePaint);
canvas.drawText(dayOfWeek, x, y, outLinePaint);
x += (halfWidth*2f)+spaceWidth;
halfWidth = outLinePaint.measureText(month)/2f;
canvas.drawRect(x - halfWidth, y - height, x + halfWidth, y + height /2f , whitePaint);
canvas.drawText(month, x, y, outLinePaint);
x += (halfWidth*2f)+spaceWidth;
halfWidth = outLinePaint.measureText(monthDay)/2f;
canvas.drawRect(x - halfWidth, y - height, x + halfWidth, y + height /2f , whitePaint);
canvas.drawText(monthDay, x, y, outLinePaint);
//THIS LINE
x += (halfWidth*2f)+spaceWidth+spaceWidth+spaceWidth;
//it looks right on the canvas, but why can I not simply
//x += (halfWidth*2f)+spaceWidth; like above?
halfWidth = outLinePaint.measureText(year)/2f;
canvas.drawRect(x - halfWidth, y - height, x + halfWidth, y + height /2f , whitePaint);
canvas.drawText(year, x, y, outLinePaint);
outLinePaint.setStyle(Paint.Style.STROKE);
}
NOTE: THIS "BUG" ONLY EFFECTS THE LAST STRING
This is what I expect (AND what I get if I use x += (halfWidth*2f)+spaceWidth+spaceWidth+spaceWidth;):
However if I use x += (halfWidth*2f)+spaceWidth; like I do with my other 3, I get:

I have solved it. I could not get #pskink's example to work for the life of me (it didn't draw on my canvas). The problem was my center alignment.
x was in the middle of my Rect not the left. Whereas I was expecting x to be the leftmost point in my Rect when I added its width to x.
I have fixed it by setting the text align to left (so that x IS my leftmost point), and changing my drawDate() method to:
float spaceWidth;
private void drawDate(float centerX, float centerY)
{
float x = centerX + centerX*DATE_AND_COMPASS_X_OFFSET;
float y = centerY + centerY*DATE_AND_COMPASS_Y_OFFSET;
String dayOfWeek = daysOfWeek[mTime.weekDay] + ",";
String month = months[mTime.month];
String monthDay = mTime.monthDay + ",";
String year = Integer.toString(mTime.year);
float height = outLinePaint.getTextSize();
float totalWidth = outLinePaint.measureText(String.format("%s %s %s %s", dayOfWeek, monthnthDay, year));
spaceWidth = outLinePaint.measureText(" ");
outLinePaint.setStyle(Paint.Style.FILL);
x-=totalWidth/2;
x+=drawDateInline(dayOfWeek, x, y, height);
x+=drawDateInline(month, x, y, height);
x+=drawDateInline(monthDay, x, y, height);
drawDateInline(year, x, y, height);
outLinePaint.setStyle(Paint.Style.STROKE);
}
private float drawDateInline(String word, float x, float y, float height) {
float width = outLinePaint.measureText(word);
canvas.drawRect(x, y - height, x + width, y + height /2f, whitePaint);
canvas.drawText(word, x, y, outLinePaint);
return width+spaceWidth;
}
I'm also not sure how this is a "bad approach".

Related

android canvas draw text on circle radius based

I need to make lucky wheel like view, and there texts are drawn regarding the radius, as you can see image below. ( there you can see red line, I want to draw texts along that red line )
This is the result I want to achieve but, right now with my method, it just draws text based on circle like below
private void drawText(Canvas canvas, float tempAngle, float sweepAngle, String text) {
Path path = new Path();
Log.d("mytag", "tempAngle = " + tempAngle + ", sweepAngle = " + sweepAngle);
path.addArc(range, tempAngle, sweepAngle);
float textWidth = textPaint.measureText(text);
int hOffset = (int) (radius * Math.PI / mWheelItems.size() / 2 - textWidth / 2);
int vOffset = (radius / 2 / 3) - 15; // here 15 is distance from image
canvas.drawTextOnPath(text, path, hOffset, vOffset, textPaint);
}
Instead of creating an arc to draw the text on, you need a path from the outside of the circle to the center. I think you need something like this
int radius = 180;
float centerX = width/2f;
float centerY = height/2f
double radians = radius * Math.PI / 180;
float x = (float)Math.sin(radians);
float y = (float)-Math.cos(radians);
Path path = new Path();
path.moveTo(x,y);
path.lineTo(centerX, centerY);
canvas.drawTextOnPath(text, path, hOffset, vOffset, textPaint);
First, find the slice centre points.
Kotlin sample snippet
val arcCenter = startAngle + (arcProgress / 2)
//middle point radius is half of the radius of the circle
val pointRadius = size.width / 4
/*Calculate the x & y coordinates
* find points using angle and radius
*https://en.wikipedia.org/wiki/Polar_coordinate_system#Converting_between_polar_and_Cartesian_coordinates
* */
val x =
(pointRadius * cos(Math.toRadians(arcCenter.toDouble()))) +
size.center.x
val y =
(pointRadius * sin(Math.toRadians(arcCenter.toDouble()))) +
size.center.y
Then Rotate your canvas to the arch centre angle, Draw your text and restore the canvas to a normal position
it.nativeCanvas.rotate( arcCenter, x, y)
it.nativeCanvas.drawText(...)
it.nativeCanvas.rotate( -arcCenter, x, y)

How to capture detected face image using MLKit firebase FaceDetection

I want to only capture detected face image not whole image on camerasource.
I am drowing box like this
public void draw(Canvas canvas) {
Face face = mFace;
if (face == null) {
return;
}
// Draws a circle at the position of the detected face, with the face's track id below.
float x = translateX(face.getPosition().x + face.getWidth() / 2);
float y = translateY(face.getPosition().y + face.getHeight() / 2);
canvas.drawCircle(x, y, FACE_POSITION_RADIUS, mFacePositionPaint);
canvas.drawText("id: " + mFaceId, x + ID_X_OFFSET, y + ID_Y_OFFSET, mIdPaint);
canvas.drawText("happiness: " + String.format("%.2f", face.getIsSmilingProbability()), x - ID_X_OFFSET, y - ID_Y_OFFSET, mIdPaint);
canvas.drawText("right eye: " + String.format("%.2f", face.getIsRightEyeOpenProbability()), x + ID_X_OFFSET * 2, y + ID_Y_OFFSET * 2, mIdPaint);
canvas.drawText("left eye: " + String.format("%.2f", face.getIsLeftEyeOpenProbability()), x - ID_X_OFFSET*2, y - ID_Y_OFFSET*2, mIdPaint);
// Draws a bounding box around the face.
float xOffset = scaleX(face.getWidth() / 2.0f);
float yOffset = scaleY(face.getHeight() / 2.0f);
float left = x - xOffset;
float top = y - yOffset;
float right = x + xOffset;
float bottom = y + yOffset;
this.faceTrackingCords.y = top;
this.faceTrackingCords.width = right;
this.faceTrackingCords.x = left-right;
this.faceTrackingCords.height = bottom;
canvas.drawRect(left, top, right, bottom, mBoxPaint);
}
and trying to capture image like this but cropped image is not as expected.
mCameraSource.takePicture(null, new CameraSource.PictureCallback() {
#Override
public void onPictureTaken(byte[] bytes) {
Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
Bitmap bitmapCropped = Bitmap.createBitmap(bitmap,(int)faceTrackingCords.x, (int)faceTrackingCords.y,
(int)faceTrackingCords.width, (int)faceTrackingCords.height);
screenImage.setImageBitmap(bitmapCropped);
}
});
Kindly please help

How to create dripping Spray can tool for Graffiti app in Android

I am trying to create a spray can tool in Android for a Graffiti app. I want to achieve something similar done in the below image
Dripping Spray Can Sample image
Requirements: If somebody is spraying the can then it should drip some color downwards while drawing a spray line
I am currently using the following code, but not getting the correct results:
if (bufferPaint == null) {
bufferPaint = new Paint();
bufferPaint.setAntiAlias(true);
bufferPaint.setDither(true);
bufferPaint.setXfermode(null);
if (mPaint == null)
setupColor(0f, 100f);
}
int alpha = Math.round((float) 100 / 100 * 255);
bufferPaint.setAlpha(alpha);
private void paintOneDab(float x, float y) {
float radius = 5 / 2f;
float scatter = 500 / 100f;
x += radius 2 scatter (1 - 2 (float) Math.random());
y += radius 2 scatter (1 - 2 (float) Math.random());
float hardness = 20 / 100f;
positions[0] = 0;
positions[1] = (float) (Math.sqrt(hardness));
positions[2] = 1;
bufferPaint.setShader(new RadialGradient(x, y, radius, colors, positions, Shader.TileMode.CLAMP));
mCanvas.save();
int angle = 180;
mCanvas.rotate(angle, x, y);
int roundness = 100;
mCanvas.scale(1f, 100f / roundness, x, y);
mCanvas.drawCircle(x, y, radius, bufferPaint);
mCanvas.restore();
}

rotation of line in an android canvas

i've a math problem, i create a line with each extremety, a perpendicular line but i would like to choose the length of these perpendicular lines but i don't know how to do this :(
this is my code :
int vX = fleche.endPoint.x - fleche.startPoint.x;
int vY = fleche.endPoint.y - fleche.startPoint.y;
int vXP = - ( fleche.endPoint.y - fleche.startPoint.y );
Paint p = new Paint();
p.setColor(fleche.color);
p.setTextSize(30);
p.setTextAlign(Paint.Align.CENTER);
p.setStrokeWidth(8);
p.setAlpha(fleche.alpha);
Path path = new Path();
path.moveTo(fleche.startPoint.x - 10,fleche.startPoint.y - 10);
path.lineTo(fleche.endPoint.x - 10, fleche.endPoint.y - 10);
c.drawTextOnPath(fleche.value + fleche.unit, path, 30, 0, p);
c.drawPath(path, p);
path.moveTo(fleche.startPoint.x - 10,fleche.startPoint.y - 10);
path.lineTo(fleche.endPoint.x - 10, fleche.endPoint.y - 10);
c.drawTextOnPath(fleche.value + fleche.unit, path, 30, 0, p);
//ligne principale
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.endPoint.x, fleche.endPoint.y, p);
//left
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x + vXP, fleche.startPoint.y + vX, p);
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x - vXP, fleche.startPoint.y - vX, p);
//right
c.drawLine(fleche.endPoint.x, fleche.endPoint.y, fleche.endPoint.x + vXP, fleche.endPoint.y + vX, p);
c.drawLine(fleche.endPoint.x, fleche.endPoint.y, fleche.endPoint.x - vXP, fleche.endPoint.y - vX, p);
//Tools.logDebug("Fleche créée(" + i + "/" + (arrows.size()-1) + ") :" + fleche.toString());
Thanks in advance to all :D
This is how you can scale dx and dy to length L:
float ratio = L / Math.sqrt(dx * dx + dy * dy);
dx *= ratio;
dy *= ratio;
edit after comment:
//left
final float L = 20.0f; // for instance
final float ratio = L / Math.sqrt(vXP * vXP + vX * vX);
final float dx = vXP * ratio;
final float dy = vX * ratio;
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x + dx, fleche.startPoint.y + dy, p);
c.drawLine(fleche.startPoint.x, fleche.startPoint.y, fleche.startPoint.x - dx, fleche.startPoint.y - dy, p);

Alignment issues in view

This question is in continuation to my previous doubt
Now I am trying to make a guage view. I am drawing a scale but the alignment is not proper and I am not able to figure out the problem. Here is my code:
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
w= canvas.getWidth();
h=canvas.getHeight();
DrawRange(canvas,innerRadius,outerRadius);
}
here innerRadius =250;
and outer radius = 300;
private void DrawRange(Canvas canvas,int r,int R) {
RectF rect = new RectF(canvas.getWidth()/2- r, canvas.getHeight()/2-r, canvas.getWidth()/2+r, canvas.getHeight()/2+r);
RectF rect1 = new RectF(canvas.getWidth()/2- R, canvas.getHeight()/2-R, canvas.getWidth()/2+R, canvas.getHeight()/2+R);
Paint scalePaint = new Paint();
scalePaint.setStyle(Paint.Style.STROKE);
scalePaint.setColor(0x9f004d0f);
scalePaint.setStrokeWidth(2);
scalePaint.setAntiAlias(true);
scalePaint.setTextSize(35.0f);
scalePaint.setTypeface(Typeface.SANS_SERIF);
scalePaint.setTextScaleX(0.4f);
scalePaint.setTextAlign(Paint.Align.CENTER);
canvas.drawOval(rect1, scalePaint);
canvas.drawOval(rect, scalePaint);
canvas.save(Canvas.CLIP_SAVE_FLAG);
int xc = 0;
for (int i = 0; i < totalNicks; i++) {
float y1 = 330;
float y2 = y1 + 5;
if (i % 5 == 0) {
canvas.drawText(""+xc, r-15, y2 , scalePaint);
xc+=5;
}else{
canvas.drawLine(r, y1, r, y2, scalePaint);
}
canvas.rotate(degreesPerNick, w/2, h/2);
}
canvas.restore();
}
I wonder if you are drawing the text and the dashes in the wrong place. The key reference point is the centre of the circles:
int cX = canvas.getWidth()/2;
int cY = canvas.getHeight()/2;
The other key reference is the difference between the two radii:
int deltaR = R - r;
The dashes and text are always drawn at 12 o'clock, say 20% above the inner circle to 1/3 of the way from the outer circle:
int dashInnerY = cY - r - deltaR/5; // 20% of the way between inner and outer radii
int dashOuterY = cY - R + deltaR/3; // 1/3 of the way between outer and inner radii
Then to render a dash:
canvas.drawLine(cX, dashInnerY, cX, dashOuterY, scalePaint);
And the number:
canvas.drawText(""+xc, cX, dashInnerY, scalePaint);

Categories

Resources