美文网首页
Scroll效果的几种实现办法

Scroll效果的几种实现办法

作者: JC_Hou | 来源:发表于2016-10-10 12:18 被阅读414次

    首先都是对view的onTouchEvent()方法进行操作,对于
    MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP进行操作

    一、

    首先声明全局变量lastX,lastY保存手指按下位置;

    二、直接使用layout的方式

    /**
     * 在View内部可以通过getLeft(),getRight(),getTop(),getBottom()方法获取位置
     * 在MotionEvent可以通过getX(),getY(),getRawX(),getRawY()方法获取坐标位置
     * 区别在于getX(),getY()是获取相对View左上角的坐标,getRawX(),getRawY()是获取相对屏幕左上角的坐标
     */
    
    //方法1、通过layout()和getX()方法产生scroll效果
    private boolean onTouchEvent(MotionEvent ev){
        int x=(int)ev.getX();//相对于View自身的x方向位置,根据移动变化
        int y=(int)ev.getY();//相对于View自身的y方向位置
        switch(ev.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;//消费触摸事件
    }
    
    //方法2、通过layout()和getRawX()方法产生scroll效果
    private boolean onTouchEvent(MotionEvent ev){
        int rawX=(int)ev.getRawX();//相对于屏幕的x方向位置,根据移动变化
        int rawY=(int)ev.getRawY();//相对于屏幕的y方向位置
        switch(ev.getAction){
            case MotionEvent.ACTION_DOWN:
                lastX=rawX;//保存手指位置
                lastY=rawY;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX=rawX-lastX;//计算手指移动距离
                int offsetY=rawY-lastY;
                //重新布局
                layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);
                //需要重新保存lastX,lastY
                //因为触控点所在的当前View都会跟着手指滑动(调用了layout()),这会导致getRawX(等于当前View左边缘绝对坐标+getX)的值持续变化,而getX不受影响(view跟着手指一起动)。
                lastX=rawX;
                lastY=rawY;
                break;
        }
      return true;//消费触摸事件
    }
    
    //方法3、通过offsetLeftAndRight(int offset),offsetTopAndBottom(int offset)方法取代layout()产生scroll效果
    修改上面的代码
            case MotionEvent.ACTION_MOVE:
                int offsetX=x-lastX;//计算手指移动距离
                int offsetY=y-lastY;
                //重新布局
                offsetLeftAndRight(offsetX);//同时对左右都进行移动
                offsetTopAndBottom(offsetY);
                break;
    
    

    三、使用scrollBy()方法,使用此方法需要有父布局

    private boolean onTouchEvent(MotionEvent ev){
        int x=(int)ev.getX();//相对于View自身的x方向位置,根据移动变化
        int y=(int)ev.getY();//相对于View自身的y方向位置
        switch(ev.getAction){
            case MotionEvent.ACTION_DOWN:
                lastX=x;//保存手指位置
                lastY=y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetX=x-lastX;//计算手指移动距离
                int offsetY=y-lastY;
                //重新布局,必须使用父布局的scrollBy()方法
                ((View)getParent()).scrollBy(-offsetX,-offsetY);//注意这里必须加“-”,往正方向移动,必须是负值
                break;
        }
      return true;//消费触摸事件
    }```
    
    ####四、使用Scroller类,内部其实是通过scrollTo()方法
    - 初始化Scroller
    在构造方法中进行
    

    scroller=new Scroller(context);

    - 重写computeScroll()方法,这是核心,必须要有
    

    @Override
    public void computeScroll() {
    super.computeScroll();
    //判断Scroller是否执行完毕
    if(scroller.computeScrollOffset()){
    ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());//通过getCurrX()和getCurrY()获得当前滑动坐标
    //通过重绘不断调用computeScroll
    invalidate();
    }
    }
    computeScroll()不会自动调用,只能通过invalidate()-->draw()-->computeScroll()来循环获得scrollX和scrollY```

    • startScroll
      有两个重载方法
    scroller.startScroll(int startX,int startY,int dX,int dY);
    scroller.startScroll(int startX,int startY,int dX,int dY,int duration);```
    前四个参数为起始坐标和偏移量,duration则为持续时间
    在获取坐标时,通常用父布局的getScrollX()和getScrollY()来获取父视图中content的滑动到的点
    
    在这里添加ACTION_UP事件,演示:
    代码如下
    

    public class DragView extends ImageView {
    private Scroller scroller;
    private int lastX,lastY;
    public DragView(Context context) {
    super(context);
    }

    public DragView(Context context, AttributeSet attrs) {
        super(context, attrs);
        scroller=new Scroller(context);
    }
    
    public DragView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @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;
                ((View)getParent()).scrollBy(-offsetX,-offsetY);
                break;
            case MotionEvent.ACTION_UP:
                View viewGroup= (View) getParent();
                scroller.startScroll(viewGroup.getScrollX(),
                                              viewGroup.getScrollY(),
                                              -viewGroup.getScrollX(),
                                              -viewGroup.getScrollY(),1000);//返回原来的位置
                //通过重绘不断调用computeScroll
                invalidate();
        }
        return true;
    }
    @Override
    public void computeScroll() {
        super.computeScroll();
        //判断Scroller是否执行完毕
        if(scroller.computeScrollOffset()){
            ((View)getParent()).scrollTo(scroller.getCurrX(),scroller.getCurrY());
            //通过重绘不断调用computeScroll
            invalidate();
        }
    }
    

    }```
    效果图如下

    scroller.gif

    相关文章

      网友评论

          本文标题:Scroll效果的几种实现办法

          本文链接:https://www.haomeiwen.com/subject/icbmyttx.html