Android implements View's slide series one -- using layout() method

Keywords: Android xml encoding

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;

Posted by sprintlife on Mon, 30 Mar 2020 23:08:27 -0700