Android開發(fā)之模仿微信打開網(wǎng)頁的進(jìn)度條效果(高仿)
一,為什么說是真正的高仿?
闡述這個問題前,先說下之前網(wǎng)上的,各位可以復(fù)制這段字,去百度一下 "仿微信打開網(wǎng)頁的進(jìn)度條效果" ,你會看到有很多類似的文章,不過他們有個共同點(diǎn),就是實(shí)現(xiàn)方法都是一樣的,而且,都忽略了微信加載網(wǎng)頁時,進(jìn)度條的緩慢動畫效果,它不是生硬地一滑而過,而是用戶體驗很好,有個速度的變化,由慢到快的效果,語言難于描述,相信各位都有下載微信,可以隨便打開個公眾號的文章看看效果。
好了,上面說到,之前網(wǎng)上的方法都是都忽略了微信加載網(wǎng)頁時,進(jìn)度條的緩慢動畫效果,實(shí)現(xiàn)代碼也是千篇一律,如下:
/** 先實(shí)例化個進(jìn)度條 */
ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.ProgressBar);
/** 再實(shí)例化個 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 控件可能自身提供了動畫的 API,可惜,沒有,故自己動手寫了這個,你如果找到了,告訴下我。
二,為什么要搞緩慢效果?
對,為什么要這么麻煩,你如果要搞個網(wǎng)頁加載進(jìn)度條,上面的代碼不過 10 行,妥妥地實(shí)現(xiàn)了。因為用戶體驗,我不是產(chǎn)品經(jīng)理,我是個程序員,而且這個效果也不是有誰叫我這樣去做的,我就是看著別扭,微信的成功,我相信不僅僅是個朋友圈那么簡單!
程序員應(yīng)該具備注重用戶體驗的想法。
三,我的實(shí)現(xiàn)思路
方法很多,這話我說在前面,我的這種肯定不是最好的,但不失一用或改進(jìn)。
主要是通過改變 view 的 LayoutParam 來實(shí)現(xiàn)有不同速度的移動效果,在每一次的進(jìn)度段,例如第一次0~24,第二次24~56,這就是兩個進(jìn)度段,這兩個進(jìn)度段,具有不同的速度,這個需要計算出來,先根據(jù)手機(jī)屏幕寬度和 0~100 的進(jìn)度數(shù)值來等比計算出實(shí)際的寬度,再計算出移動的速度,計算出來每個進(jìn)度段的數(shù)據(jù)后,講它們放進(jìn)一個列表容器里面,然后通過一個 handler 來循環(huán)提取同期數(shù)據(jù),不斷地發(fā)消息,不停地 setLayoutParam。在達(dá)到 100 后,就證明加載完畢。
在這個過程需要處理計算的誤差,例如第一個加載 20,第二次24,24-20 = 4,4/100,程序里面是 0 ,如果計算速度的話,就會差生0,所以要稍微加個 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)頁打開的進(jìn)度條
*
* 下面的所有屬性都可以自己采用 get set 來自定義
*
*/
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)度長度 */
private int record = 0; /** 移動單位 */
private int width = 10; /** 10dp each time */
private int height = 3; /** 3dp */
private boolean isStart = false;
private int phoneWidth = 0; /** 屏幕寬度 */
private int i = 0;
/** 每次的移動記錄容器,位移對應(yīng)每幀時間 */
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){ /** 不能超過100 */
return;
}
/** 每次傳入的 width 應(yīng)該是包含之前的數(shù)值,所以下面要減去 */
/** 下面記得轉(zhuǎn)化比例,公式 (屏幕寬度 * progress / 100) */
this.width = (progress * phoneWidth)/100;
/** lp.width 總是獲取前一次的 大小 */
/** 移動 100px 時的速度一次倍率 是 2 */
int size = progressQuery.size();
if(size != 0){
size = progressQuery.get(size-1);
}
Log.d("zzzzz","width - size = "+(width - size));
/** 計算倍率,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);
/** 開始 */
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:
/** 提取隊列信息 */
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ā)信息的延時長度并不會影響速度 */
handler.sendEmptyMessageDelayed(StartAnimation,1);
break;
}
}
};
}
/** 移動 */
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 ++;
}
}
五,使用方法與截圖
超簡單引入,view 可以是隨便一個,例如 TextView,給它一個 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開發(fā)之模仿微信打開網(wǎng)頁的進(jìn)度條效果(高仿),如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場景
這篇文章主要為大家介紹了Android基于方法池與回調(diào)實(shí)現(xiàn)登錄攔截的場景詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08
Android中ConstraintLayout約束布局的最全詳細(xì)解析
ConstraintLayout是Google在Google?I/O?2016大會上發(fā)布的一種新的布局容器(ViewGroup),它支持以靈活的方式來放置子控件和調(diào)整子控件的大小,下面這篇文章主要給大家介紹了關(guān)于Android中ConstraintLayout約束布局詳細(xì)解析的相關(guān)資料,需要的朋友可以參考下2022-08-08
Android okhttputils現(xiàn)在進(jìn)度顯示實(shí)例代碼
本文通過實(shí)例代碼給大家詳細(xì)介紹了Android okhttputils現(xiàn)在進(jìn)度顯示,代碼簡答易懂,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2016-12-12
Android百度地圖應(yīng)用之基本地圖功能實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了Android百度地圖應(yīng)用之基本地圖功能實(shí)現(xiàn)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-06-06
Android實(shí)現(xiàn)仿360桌面懸浮清理內(nèi)存
今天給大家?guī)硪粋€仿360手機(jī)衛(wèi)士懸浮窗清理內(nèi)存的效果的教程,非常的簡單實(shí)用,需要的小伙伴可以參考下2015-12-12
關(guān)于Android發(fā)送短信獲取送達(dá)報告的問題(推薦)
最近公司開發(fā)一個項目,要求app能夠發(fā)送短信并獲取送達(dá)報告。實(shí)現(xiàn)代碼非常簡單的,下面小編給大家分享關(guān)于Android發(fā)送短信獲取送達(dá)報告的問題,感興趣的朋友一起看看吧2017-03-03

