preface

Use book APP classmates know, Jane Jane’s book has such a function: the article page length on the bottom of the content will be a photo sharing button, click on the following can be the current pictures generated a long article, the image can be saved to a local or Shared with friends, also can be set up for images become white and black two kinds of style, art van. Personally, I’ve always liked this feature.

At one point, however, the feature became buggy, producing images with a fixed title at the bottom, not the content of the article, and long images becoming short ones. After giving feedback to Jian Shu, I got the reply that I would use the share button to generate pictures. The share menu includes a growth map feature that does work. However, I still miss the function of long press to generate pictures before, so as a program ape; With curiosity, I decided to implement such a feature myself.

Results the preview

Old rule, first look at the implementation of the effect; Although the whole Jane book has no fan, personal feeling or quite like.

Article page implementation

content

The realization of the content of the article page, there is no difficulty. The layout is generally very simple, a LinearLayout that contains household information and article information, plus a WebView. The data is based on the content needed in the layout, encapsulating an HtmlBean object, and this object is obtained by using Jsoup to parse the HTML document content of the current page (here using Jsoup to get the simple book web page content, just for personal learning, no other purpose). Specific implementation can view the source code

Long press menu implementation

Here specifically to say, long press pop-up bottom button to achieve the way. In general, we will set the OnLongClickListene event of the View to achieve the corresponding function, but for the WebView can be implemented as follows:

mWebView.setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { genImg.setVisibility(View.VISIBLE); T. shostoast (mContext, "Click article again to hide photo sharing "); }});Copy the code

// Click the hide bottom button

mWebView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: lastTime = SystemClock.uptimeMillis(); break; case MotionEvent.ACTION_UP: if (SystemClock.uptimeMillis() - lastTime < 300) { genImg.setVisibility(View.GONE); } break; } return false; }});Copy the code

Here we listen for the ContextMenu of the WebView to see when the bottom button is displayed; Also hide the bottom button in the onTouch method.

genImg.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { genImg.setVisibility(View.INVISIBLE); Intent intent = new Intent(FakeJianShuActivity.this, GenScreenShotActivity.class); intent.putExtra("data", mHtmlBean); startActivity(intent); }});Copy the code

Click the Button at the bottom to jump to the interface of the growth diagram, and pass in the HTMLBean object obtained previously.

Long graph effect implementation

Here is the implementation idea (from which the idea comes).

  • Start by loading a native Html page with a WebView that contains some fixed tags. Then, based on the information passed in the mHtmlBean object, the content of the static HTML page is dynamically replaced by executing JavaScript.

  • About the implementation of black and white two styles, the same is WebView implementation Js, dynamic replacement of HTML CSS style, modify the background color of WebView to present two different UI effects.

  • The current WebView Bitmap object can be generated through the WebView’s capturePicture and Canvas. With this Bitmap, the image can be saved.

Ok, let’s do each of these steps in code.

Html page

style="position:absolute; top: 0px; left: 12px; margin-bottom: 15px;" /> function changeContent(content) { document.getElementById('content').innerHTML = content; }Copy the code

The content of this HTML page is very simple. In the upper left corner of the entire document is placed a small corner mark, which is the mark used when the Simple book APP generates the growth diagram.

It also defines a simple JavaScript method that replaces the document content in the article tag with the passed parameter Content.

Custom WebView

For convenience, let’s customize the WebView. Here’s the core logic:

public class FakeWebView extends WebView { private boolean isFirstLoad = false; public void loadData(HtmlBean bean) { assembleData(bean); if (Build.VERSION.SDK_INT >= 21) { isFirstLoad = true; webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { if (isFirstLoad) { isFirstLoad = false; Log.e("TAG", "onProgressChanged"); updateView(); }}}}); } else { isFirstLoad = true; webView.setVisibility(View.INVISIBLE); webView.setWebChromeClient(new WebChromeClient() { @Override public void onProgressChanged(WebView view, int newProgress) { if (newProgress == 100) { updateView(); if (! isFirstLoad) webView.setVisibility(View.VISIBLE); }}}); } webView.loadUrl("file:///android_asset/JianShu.html"); } private void assembleData(HtmlBean bean) { final String data = bean.getContent(); final String title = bean.getTitle(); final String username = bean.getUsername(); final String publishTime = bean.getPublishTime(); String title = "<h2>"+title+"</h2>"; String Footer ="<p>"+username+"</p><p>"+publishTime+"</p>"; content = Title + data + Footer; } public void updateView() { if (mode == MODE_DAY) { webView.setBackgroundColor(Color.WHITE); } else { webView.setBackgroundColor(Color.parseColor("#263238")); content = " " + content + " "; } webView.loadUrl( "javascript:changeContent(\"" + content.replace("\n", "\\n").replace("\"", "\\\"").replace("'", "\ \" ") + "\") "); }}Copy the code

These methods are at the heart of the growth map. The loadData method first calls assembleData, which concatenates an HTML document from the data in the mHtmlBean object. In the loadUrl method of the webView, the jianshu.html page is loaded locally. The updateView method is then called when the page has finished loading, that is, when the value of newProgress in the onProgressChanged callback is equal to 100; This method sets the background of the WebView based on the currently set mode. If it is in night mode, it adds a grey-style div tag to the document generated in assembleData and wraps the entire content in this div tag. Finally, the WebView executes the JS method changeContent, passing in the same arguments that we concatenated earlier. The entire WebView is refreshed again, and the content of the entire WebView is the content of the article.

The code for GenScreenShotActivity is as follows:

mFakeWebView = (FakeWebView) findViewById(R.id.fakeWebView); bean = (HtmlBean) getIntent().getSerializableExtra("data"); RadioGroup changeMode = (RadioGroup) findViewById(R.id.changeMode); changeMode.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() { @Override public void onCheckedChanged(RadioGroup group, @IdRes int checkedId) { if (checkedId == R.id.rb_day) { mFakeWebView.setMode(FakeWebView.MODE_DAY); } else { mFakeWebView.setMode(FakeWebView.MODE_NIGHT); }}}); mFakeWebView.loadData(bean); public void setMode(@ViewMode int mode) { this.mode = mode; updateView(); }Copy the code

In the Activity, the mFakeWebView object updates the current view through the mHtmlBean object passed from the previous page (the article page), and the page style can be switched using RadioButton.

Save the picture

We are only 50 percent of the way to the final goal of generating images, because so far we have just loaded the entire article into the WebView. I don’t have the long picture yet. So, the next job is to generate a growth diagram from a WebView.

public Bitmap getScreenView(){
    Picture snapShot = webView.capturePicture();
    Bitmap bmp = Bitmap.createBitmap(snapShot.getWidth(),snapShot.getHeight(),     
                                         Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bmp);
    snapShot.draw(canvas);
    return bmp;

}
Copy the code

WebVeiw is very user-friendly, with this method we can get a Bitmap of the visible and invisible parts of the current WebView.

In fact, it is not difficult to generate pictures through WebView, it is difficult to save our pictures here; Because what we’re generating here is a long image, as you can see below, the height of this image is amazing. Therefore, the first compression method mentioned earlier in the Bitmap exploration is required to compress the file size. Specific implementation, will not repeat the post code, interested students can refer to Github source code.

At this point, we have fully realized the function of long press to generate pictures. So let’s go back and see why there is a bug in the long press function of Jianshu APP on my phone.


defects

The WebView of the article details page is the WebView of the system. When loading the article with code, there is no special parsing of the content of the code class, so the code cannot be highlighted. Only the most plain text is displayed, so the code in the resulting long graph is plain text. Simple book APP is still outstanding, the code highlighting is awesome!


The latter

By chance, when I tried the function of long press to generate pictures in simple book, I found that simple book was used to generate the content of the second page through the selected area of WebView. So when I long press on a blank area of the article page, when I click to generate an image, there is nothing but a few fixed tabs at the bottom. Therefore, this should not be a bug, but just a convenient way for people to generate more efficient long graphs of their favorite content.


Original website: www.jb51.net/article/108…