I've very annoying problem. Hope you can help me.
This part of my application is simple. When user taps NEXT or PREVIOUS button, imageview switches to previous or next image available. It works great but only if user does not use multitouch to ZOOM image. Please check images below to see what my problem is. I'm using TouchImageView library to zoom images.
IMAGE 1: This is image in it's normal state.
IMAGE 1 - ZOOM: User decides to use multitouch because it wants to ZOOM the image.
IMAGE 2: User taps Next button, but on the screen appears next image but it is in its ZOOMED state (from previous image).
Instead it should be like this:
Does anyone have any idea how to "reset" image and even if current picture is zoomed, next picture should not be zoomed?
Assuming you're talking about this TouchImageView, you could add a method that wraps the logic inside
public boolean onScale(ScaleGestureDetector detector);
in a method called setScaleFactor(float scaleFactor, float focusX, floatY);
That way, onScale method would look like.-
#Override
public boolean onScale(ScaleGestureDetector detector) {
float mScaleFactor = detector.getScaleFactor();
setScaleFactor(mScaleFactor, detector.getFocusX(), detector.getFocusY());
return true;
}
And you could call
setScaleFactor(1.0f, 0.5f, 0.5f);
to 'reset' the scale.
EDIT
Assuming you're working with the TouchImageView implementation given on the link above, setScaleFactor would look like this.-
public void setScaleFactor(float mScaleFactor, float focusX, float focusY) {
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale) {
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
} else if (saveScale < minScale) {
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
if (origWidth * saveScale <= viewWidth || origHeight * saveScale <= viewHeight) {
matrix.postScale(mScaleFactor, mScaleFactor, viewWidth / 2, viewHeight / 2);
} else {
matrix.postScale(mScaleFactor, mScaleFactor, focusX, focusY);
}
fixTrans();
}
Related
On clicking 2nd sticker it should display the second sticker alone (the first one should be removed).
current output
when clicking in sticker 1(yellow),it display sticker 1 on screen and when sticker 2 (red) is clicked the previous sticker is still on the screen(which i do not want)
The output must be sticker 2 alone
I have tried implementing a for loop but it does not work.
Full Activity source code
public void addSticker(final Sticker sticker) {
if (sticker == null) {
Log.e(TAG, "Sticker to be added is null!");
return;
}
float offsetX = (getWidth() - sticker.getWidth());
float offsetY = (getHeight() - sticker.getHeight());
sticker.getMatrix().postTranslate(offsetX, offsetY);
float scaleFactor;
if (getWidth() < getHeight()) {
scaleFactor = (float) getWidth() / sticker.getDrawable().getIntrinsicWidth();
}
else {
scaleFactor = (float) getHeight() / sticker.getDrawable().getIntrinsicHeight();
}
sticker.getMatrix().postScale(scaleFactor, scaleFactor, getWidth(), getHeight());
mHandlingSticker = sticker;
mStickers.add(sticker);
invalidate();
}
The task is to crop video by given points(like rectangle) and display the cropped video.
The code works with cropping the first halh of video(0, 0, videoWidth/2, videoHeight). But when i tryed to display the second one(videoWidth/2, 0, videoWidth, videoHeight), that is what was displayed.
The video is displayed on TextureView inside FrameLayout.
The part, that doesn't work:
private void updateTextureViewSize(int ax, int ay, int bx, int by) {
float scaleX;
float scaleY;
//proportions between screen and frame dimensions
scaleX = mVideoWidth / mDisplayWidth;
scaleY = mVideoHeight / mDisplayHeight;
float scaleRegionW = mVideoWidth / Math.abs(ax - bx);
float scaleRegionH = mVideoHeight / Math.abs(ay - by);
float scaleRegion = scaleRegionW < scaleRegionH ? scaleRegionW : scaleRegionH;
Matrix matrix = new Matrix();
if (scaleX > scaleY) {
matrix.setScale(scaleRegion / scaleY, scaleRegion);
matrix.postTranslate(-ax * (int) scaleRegion / scaleY, -ay * scaleRegion / scaleY);
} else {
matrix.setScale(scaleRegion, scaleRegion / scaleX);
matrix.postTranslate(-ax * scaleRegion / scaleX, -ay * scaleRegion / scaleX);
}
mTextureView.setTransform(matrix);
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
}
The answer was found by Dmitry Yacenko.
The full code.
An easy way to crop video by given points (ax, ay, bx, xy) is:
float scaleX = mDisplayWidth / mVideoWidth, scaleY = mDisplayHeight / mVideoHeight;
//proportions between screen and frame dimensions
float scale = mDisplayHeight / Math.abs(by - ay);
Matrix matrix = new Matrix();
matrix.reset();
matrix.setScale(scale / scaleX, scale / scaleY);
//scaling video
matrix.postTranslate(-scale * ax, -scale * ay);
//move video, so the needed part of it will be displayed properly
mTextureView.setLayoutParams(new FrameLayout.LayoutParams((int) mDisplayWidth, (int) mDisplayHeight));
mTextureView.setTransform(matrix);
//updating the Texture view
I am trying to make a sprite walk to the mouse position. However, when the mouse is clicked and the sprite walks to the mouse position, it won't stop and keeps moving in the same direction.
Here's my code:
public void render(float delta) {
Gdx.gl.glClearColor(1,1,1,1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
if(Gdx.input.isTouched()){
projected= new Vector3(Gdx.input.getX(), Gdx.input.getY(), 0);
cam.unproject(projected);
if(position.x != projected.x || position.y != projected.y){
pathX = projected.x - position.x;
pathY = projected.y - position.y;
distance = (float) Math.sqrt(pathX * pathX + pathY * pathY);
directionX = pathX / distance;
directionY = pathY / distance;
}
}
position.x += directionX * Speed * delta;
position.y += directionY * Speed * delta;
}
Please help and thank you so much.
This is basically a duplicate of How to stop drawing a SpriteBatch animation in libgdx? || how do I pause the SpriteAnimation in libGDX with a button to be able to view the current frame when pause button is pressed? , check out this article to see if it helps.
In short, you want to keep track of the player moving and when they get to the x, y coordinates of your mouse, set the moving to false. Have the logic within your render to only render when your boolean is true.
I'm kinda desperate already =)...
I'am drawing points and lines onto a canvas in Android. The points I'm displaying should be displayed in a mathematical system. So I did canvas.getHeight() - point.y to display the points in the right way.
But if I would like to zoom into the drawn object the y coordinate gets scaled out of my view.
That's because x = 10 and y = 700. If I scale it with a scale factor of 10, the y make the object disappear.
I hope you get what I'm talking about...
How do I display my coordinates in the right (mathematical) way without moving the y coordinate far away??
Here is what I do:
canvas.drawPoint(startPoints[i][0], height-startPoints[i][1], pointColor);
canvas.drawPoint(endPoints[i][0], height-endPoints[i][1], pointColor);
Then my point (x=10, y=10) is going to be displayed as x=10 , y = 714.
Here's my full routine
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
final float[][] startPoints;
final float[][] endPoints;
int count = 0;
height = canvas.getHeight();
canvas.save();
canvas.scale(scaleFactor, scaleFactor);
canvas.translate(translateX / scaleFactor, translateY / scaleFactor);
Paint lineColor = new Paint();
lineColor.setColor(Color.BLACK);
Paint pointColor = new Paint();
pointColor.setColor(Color.RED);
pointColor.setStrokeWidth(5f);
startPoints = data.getStartPoints();
endPoints = data.getEndPoints();
count = data.getSize();
for (int i = 0; i < count; i++) {
canvas.drawLine(startPoints[i][0], height-startPoints[i][1],
endPoints[i][0], height-endPoints[i][1], lineColor);
canvas.drawPoint(startPoints[i][0], height-startPoints[i][1], pointColor);
canvas.drawPoint(endPoints[i][0], height-endPoints[i][1], pointColor);
}
canvas.restore();
}
private class ScaleListener extends
ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
scaleFactor *= detector.getScaleFactor();
scaleFactor = Math.max(MIN_ZOOM, Math.min(scaleFactor, MAX_ZOOM));
return true;
}
}
scaling factor x = screen width in pixels / target width in pixels
scaling factor y = screen height in pixels / target height in pixels
or
scaled x point = x on resized canvas * (resized width / original width)
scaled y point = y on resized canvas * (resized height / original height)
I scaled my canvas as following (in onDraw):
canvas.scale(mScaleFactor, mScaleFactor, mScaleFocusX, mScaleFocusY);
My onScale function is:
private float mScaleFactor = 1.f;
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
mScaleFocusX = detector.getFocusX();
mScaleFocusY = detector.getFocusY();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
Now I get more points (using onTouchEvent) to create new path which eventually I want to draw.
onTouchEvent gives me x and y but doesn't take into account that a scale occurred.
How can I know where is the new position of x and y after the scaling?
From your question it is not clear what you do with mScaleFactor, mScaleFocusX, mScaleFocusY when rendering you canvas.
But, basically you just need to reverse this process to calculate the original coordinates of the touch (or any other form of interaction).
So for example if you calculate the render coordinates like this:
float renderX = originalX * mScaleFactor + mScaleFocusX;
float renderY = originalY * mScaleFactor + mScaleFocusY;
so would need to use
float correctedTouchX = (touchX - mScaleFocusX) / mScaleFactor;
float correctedTouchY = (touchY - mScaleFocusY) / mScaleFactor;
to calculate the corrected (original) coordinates. If you use mScaleFactor, mScaleFocusX, mScaleFocusY in some other way, you need to reverse that.
UPDATE: It seems that Canvas.scale() first uses mScaleFocusX and mScaleFocusY to define a pivot point (i.e. offset) and then scale. So you probably need these formulas (maybe change a minus into a plus sign somewhere):
float correctedTouchX = touchX / mScaleFactor - mScaleFocusX;
float correctedTouchY = touchY / mScaleFactor - mScaleFocusY;