记录Android中实现滑动的几种方法

一、layou方法

代码示例如下,自定义一个view,在onTouchEvent()方法中计算手指滑动时的偏移量,调用view的layout()方法,在当前left、top、right、bottom上加上偏移量,实现view的滑动。

public class TestView extends View {
    private static final String TAG = "TestView";
    public TestView(Context context) {
        super(context);
    }

    public TestView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
       
    }

    public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    float startX;
    float startY;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录初始触摸点坐标
                startX = event.getRawX();
                startY = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //手指滑动过程中经过的点坐标
                float lastX = event.getRawX();
                float lastY = event.getRawY();
                //计算偏移量
                int offsetX = (int) (lastX - startX);
                int offsetY = (int) (lastY - startY);
                //在当前的left、top、right、bottom上加上偏移量
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                Log.e(TAG, "onTouchEvent: layout: " + offsetX + "/" + offsetY);
                //重新设置初始坐标 ,这一步很重要            
                startX = lastX;
                startY = lastY;
            break;
          }
        return true;
    }
 }

二、offsetLeftAndRight()与offsetTopAndBottom()方法

这两个方法相当于系统提供的一个对左右、上下移动的API的封装。使用方法同样先在onTouchEvent()方法中计算出手指滑动的偏移量,然后将偏移量作为方法参数传入。关键代码如下:

    float startX;
    float startY;
    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录初始触摸点坐标
                startX = event.getRawX();
                startY = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //手指滑动过程中经过的点坐标
                float lastX = event.getRawX();
                float lastY = event.getRawY();
                //计算偏移量
                int offsetX = (int) (lastX - startX);
                int offsetY = (int) (lastY - startY);
                //调用方法,参数为计算出的偏移量
                offsetLeftAndRight(offsetX);
                offsetTopAndBottom(offsetY);
                Log.e(TAG, "onTouchEvent: offsetLeftAndRight_offsetTopAndBottom: " + offsetX + "/" + offsetY);
                //重新设置初始坐标 ,这一步很重要   
                startX = lastX;
                startY = lastY;
                break;
              }
        return true;
    }

三、修改view的LayoutParams

LayoutParams保存着一个View的布局参数。可以通过改变LayoutParams来动态修改一个View的位置参数,以此达到改变View位置的效果。关键代码如下:

    float startX;
    float startY;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                //记录初始触摸点坐标
                startX = event.getRawX();
                startY = event.getRawY();
                break;
            case MotionEvent.ACTION_MOVE:
                //手指滑动过程中经过的点坐标
                float lastX = event.getRawX();
                float lastY = event.getRawY();
                //计算偏移量
                int offsetX = (int) (lastX - startX);
                int offsetY = (int) (lastY - startY);
                //修改LayoutParams参数,这里要改变位置主要是修改LayoutParams的margin属性,因此这里直接使用
                // ViewGroup.MarginLayoutParams以求方便,不必考虑view的父布局类型。在一般应用中,如若有需要
                // 修改LayoutParams的其他属性,要注意getLayoutParams()必须获取的是父布局类型的LayoutParams。
                ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) getLayoutParams();
                layoutParams.leftMargin = getLeft() + offsetX;
                layoutParams.topMargin = getTop() + offsetY;
                setLayoutParams(layoutParams);
                Log.e(TAG, "onTouchEvent: layoutParams: " + offsetX + "/" + offsetY);
                //重新设置初始坐标,这一步很重要
                startX = lastX;
                startY = lastY;
                break;
               }
        return true;
    }

四、scrollTo与scrollBy

1.scrollTo(int x,int y):移动到一个坐标点
2.scrollBy(int x,int y):按照x轴增量x,y轴增量y的方式移动
这两个方法实质上移动的是调用方法的对象所包含的内容。即:如果对一个ViewGroup(如LinearLayout)调用这两个方法,会发现其内部所有的子view会一起发生移动;而如果对一个view(如TextView)调用,则会发现看不到移动的效果。要对view使用这两个方法,实际上是需要对该view 的parent使用。代码示例如下:
1.在ViewGroup中,可以直接调用

float startX;
float startY;
@Override
public boolean onTouchEvent(MotionEvent event) {
    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = event.getRawX();
            startY = event.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:
            float lastX = event.getRawX();
            float lastY = event.getRawY();
            int offsetX = (int) (lastX - startX);
            int offsetY = (int) (lastY - startY);
            //注意这里的参数要变成相反数。由于作用对象是parent,所以实际发生
            //移动的应该是parent,但我们的目标是子view。因此,以相对视图关系
            //来看,要让子view产生所期望的移动效果,parent应该要向反方向移动。
            scrollBy(-offsetX, -offsetY);
            startX = lastX;
            startY = lastY;
            break;
    }
    return true;
}

2.在view中,需要由view的parent来调用

 ((View) getParent()).scrollBy(-offsetX, -offsetY);

五、使用Scroller实现带过度动画的滑动

使用前面几种方法实现view位置的改变,如果不是通过手指触摸事件,而是通过如按钮点击事件调用,view的位置变化是瞬间完成的。如果要让位置变化有一个过渡动画的过程,可以使用Scroller来实现。Scroller的使用可以分为3步骤:
1.初始化Scroller: Scroller scroller=new Scroller(context);
2.重写computeScroll()方法,实现模拟滑动

@Override
public void computeScroll() {
    super.computeScroll();
    if (mScroller.computeScrollOffset()) {
        ((View) getParent()).scrollTo(scroller.getCurrX(), scroller.getCurrY());
        invalidate();
    }
}

3.startScroll()方法开启模拟过程。可以在自定义view内部合适的位置调用下列方法,也可以在自定义view内部声明一个调用该方法的方法,然后在外部Activity等需要调用的位置调用。

scroller.startScroll(startX, startY, dx, dy, duration);

代码示例:

自定义View
public class TestView extends View {
private static final String TAG = "TestView";
private Scroller mScroller;

public TestView(Context context) {
    super(context);
}

public TestView(Context context, @Nullable AttributeSet attrs) {
    super(context, attrs);
    mScroller = new Scroller(context);
}

public TestView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@Override
public void computeScroll() {
    super.computeScroll();
    if (mScroller.computeScrollOffset()) {
        ((View) getParent()).scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
        invalidate();
    }
}

public void scrollAnimation(int startX, int startY, int dx, int dy, int duration) {
    mScroller.startScroll(startX, startY, dx, dy, duration);
    invalidate();
}
}

在Activity中调用:

 @Override
public void onClick(View v) {
    mTestView.scrollAnimation(0,0,-300,-400,2000);
}

你可能感兴趣的:(记录Android中实现滑动的几种方法)