In case you need to resize and rotate image simultaneously using one handler icon, some trigonometrical calculations should be performed.
It is not so difficult to calculate angle by which image should be rotated, based on its initial angle and angle, by which the vector, that connects center of image and current finger position, is rotated. A little bit more complicated task is to position the handler in a proper place of the screen to make it always connect the corner of main image.
public void setUpResize() {
dragHandle.setOnTouchListener(new View.OnTouchListener() {
float centerX, centerY, startR, startScale, startX, startY, startRotation, startA ;
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
centerX = (imageView.getLeft() + imageView.getRight()) / 2f;
centerY = (imageView.getTop() + imageView.getBottom()) / 2f;
startX = e.getRawX() - dragHandle.getX() + centerX;
startY = e.getRawY() - dragHandle.getY() + centerY;
startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
startA = (float) Math.toDegrees(Math.atan2(e.getRawY() - startY, e.getRawX() - startX));
startScale = imageView.getScaleX();
startRotation = imageView.getRotation();
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
float newA = (float) Math.toDegrees(Math.atan2(e.getRawY() - startY, e.getRawX() - startX));
float newScale = newR / startR * startScale;
float newRotation = newA - startA + startRotation;
imageView.setScaleX(newScale);
imageView.setScaleY(newScale);
imageView.setRotation(newRotation);
// ----- this part takes some effort to understand... ------
dragHandle.setX((float) (centerX + Math.hypot(imageView.getWidth(), imageView.getHeight())/2f * newScale
* Math.cos(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))));
dragHandle.setY((float) (centerY + Math.hypot(imageView.getWidth(), imageView.getHeight())/2f * newScale
* Math.sin(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))));
//-----------------------------------------------------------
dragHandle.setPivotX(0);
dragHandle.setPivotY(0);
dragHandle.setRotation(newRotation);
} else if (e.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
So, what I'm doing?
Math.hypot(imageView.getWidth(), imageView.getHeight()) / 2f * newScale
--this calculates half length of diagonal of the main image, i. e. distance between its center and corner point
Math.atan2(imageView.getHeight(), imageView.getWidth())
--this is angle by which diagonal was rotated initially (since image must not be square, this angle is not always 45 deg.)
Math.cos(Math.toRadians(newRotation) + Math.atan2(imageView.getHeight(), imageView.getWidth()))
--this gives us projection onto X axis of unit vector, rotated by an angle composed with angle, at which image is rotated, and angle of initial rotation of its diagonal. After multiplying it to half length of diagonal, we get X of image corner.
The same with Y, but using sin
instead of cos
.