It's possible to scale a RectF object of by an arbitrary factor in each direction?
In practice i would resize of 2 factor a RectF (if RectF is 200X200 i would that he becomes 100x100)
Try something like this:
private void scale(RectF rect, float factor){
float diffHorizontal = (rect.right-rect.left) * (factor-1f);
float diffVertical = (rect.bottom-rect.top) * (factor-1f);
rect.top -= diffVertical/2f;
rect.bottom += diffVertical/2f;
rect.left -= diffHorizontal/2f;
rect.right += diffHorizontal/2f;
}
This is done without testing but I think it should work. This should keep the center in the same place and expand outward. All sides will be twice as big.
Here my solution in Kotlin.
private fun RectF.scale(factor: Float) {
val oldWidth = width()
val oldHeight = height()
val rectCenterX = left + oldWidth / 2F
val rectCenterY = top + oldHeight / 2F
val newWidth = oldWidth * factor
val newHeight = oldHeight * factor
left = rectCenterX - newWidth / 2F
right = rectCenterX + newWidth / 2F
top = rectCenterY - newHeight / 2F
bottom = rectCenterY + newHeight / 2F
}
The transformation should keep the center of the rect is the same coordinate (rectCenterX, rectCenterY) and set new width and height with the float scale factor.
Have a nice day!
Related
On scroll, I want to rotate and translate these list items in a way that they still are around in a circular manner. I have made a custom view and over ride these methods with this rotation and translation as used Here. But rotations are a bit weird and non circular.
This is what I want to achieve
#Override
protected void dispatchDraw(Canvas canvas) {
canvas.save();
int top = getTop();
float rotate = calculateAngle(top, recyclerViewHeight);
Matrix m = canvas.getMatrix();
m.preTranslate(-2 / getWidth(), -2 / getHeight());
m.postRotate(rotate);
m.postTranslate(2 / getWidth(), 2 / getHeight());
canvas.concat(m);
super.dispatchDraw(canvas);
canvas.restore();
}
private float calculateAngle(int top, float height) {
float result = 0f;
float fullAngleFactor= 60f;
if (top < height / 2f) {
result = (top - (height / 2f)) / (height / 2f) * fullAngleFactor;
} else if (top > height / 2f) {
result = (top - (height / 2f)) / (height / 2f) * fullAngleFactor;
}
return result;
}
I used this library to achieve same behavior. No need to create any custom view and override onDraw() or onDispatchDraw(). I used this layout manager configuration:
layoutManager = new CircleLayoutManager.Builder(this)
.setRadius(900)
.setAngleInterval(30)
.setDistanceToBottom(-350)
.setGravity(CircleLayoutManager.LEFT)
.build();
I successfully made the auto crop to some extent for small devices so far. I am facing two issues:
1) the auto crop in big devices lets say 6.5 inches is not working properly
2) i want to take picture inside the rectangle frame
Below is my code:
public static Bitmap crop(Bitmap originalBitmap)
{
double originalWidth = originalBitmap.getWidth();
double originalHeight =
originalBitmap.getHeight();
double scaleX = originalWidth / 1280;
int navBarHeightPxIn1280x720Ui
CommonUtils.px2dp(CommonUtils.get
NavigationBarHeightInPx()) * 5 ;
double scaleXMultiplier = ((double) 1280) /
((double) (1280 - navBarHeightPxIn1280x720Ui));
scaleX = scaleX * scaleXMultiplier;
double scaleY = originalHeight / 720;
int x = (int) (52 * scaleX + 0.5);
int y = (int) (80 * scaleY + 0.5);
int width = (int) (896 * scaleX + 0.5);
int height = (int) (588 * scaleY + 0.5);
return Bitmap.createBitmap(originalBitmap, x, y,
width, height);
}
Currently I am making a camera player with a textureview to render my camera. Because the preview can have any dimension I have created some custom code to alter the textureview when OnSurfaceTextureUpdated is called:
void updateTextureMatrix(int width, int height) {
Display display = WindowManager.DefaultDisplay;
var isPortrait = (display.Rotation == SurfaceOrientation.Rotation0 || display.Rotation == SurfaceOrientation.Rotation180);
int previewWidth = orgPreviewWidth;
int previewHeight = orgPreviewHeight;
if(isPortrait) {
previewWidth = orgPreviewHeight;
previewHeight = orgPreviewWidth;
}
// determine which part to crop
float widthRatio = (float)width / previewWidth;
float heightRatio = (float)height / previewHeight;
float scaleX;
float scaleY;
if(widthRatio > heightRatio) {
// height must be cropped
scaleX = 1;
scaleY = widthRatio * ((float)previewHeight / height);
} else {
// width must be cropped
scaleX = heightRatio * ((float)previewWidth / width);
scaleY = 1;
}
Android.Graphics.Matrix matrix = new Android.Graphics.Matrix();
matrix.SetScale(scaleX, scaleY);
_textureView.SetTransform(matrix);
float scaledWidth = width * scaleX;
float scaledHeight = height * scaleY;
float dx = (width - scaledWidth) * 0.5f;
float dy = (height - scaledHeight) * 0.5f;
_textureView.TranslationX = dx;
_textureView.TranslationY = dy;
}
The scaling & calculation of dx & dy work perfectly fine on older android devices but the devices I have at my disposal with API level 23 throw unexpected behaviour.
The galaxy S3 displays it correctly:
But on the S7:
The phone cuts off a lot of the image, despite positioning it correctly. This makes me believe the bottom part is not being rendered where on older devices it is. Can anyone confirm this and point me in the correct position to fix this issue?
After long testing I figured out the issue was due to the SetTransform method. I was setting my scale using the matrix but this somehow rendered my texture & ignored the TranslationX & TranslationY. Removing the matrix & replacing it by
float scaledWidth = width * scaleX;
float scaledHeight = height * scaleY;
float dx = (width - scaledWidth) * 0.5f;
float dy = (height - scaledHeight) * 0.5f;
_textureView.ScaleX = scaleX;
_textureView.ScaleY = scaleY;
_textureView.TranslationX = dx;
_textureView.TranslationY = dy;
Fixed my issue of rendering wrongly on certain android devices.
It's no secret. My math skills aren't that impressive.
I'm developing my own Wear Watchface. But I want to draw a Drawline to the center of the screen for every 10 minute place on the watch. (See the 500px analog example).
By using the Google example code I can achieve this but only an entire line from the side of the screen to the center. But I want it to be like 5% (or a fixed amount of pixels) in length of that like in the 500px watchface. This is Google's code for drawing the second dial:
float centerX = width / 2f;
float centerY = height / 2f;
float secRot = mTime.second / 30f * (float) Math.PI;
float secLength = centerX - 20;
float secX = (float) Math.sin(secRot) * secLength;
float secY = (float) -Math.cos(secRot) * secLength;
canvas.drawLine(centerX, centerY, centerX + secX, centerY + secY, mHandPaint);
By changing the mTime.second I can draw from a specific second.
Found the solution, here's a snippet:
int teller_minuut_stip = 0; //Current minute
float secRot_stip = teller_minuut_stip / 30f * (float) Math.PI;
float secRot_stip_klein = teller_minuut_stip / 30f * (float) Math.PI;
float secLength_stip = centerX - 10;
float secX = (float) Math.sin(secRot_stip) * secLength_stip;
float secY = (float) -Math.cos(secRot_stip) * secLength_stip;
float secLength_stip_klein = centerX - 140;
float secX_klein = (float) Math.sin(secRot_stip_klein) * secLength_stip_klein;
float secY_klein = (float) -Math.cos(secRot_stip_klein) * secLength_stip_klein;
float eindpunt_x = centerX + secX;
float eindpunt_y = centerY + secY;
float lijn_x = eindpunt_x - secX_klein;
float lijn_y = eindpunt_y - secY_klein;
canvas.drawLine(eindpunt_x, eindpunt_y, lijn_x, lijn_y, datePaint_cirkel_kleurtien);
I am using http://www.codeproject.com/Articles/146145/Android-3D-Carousel code to create a vertical carousel view.i can see the vertical carousel using below changes in the code but center item is not properly placed in the screen and if the list items size increased, diameter moves upwards.
private void setUpChild(CarouselImageView child, int index, float angleOffset) {
// Ignore any layout parameters for child, use wrap content
addViewInLayout(child, -1 /*index*/, generateDefaultLayoutParams());
child.setSelected(index == mSelectedPosition);
int h;
int w;
if (mInLayout)
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
else
{
h = (getMeasuredHeight() - getPaddingBottom()-getPaddingTop())/3;
w = getMeasuredWidth() - getPaddingLeft() - getPaddingRight()/3;
}
child.setCurrentAngle(angleOffset);
// modify the diameter.
Calculate3DPosition(child, w*(getAdapter().getCount()/4), angleOffset);
// Measure child
child.measure(w, h);
int childLeft;
// Position vertically based on gravity setting
int childTop = calculateTop(child, true);
childLeft = 0;
child.layout(childLeft, childTop, w, h);
}
change in calculate3position function as below
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
child.setX(x);
child.setZ(z);
child.setY(y);
I think that this calculation:
float x = (float) (-diameter/2 * Math.cos(angleOffset) * 0.00001);
float z = diameter/2 * (1.0f - (float)Math.cos(angleOffset));
float y = (float) (diameter/2 * Math.sin(angleOffset)) + diameter/2 - child.getWidth();
should be this:
float x = 0.0f
float z = diameter/2.0f * (1.0f - (float)Math.cos(angleOffset));
float y = (diameter/2.0f * Math.sin(angleOffset)) + diameter/2.0f - child.getHeight()/2.0f;
Your x position should always be zero, and your y position should be based on the sin, and should be offset by 1/2 of the height of the child instead of 1/2 of the width.
Hello try this code and replace with this code in your Calculate3DPosition method
angleOffset = angleOffset * (float) (Math.PI / 180.0f);
float y = (float) (((diameter * 60) / 100) * Math.sin(angleOffset)) + ((diameter * 50) / 100);
float z = diameter / 2 * (1.0f - (float) Math.cos(angleOffset));
float x = (float) (((diameter * 5) / 100) * Math.cos(angleOffset) * 0.3);
child.setItemX(x);
child.setItemZ((z * 30) / 100);
child.setItemY(-(y));
its solve my problem please try this one