I want to know about How to rotate the bitmap image with single touch gestures.kindly help and suggest some solutions. I done scaling the bitmap with the help of
http://grishma102.blogspot.in/2013/10/drag-and-drop-functionality-to-move.html . Now I need to rotate the whole image while touch and rotate the resize button. How to acheive it?
Thanks in advance
Check out my blogspot in which i have tried to implement the functionality of stretch the image on arrow click and also delete it, and also you can move the image on the screen using gesture.
Drag-Drop image Also check out the Demo of DragDropImage
function that handles rotation with one finger, the main idea is to calculate the centerX and centerY of your view and taking into consideration the status bar height if you using one.
#Override
public boolean onTouch(View view, MotionEvent event) {
switch (action) {
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_DOWN:
rotateX = event.getRawX();
rotateY = event.getRawY();
centerX = view.getX() + ((View) getParent()).getX() + (float) view.getWidth() / 2;
centerY = view.getY() + statusBarHeight + (float) view.getHeight() / 2;
break;
case MotionEvent.ACTION_MOVE:
newRotateX = event.getRawX();
newRotateY = event.getRawY();
double angle = Math.atan2(event.getRawY() - centerY, event.getRawX() - centerX) * 180 / Math.PI;
view.setRotation((float) angle - 45);
rotateX = newRotateX;
rotateY = newRotateY;
}
}
return true;
}
};
Related
I looked on many posts but couldnt find the answer.
I would like to rotate an root image with another small image that is located on the lower side of the root image.
while rotation its working but the first time I press it, it jumps to 45 degrees because of the math.tan(), I think I have a calculation problem.
rotateImage.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent event) {
final int action = MotionEventCompat.getActionMasked(event);
switch (action) {
case MotionEvent.ACTION_UP:
break;
case MotionEvent.ACTION_DOWN:
rotateX = event.getRawX() - rotateImage.getWidth() / 2;
rotateY = event.getRawY() - rotateImage.getHeight() / 2;
break;
case MotionEvent.ACTION_MOVE:
float angle = (float) Math.toDegrees(Math.atan2(event.getRawY() - rotateY, event.getRawX() - rotateX));
if (angle < 0){
angle += 360;
}
mBinding.getRoot().setRotation(angle);
}
return true;
}
});
please advice.
I think this library can help you.
https://github.com/kencheung4/android-StickerView
I need to click on particular item on the canvas while zooming and moving functionalities also enable for canvas. I can calculate the rectangle position while moving the canvas. There I just calculate the touch movement distance by (CurrenTouchXPosition - StartXPosition).
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
int x = (int) event.getX();
int y = (int) event.getY();
float moveOffsetX = (event.getX() - start.x);
float moveOffsetY = (event.getY() - start.y);
Then,
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
mode = DRAG;
break;
case MotionEvent.ACTION_POINTER_DOWN:
break;
case MotionEvent.ACTION_UP:
Log.d(TAG, "action up");
secondRectUpperX = secondRectUpperX + moveOffsetX;
secondRectBottomX = secondRectBottomX + moveOffsetX;
secondRectUpperY = secondRectUpperY + moveOffsetY;
secondRectBottomY = secondRectBottomY + moveOffsetY;
This can identify the new canvas position of the rectangle. This works perfectly. I can identify the touch event of particular item while moving the canvas by this logic.
But now i need to calculate the rectangle position relative to the canvas, after zoom the canvas. Whats the maths behind the zooming. If anyone knows please help in this.
Thank you.
Finally I come up with a solution.
I translate my touch position screen coordinates to canvas coordinates.
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
...
break;
case MotionEvent.ACTION_POINTER_DOWN:
...
break;
case MotionEvent.ACTION_UP:
float []m = new float[9];
matrix.getValues(m);
float transX = m[Matrix.MTRANS_X] * -1;
float transY = m[Matrix.MTRANS_Y] * -1;
float scaleX = m[Matrix.MSCALE_X];
float scaleY = m[Matrix.MSCALE_Y];
lastTouchX = (int) ((event.getX() + transX) / scaleX);
lastTouchY = (int) ((event.getY() + transY) / scaleY);
lastTouchX = Math.abs(lastTouchX);
lastTouchY = Math.abs(lastTouchY);
Thanks for Andres Cardenas Pardo's answer here
I could able to get the touch position coordinates according to the canvas coordinates. Since i know the coordinates of my drawn object, i check whether the touch position is within the range of drawn object.
if((lastTouchX>=firstRectUpperX && firstRectBottomX>=lastTouchX) && (lastTouchY>=firstRectUpperY && firstRectBottomY>=lastTouchY)) {
isbtn1Clicked = true;
}
I am trying to make an Android paint application for finger painting and I am having trouble with moving the lines I draw.
What I tried to do was offset the path of the currently selected line by the difference between the initial finger press coordinates and the current coordinates in OnTouchEvent during ACTION_MOVE.
case MotionEvent.ACTION_MOVE:
selectline.getLine().offset(x - otherx, y - othery);
otherx and othery are set as the x and y coordinates during ACTION_MOVE and x and y are the current cursor coordinates. My lines are stored as a separate class containing the path, color, thickness and bounding box.
What I got was the shape flying off the screen in the direction of my finger without stopping at the slightest movement. I tried using a matrix to move the path, but the result was the same.
When I tried to insert a "do while" that would check whether the current coordinates would match the path's .computeBounds() rectangle center, but the program crashes as soon as I move my finger.
Any help would be appreciated, thanks.
Most likely that you did not use the right scale for the coordinates.
Source: Get Canvas coordinates after scaling up/down or dragging in android
float px = ev.getX() / mScaleFactor + rect.left;
float py = ev.getY() / mScaleFactor + rect.top;
// where mScaleFactor is the scale use in canvas and rect.left and rect.top is the coordinate of top and left boundary of canvas respectively
Its a bit late but it may solve others problem. I solved this issue like this,
get initial X,Y position on onLongPress
public void onLongPress(MotionEvent motionEvent) {
try {
shapeDrag = true;
SmEventX = getReletiveX(motionEvent);
SmEventY = getReletiveY(motionEvent);
} catch (Exception e) {
e.printStackTrace();
}
and then on onToucn(MotionEvent event)
case MotionEvent.ACTION_MOVE: {
actionMoveEvent(motionEvent);
try {
if (shapeDrag) {
StylePath sp = alStylePaths
.get(alStylePaths.size() - 1);
Path mpath = sp.getPath();
float tempX = getReletiveX(motionEvent) - SmEventX;
float tempY = getReletiveY(motionEvent) - SmEventY;
mpath.offset(tempX, tempY);
SmEventX = getReletiveX(motionEvent);
SmEventY = getReletiveY(motionEvent);
}
} catch (Exception e) {
e.printStackTrace();
}
break;
}
}
I faced the same trouble and in my case it was a very naive mistake. Since the description of the "symptoms" matches exactly (shape flying off the screen in the direction of the finger at the slightest movement, shape moved correctly at ACTION_UP event), I think the reason behind might be the same.
Basically the problem is in the update of the touch position coordinates within the ACTION_MOVE event. If you don't update the last touch position, the calculated distance will be always between the current touch position and the first touch position stored at ACTION_DOWN event: if you apply this offset consecutively to the path, the translation will sum up and consequently the shape will "fly" rapidly off the screen.
The solution is then quite simple: just update the last touch position at the end of the ACTION_MOVE event:
float mLastTouchX, mLastTouchY;
#Override
public boolean onTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN: {
// get touch position
final float x = ev.getX();
final float y = ev.getY();
// save the initial touch position
mLastTouchX = x;
mLastTouchY = y;
break;
}
case MotionEvent.ACTION_MOVE: {
// get touch position
final float x = ev.getX();
final float y = ev.getY();
// calculate the distance moved
final float dx = x - mLastTouchX;
final float dy = y - mLastTouchY;
// here apply translation to the path
// update touch position for the next move event
mLastTouchX = x;
mLastTouchY = y;
break;
}
}
return true;
}
Hope this helps.
I am trying to move an ImageView (not rotate). The movement is supposed to be on the edge of a circle. This circle is also an image view.
based on the onTouch, ACTION_MOVE event, I am trying to move it.
Noe the Dilema is that the use may not move the finger in a perfectly circular fashion but I would like to make sure that the image still moves around edge of this circle.
I am currently using the following inside ACTION_MOVE:
mCurrTempIndicator.setTranslationX(event.getX());
mCurrTempIndicator.setTranslationY(event.getY());
But this will not move in a perfect circle.
could someone please help.
UPDATE: code
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialX = event.getX();
mInitialY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mEndX = event.getX();
mEndY = event.getY();
float deltaX = mEndX - mInitialX;
float deltaY = mEndY - mInitialY;
double angleInDegrees = Math.atan(deltaY / deltaX) * 180 / Math.PI;
mInitialX = mEndX;
mInitialY = mEndY;
mCurrTempIndicator.setRotation((float)angleInDegrees);
mCurrTempIndicator.setTranslationX((float)(310*(Math.cos(angleInDegrees))));
mCurrTempIndicator.setTranslationY((float)(310*(Math.sin(angleInDegrees))));
break;
case MotionEvent.ACTION_UP:
allowRotating = true;
break;
}
return true;
}
calculate the center Point of the Circle
get the current touch point
calculate the angle between center and new touch point
Calculate the point on the circle using angle and radius of circle (x = r * cos(angle), y = r * sin(angle)).
Reset the image position to the new point.
To get the angle use the below equation
deltaY = P2_y - P1_y
deltaX = P2_x - P1_x
angleInDegrees = arctan(deltaY / deltaX) * 180 / PI
//Code inside ACTION_MOVE case
mInitialX = event.getX();
mInitialY = event.getY();
float deltaX = circleCenter.x - mInitialX;
float deltaY = circleCenter.y - mInitialY;
double angleInRadian = Math.atan2(yDiff, xDiff);
PointF pointOnCircle = new PointF();
pointOnCircle.x = circleCenter.x + ((float)(circleRadius*(Math.cos(angleInRadian))));
pointOnCircle.y = circleCenter.y + ((float)(circleRadius*(Math.cos(angleInRadian))));
I am moving an image around a circle via touch events.
I want the user to touch the image and when the user drags this image around the cirle, it moves, otherwise it doesn't move.
Could someone please help with the math on how to check if the finger in moving along the circle or not and them move the image accordingly.
Thanks.
UPDATE:
I am trying to revolve an image around a circle. It is already placed on the circle edge.
But on touch and move actions it takes it self as the centre and then starts moving around a defined radius.
could someone pls see the code and let me know where i am going wrong.
Thanks.
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialX = event.getX();
mInitialY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
mEndX = event.getX();
mEndY = event.getY();
float deltaX = mEndX - mInitialX;
float deltaY = mEndY - mInitialY;
double angleInDegrees = Math.atan(deltaY / deltaX) * 180 / Math.PI;
mInitialX = mEndX;
mInitialY = mEndY;
mCurrTempIndicator.setRotation((float)angleInDegrees);
mCurrTempIndicator.setTranslationX((float)(310*(Math.cos(angleInDegrees))));
mCurrTempIndicator.setTranslationY((float)(310*(Math.sin(angleInDegrees))));
break;
case MotionEvent.ACTION_UP:
allowRotating = true;
break;
}
return true;
}
float dx = event.getX() - circleCenterX
float dy = event.getY() - circleCenterY;
// r is now the radius of the touch event, you can compare it with the radius of your circle to find out if it's close enough
float r = FloatMath.sqrt((dx * dx) + (dy * dy));
if(r > circleRadius - 10 && r < circleRadius + 10){
// a is now the angle between the center point and the touch point in radians. With 0 being 3 o'clock, -/+PI being 9 o'clock -PI/2 at 12 o'clock and +PI/2 at 6 o'clock.
float a = Math.atan2(dy, dx);
}
Adding to the above answer. I made some changes to make it work properly. In this I'm making an ImageView to revolve around a fixed center point meaning ImageView will move along the circumference of the circle.
double centerX, centerY; //Center coordinates of the circle
int radius; //Set the radius in pixels
//The view which will revolve on the circumference of the circle
imageView = new ImageView(this);
imageView.setBackgroundResource(android.R.drawable.ic_menu_add); //Set your view icon
imageView.setPadding(10, 10, 10, 10);
relativeLayout.addView(imageView);
//Setting the imageView on the circumference of the circle
imageView.setTranslationX(centerX + radius);
imageView.setTranslationY(centerY);
//Add imageview to the parent layout dynamically(choice)
relativeLayout.addView(imageView);
imageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_MOVE:
double dx = motionEvent.getRawX() - centerX;
double dy = motionEvent.getRawY() - centerY; //Also subtract toolbar height and status bar height if applicable
//Distance between user's point of touch and circle center
double distance = Math.sqrt((dx * dx) + (dy * dy));
if (distance > radius - 200 && distance < radius + 200) {
double angle = Math.atan2(dy, dx);
//Getting the point on the circumference of the circle using the angle and the radius
double x = centerX + radius * Math.cos(angle);
double y = centerY + radius * Math.sin(angle);
//Finally move the view along the circimference of the circle as the user drags the view
imageView.animate().y((float) y).x((float) x).setDuration(0).start();
}
break;
}
return true;
}
});