Android開(kāi)發(fā)之模仿微信打開(kāi)網(wǎng)頁(yè)的進(jìn)度條效果(高仿)
一,為什么說(shuō)是真正的高仿?
闡述這個(gè)問(wèn)題前,先說(shuō)下之前網(wǎng)上的,各位可以復(fù)制這段字,去百度一下 "仿微信打開(kāi)網(wǎng)頁(yè)的進(jìn)度條效果" ,你會(huì)看到有很多類似的文章,不過(guò)他們有個(gè)共同點(diǎn),就是實(shí)現(xiàn)方法都是一樣的,而且,都忽略了微信加載網(wǎng)頁(yè)時(shí),進(jìn)度條的緩慢動(dòng)畫(huà)效果,它不是生硬地一滑而過(guò),而是用戶體驗(yàn)很好,有個(gè)速度的變化,由慢到快的效果,語(yǔ)言難于描述,相信各位都有下載微信,可以隨便打開(kāi)個(gè)公眾號(hào)的文章看看效果。
好了,上面說(shuō)到,之前網(wǎng)上的方法都是都忽略了微信加載網(wǎng)頁(yè)時(shí),進(jìn)度條的緩慢動(dòng)畫(huà)效果,實(shí)現(xiàn)代碼也是千篇一律,如下:
/** 先實(shí)例化個(gè)進(jìn)度條 */ ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.ProgressBar); /** 再實(shí)例化個(gè) webView */ WebView webView = (WebView) findViewById(R.id.webview); /** 然后就直接在 webClient 回調(diào)函數(shù)里面set 進(jìn)度,這樣的做法是生硬的效果 */ webView.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); mProgressBar.setProgress(newProgress); } }); /** 其他是顏色樣式等,不是重點(diǎn) */ .....
我以為是 ProgressBar 控件可能自身提供了動(dòng)畫(huà)的 API,可惜,沒(méi)有,故自己動(dòng)手寫(xiě)了這個(gè),你如果找到了,告訴下我。
二,為什么要搞緩慢效果?
對(duì),為什么要這么麻煩,你如果要搞個(gè)網(wǎng)頁(yè)加載進(jìn)度條,上面的代碼不過(guò) 10 行,妥妥地實(shí)現(xiàn)了。因?yàn)橛脩趔w驗(yàn),我不是產(chǎn)品經(jīng)理,我是個(gè)程序員,而且這個(gè)效果也不是有誰(shuí)叫我這樣去做的,我就是看著別扭,微信的成功,我相信不僅僅是個(gè)朋友圈那么簡(jiǎn)單!
程序員應(yīng)該具備注重用戶體驗(yàn)的想法。
三,我的實(shí)現(xiàn)思路
方法很多,這話我說(shuō)在前面,我的這種肯定不是最好的,但不失一用或改進(jìn)。
主要是通過(guò)改變 view 的 LayoutParam 來(lái)實(shí)現(xiàn)有不同速度的移動(dòng)效果,在每一次的進(jìn)度段,例如第一次0~24,第二次24~56,這就是兩個(gè)進(jìn)度段,這兩個(gè)進(jìn)度段,具有不同的速度,這個(gè)需要計(jì)算出來(lái),先根據(jù)手機(jī)屏幕寬度和 0~100 的進(jìn)度數(shù)值來(lái)等比計(jì)算出實(shí)際的寬度,再計(jì)算出移動(dòng)的速度,計(jì)算出來(lái)每個(gè)進(jìn)度段的數(shù)據(jù)后,講它們放進(jìn)一個(gè)列表容器里面,然后通過(guò)一個(gè) handler 來(lái)循環(huán)提取同期數(shù)據(jù),不斷地發(fā)消息,不停地 setLayoutParam。在達(dá)到 100 后,就證明加載完畢。
在這個(gè)過(guò)程需要處理計(jì)算的誤差,例如第一個(gè)加載 20,第二次24,24-20 = 4,4/100,程序里面是 0 ,如果計(jì)算速度的話,就會(huì)差生0,所以要稍微加個(gè) if 判斷。
四,代碼,內(nèi)涵注釋
核心類:
package com.slowlyprogressbar; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.widget.RelativeLayout; import java.util.ArrayList; import java.util.List; /** * Created by 林冠宏 on 2016/7/11. * * 真正的仿微信網(wǎng)頁(yè)打開(kāi)的進(jìn)度條 * * 下面的所有屬性都可以自己采用 get set 來(lái)自定義 * */ public class SlowlyProgressBar { private static final int StartAnimation = 0x12; private Handler handler; private View view; /** 當(dāng)前的位移距離和速度 */ private int thisWidth = 0; private int thisSpeed = 0; private int progress = 0; /** 當(dāng)前的進(jìn)度長(zhǎng)度 */ private int record = 0; /** 移動(dòng)單位 */ private int width = 10; /** 10dp each time */ private int height = 3; /** 3dp */ private boolean isStart = false; private int phoneWidth = 0; /** 屏幕寬度 */ private int i = 0; /** 每次的移動(dòng)記錄容器,位移對(duì)應(yīng)每幀時(shí)間 */ private List<Integer> progressQuery = new ArrayList<>(); private List<Integer> speedQuery = new ArrayList<>(); public SlowlyProgressBar(View view, int phoneWidth) { initHandler(); this.phoneWidth = phoneWidth; this.view = view; } /** 善后工作,釋放引用的持有,方能 gc 生效 */ public void destroy(){ if(progressQuery!=null){ progressQuery.clear(); progressQuery = null; } if(speedQuery!=null){ speedQuery.clear(); speedQuery = null; } view = null; handler.removeCallbacksAndMessages(null); handler = null; } public void setProgress(int progress){ if(progress>100 || progress <= 0){ /** 不能超過(guò)100 */ return; } /** 每次傳入的 width 應(yīng)該是包含之前的數(shù)值,所以下面要減去 */ /** 下面記得轉(zhuǎn)化比例,公式 (屏幕寬度 * progress / 100) */ this.width = (progress * phoneWidth)/100; /** lp.width 總是獲取前一次的 大小 */ /** 移動(dòng) 100px 時(shí)的速度一次倍率 是 2 */ int size = progressQuery.size(); if(size != 0){ size = progressQuery.get(size-1); } Log.d("zzzzz","width - size = "+(width - size)); /** 計(jì)算倍率,2/100 = x/width */ int distance = width - size; int speedTime; if(distance<=100){ speedTime = 2; }else{ speedTime = (int) ((2 * distance)/100.0); } /** 添加 */ progressQuery.add(this.width); speedQuery.add(speedTime); /** 開(kāi)始 */ if(!isStart){ isStart = true; handler.sendEmptyMessage(StartAnimation); } } public SlowlyProgressBar setViewHeight(int height){ this.height = height; return this; } private void initHandler(){ handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what){ case StartAnimation: /** 提取隊(duì)列信息 */ if(progress >= thisWidth){ /** 如果已經(jīng)跑完,那么移出 */ if(progressQuery.size() == i){ Log.d("zzzzz","break"); if(progress >= 100){ /** 全部走完,隱藏進(jìn)度條 */ view.setVisibility(View.INVISIBLE); } isStart = false; break; } Log.d("zzzzz", "size is " + progressQuery.size()); thisWidth = progressQuery.get(i); thisSpeed = speedQuery.get(i); i ++; } move(thisSpeed,view.getLayoutParams().width); Log.d("zzzzz", "send 100 "+thisSpeed); /** 發(fā)信息的延時(shí)長(zhǎng)度并不會(huì)影響速度 */ handler.sendEmptyMessageDelayed(StartAnimation,1); break; } } }; } /** 移動(dòng) */ private void move(int speedTime,int lastWidth){ if(speedTime > 9){ speedTime = 9; /** 控制最大倍率 */ } /** 乘 3 是糾正誤差 */ progress = (record * speedTime); /** 糾正 */ if(progress >= lastWidth){ view.setLayoutParams(new RelativeLayout.LayoutParams(progress,height*3)); }else{ Log.d("zzzzz","hit "+progress+"---"+lastWidth); } record ++; } }
五,使用方法與截圖
超簡(jiǎn)單引入,view 可以是隨便一個(gè),例如 TextView,給它一個(gè) background 就行了,就有顏色了。
public class MainActivity extends AppCompatActivity { private SlowlyProgressBar slowlyProgressBar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); slowlyProgressBar = new SlowlyProgressBar ( findViewById(R.id.p), getWindowManager().getDefaultDisplay().getWidth() ) .setViewHeight(3); WebView webView = (WebView) findViewById(R.id.webview); webView.setWebChromeClient(new WebChromeClient(){ @Override public void onProgressChanged(WebView view, int newProgress) { super.onProgressChanged(view, newProgress); slowlyProgressBar.setProgress(newProgress); } }); webView.loadUrl("http://www.cnblogs.com/linguanh"); } @Override public void finish() { super.finish(); if(slowlyProgressBar!=null){ slowlyProgressBar.destroy(); slowlyProgressBar = null; } } }
以上所述是小編給大家介紹的Android開(kāi)發(fā)之模仿微信打開(kāi)網(wǎng)頁(yè)的進(jìn)度條效果(高仿),如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android學(xué)習(xí)筆記——Menu介紹(二)
這次將繼續(xù)上一篇文章沒(méi)有講完的Menu的學(xué)習(xí),上下文菜單(Context menu)和彈出菜單(Popup menu)2014-10-10Android實(shí)現(xiàn)加載時(shí)提示“正在加載,請(qǐng)稍后”的方法
在現(xiàn)在的很多應(yīng)用中,當(dāng)在加載的時(shí)候,如果頁(yè)面動(dòng)態(tài)數(shù)據(jù)較多,會(huì)有很長(zhǎng)一段時(shí)間的空白頁(yè)面,如果加上這個(gè)頁(yè)面正在加載的提示,使得應(yīng)用更加人性化。這篇文章就給大家分享了在 Android實(shí)現(xiàn)加載時(shí)提示“正在加載,請(qǐng)稍后”的方法,有需要的朋友們可以參考借鑒。2016-10-10android RecyclerView實(shí)現(xiàn)條目Item拖拽排序與滑動(dòng)刪除
本篇文章主要介紹了android RecyclerView實(shí)現(xiàn)條目Item拖拽排序與滑動(dòng)刪除,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。2017-03-03如何在Android Studio下進(jìn)行NDK開(kāi)發(fā)
這篇文章主要介紹了如何在Android Studio下進(jìn)行NDK開(kāi)發(fā),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-05-05Android內(nèi)容提供者ContentProvider用法實(shí)例分析
這篇文章主要介紹了Android內(nèi)容提供者ContentProvider用法,結(jié)合實(shí)例形式較為詳細(xì)的分析了內(nèi)容提供者ContentProvider獲取及解析數(shù)據(jù)的相關(guān)技巧,需要的朋友可以參考下2016-03-03詳解Android獲得系統(tǒng)GPU參數(shù) gl.glGetString
這篇文章主要介紹了詳解Android獲得系統(tǒng)GPU參數(shù) gl.glGetString的相關(guān)資料,需要的朋友可以參考下2017-07-07Android實(shí)現(xiàn)知乎選項(xiàng)卡動(dòng)態(tài)隱藏效果實(shí)例
選項(xiàng)卡相信對(duì)大家來(lái)說(shuō)應(yīng)該不陌生,最近發(fā)現(xiàn)知乎選項(xiàng)卡的動(dòng)態(tài)隱藏效果不錯(cuò),下面這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)知乎選項(xiàng)卡動(dòng)態(tài)隱藏效果的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02Android獲得所有存儲(chǔ)設(shè)備位置的最佳方法
今天小編就為大家分享一篇Android獲得所有存儲(chǔ)設(shè)備位置的最佳方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-08-08Android自定義ViewGroup實(shí)現(xiàn)標(biāo)簽浮動(dòng)效果
這篇文章主要為大家詳細(xì)介紹了Android自定義ViewGroup實(shí)現(xiàn)標(biāo)簽浮動(dòng)效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-06-06