I'm trying to rotate and scale a view based on one "drag" handle in Android. With the layout rotating, and the view resizing, the end result should be that the drag handle follows the users finger where ever it moves.
This is based on combining these two questions:
The only thing that seems wrong is the rotation code.
Here is my activity code:
public class MainActivity extends Activity {
ImageView imageView;
ImageView dragHandle;
RelativeLayout layout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView1);
imageView.setBackgroundColor(Color.MAGENTA);
dragHandle = (ImageView) findViewById(R.id.imageView2);
dragHandle.setBackgroundColor(Color.CYAN);
layout = (RelativeLayout) findViewById(R.id.relativeLayout2);
layout.setBackgroundColor(Color.YELLOW);
setUpResize();
}
public void setUpResize() {
dragHandle.setOnTouchListener(new View.OnTouchListener() {
float centerX, centerY, startR, startScale, startX, startY;
float startAngle;
float zeroAngle;
int firstPointX;
int firstPointY;
public boolean onTouch(View v, MotionEvent e) {
if (e.getAction() == MotionEvent.ACTION_DOWN) {
// calculate center of image
centerX = (imageView.getLeft() + imageView.getRight()) / 2f;
centerY = (imageView.getTop() + imageView.getBottom()) / 2f;
// recalculate coordinates of starting point
startX = e.getRawX() - dragHandle.getX() + centerX;
startY = e.getRawY() - dragHandle.getY() + centerY;
// get starting distance and scale
startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
startScale = imageView.getScaleX();
/*
* Rotate code
*/
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
layout.getLocationOnScreen(locationOfLayout);
dragHandle.getLocationOnScreen(locationOfDrag);
firstPointX = locationOfLayout[0];
firstPointY = locationOfLayout[1];
float secondPointX = e.getRawX();
float secondPointY = e.getRawY();
zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY); // remember
// "zero"
// angle
startAngle = layout.getRotation(); // remember angle at
// which layout is
// rotated at the start
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
// calculate new distance
float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
// set new scale
float newScale = newR / startR * startScale;
imageView.setScaleX(newScale);
imageView.setScaleY(newScale);
// move handler image
dragHandle.setX(centerX + imageView.getWidth() / 2f * newScale);
dragHandle.setY(centerY + imageView.getHeight() / 2f * newScale);
/*
* Rotate code
*/
layout.setRotation(findRotation(firstPointX, firstPointY, e.getRawX(), e.getRawY()) - zeroAngle
+ startAngle); // rotate relative to start and zero
// angle
} else if (e.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
});
}
private float findRotation(float firstPointX, float firstPointY, float secondPointX, float secondPointY) {
double delta_x = (secondPointX - firstPointX);
double delta_y = (secondPointY - firstPointY);
double radians = Math.atan2(delta_y, delta_x);
return (float) Math.toDegrees(radians);
}
}
xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:id="@+id/relativeLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" >
<ImageView
android:id="@+id/imageView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:src="@drawable/ic_launcher" />
<ImageView
android:id="@+id/imageView2"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_below="@+id/imageView1"
android:layout_toRightOf="@+id/imageView1"
android:src="@drawable/meanicons" />
</RelativeLayout>
</RelativeLayout>