自定义View的5中滑动方式

来源:互联网 发布:郑州中大门网络 编辑:程序博客网 时间:2024/06/05 22:44

自定义View的5中滑动方式分别是:

   layout()

    offsetLeftAndRight() 和 offsetTopAndBottom()

   LayoutParams

   动画

  scollTo与scollBy和Scroller

 这5中方式基本在项目中已经够用了。


第一种  layout()

  Layout is a two pass process: a measure pass and a layout pass. The measuring pass is implemented in measure(int, int) and is a top-down traversal of the view tree. Each view pushes dimension specifications down the tree during the recursion. At the end of the measure pass, every view has stored its measurements. The second pass happens in layout(int, int, int, int) and is also top-down. During this pass each parent is responsible for positioning all of its children using the sizes computed in the measure pass

文档中对layout的定义

效果图:


-----------------------------------代码----------------------------------------------------

 @Override    public boolean onTouchEvent(MotionEvent event) {        x =  event.getX();        y = event.getY();        if (event.getAction()==MotionEvent.ACTION_DOWN){            lastX=x;            lastY=y;        }else if (event.getAction()==MotionEvent.ACTION_MOVE){            int offsetX = (int) (x - lastX);            int offsetY = (int) (y - lastY);            layout(getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY);        }        return true;    }

第二种:offsetLeftAndRight() 和  offsetTopAndBottom()

void offsetLeftAndRight (int offset)
Offset this view's horizontal location by the specified amount of pixels.
void offsetTopAndBottom (int offset)

Offset this view's vertical location by the specified number of pixels


代码:

    @Override    public boolean onTouchEvent(MotionEvent event) {        x =  event.getX();        y = event.getY();        if (event.getAction()==MotionEvent.ACTION_DOWN){            lastX=x;            lastY=y;        }else if (event.getAction()==MotionEvent.ACTION_MOVE){            int offsetX = (int) (x - lastX);            int offsetY = (int) (y - lastY);            offsetLeftAndRight(offsetX);            offsetTopAndBottom(offsetY);        }        return true;    }

第三种:LayoutParams

void setLayoutParams (ViewGroup.LayoutParams params)

Set the layout parameters associated with this view. These supply parameters to the parent of this view specifying how it should be arranged. There are many subclasses of ViewGroup.LayoutParams, and these correspond to the different subclasses of ViewGroup that are responsible for arranging their children.


代码:

 @Override    public boolean onTouchEvent(MotionEvent event) {        x =  event.getX();        y = event.getY();        if (event.getAction()==MotionEvent.ACTION_DOWN){            lastX=x;            lastY=y;        }else if (event.getAction()==MotionEvent.ACTION_MOVE){            int offsetX = (int) (x - lastX);            int offsetY = (int) (y - lastY);            LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams();            layoutParams.leftMargin=getLeft()+offsetX;            layoutParams.topMargin=getTop()+offsetY;            setLayoutParams(layoutParams);        }        return true;    }

第四种:动画
   使用View的移动动画来实现,在res目录下创建anim文件夹并创建translate.xml:
    View.setAnimation(AnimationUtils.loadAnimation(this, R.anim.translate));
      这个用的不是太多 只对于动画
第五种 scollTo与scollBy
scollTo(x,y)表示移动到一个具体的坐标点,而scollBy(dx,dy)则表示移动的增量为dx、dy。其中scollBy最终也是要调用scollTo的。
scollTo、scollBy移动的是View的内容,如果在ViewGroup中使用则是移动他所有的子View。我们将ACTION_MOVE中的代码替换成如下代码:
((View)getParent()).scrollBy(-offsetX,-offsetY);
这里要实现View随着我们手指移动的效果的话,我们就需要将偏移量设置为负值。
Scroller:
我们用scollTo/scollBy方法来进行滑动时,这个过程是瞬间完成的,所以用户体验不大好。这里我们可以使用Scroller来实现有过度效果的滑动,
这个过程不是瞬间完成的,而是在一定的时间间隔完成的。Scroller本身是不能实现View的滑动的,它需要配合View的computeScroll()方法才能弹性滑动的效果。
在这里我们实现View平滑的向右移动。

首先对Scroller进行初始化

 public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        scroller = new Scroller(context);    }

接下来重写computeScrool()方法,系统在绘制View的时候onDraw()方法调用改方法,这个方法中我们调用系统的ScroolTo()方法并通过Scroller来不断获取当前的滚动值每滑动一小段距离我们就调用invalidate()方法不断的进行重绘,重绘就会调用computeScroll()方法,这样我们就通过不断的移动一个小的距离并连贯起来就实现了平滑移动的效果:

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

调用Scroller.startScroll()方法。我们在CustomView中写一个smoothScrollTo()方法,调用Scroller.startScroll()方法,在2000毫秒内沿X轴平移delta像素:

 public void smoothScrollTo(int destX,int destY){        int scrollX=getScrollX();        int scrolly = getScrollY();        int deltaX=destX-scrollX;        int deltaY=destY-scrolly;        scroller.startScroll(scrollX,scrolly,deltaX,deltaY,2000);        invalidate();    }

在onLayout 中调用

  @Override    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        smoothScrollTo(-400,-200);    }