View的滑动
Scroller 弹性滑动对象,用来实现View的弹性滑动。首先看scrollto跟scrollby
/**
* Set the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the x position to scroll to
* @param y the y position to scroll to
*/
public void scrollTo(int x, int y) { //绝对滑动
if (mScrollX != x || mScrollY != y) {
int oldX = mScrollX;
int oldY = mScrollY;
mScrollX = x;
mScrollY = y;
invalidateParentCaches();
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
if (!awakenScrollBars()) {
postInvalidateOnAnimation();
}
}
}
/**
* Move the scrolled position of your view. This will cause a call to
* {@link #onScrollChanged(int, int, int, int)} and the view will be
* invalidated.
* @param x the amount of pixels to scroll by horizontally
* @param y the amount of pixels to scroll by vertically
*/
public void scrollBy(int x, int y) { //当前位置相对滑动
scrollTo(mScrollX + x, mScrollY + y);
}
手指向左,也就是由右向左滑 显示右边的内容,mScrollX等于view左边缘与内容左边缘的距离,mScrollX>0;
手指向上,也就是有下往上滑 显示下边的内容,mScrollY等于view上边缘与内容上边缘的举例mScrollY>0
Scroller原理:
Scroller需要和View的computeScroll()方法一起使用才能实现弹性滑动。scroller.startScroll(int startX,int startY,int dx,int dy,int duration);中的参数是滑动的起点坐标,dx,dy 是水平和竖直方向上的滑动距离,duration是完成滑动需要的时间。调用startScroll(),滑动还没有开始。startScroll()之后的invalidate()将使View重绘,在View重绘的时候会调用computeScroll()方法,在此方法中调用scroller.computeScrollOffset()判断如果滑动未结束使用scrollTo(),来滑动View,scrollTo()之后再调用invalidate()重新绘制View,在View重绘的时候会又调用computeScroll()方法,如此循环直至滑动结束。多次的小幅度滑动组成了弹性滑动
#1 mScroller.startScroll(...)
#2 invalidate() 请求重绘
#3 view的draw中调用computeScroll,需要重写此方法
@Override
public void computeScroll() {
if(scroller.computeScrollOffset()){ #4 判断是否滑动结束,未结束继续
scrollTo(scroller.getCurrX(),scroller.getCurrY()); #5 获取scroller当前scrollX和scrollY 然后滑动
//重绘
postInvalidate(); #6 再次请求重绘 又去跳转到#3
}
}
另外scroller还有fling 惯性滑动
给定一个初始速度(velocityX,velocityY),该方法内部会根据这个速度去计算需要滑动的距离以及需要耗费的时间。通常用于:界面的惯性滑动等
/**
* Start scrolling based on a fling gesture. The distance travelled will
* depend on the initial velocity of the fling.
*
* @param startX Starting point of the scroll (X)
* @param startY Starting point of the scroll (Y)
* @param velocityX Initial velocity of the fling (X) measured in pixels per
* second.
* @param velocityY Initial velocity of the fling (Y) measured in pixels per
* second
* @param minX Minimum X value. The scroller will not scroll past this
* point.
* @param maxX Maximum X value. The scroller will not scroll past this
* point.
* @param minY Minimum Y value. The scroller will not scroll past this
* point.
* @param maxY Maximum Y value. The scroller will not scroll past this
* point.
*/
public void fling(int startX, int startY, int velocityX, int velocityY,
int minX, int maxX, int minY, int maxY)
使用步骤与startscroll类似, 除了上述的操作外,我们需要在处理ACTION_DOWN事件时,对屏幕当前状态进行判断,如果屏幕现在正在滚动(用户刚进行了Fling手势),我们需要停止屏幕滚动。
case MotionEvent.ACTION_DOWN:
...
if (!mScroller.isFinished()) { //fling
mScroller.abortAnimation();
}
break;
OverScroll越界回弹
升级版的scroller,可以实现越界回弹的效果
Android Scroll详解(二):OverScroller实战
ViewDragHelper
主要用于处理ViewGroup中对子View的拖拽处理,封装了对View的触摸位置,触摸速度,移动距离等的检测和Scroller,通过接口回调的方式通知我们。所以我们需要做的只是用接收来的数据指定这些子View是否需要移动,移动多少等
三个状态
STATE_IDLE:空闲
STATE_DRAGGING:正在拖拽
STATE_SETTLING:拖拽结束,放置View
其他
判断能否向上滑动
public static boolean defaultCanScrollUp(View view) {
if (view == null) {
return false;
}
if (android.os.Build.VERSION.SDK_INT < 14) {
if (view instanceof AbsListView) {
final AbsListView absListView = (AbsListView) view;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return ViewCompat.canScrollVertically(view, -1) || view.getScrollY() > 0;
}
} else {
return ViewCompat.canScrollVertically(view, -1);
}
}
--------------------------------------------------------------------------------------------------------
canScrollVertically的参数含义
/**
* Check if this view can be scrolled vertically in a certain direction.
*
* @param v The View against which to invoke the method.
* @param direction Negative to check scrolling up, positive to check scrolling down.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
public static boolean canScrollVertically(View v, int direction) {
return IMPL.canScrollVertically(v, direction);
}
网友评论