In my Nougat device, webview inside RecyclerView is blank sometimes. When I scroll slowly and then go back to webview item content disappear. There is no issue on devices below Android N. Android N uses Chrome as the default browser for apps. So I thought there might be a bug in Chrome so I raise a bug in chrome portal as well. There are a couple of related question in SO but that didn't solve my problem. So is there a way in Android webview setting which can solve this problem? I have written detail description in the bug link.
Bug link: click here
My onBindViewHolder method code for WebView is
final VHItem vhItem = (VHItem) holder;
vhItem.webViewChild.getSettings().setUseWideViewPort(false);
vhItem.webViewChild.getSettings().setJavaScriptEnabled(true);
vhItem.webViewChild.loadData("<body>" + html + "</body>", "text/html;charset=utf-8", "utf-8");
where
html is the html string
Update
They have fixed the issue. If you are still having the same problem try updating your Android chrome version to 61 or above.
For a start webview consumes memory because it load has to load and render html data. Rather than using a webview in a recycler view, I think it would be better if you implemented it either of these two ways:
You handle the list of data in html and send it into the webview and remove the recycler view completely
You draw the layout of the expected contents in xml and inflate it directly into the recyclerview and remove webview completed. (Note: you can inflate different views into a recycler depending on the adapter position and data at that position).
Using a webview might seem the easy way to implement whatever you are trying but trust me, the drawbacks outweight the benefit. So its just best to avoid it.
This problem can arrive for many possible reasons
When you scroll very fast
Recyclerview is purely based on Inflating the view minimal times and reusing the existing views. This means that while you are scrolling when a view(An item) exits your screen the same view is bought below just by changing its contents.When you load from internet it's always better to first download all the data and then display it. Webview's consume a lot of data and its totally Against the design principle to have them in a Recyclerview.
To repair this you could possibly add some button to reload data or refresh each time you display the view.
Nougat removed some functions from http urlconnection class
I am not sure about this one. But in one of google developer video ,T had seen something about depreciation of some functions and methods
hope You find this Helpful.
I solved this problem by floating a WebView in a up layer of RecyclerView, meanwhile placing a HOLDER view in RecyclerView.
And then I register an listener to the scroll event of RecyclerView. I Control the position and visibility of the floating WebView
You can try this code in onCreateViewHolder
ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
WebView web = new WebView(parent.getContext());
web.setLayoutParams(lp);
String url="...";
WebSettings settings = web.getSettings();
settings.setJavaScriptEnabled(true);
settings.setDomStorageEnabled(true);
web.loadUrl(url);
holder = new ViewHolder(web);
Related
I am working on and Android app which has legacy code and we are using ListView and optimizing the listview by using ViewHolder.
Our listview has different types of custom views which are a bit complext. The scrolling performance of the listview is pretty good till now.
A new requirement has come up to support Webviews in the same listview. The webview content to be loaded from disk and javascript is enabled.
The problem is that when I add webviews in list the scrolling become jittery. During the scrolling I can see that the webview content is blank as it is still to be loaded.
I think the performance degradation is due to two reasons.
1) creation+Loading of new Webviews everytime getView of listview adapter is called
2) Displaying the content of webview
To solve these issues I started caching 7 webviews and I am recycling the webviews by detaching from previous parent view and attaching to new parent view. For example if the current visible item index is 5. I will also create the webview for three next(6,7,8) and three prev(2,3,4) items and keep them in a cache based on some id of listview item content. So when there is requirement for next item say for index 6, I will simply return one item from cache and update the both from front and back to hold 3,4,5 and 7,8,9 index items.
I was thinking that by creating a pool of webviews I will solve both the problems. 1) creating new webview ever time getview is called. And by prefetching the next/prev 3-3 items I can preload url so display will happen in background.
But I can see that display is still taking time and scrolling is still jittery.
So my questions are:-
Does webview display the content only when it is attach to a window ? (In my case the webviews in caches are not attached to window and I am loading the url in them.)
Does webview display the content only when it is visible ?
Is there a way to render the content of webview in background so that by creating cache of Webview I can do smooth scrolling.
In my app I am making a web browser in which I want to show different pages in form of tabs. I want to create a view like this
But I have no idea how to do this. Need guidance regarding the components required.
Well the "simple" way to achieve this would be to create an adapter of some sort that overrides the getView() function to create a WebView
and return it as one of the items. The URL of this webview can be mapped to an array or cursor. Since a WebView is a very costly component, you will need to implement the ViewHolder pattern to ensure the webviews are recycled properly.
A lot more work is required to get the rounded corners plus the extra top features but hopefully this can get you started on the right track.
i'm displaying a web page in android webview. and i want to trigger a message when the user reaches end of page while scrolling. how can i do that? TIA
One way is we can write custom MyWebView class that extends WebView and then we can use the function called computeHorizontalScrollRange() orcomputeVirticalScrollRange() to get the scroll range of webview.
AFAIK, I don't think there is any event that triggers this. But here's one way - you will have to try and see if it works though. Have a ListView with two rows - one having the WebViewClient and another just an ordinary TextView - You could use something like SackOfViewsAdapter for this.
In your adapter's getView(), when the function is called to display the bottom TextView, that's your cue on the user having scrolled down.
I update the html in a webView using loadData() followed by a reload(). I get the new data to display but the scroll of the page has not updated. I want to keep the view of the page at the bottom. I can wait a long time and it still doesn't update. Once I click the webView the scroll bars adjust and I can drag to the bottom of the page and see the new text.
Things I have tried:
- multiple settings and calls in onPageFinished(). None worked because the getContentHeight() hasn't changed yet. I have also tried to scrollTo(100 + getContentHeight) and that doesn't work.
- pageDown(true)
calling requestLayout() after reload()
browser.requestFocusFromTouch() - still no good, thinking i could simulate my click.
adding a few br tags. This worked a bit, but the number of br's has to equal the number of lines of new text. Since the number of new lines is not something that can be exactly determined based on orientation and screen variables it's not a good fix.
Any ideas? TIA
If you want the webview to be scrolled to the bottom after it's finished loading, I found I had to use pageDown(true) in onNewPicture. (I believe that's the event fired when a view is finished drawing.)
So the code looks something like
webView.setPictureListener( new WebView.PictureListener() {
public void onNewPicture(WebView view, Picture picture) {
webView.pageDown(true);
}
}
Using pageDown has the unfortunate problem of visibly scrolling the page; I'm having problems finding any other way to jump to the bottom of the webView, found this question while looking for a solution! (I haven't tried reaching inside the WebView and using javascript yet, though.)
I am a newbie Android guy.
I have a ListView displaying images on every element of the ListView, It works fine... but when I start to scrolling I have realized my image is downloaded again if it is displayed in the screen of my phone device!
How could I stop reloading the images or all the content of the in ListView again?
Or how could I avoid reading the getView() function again If I have already downloaded all its content?
It is possible to create an efficient adapter with different view types. Take a look at this question.
It's fairly simple. Just need to override getItemViewType and getViewTypeCount. Then you can count on convertView being the correct view type.