Add sticker only once using invalidate() - java

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();
}

Related

How can I save and load each bitmap after drawing, instead of re-drawing each stroke every time

I'm working on a drawing application in Android/Java, and at the moment I re-draw every stroke instead of just loading the Bitmap. I'm thinking it will be a good idea to store a bitmap after each stroke and just load that onto the Canvas, but I'm not sure how to go about doing that.
This is what I have so far:
protected void touchStart(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
protected void touchMove(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
mX = x;
mY = y;
}
}
protected void touchUp() {
mPath.lineTo(mX, mY);
mMyPathsDrawn.add(new Pair<>(mPath, mPaint));
// Kill this so we don't double draw
mPath = new Path();
mPaint = new Paint(mPaint);
}
protected void onDraw() {
if (mCanvas == null) {
return;
}
mCanvas.drawBitmap(mBgBitmap, null, mSurfaceHolder.getSurfaceFrame(), null);
for (Pair<Path, Paint> p : mPathsToDraw) {
mCanvas.drawPath(p.first, p.second);
}
mCanvas.drawPath(mPath, mPaint);
Canvas surfaceCanvas = mSurfaceHolder.lockCanvas();
surfaceCanvas.drawBitmap(mBitmap, 0, 0, null);
mSurfaceHolder.unlockCanvasAndPost(surfaceCanvas);
}
The workflow is: touchStart/touchMove/touchUp get called, and then onDraw gets called each time after each method.
If I am thinking correctly, I want to save mBitmap into an ArrayList / Stack, so everytime a new drawing happens, a new mBitmap is pushed into the array list / stack. Then, if someone wants to undo the last drawn stroke, I just need to pop the most recent Bitmap and load the 2nd most recent bitmap.
I'm trying to implement FloodFill to fill drawings after this, so I think switching to this approach will be better long-run.

Swing graphics Update image position after performing zoom

I have the following variables that represent the position of the image (image is drag-able):
private int translateX, translateY;
And I render the image like with the paintComponent method:
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
g2d.drawImage(image, (int) (translateX * zoom), (int) (translateY * zoom), (int) (image.getWidth() * zoom), (int) (image.getHeight() * zoom), null);
}
Where zoom is the zoom amount (min 0.8) and I multiply image dimension by the zoom.
This is how I handle the zoom value in my controller:
#Override
public void mouseWheelMoved(MouseWheelEvent e) {
int delta = e.getWheelRotation();
double temp = map.getZoom() - (delta * 0.1);
temp = Math.max(temp, 0.8);
temp = Math.max(temp, 0.8);
if (temp != map.getZoom()) {
map.setZoom(temp);
map.repaint();
}
}
What happens here, is that the zoom works great, zooms into the center like it should, but what I have is a big map image inside a JPanel that has size limits (getWidth() and getHeight()) and when you drag the map image, you can't go out of the panel bounds unless the map image is there, but if it's the end of the map image width or height, it will stop at the maximum, I do these bound calculation like this:
public void translateSafely(int x, int y) {
if (!(translateY + y > 0 || (translateY + y) * zoom < getHeight() - image.getHeight() * zoom)) {
this.translateY += y;
}
if (!(translateX + x > 0 || (translateX + x) * zoom < getWidth() - image.getWidth() * zoom)) {
this.translateX += x;
}
this.repaint();
}
getWidth() and getHeight() are the methods from the inhering JPanel
This will make you able to drag the map (by adding x and y from drag event) with limits, if the map is ending on the map by calculating the map width or height with panel width and height.
The problem
If you zoom in, and drag your map to the left and then zoom out, the map will go outside the bounds (negative x) and stay there and you will not be able to move it back because of the limits unless you zoom back in and move it to the right.
The question is, how do I make the map move back without jumps when I zoom out?.
GIF sample of the problem:
https://gyazo.com/ba1d69f2720dee10a19ba65bdac0e81a

how to scale the drawable to fit the screen

in my project I want to draw my drawable to the screen to fit its height and width , and then I want to draw other things on its center . The problem is when I want to draw it , it not shows fit to the screen , I have tried many things but nothing work for me.
I know my question is not clear so shortly asking that how to fit the image to fit the background using canvas.drawmethod()
here is what I am using
final Drawable dial = mDial;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
if (availableWidth < w || availableHeight < h) {
scaled = true;
float scale = Math.min((float) availableWidth / (float) w,
(float) availableHeight / (float) h);
canvas.save();
canvas.scale(scale, scale, x, y);
Log.d("Scaling the width and height","here we go");
}
if (changed) {
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
Log.d("bounds have been changed","here we go");
}
dial.draw(canvas);
please help

Android: Canvas scaling in different coordinate system

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)

Zoom persist on next imageview

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();
}

Categories