本文最后更新于 650 天前
1. Scroller
public void fling(int startX, int startY, int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY) {}
public void startScrollBy(int dx,int dy) {
mScroller.forceFinished(true);
int startX = getScrollX();
int startY = getScrollY();
// 开启滑动
mScroller.startScroll(startX,startY,startX+dx,startY+dy,1000);
// 最终的onDraw会调用computeScroll
invalidate();
}
@Override
public void computeScroll() {
super.computeScroll();
// 不断判断是否到预定位置,并通过scrollToscrollBy进行滑动
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(),mScroller.getCurrY());
if (mScroller.getCurrX() == getScrollX()
&& mScroller.getCurrY() == getScrollY() ) {
postInvalidate();
}
}
}
2. ViewDragHelper
mDragHelper = ViewDragHelper.create(this, new ViewDragHelper.Callback() {
// 返回true才会后续的相关回调,可以根据需要对某个child执行
@Override
public boolean tryCaptureView(View child, int pointerId) {
return true;
}
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
mDragOriLeft = capturedChild.getLeft();
mDragOriTop = capturedChild.getTop();
}
// left 最终的坐标 dx 本场偏移,可以对left进行修正如:边缘检测 返回修正后的left
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return left;
}
// 同上
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return top;
}
// 结束拖拽的回调
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
// 设置位置 需要配合Scroller 或者 不用该方式 直接使用:
// mDragHelper.smoothSlideViewTo(child, getLeft(),getTop());
mDragHelper.settleCapturedViewAt((int)mDragOriLeft,(int)mDragOriLeft);
invalidate();
}
// 对于本身clickable组件需要设置 > 0才可以滑动
@Override
public int getViewHorizontalDragRange(View child) {
return 1;
}
@Override
public int getViewVerticalDragRange(View child) {
return 1;
}
//
@Override
public void onEdgeDragStarted(int edgeFlags, int pointerId) {
super.onEdgeDragStarted(edgeFlags, pointerId);
// 此处可以指定View,用于表现边缘是相对于父容器边界 而非子View,无实际意义
mDragHelper.captureChildView(getChildAt(getChildCount()-1),pointerId);
}
});
// 边缘是相对于父容器边界 而非子View
mDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL);
@Override
public void computeScroll() {
super.computeScroll();
if (mDragHelper != null && mDragHelper.continueSettling(true)) {
invalidate();
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return mDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
3. ViewConfiguration
- getScaledTouchSlop():获取触摸的最小移动距离,用于判断用户是否正在进行滑动操作。
- getDoubleTapTimeout():获取双击操作的超时时间。
- getLongPressTimeout():获取长按操作的超时时间。
- getTapTimeout():获取单击操作的超时时间。
- getHoverTapTimeout():获取悬停操作的超时时间。
- getEdgeSlop():获取触摸边界的容差距离,用于判断用户是否触摸了屏幕的边缘。
- getFadingEdgeLength():获取渐隐边缘的长度。
- getMinimumFlingVelocity():获取最小滑动速度。
- getMaximumFlingVelocity():获取最大滑动速度。
getWindowTouchSlop() 方法是 ViewConfiguration 类中的一个方法,它用于获取窗口中的触摸容差距离。这个容差距离是指当用户在屏幕上触摸时,允许手指在按下时稍微移动一定距离,而不被认为是滑动操作的距离阈值。
与 getScaledTouchSlop() 方法不同的是,getWindowTouchSlop() 方法返回的值不是一个经过缩放处理的值,而是原始的像素值。这意味着它可以用于与屏幕像素密度无关的计算。
通常情况下,可以使用 getScaledTouchSlop() 方法来获取触摸容差距离,但在某些情况下,例如在自定义绘制的视图中,开发者可能需要使用 getWindowTouchSlop() 方法来获取正确的值。
4. 其他移动方式
ViewCompat.offsetLeftAndRight(mDragView,deltaX);
ViewCompat.offsetTopAndBottom(mDragView,deltaY);
View.layout(left, top, right, bottom) 方法
View 的 translationX 和 translationY 属性