实现View滑动的几种方法

实现view滑动的方法:

一、layout方法

在View绘制的时候,系统都会调用layout(int l, int t, int r, int b)方法来确定View的具体位置。既然这样来,那么我们也可以通过调用layout(int l, int t, int r, int b)`方法修改left,top,right,bottom这四个属性来控制View的位置。

首先写一个自定义类继承view,重写onToucnEvent()方法;

public class LayoutView extends View {

    private int lastX,lastY;

    public LayoutView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

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

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                // 记录触摸点坐标
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                // 计算偏移量
                int offsetX = x - lastX;
                int offsetY = y - lastY;
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                break;
        }
        return true;
    }
}

然后再布局中使用LayouView,最后效果如图:

二、offsetLeftAndRight和offsetTopAndBottom

这两个方法是系统提供对左右,上下移动api的封装,当计算出偏移量后,只需要调用一下两个方法就可以完场重新布局,

case MotionEvent.ACTION_MOVE: 

   int offsetX = x - lastX; 
   int offsetY = y - lastY; 

   //同时对left和right进行偏移
   offsetLeftAndRight(offsetX);

   //同时对top和bottom进行偏移
   offsetTopAndBottom(offsetY); 

break;

这里的offsetX,和offsetY的计算方法和第一种方法相同,这里就不多解释

三、LayoutParams

通过改变View的LayoutParams布局参数,就可以移动View的位置,这里通常修改View的Margin属性,代码如下:

 private int lastX,lastY;

    ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams) getLayoutParams();

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX = x - lastX;
                int offsetY = y - lastY;
                params.leftMargin = getLeft() + offsetX;
                params.topMargin = getTop() + offsetY;
                break;
        }

        return true;
}

四、ScrollTo 和ScrollBy

上面的方法都是移动View自己本身,而第四种方法移动的是view的内容,如果放在ViewGroup中使用,则移动的是ViewGroup里面所有的子View

scrollTo(x,y) : 移动到 (x,y) 这个坐标点
scrlollBy(dx,dy) : 移动的增量为 dx,dy。

case MotionEvent.ACTION_MOVE:

    int offsetX = x - lastX;
    int offsetY = y - lastY;

//scroll方法移动的是View的父布局,因此,子View相对于父布局移动,相当于父布局取反移动
    ((View)getParent()).scrollBy(-offsetX,-offsetY);

    break;

五、Scroller

Scroll本身无法让View滑动,它需要和View的computeScroll方法配合才能使用

//(1)创建Scroller类
Scroller scroller =new Scroller(mContext);

//(2)重写computeScroll方法
@Override
public void computeScroll(){
   // 判断Scroller滑动是否执行完毕
  if(mSroller.computeScrollOffset()) {

      scrollTo(mScroller.getCurrX().mScroller.getCurrY());
  // 通过重绘让系统调用onDraw,onDraw中又会调用computeScroll,如此不断循环,直到Scroller执行完毕
      postInvalidate();
  }
}

 //(3)调用Scroller类的startScroll方法开启滚动过程
private void smoothScrollTo(int destX,int destY) {
    int scrollX=getScrollX();
    int delta = destX - scrollX;
 
     mSroller.startScroll(scrollX,0,delta,0,1000);
     invalidate();// 必须调用该方法通知View重绘以便computeScroll方法被调用。
}


接下来就开始模拟滑动过程了,重写onTouchEvent方法,代码如下:

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                lastX = x;
                lastY = y;
                break;
            case MotionEvent.ACTION_UP:
                int offX = x - lastX;
                int offY = y -lastY;
                smoothScrollBy(-offX,-offY);
                break;
        }
        return true;
    }

六、动画

使用动画来实现View的滑动主要通过改变View的translationX和translationY参数来实现,使用动画的好处在于滑动效果是平滑的。

1.使用补间动画

先定义一个动画的xml文件(R.anim.anim),再在代码中调用,不过补这种方式只是移动view的影像,真正的view并没有移动。

<?xml version="1.0" encoding="utf-8"?> 
<set 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:fillAfter="true"> 
    <translate 
        android:duration="100" 
        android:fromXDelta="0" 
        android:fromYDelta="0"         
        android:interpolator="@android:anim/linear_interpolator" 
        android:toXDelta="100" 
        android:toYDelta="100"/> 
</set>

final Animation anim = AnimationUtils.loadAnimation(this, R.anim.anim);
targetView.startAnimation(anim);

2.属性动画

属性动画很简单,一句代码即可:

ObjectAnimator.ofFloat(targetView, "translationX", 0, 100).setDuration(100).start();

猜你喜欢

转载自blog.csdn.net/hua93/article/details/82981401