Basic usage of WebView (webpage view)


Introduction to this section

What this section brings to you is a control in Android used to display web pages: WebView (web page view).

Now Android App There are two directions for layer development: client development and HTML5 mobile development!

The so-called HTML5 end is: HTML5 + CSS + JS to build A web version of the application, and the intermediate medium is the WebView, and the web and web pages can interact through JS, for example, The web page reads mobile phone contacts, calls mobile phone-related APIs, etc.!

And compared with ordinary client development, HTML5 mobile terminal has advantages: You can use percentages for layout, and if there are any major changes on the HTML5 side, we don't have to re-create the APP like the client does, and then To overwrite the installation, we only need to modify the web page! And the client... is terrible. Of course, HTML5 also has a shortcoming, which is performance issues. Data accumulation, power consumption issues, flickering screens, etc...

In addition, for this kind of cross-platform, we can use other third-party rapid development Frameworks, such as PhoneGap, yes, there are also many one-click APP-like websites on the Internet. Users can drag and drop to set pictures. Simple operations like this can generate an application, most of which are done using HTML5! There are templates, just apply them, you know~ Okay, without further ado, let’s start this section!

1. What is WebView?

Answer: Android is a high-performance browser with built-in webkit kernel, and WebView is encapsulated on this basis. Control, WebView literal translation of web view, we can simply regard it as a browser control that can be nested on the interface!

2. Related methods

Go to the official documentation first: WebViewI don’t intend to talk about the properties one by one, and write whichever one is used. For other information, please consult the documentation yourself! In addition to direct WebView, we can also add your own behavior, and you can customize the following classes:


WebChromeClient: assists WebView in processing Javascript dialog boxes and website icons , website title, loading progress, etc.! For example:

Handling Alert dialog box in JsHandling Confirm dialog box in JsHandling Prompt dialog box in JsWhen loading progress bar Call when a change occurs##Get the icon of the web page
MethodFunction
##onJsAlert(WebView view,String url,String message,JsResult result)
onJsConfirm(WebView view,String url,String message, JsResult result)
onJsPrompt(WebView view,String url,String message,String defaultValue,JsPromptResult result )
onProgressChanged(WebView view,int newProgress)
onReceivedIcon(WebView view, Bitmap icon)
##onReceivedTitle(WebView view, String title)Get the title of the web page

##WebViewClient: Assist WebView to handle various notification and request events! For example, the following methods:

MethodFunctionNotify the main program that the web page starts loadingNotify the main program that the web page is loaded##doUpdateVisitedHistoryonLoadResourceonScaleChangedshouldOverrideKeyEventshouldOverrideUrlLoadingonReceivedError

WebSettings: WebView related configuration settings, such as setJavaScriptEnabled() setting whether to allow JS script execution Some methods are as follows:

onPageStared (WebView view,String url)
onPageFinished(WebView view,String url,Bitmap favicon )
(WebView view,String url,boolean isReload)Update History
(WebView view,String url)Notify the main program that WebView is about to load the resource of the specified url
(WebView view, float oldScale, float newScale) Called when the scaling of ViewView changes
(WebView view,KeyEvent event) Controls whether webView handles key press time. If true is returned, WebView will not process it. If false is returned, it will be processed.
(WebView view, String url) Controls the processing of newly loaded Url. Returning true means that the main program does not process WebView. Returning false means that WebView will process it. Handling
(WebView view,int errorCode,String description,String failingUrl)Called when an unrecoverable error message is encountered
Load the specified UrlLoad the specified Data into WebView. Use " data: "As a mark header, this method cannot load network data. mimeType is the data type such as: textml, image/jpeg. encoding is the character encoding methodMore powerful than the loadData aboveSpecify a WebViewClient object for WebView. WebViewClient can assist WebView in processing various notifications, requests and other events. Specify a WebChromeClient object for WebView. WebChromeClient is specially used to assist WebView in processing js dialog boxes and website titles. , website icon, loading progress bar, etc.

It is important to distinguish the differences between the three load methods:

loadUrl(): directly displays the web page content (displays the network image separately), generally no garbled characters will appear. loadData(data, "text/html", "UTF-8"): Used to load data in URI format. Content cannot be loaded through the network. Images cannot be loaded, and garbled characters are often encountered. We know that String type data is mainly Unicode encoded. WebView generally uses UTF-8 encoding to save resources. Although we wrote it above, we still need to set it for webView: webview.getSettings().setDefaultTextEncodingName("UTF -8");loadDataWithBaseURL(baseUrl, string, "text/html", "utf-8", null): one of the loadData class Enhanced class, you can load images, baseUrl is the image path stored for you, and you only need to set utf-8 here to solve the garbled code. Problem!

Here are just some of the attributes listed. For others, you need to check the official documentation yourself:

WebChromeClient Documentation

WebViewClient Document

WebSettings Document


3. Explanation of some common requirements

Requirement 1: Load web pages according to URL

1) Load a WebView directly on the Activity

Running renderings:

1.gif

Implementation code:

public class MainActivity extends AppCompatActivity {

    private WebView webView;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webView = new WebView(this);
        webView.setWebViewClient(new WebViewClient() {
            //设置在webView点击打开的新网页在当前界面显示,而不跳转到新的浏览器中
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
        webView.getSettings().setJavaScriptEnabled(true);  //设置WebView属性,运行执行js脚本
        webView.loadUrl("http://www.baidu.com/");          //调用loadView方法为WebView加入链接
        setContentView(webView);                           //调用Activity提供的setContentView将webView显示出来
    }


    //我们需要重写回退按钮的时间,当用户点击回退按钮:
    //1.webView.canGoBack()判断网页是否能后退,可以则goback()
    //2.如果不可以连续点击两次退出App,否则弹出提示Toast
    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                super.onBackPressed();
            }

        }
    }
}

2) Set WebView in the layout code

I believe everyone has seen a lot of news apps or portal information Class App, its structure may be like this:

2.png

#There is a button in the upper left corner to close the current Activity, in the middle is the title of the news, and on the right is a refresh button. There may be such a floating button in the lower right corner. When we slide beyond the width of the screen, it will be displayed. When the user clicks, it will scroll back to the top of the web page! Let’s implement it simply!

Running renderings

3.gif

Implementation code

MainActivity .java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {


    private Button btn_back;
    private TextView txt_title;
    private Button btn_top;
    private Button btn_refresh;
    private WebView wView;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        bindViews();
    }


    private void bindViews() {
        btn_back = (Button) findViewById(R.id.btn_back);
        txt_title = (TextView) findViewById(R.id.txt_title);
        btn_top = (Button) findViewById(R.id.btn_top);
        btn_refresh = (Button) findViewById(R.id.btn_refresh);
        wView = (WebView) findViewById(R.id.wView);

        btn_back.setOnClickListener(this);
        btn_refresh.setOnClickListener(this);
        btn_top.setOnClickListener(this);

        wView.loadUrl("http://www.baidu.com");
        wView.setWebChromeClient(new WebChromeClient() {
            //这里设置获取到的网站title
            @Override
            public void onReceivedTitle(WebView view, String title) {
                super.onReceivedTitle(view, title);
                txt_title.setText(title);
            }
        });


        wView.setWebViewClient(new WebViewClient() {
            //在webview里打开新链接
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.btn_back:
                finish();          //关闭当前Activity
                break;
            case R.id.btn_refresh:
                wView.reload();    //刷新当前页面
                break;
            case R.id.btn_top:
                wView.setScrollY(0);   //滚动到顶部
                break;
        }
    }
    
    @Override
    public void onBackPressed() {
        if (wView.canGoBack()) {
            wView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                finish();
            }

        }
    }
}

Question and Answer

I believe that attentive friends will see that after we return to the page that was loaded at the beginning, press the return key and press Tried several times but still didn’t exit For the current APP, do we need to manually click the back button and call the finish method to close the current Activity? Why is this? It's obviously the first page on Baidu?

Answer: In fact, the reason for this is: the redirection problem of the URL. In fact, when we visit Baidu:

Although we load www.baidu.com, Baidu I did a redirect and jumped to the mobile version of Baidu web page: That is, your actual process is: www.baidu.com -> Mobile version of Baidu -> Open other links!

We see that the shouldOverrideUrlLoading() method above is written like this:

view.loadUrl(url);return true;We know that the user clicks the back button once , then the webview will call the goback method () once, we put the above three Suppose there are three sites A, B, and C. If you click back at C, then C - > B will be fine. Then click B - > A. At this time, there will be a problem. Even though B came to A, it jumped to B again because of the redirection, and so on... This is why The reason why the WebView is not launched when clicking the back button, the solution: hand speed, the webpage is not loaded in the webview Double-click the back button continuously, and your hand speed must be fast enough, haha! Just kidding, to solve this problem, we just need to Delete the stuff in shouldOverrideUrlLoading and write return false; That’s it! If you don’t believe it’s a redirect, you can try modifying the URL yourself~


Requirement 2: Monitoring of WebView scrolling events

We all know that monitoring scrolling events generally involves setting setOnScrollChangedListener ,Unfortunately WebView does not provide us with such a method, but we can rewrite WebView and override one of its methods: protected void onScrollChanged(final int l, final int t, final int oldl,final int oldt){} Then provide an interface to the outside world. The sample code is as follows:

MyWebViewDemo.java

/**
 * Created by Jay on 2015/9/11 0011.
 */
public class MyWebView extends WebView {

    private OnScrollChangedCallback mOnScrollChangedCallback;

    public MyWebView(Context context) {
        super(context);
    }

    public MyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        super.onScrollChanged(l, t, oldl, oldt);
        if (mOnScrollChangedCallback != null) {
            mOnScrollChangedCallback.onScroll(l - oldl, t - oldt);
        }
    }

    public OnScrollChangedCallback getOnScrollChangedCallback() {
        return mOnScrollChangedCallback;
    }

    public void setOnScrollChangedCallback(
            final OnScrollChangedCallback onScrollChangedCallback) {
        mOnScrollChangedCallback = onScrollChangedCallback;
    }

    public static interface OnScrollChangedCallback {
        //这里的dx和dy代表的是x轴和y轴上的偏移量,你也可以自己把l, t, oldl, oldt四个参数暴露出来
        public void onScroll(int dx, int dy);
    }

}

MainActivity.java:

public class MainActivity extends AppCompatActivity {

    private MyWebView wView;
    private Button btn_icon;
    private long exitTime = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        btn_icon = (Button) findViewById(R.id.btn_icon);
        wView = (MyWebView) findViewById(R.id.wView);
        wView.loadUrl("http://www.hao123.com");
        wView.setWebViewClient(new WebViewClient() {
            //在webview里打开新链接
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

        //比如这里做一个简单的判断,当页面发生滚动,显示那个Button
        wView.setOnScrollChangedCallback(new MyWebView.OnScrollChangedCallback() {
            @Override
            public void onScroll(int dx, int dy) {
                if (dy > 0) {
                    btn_icon.setVisibility(View.VISIBLE);
                } else {
                    btn_icon.setVisibility(View.GONE);
                }
            }
        });

        btn_icon.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                wView.setScrollY(0);
                btn_icon.setVisibility(View.GONE);
            }
        });

    }

    @Override
    public void onBackPressed() {
        if (wView.canGoBack()) {
            wView.goBack();
        } else {
            if ((System.currentTimeMillis() - exitTime) > 2000) {
                Toast.makeText(getApplicationContext(), "再按一次退出程序",
                        Toast.LENGTH_SHORT).show();
                exitTime = System.currentTimeMillis();
            } else {
                finish();
            }

        }
    }
}

Running renderings:

4.gif

When the web page starts to scroll, a hehe button will appear. We can click the hehe button to return to the top! Then the hehe button will be hidden~


Requirement 3: Scroll bar problem

The attributes you may use are as follows:

  • setHorizontalScrollBarEnabled(false );//Does not display horizontally
  • setVerticalScrollBarEnabled(false); //Does not display vertically
  • setScrollBarStyle(View.SCROLLBARS_OUTSIDE_OVERLAY);//Scroll bar is displayed inside WebView
  • setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY)//The scroll bar is displayed outside the WebView

Requirement 4: Set scaling and adaptive screen

Open according to our general habits For parts of the web page that cannot be seen clearly, we like to use two fingers to zoom in and out of the web page, and WebView We need to manually set whether this supports scaling!

You only need to add the following code:

WebSettings settings = wView.getSettings();
settings.setUseWideViewPort(true);//设定支持viewport
settings.setLoadWithOverviewMode(true);   //自适应屏幕
settings.setBuiltInZoomControls(true);
settings.setDisplayZoomControls(false);
settings.setSupportZoom(true);//设定支持缩放

After using the above code, the page will look like this:

5.png

When we zoom, a disgusting problem arises, which is a very common zoom control. We definitely don’t want it. Then add the following code to hide the zoom control!

settings.setDisplayZoomControls(false);

We can also set the initial scaling ratio ourselves, just for the webView:

wView.setInitialScale(25);//为25%,最小缩放等级

Hey, the above is scaling of the entire web page, but sometimes we just need to scale the font. , then OK Do this:

settings.setTextZoom(int);

You can also set the size directly via:

settings.setTextSize(TextSize.LARGER);

.

Android comes with five optional font size values: SMALLEST (50%), SMALLER (75%), NORMAL (100%), LARGER (150%), LARGEST (200%).


Requirement 5. Obtain Cookie data of WebView

We all know that Cookie is actually just a string representing the user's unique identifier. The scenario is generally: After the user enters the account password and clicks to log in, the user needs to use this cookie to access related services provided by the server! We can write the cookie acquisition into the onPageFinsihed method. It can be simply written like this:

@Override
public void onPageFinished(WebView view, String url) {             
    CookieManager cookieManager = CookieManager.getInstance();
    String CookieStr = cookieManager.getCookie(url);
    Log.e("HEHE", "Cookies = " + CookieStr);
    super.onPageFinished(view, url);
}

Requirement 6. Set the Cookie data of WebView

Hey, we got the Cookie above Or if we obtain cookies through other means, how do we set cookies for WebView? We can add the following code where Cookie needs to be set:

CookieSyncManager.createInstance(MainActivity.this);  
CookieManager cookieManager = CookieManager.getInstance();  
cookieManager.setAcceptCookie(true);  
cookieManager.setCookie(url, cookies);  //cookies是要设置的cookie字符串 
CookieSyncManager.getInstance().sync();

By the way, the above code needs to be written before loadUrl(), and if Cookie is set, try not to make other settings. Otherwise it may be invalid. It is recommended to write the cookie setting at the end of the webView related settings ~ before loadUrl()!


4. Sample code download:

WebViewDemo1: Download WebViewDemo1.zip

WebViewDemo2:Download WebViewDemo2.zip


##Summary of this section:

Okay, this This section introduces you to the basic usage of WebView, loading web pages, setting zoom, font zoom, Adaptive screen, as well as cookie acquisition and setting; I believe there are various strange needs in daily development, but Due to space limitations, I will only write so much. If you have a welcome message for ideas, in the next section we will learn how to use JavaScript on the HTML5 side. Come interact with WebView and get relevant data of your phone! Stay tuned~Thank you~

MethodFunction
getSettings()Returns a WebSettings object, used to control the property settings of WebView
##loadUrl(String url)
loadData(String data,String mimeType,String encoding)
loadDataWithBaseURL(String baseUrl, String data, String mimeType, String encoding, String historyUrl)
setWebViewClient( WebViewClient client)
setWebChromeClient(WebChromeClient client)