專案需求討論-WebView進度載入條

青蛙要fly發表於2017-07-26

又到了每次的實際專案開發中的需求討論了。這次是因為做的專案是原生內嵌WebView,所以當我們的WebView在載入網頁的時候,需要有個載入進度條,當然這時候有很多種選擇,但是因為普通的對話方塊型別的載入框太醜,我們就捨棄掉了,而是模仿微信裡面的進度載入條,也就是在WebView 的頂部會有一條線來顯示載入進度。(也就是下方GIF圖中的那個紫紅色的進度條,別問我為啥用紫紅色。我就覺得用這個顏色更加明顯點。O(∩_∩)O~)

宣告大家不要噴哈,有問題可以評論反饋。我做的可能也不是很好

先附上Demo:DEMO

一些關於WebView的基礎我就不說了。大家可以看看
Android之WebView快速上手


OK ,進入我們的正題,我們先要知道怎麼監聽到網頁載入的進度。

監聽網頁載入進度:

我們按照上面的Android之WebView快速上手所說的:

我們知道了WebChromeClient中有個onProgressChanged方法可以用來監聽,所以我們複寫onProgressChanged方法:

WebView webView = (WebView) findViewById(R.id.webview);
webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);
        ....
        ....
        ....

    }
});複製程式碼

好了,我們現在在訪問網頁的時候已經可以拿到了進度值了。也就是newProgress。這裡要注意一個問題,那就是如果你在這裡打上Log你會發現,這個newProgress值不是說按我們想象中那樣,從0慢慢到100,可能就是(0->16->30->100)就返回這四次數字。所以如果我們直接讓我們的進度條按照它的newProgress值來變化,就有個問題,那就是會變化特別大,而且速度也特別快。體驗一點也不好。所以這裡我處理方式是,當newProgress 大於85 的時候,讓他慢慢的在特定時間內載入完剩下的進度,這樣給人的感覺也是很平穩的


自定義進度條:

其實這個自定義進度條很簡單,其實就是畫了一個矩形,然後矩形的width就是根據我們拿到的網頁的進度來實時的變化:

public class WebProgressBarView extends View{

    ....
    ....
    ....

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mWidth = MeasureSpec.getSize(widthMeasureSpec);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        float result = mWidth * ((float) mCurProgress / (float) 100);
        canvas.drawRect(0, 0, result, mHeight, mPaint);
    }
}複製程式碼

我們在上面提到。我們在大於85的時候,讓他慢慢的載入完畢,所以我們這裡要有二個方法:

  1. 正常方法:

    public void setNormalProgress(int mCurProgress){
     this.mCurProgress = mCurProgress;
     postInvalidate();
    }複製程式碼

    2.慢慢載入的方法:

    public void setCurProgress(long time, final EventEndListener endListener){
         ValueAnimator animator = ValueAnimator.ofInt(mCurProgress,100);
         animator.setDuration(time);
         animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
             @Override
             public void onAnimationUpdate(ValueAnimator animation) {
                 setNormalProgress((Integer) animation.getAnimatedValue());
             }
         });
    
         animator.addListener(new Animator.AnimatorListener() {
             @Override
             public void onAnimationStart(Animator animation) {
    
             }
    
             @Override
             public void onAnimationEnd(Animator animation) {
                  if(endListener != null){
                      endListener.onEndEvent();
                  }
             }
    
             @Override
             public void onAnimationCancel(Animator animation) {
    
             }
    
             @Override
             public void onAnimationRepeat(Animator animation) {
    
             }
         });
    
         animator.start();
    
     }複製程式碼

繼續補充onProgressChanged方法:

既然我們寫好了自定義進度條的View ,我們回頭再來補充下onProgressChanged方法:

webView.setWebChromeClient(new WebChromeClient() {
    @Override
    public void onProgressChanged(WebView view, int newProgress) {
        super.onProgressChanged(view, newProgress);

        //如果進度條隱藏則讓它顯示
        if (View.GONE == progressBarView.getVisibility()) {
            progressBarView.setVisibility(View.VISIBLE);
        }

        if (newProgress >= 85) {
            if (isContinue) {
                return;
            }
            isContinue = true;
            progressBarView.setCurProgress(1000, new WebProgressBarView.EventEndListener() {
                @Override
                public void onEndEvent() {
                    isContinue = false;
                    if (progressBarView.getVisibility() == View.VISIBLE) {
                        hideProgress();
                    }
                }
            });
        } else {
            progressBarView.setNormalProgress(newProgress);
        }
    }
});複製程式碼

我們看到了。我們的進度大於85的話,就在一秒鐘內慢慢的載入完,載入完後呼叫hideProgress方法來隱藏進度條,

private void hideProgressWithAnim() {
    AnimationSet animation = getDismissAnim(MainActivity.this);
    animation.setAnimationListener(new Animation.AnimationListener() {
        @Override
        public void onAnimationStart(Animation animation) {
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            progressBarView.setVisibility(View.GONE);
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    });
    progressBarView.startAnimation(animation);
}

private AnimationSet getDismissAnim(Context context) {
    AnimationSet dismiss = new AnimationSet(context, null);
    AlphaAnimation alpha = new AlphaAnimation(1.0f, 0.0f);
    alpha.setDuration(1000);
    dismiss.addAnimation(alpha);
    return dismiss;
}複製程式碼

問題:

實際操作中的問題,這裡我也遇到問題:

  1. 那就是網頁載入沒有想象中那樣載入一次。網頁可能會有重定向跳轉這種,雖然你可能感覺就開啟了一個連結,你會發現newProgress 從0 -> 100後,會再多次呼叫0->100。這裡我不知道一般大家在做其他APP的WebView進度條的時候,是按照它真實的newProgress來載入,也就是載入了一次全的,然後進度條重新載入一次,再載入一次。還是說只載入第一次的0->100的進度條。
  2. 我本來想載入第一次進度條,後面的newProgress的重新0->100我就不管了。我就想到重寫WebViewClient,因為裡面有二個方法:
    //當網頁載入完畢後這個方法會被回撥
    public void onPageFinished (WebView view, String url)
    //當網頁開始載入時這個方法會被回撥
    public void onPageStarted (WebView view, String url, Bitmap favicon)複製程式碼
    然後我就想到定義一個boolean值,這樣豈不是可以在這二個方法裡面賦值,然後用來控制。
    可是我打了Log發現,比如我WebView開啟的是https://www.baidu.com,然後開啟顯示的百度首頁中某個新聞,onPageStarted並不會呼叫。而onPageFinished還是會被呼叫,我想了解下什麼時候onPageStarted不會被去呼叫。 ╮(╯﹏╰)╭

如果大家能幫忙答疑就謝謝了。

相關文章