一、
one。 通过改变view 在父空间的layout位置来移动, 但是只能移动指定的view:
view.layout(l,t,r,b);
view.offsetLeftAndRight(offset);
view.offsetTopAndBottom(offset);
two。通过改变scrollX 和 scrollY 来移动, 但是 可以移动所有的子view
scrollTo(x,y); x,y 将要滚动到的位置
scrollBy(xOffset,yOffset); 滚动的偏移量
three。通过改变canvas 绘制的位置来移动view 的内容(不常用)
canvas.drawBitmap(bitmap,l,t,paint);
二、使用ViewDragHelper来处理移动
one。ViewDragHelper 在 support v4中 如要导入v4包
two。主要用于处理ViewGroup中对子View的拖拽处理
three。在Google2013年大会中提出
four。主要封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,
five。本质是对触摸事件的解析类
通过接口回调的方式告诉我们;只需要我们指定是否需要移动,移动多少等。
use:forParent 父View sensitivity 敏感度 默认为1.0f cb 回调接口
ViewDragHelper mViewDragHelper=ViewDragHelper.create(
ViewGroup forParent, float sensitivity, Callback cb
)
如果使用ViewDragHelper 需要重写两个事件
// 拦截触摸事件 @Override public boolean onInterceptTouchEvent(MotionEvent ev) { return mViewDragHelper.shouldInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { // 处理拖拽事件 mViewDragHelper.processTouchEvent(event); return true; }
/** * 回调 */ private class MyCallBack extends ViewDragHelper.Callback { /** * * 用于判断是否捕捉当前 child 的触摸事件 * * @param child 当前触摸的子View * @param pointerId 尝试捕获id 的 指针 * @return true 捕获别切 解析 false 不处理 */ @Override public boolean tryCaptureView(View child, int pointerId) { return child == redView || child == blueView; } /** * 当view 被开始捕获和解析的回调 用处不太大 * * @param capturedChild 当前被捕获的子View * @param activePointerId */ @Override public void onViewCaptured(View capturedChild, int activePointerId) { super.onViewCaptured(capturedChild, activePointerId); } /** * 获取view 水平方向的拖范围 但是目前不能限制边界, * 在 clampViewPositionHorizontal 计算实现 * 返回的值用在手指抬起的时候,view缓慢移动的动画的时间计算上面 * * @param child * @return 最好不要返回 0 */ @Override public int getViewHorizontalDragRange(View child) { return getMeasuredWidth() - child.getMeasuredWidth(); } /** * 获取view 垂直方向的拖范围 但是目前不能限制边界, * 在 clampViewPositionVertical 计算实现 * 返回的值用在手指抬起的时候,view缓慢移动的动画的时间计算上面 * * @param child * @return 最好不要返回 0 */ @Override public int getViewVerticalDragRange(View child) { return getMeasuredHeight() - child.getMeasuredHeight(); } /** * 控制child在 水平方向的移动 clamp ->修正 * * @param child * @param left 表示ViewDragHelper 认为你想让当前child的left改变的值 * left=child.getLeft() + dx; * @param dx 相对于 控件移动前,水平移动的距离 * 负数为向左边移动正数为向右边移动 * @return 表示真正你想让child的left 改变成的值 */ @Override public int clampViewPositionHorizontal(View child, int left, int dx) { // 如果不想让view 水平移动 return left - dx 或者 child.getLeft(); return left; } /** * 控制child在 垂直方向的移动 clamp ->修正 * * @param child * @param top 表示ViewDragHelper 认为你想让当前child的top改变的值 * top=child.getTop() + dy; * @param dy 相对于 控件移动前,水平移动的距离 * 负数为向左边移动正数为向右边移动 * @return 表示你真正想让child的top 改变成的值 */ @Override public int clampViewPositionVertical(View child, int top, int dy) { return top; } /** * 当child 位置改变的时候执行 一般用来做其它子view 的伴随移动 * * @param changedView 位置改变的 child * @param left child 当前最新的left * @param top child 当前最新的top * @param dx 本次水平移动的距离 因为每一次滑动都不一样 * @param dy 本次垂直移动的距离 为每一次滑动都不一样 */ @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { } /** * 当手指抬起的时候会执行这个方法 * * @param releasedChild 当前抬起的view * @param xvel x方向移动的速度 正 向右移动 负数 向左移动 * @param yvel y方向移动的速度 正 向右移动 负数 向左移动 */ @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); if (releasedChild.getLeft() > getMeasuredWidth() / 2 - releasedChild.getMeasuredWidth() / 2) { // 在右边 向右边缓慢移动 移动 view 到右边 mViewDragHelper.smoothSlideViewTo(releasedChild, getMeasuredWidth() - releasedChild.getMeasuredWidth(), releasedChild.getTop()); ViewCompat.postInvalidateOnAnimation(DragLayout.this); } else { // 在左边 向左边缓慢移动 mViewDragHelper.smoothSlideViewTo(releasedChild, 0, releasedChild.getTop()); ViewCompat.postInvalidateOnAnimation(DragLayout.this); } } } /** * 计算滚动 配合 mViewDragHelper.smoothSlideViewTo(releasedChild, 0, releasedChild.getTop()); * 一直刷新界面 */ @Override public void computeScroll() { // 如果继续移动 刷新界面 if (mViewDragHelper.continueSettling(true)) { ViewCompat.postInvalidateOnAnimation(DragLayout.this); } }