A few days ago, the picture sharing effect of Jane book suddenly flashed in my mind. I felt very simple and beautiful. I thought if I could use my own way to achieve it, so I created this article today. Ok, let’s take a look at the image first:




GeneratePicture


Project address: github.com/zhangke3016… Welcome to Star, issues~

To achieve this effect, we must first understand the following questions:

One, how to obtain the selected web content two, how to obtain the web content load display




GeneratePicture


How to obtain the selected web page content

It is very difficult to obtain the selected web content through Java, and the effect must be obtained by the selected web content, we can change the idea, since it is not easy to get through the Java layer, is it easier to get through JavaScript? The later implementation confirmed that the idea is correct. JavaScript makes it easy to get selected web content.

So our idea is: when the user clicks the “generate photo share” button, we call JavaScript method to get the selected web content and call back the Java method to get the web content to the Java layer, we can get the web content. Take a quick look at the code:

mWebView.addJavascriptInterface(new WebAppInterface(onGetDataListener), "JSInterface");

public void getSelectedData(WebView webView) {
        String js = "(function getSelectedText() {" +
                "var txt;" +
                "if (window.getSelection) {" +
                "var range=window.getSelection().getRangeAt(0);" +
                "var container = window.document.createElement('div');" +
                "container.appendChild(range.cloneContents());" +
                "txt = container.innerHTML;" +
                "} else if (window.document.getSelection) {" +
                "var range=window.getSelection().getRangeAt(0);" +
                "var container = window.document.createElement('div');" +
                "container.appendChild(range.cloneContents());" +
                "txt = container.innerHTML;" +
                "} else if (window.document.selection) {" +
                "txt = window.document.selection.createRange().htmlText;" +
                "}" +
                "JSInterface.getText(txt);" +
                "}) ()";

        // calling the js function
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            webView.evaluateJavascript("javascript:" + js, null);
        } else {
            webView.loadUrl("javascript:" + js);
        }
        webView.clearFocus();
    }
 static class WebAppInterface {
        WebViewHelper.OnGetDataListener onGetDataListener;
        WebAppInterface(WebViewHelper.OnGetDataListener onGetDataListener) {
            this.onGetDataListener = onGetDataListener;
        }
        @JavascriptInterface
        public void getText(String text) { onGetDataListener.getDataListener(text); }}public interface OnGetDataListener{
        void getDataListener(String text);
    }Copy the code

The idea is that when we want to get the selected content of the web page, we inject a JavaScript script written by ourselves into the WebView. The meaning of this JavaScript code is to get the selected content of the current page contains THE HTML tag. Call JSInterface. GetText () method to content back to the Java getText (String text) method, we set onGetDataListener. GetDataListener (text) callback method, Get the content by calling it where it is needed.

How to load and display the content of the web page

We have obtained the content of the web page, according to the truth in fact call TextView setText(html.fromhtml ()) this method can display our selected effect, but for aesthetic and screenshot saving function, the normal display of images, I choose to use WebView to load the content of the web page.

Here’s how I handled it: First, create an HTML page in the local assets folder, load the basic display content in the page and add CSS tags to modify the loaded content. When the web content is obtained, use JavaScript to dynamically replace the corresponding tag content specified in the local HTML page with the obtained web content. And modify the display content in the local HTML page.

Take a look at the code:

webView.loadUrl("file:///android_asset/generate_pic.html");

public void changeDay(String strData,String userInfo,String userName,String other) {
        if(userInfo == null)
            userInfo ="";
        if(strData == null)
            strData ="";
        if(userName == null)
            userName ="";
        if(other == null)
            other ="";
        strData+="<br /><br />\n" +
                "\t\t"+userInfo+"</span>\n" +
                "\t\t<br /><br />\n" +
                "\t\t
       
\n"
+ "\t\t<br />\n" + "\t\t

< strong >"

+userName+"< / strong > send"+other+"</p>"; webView.loadUrl("javascript:changeContent(\"" + strData.replace("\n"."\\n").replace("\" "."\ \ \" ").replace("'"."\ \" ") + "\")"); webView.setBackgroundColor(Color.WHITE); }Copy the code

The different display effects of white and black can be implemented by changing the CSS style in the changeDay method, which is relatively simple.

But there is a problem: when the selected page content has an image and the image is displayed in a relative path, the image does not load.

In this case, the image is a relative path, so if you look at the local relative path, you can’t find it locally, so the image won’t show up. In order to make the picture display normally, call onLoadResource method on the selected content page to judge the loaded resource and save the picture path, because the selected page picture can be displayed, indicating that the path is HTTP path, and the picture can be displayed. Take a look at the code:

 mWebView.setWebViewClient(new WebViewClient(){
            @Override
            public void onLoadResource(WebView view, String url) {
                //Log.e("TAG","url :"+url);
                if(url.toLowerCase().contains(".jpg")
                        ||url.toLowerCase().contains(".png")
                        ||url.toLowerCase().contains(".gif")){
                    mlistPath.add(url);
                }
                super.onLoadResource(view, url);
            }Copy the code

Dynamically modify the picture path when displaying the selected content page, so that the picture is displayed:

 webView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //view.loadUrl(url);
                return true;
            }
            public WebResourceResponse shouldInterceptRequest(WebView view, String url) {
                WebResourceResponse response = null;
                for (String path:WebViewHelper.getInstance().getAllListPath()){
                    if (path.toLowerCase().contains(url.replace("file://"."").toLowerCase())){
                        try {
                            response = new WebResourceResponse("image/png"."UTF-8".new URL(path).openStream());
                        } catch(IOException e) { e.printStackTrace(); }}}returnresponse; }});Copy the code

This way, our image can be displayed! Finally, to implement our screenshot save function, take a look at the code:

 /** ** screenshot ** @return */
    public Bitmap getScreen() {
        Bitmap bmp = Bitmap.createBitmap(webView.getWidth(), 1, Bitmap.Config.ARGB_8888);
        int rowBytes = bmp.getRowBytes();
        bmp = null;

        if (rowBytes*webView.getHeight()>=getAvailMemory()){
            return null;
        }
        bmp = Bitmap.createBitmap(webView.getWidth(), webView.getHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bmp);
        webView.draw(canvas);
        return bmp;
    }
   private long getAvailMemory() {
        return Runtime.getRuntime().maxMemory();
    }Copy the code

You need to determine the size of the saved picture to avoid creating a picture that is too large.

At this point, the basic functionality has been implemented. Share the pictures with your friends

Project address: github.com/zhangke3016… Welcome to Star, issues~