android開(kāi)發(fā)教程之使用線程實(shí)現(xiàn)視圖平滑滾動(dòng)示例
最近一直想做下拉刷新的效果,琢磨了好久,才走到通過(guò)onTouch方法把整個(gè)視圖往下拉的步驟,接下來(lái)就是能拉下來(lái),松開(kāi)手要能滑回去啊。網(wǎng)上看了好久,沒(méi)有找到詳細(xì)的下拉刷新的例子,只有自己慢慢琢磨了。昨天和今天,研究了兩天,下拉之后回滾回去的效果終于今天做出來(lái)了!開(kāi)心?,F(xiàn)在來(lái)分享下我的實(shí)現(xiàn)方法和一些心得體會(huì)吧。
我看了網(wǎng)上一個(gè)大神的例子,發(fā)現(xiàn)是在onTouch里面使用View的scrollTo(int, int)方法,來(lái)使整個(gè)視圖往下滾動(dòng)的,我嘗試了使用setTranslationY()來(lái)對(duì)視圖進(jìn)行回滾,第一次是沒(méi)問(wèn)題的,但多滾動(dòng)幾次之后,整個(gè)視圖實(shí)際上已經(jīng)到了非?!案摺钡牡胤搅?,要拉很長(zhǎng)的距離才能看到內(nèi)容。所以回滾也必須使用scrollTo(int, int)方法來(lái)操作。
但scrollTo(int, int)執(zhí)行是瞬間的,方法名講是滾動(dòng)到,實(shí)際上就是“瞬移到”某個(gè)位置,因此需要一步一步的去瞬移它,讓它看上去是滾過(guò)去的……
因?yàn)榈认乱ヅ懿搅耍€有就是也沒(méi)有什么很多的要點(diǎn)需要講解,我就直接上代碼給大家看,注釋都寫(xiě)好了,要點(diǎn)會(huì)單獨(dú)提一下,更詳細(xì)的講解與心得就等著我哪天把下拉刷新實(shí)現(xiàn)了吧。
/**
* @desc 平滑滾動(dòng)
* @param v 需要操控的視圖
* @param fromY 起始Y坐標(biāo)
* @param toY 終止Y坐標(biāo)
* @param fps 幀率
* @param durtion 動(dòng)畫(huà)完成時(shí)間(毫秒)
* */
private void smoothScroll(View v, int fromY, int toY, int fps, long durtion) {
smoothScrollThread = new SmoothScrollThread(v, fromY, toY, durtion, fps);
smoothScrollThread.run();
}
/**
* @desc 平滑滾動(dòng)線程,用于遞歸調(diào)用自己來(lái)實(shí)現(xiàn)某個(gè)視圖的平滑滾動(dòng)
* */
class SmoothScrollThread implements Runnable {
//需要操控的視圖
private View v = null;
//原Y坐標(biāo)
private int fromY = 0;
//目標(biāo)Y坐標(biāo)
private int toY = 0;
//動(dòng)畫(huà)執(zhí)行時(shí)間(毫秒)
private long durtion = 0;
//幀率
private int fps = 60;
//間隔時(shí)間(毫秒),間隔時(shí)間 = 1000 / 幀率
private int interval = 0;
//啟動(dòng)時(shí)間,-1 表示尚未啟動(dòng)
private long startTime = -1;
/減速插值器
private DecelerateInterpolator decelerateInterpolator = null;
/**
* @desc 構(gòu)造方法,做好第一次配置
* */
public SmoothScrollThread(View v, int fromY, int toY, long durtion, int fps) {
this.v = v;
this.fromY = fromY;
this.toY = toY;
this.durtion = durtion;
this.fps = fps;
this.interval = 1000 / this.fps;
decelerateInterpolator = new DecelerateInterpolator();
}
@Override
public void run() {
//先判斷是否是第一次啟動(dòng),是第一次啟動(dòng)就記錄下啟動(dòng)的時(shí)間戳,該值僅此一次賦值
if (startTime == -1) {
startTime = System.currentTimeMillis();
}
//得到當(dāng)前這個(gè)瞬間的時(shí)間戳
long currentTime = System.currentTimeMillis();
//放大倍數(shù),為了擴(kuò)大除法計(jì)算的浮點(diǎn)精度
int enlargement = 1000;
//算出當(dāng)前這個(gè)瞬間運(yùn)行到整個(gè)動(dòng)畫(huà)時(shí)間的百分之多少
float rate = (currentTime - startTime) * enlargement / durtion;
//這個(gè)比率不可能在 0 - 1 之間,放大了之后即是 0 - 1000 之間
rate = Math.min(rate, 1000);
//將動(dòng)畫(huà)的進(jìn)度通過(guò)插值器得出響應(yīng)的比率,乘以起始與目標(biāo)坐標(biāo)得出當(dāng)前這個(gè)瞬間,視圖應(yīng)該滾動(dòng)的距離。
int changeDistance = (int) ((fromY - toY) * decelerateInterpolator.getInterpolation(rate / enlargement));
int currentY = fromY - changeDistance;
v.scrollTo(0, currentY);
if (currentY != toY) {
postDelayed(this, this.interval);
} else {
return;
}
}
public void stop() {
removeCallbacks(this);
}
}
一些要點(diǎn):
1.使用線程的目的是可以遞歸的調(diào)用自己,在每個(gè)run()方法里只滾動(dòng)一點(diǎn)點(diǎn),這個(gè)一點(diǎn)點(diǎn)根據(jù)幀率和插值器來(lái)決定。
2.插值器實(shí)際上就是一個(gè)函數(shù)(數(shù)學(xué)里的函數(shù)),輸入0-1之間的浮點(diǎn)數(shù),輸出0-1之間的浮點(diǎn)數(shù),輸出的曲線是什么樣的,就看是什么插值器了,decelerate就是減速插值器了,在平面直角坐標(biāo)系里面,x值均勻變化,y軸的變化越來(lái)越慢。
3.放大倍數(shù)(就是那里乘以1000)是為了提高精度,因?yàn)橥ㄟ^(guò)實(shí)踐發(fā)現(xiàn)用已經(jīng)過(guò)的毫秒數(shù)除以整個(gè)動(dòng)畫(huà)周期得出的結(jié)果是0.0 -> 0.0 -> 0.0 -> 0.0 -> 1.0 -> 1.0 -> 1.0 -> 1.0 -> 1.0 -> 2.0 -> 2.0 -> 2.0,雖然是浮點(diǎn)數(shù),但精度卻莫名的保持在個(gè)位數(shù)上,乘以1000后,便會(huì)出現(xiàn)0-1000的均勻變化,這個(gè)時(shí)候去除以1000,便可得到0.000 - 1.000之間的均勻變化的數(shù)。
4.還有個(gè)很奇葩的是MotionEvent.getY()的值和scrollTo(int,int)的值貌似不是在同一個(gè)坐標(biāo)系里面的。這個(gè)還有待進(jìn)一步的分析和研究啊。
相關(guān)文章
Android中捕獲TTextView文本中的鏈接點(diǎn)擊事件方法
這篇文章主要介紹了Android中捕獲TTextView文本中的鏈接點(diǎn)擊事件方法,本文給出了實(shí)現(xiàn)代碼和使用方法以及實(shí)現(xiàn)自己控制的方法,需要的朋友可以參考下2015-01-01
Android實(shí)現(xiàn)截圖分享qq 微信功能
在日常生活中,經(jīng)常用到qq,微信截圖分享功能,今天小編通過(guò)本文給大家介紹Android實(shí)現(xiàn)截圖分享qq 微信功能,具體實(shí)現(xiàn)代碼大家參考下本文2017-12-12
詳解Android開(kāi)發(fā)數(shù)據(jù)持久化之文件存儲(chǔ)(附源碼)
本篇文章主要介紹了詳解Android開(kāi)發(fā)數(shù)據(jù)持久化之文件存儲(chǔ)(附源碼),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03
Android實(shí)現(xiàn)多點(diǎn)觸控,自由縮放圖片的實(shí)例代碼
本篇文章主要介紹了Android實(shí)現(xiàn)多點(diǎn)觸控,自由縮放圖片的實(shí)例代碼,可以自由地對(duì)圖片進(jìn)行縮放和移動(dòng),非常具有實(shí)用價(jià)值,需要的朋友可以參考下。2016-12-12
Android四種數(shù)據(jù)存儲(chǔ)的應(yīng)用方式
這篇文章主要介紹了Android四種數(shù)據(jù)存儲(chǔ)的應(yīng)用方式的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家理解掌握Android存儲(chǔ)數(shù)據(jù)的方法,需要的朋友可以參考下2017-10-10
Android開(kāi)發(fā)實(shí)現(xiàn)ImageView加載攝像頭拍攝的大圖功能
這篇文章主要介紹了Android開(kāi)發(fā)實(shí)現(xiàn)ImageView加載攝像頭拍攝的大圖功能,涉及Android基于ImageView的攝像頭拍攝圖片加載、保存及權(quán)限控制等相關(guān)操作技巧,需要的朋友可以參考下2017-11-11

