Description: I have a class called Container which can hold items. In the code below I added only one item to the container. The user can move this item by dragging it and rotating it by 90 degrees by double-clicking on it.
Before double-clicking on it (before applying the rotation), it moves as expected when the user drags the item. If the user double-clicks the item (applies 90 degrees rotation) and then tries to move it by dragging it, it unexpectedly moves so quickly out of the window and in a random direction.
Demo:
Code:
Container.java
public class Container extends ViewGroup {
public Container(Context context) {
super(context);
}
public Container(Context context, AttributeSet attrs) {
super(context, attrs);
}
public Container(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
//Layout all children used fixed position
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
for (int i = 0; i<count; i++) {
View child = getChildAt(i);
int left = child.getLeft();
int top = child.getTop();
int right = child.getRight();
int bottom = child.getBottom();
child.layout(left, top, right, bottom);
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i<count; i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, heightMeasureSpec);
}
}
}
Item.java
public class Item extends View {
// default width and height for this item
private static final int WIDTH = 200;
private static final int HEIGHT = 80;
private final Paint mPaint;
private final static int OFFSET = 1;
//Store the click position
private float mStartX = 0;
private float mStartY = 0;
//Used to detect double-click on this item
private long mStartTime = 0;
private static final int DOUBLE_TAP_THRESHOLD = 200;
public Item(Context context, int x, int y) {
super(context);
// Set the size of the item,
// No need to override onMeasure()
setLeft(x);
setTop(y);
setRight(x + WIDTH);
setBottom(y + HEIGHT);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
canvas.drawRect(OFFSET, OFFSET, width-OFFSET, height-OFFSET, mPaint);
}
// Rotate the item if the user double click on it
// And move the item if the user drag it
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
long currentTime = System.currentTimeMillis();
if(currentTime - mStartTime < DOUBLE_TAP_THRESHOLD) {
//Double click detected
// Apply rotation
setRotation(getRotation() + 90); // rotation that cause the problem
return true;
}
mStartTime = currentTime;
mStartX = event.getX();
mStartY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
// compute the new position for the item
float deltaX = event.getX() - mStartX;
float deltaY = event.getY() - mStartY;
float newX = getX() + deltaX;
float newY = getY() + deltaY;
//move the item
setX(newX);
setY(newY);
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Container container = findViewById(R.id.container);
container.addView(new Item(this, 100, 200));
}
}
activity_main.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.package.name.Container
android:id="@+id/container"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Question: Why does the item move so quickly when rotating it? and how to fix this issue.