滾動(dòng)的基礎(chǔ)
任何一個(gè)控件都可以通過View類當(dāng)中的scrollTo()和scrollBy()這兩個(gè)方法實(shí)現(xiàn)滾動(dòng)棚唆。
scrollTo:滾動(dòng)的基礎(chǔ)乒裆。
/**
* 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
*/
//視圖滾動(dòng)到的位置
public void scrollTo(int x, int y) {
// 判斷x和y軸是否發(fā)生滾動(dòng)
if (mScrollX != x || mScrollY != y) {
// 記錄起始x軸位置
int oldX = mScrollX;
// 記錄起始y軸位置
int oldY = mScrollY;
// 要滾動(dòng)到的x軸位置
mScrollX = x;
// 要滾動(dòng)到的y軸位置
mScrollY = y;
// 強(qiáng)制清空父View緩存袖迎,并不會(huì)調(diào)用invalidate()
invalidateParentCaches();
// 調(diào)用此放法位置發(fā)生變化
onScrollChanged(mScrollX, mScrollY, oldX, oldY);
// 判斷滾動(dòng)動(dòng)畫是否啟動(dòng)鸽心,是true聊闯,否false
// 如果動(dòng)畫啟動(dòng)會(huì)調(diào)用invalidate()
if (!awakenScrollBars()) {
// 動(dòng)畫發(fā)生無效
postInvalidateOnAnimation();
}
}
}
scrollBy:網(wǎng)上有一句話叫做萬物基于MIUI布疼,通過scrollBy中的scrollTo可以看到Android所有滾動(dòng)基于scrollTo摊趾。
/**
* 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);
}
Scroller是什么?
Scroller是一個(gè)專門用于處理滾動(dòng)效果的工具類游两,ViewPager砾层、ListView等控件在內(nèi)部都是使用Scroller來實(shí)現(xiàn)的,下面有一段來自官方的介紹...
This class encapsulates scrolling. You can use scrollers ({@link Scroller}or {@link OverScroller}) to collect the data you need to produce a scrolling animation—for example, in response to a fling gesture. Scrollers track scroll offsets for you over time, but they don't automatically apply those positions to your view. It's your responsibility to get and apply new coordinates at a rate that will make the scrolling animation look smooth.
使用案例
官方案例
private Scroller mScroller = new Scroller(context);
...
public void zoomIn() {
// 還原正在進(jìn)行的任何動(dòng)畫
mScroller.forceFinished(true);
// 提供X和Y軸的起點(diǎn)和滑動(dòng)距離開始滾動(dòng)
// startScroll有一個(gè)5個(gè)參數(shù)的重載方法贱案,最后一個(gè)參數(shù)是滾動(dòng)持續(xù)時(shí)間
mScroller.startScroll(0, 0, 100, 0);
// 請(qǐng)求重繪
invalidate();
}
基本用法
private Scroller mScroller = new Scroller(mContext);
private void smoothScroll(int destX, int destY) {
// 獲取當(dāng)前x軸位置
int scrollX = getScrollX();
// 計(jì)算x軸相對(duì)于當(dāng)前位置發(fā)生的偏移量
int deltaX = destX - scrollX;
// 發(fā)生滾動(dòng)肛炮,x軸從當(dāng)前位置滾動(dòng)的位移量為deltaX
mScroller.startScroll(scrollX, 0, deltaX, 0, 500);
// 強(qiáng)制重繪
invalidate();
}
@Override
public void computeScroll() {
super.computeScroll();
// 滑動(dòng)是否終止
if (mScroller.computeScrollOffset()) {
// 重置x和y軸位置
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
// 強(qiáng)制重繪
invalidate();
}
}
computeScroll:準(zhǔn)備滑動(dòng)在View中是空實(shí)現(xiàn),需要我們自己去重寫這個(gè)方法重置x和y坐標(biāo)
/**
* Called by a parent to request that a child update its values for mScrollX
* and mScrollY if necessary. This will typically be done if the child is
* animating a scroll using a {@link android.widget.Scroller Scroller}
* object.
*/
public void computeScroll() {
}
當(dāng)我們要跟蹤X/y軸偏移量時(shí)
To track the changing positions of the x/y coordinates, use
{@link #computeScrollOffset}. The method returns a boolean to indicate
whether the scroller is finished. If it isn't, it means that a fling or
programmatic pan operation is still in progress. You can use this method to
find the current offsets of the x and y coordinates, for example:
// 判斷滾動(dòng)是否完成宝踪,完成返回true
if (mScroller.computeScrollOffset()) {
// 獲取當(dāng)前的X坐標(biāo)
int currX = mScroller.getCurrX();
// 獲取當(dāng)前的Y坐標(biāo)
int currY = mScroller.getCurrY();
...
}