package com.example.view;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.Scroller;
import androidx.annotation.Nullable;
public class CoustomView extends View {
private int mLastX;//用来标记起始点x
private int mLastY;//用来标记起始点y
private Scroller scroller;
public CoustomView(Context context) {
this(context,null);
}
public CoustomView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CoustomView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
scroller = new Scroller(context);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();//这是相对与当前view的父容器的水平坐标
int y = (int) event.getY();//这是相对与当前view的父容器的垂直坐标
switch (event.getAction()){
//根据event的类型来判断如何处理
case MotionEvent.ACTION_DOWN:
mLastX = x;
mLastY = y;
//当点击的一瞬间,记录起始位置
break;
case MotionEvent.ACTION_MOVE:
//当发生滑动事件如何处理
//我们希望当前的view能跟随我们的滑动轨迹一起滑动
int deltaX = x-mLastX;//当前手指所指向的坐标减去起始坐标的水平方向的偏移量;
int deltaY = y-mLastY;//当前手指所指向的坐标减去起始坐标的垂直方向的偏移量;
//1.layout(getLeft()+deltaX,getTop()+deltaY,getRight()+deltaX,getBottom()+deltaY); //getLeft 等是绝对坐标系
//2.offsetLeftAndRight(deltaX);//水平偏移
// offsetTopAndBottom(deltaY);//垂直偏移
//3.LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) getLayoutParams(); //设置params
// params.leftMargin+=deltaX;
// params.topMargin+=deltaY;
// setLayoutParams(params);
//4.((View) getParent()).scrollBy(-deltaX, -deltaY);//通过scrollBy移动的是View的Content,那么我们要移动控件,就必须要直到当前控件属于哪个view
//的内容,这样才能移动控件
//5.smoothScroller(-deltaX,-deltaY);//通过Scroller实现弹性滑动
//6.使用动画
ObjectAnimator.ofFloat(this,"translationX",mLastX,deltaX).setDuration(500).start();
ObjectAnimator.ofFloat(this,"translationY",mLastY,deltaY).setDuration(500).start();
break;
}
return true;
}
private void smoothScroller(int dx, int dy) {
scroller.startScroll(scroller.getFinalX(), scroller.getFinalY(), dx,dy,500);
invalidate();
}
@Override
public void computeScroll() {
super.computeScroll();
//调用重新绘制时这个方法会被执行
if(scroller.computeScrollOffset()){
//判断滑动是否执行完毕
//没有执行完毕就继续执行
((View) getParent()).scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/line1"
android:background="@color/colorPrimaryDark"
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:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ViewActivity">
<com.example.view.CoustomView
android:id="@+id/cv"
android:layout_marginLeft="20px"
android:background="@color/colorAccent"
android:layout_width="100px"
android:layout_height="100px"/>
</LinearLayout>
六种滑动方式,其中只有属性动画改变了View的真实属性。其他的只是改变了位置。
详情请参考View滑动