Practice to get real knowledge, do the code!
In the drawing process of Android View, in the onLayout() method, the child view will call the layout() method to complete its own layout. We can change the parameters of view layout() to achieve the sliding effect of view!
1. Implementation steps
- Override the onTouchEvent() method of View
- Get the coordinates of view in the onTouchEvent() method and calculate the offset when sliding
- Modify the layout() method parameter of view to realize view sliding
2. Effect
2.1. Layout documents
Customize a DragView, set its width and height to 100dp, for the test of View sliding
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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.snail.viewscroller.DragView
android:id="@+id/dv_test"
android:layout_width="100dp"
android:layout_height="100dp" />
</LinearLayout>
2.2. Customized DragView
Focus on onTouchEvent()
/**
* @author yongjie on 2018/4/22.
*/
public class DragView extends View {
private int lastX;
private int lastY;
public DragView(Context context) {
this(context, null);
}
public DragView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public DragView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int widthSize;
int heightSize;
if (widthMode == MeasureSpec.EXACTLY) {
widthSize = MeasureSpec.getSize(widthMeasureSpec);
} else {
widthSize = 100;
}
if (heightMode == MeasureSpec.EXACTLY) {
heightSize = MeasureSpec.getSize(heightMeasureSpec);
} else {
heightSize = 100;
}
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.RED);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//Get the current coordinates (get the coordinates of the touch event point relative to the current view coordinate system)
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
//Record the coordinates of action "down"
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
//Calculate the offset for each slide
int offsetX = x - lastX;
int offsetY = y - lastY;
//Call the layout() method to rearrange the view layout and redraw the view
//Call getLeft, top, bottom, right and other methods to get the original position of the view in the parent view and then add the offset to get the layout position after sliding
layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
//Be sure to return true, otherwise the subsequent touch event will not be delivered here
return true;
}
}
2.3. Use offsetLeftAndRight() and offsetTopAndBottom()
As the layout method works, the system helps us encapsulate the API
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
//Get the current coordinates (get the coordinates of the touch event point relative to the current view coordinate system)
int x = (int) event.getX();
int y = (int) event.getY();
switch (action) {
case MotionEvent.ACTION_DOWN:
//Record the coordinates of action "down"
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
//Calculate the offset for each slide
int offsetX = x - lastX;
int offsetY = y - lastY;
//Just modify the code here
offsetLeftAndRight(offsetX);
offsetTopAndBottom(offsetY);
break;
case MotionEvent.ACTION_UP:
break;
}
//Be sure to return true, otherwise the subsequent touch event will not be delivered here
return true;