I am facing a curious problem with the last update of Android (4.4) : my CSS rendering is visible at screen for the user which means that my webview content is very thin before to adapt to the width:100% of the CSS.
I am using an android.webkit.WebView to display an html string like this :
webView.loadDataWithBaseURL(null, html, "text/html", "utf-8", null);
This webview has the following size set :
90% of screen width for webview width
WRAP_CONTENT for webview height
The CSS is built to fit the webview width, the height will then adjust itself. There is no absolute width or height set in the css.
When I display my webview (which is already fully loaded as I used onPageFinished callback to know the loading is finished), the CSS starts to be rendered. This is surprising me as I thought it should be rendered when I loaded the webview.
The problem is that for the user, a very small white line is displayed and then this line adjust itself to match the webview settings.
If I fix the width in the CSS, I don't have any rendering problem. But I cannot do that as I want to match all screen sizes.
There was no problem before Android 4.4 as there was nothing displayed on screen until CSS was fully rendered.
By the way, I was using the setPictureListener() method from the webview. I know that this method is deprecated (and obsolete for a while), but it was the only way to know when the webview had really finish to be "drawn" on screen. If I use this method in Android 4.4, it is called many time and this error comes up in DDMS :
W/UnimplementedWebViewApi(23891): Unimplemented WebView method run called from: android.os.Handler.handleCallback(Handler.java:733)
I don't know if there is a direct relationship, I don't think so as even not using this method, my CSS is not rendered correctly.
I tried many things :
use javascript onload to make the body visible
use a chrome client on the webview and wait for progress to be at 100% to make my webview visible
use a webview client and wait for onPageFinished to make my webview visible
use a postDelayed of 500 ms when using the PictureListener to make my webview visible
use all layer type choices : HARDWARE / SOFTWARE / NONE
make my webview parent firstly INVISIBLE / GONE and then VISIBLE
but nothing worked.
It seems like the CSS is rendered only when the webview is visible for the user.
I cannot show source code as it is for professional purpose so I would only like different point of view on where I could be searching (or if someone has already see this curious error in DDMS)
Has someone an idea on how to wait for the CSS to be rendered in the webview before to display this webview ?
Many thanks
I managed to fix this problem.
I had a display: table; in the style of the main div of my HTML and removing this makes my rendering looks good.
As it was working well with Android previous version, I am not able to determine if it is a bug of the webview, or a problem in my CSS.
By the way, thanks for having a look at my problem
Related
I've been banging my head against the wall for the whole day now, and i need some help :(
The problem is, that i have a WebApp that was designed for 640x960.
We didn't have time to write css for each screen size, so i've used initial-scale, maximum-scale, minimum-scale in the viewport meta tag to scale the app to different screen sizes.
The problem is, that in Android 4.4, no matter what i do, it always scales the app up, but never down!
I mean if i use a value of 0.7, the app is scaled up. If i use a value of 1.3, it is scaled up again :/
I've tried to change the targetSdkVersion to different versions to get the old behavior, but with no luck.
Can someone help me?
UPDATE:
So i ended up using style="zoom: <value>%" on the body tag. I calculate the percentage based on the difference between the current device screen size and the resolution my app was designed for. Now everything fits.
A viewport of
<meta name="viewport" content="width=640, initial-scale=1">
should make your fixed layout always fit (see MDN for more on the viewport meta tag).
You could be bumping in some of the following:
the contents can't be scaled down more than 'overview scale' (that is, such that your content is narrower than the screen). This is by design - making it smaller only results in rendering white to the sides so why bother. If you want this behaviour you'd need to add padding to the content,
you've specified the layout height of the WebView to be WRAP_CONTENT - this makes the WebView ignore the viewport meta tag, don't do that - set it to MATCH_PARENT or a fixed size,
you're using certain WebSettings:
setUseWideViewport (which overrides the viewport meta tag) or
setInitialScale (which can alter the size of the viewport).
The best way to check if it's the content's fault or the WebView's fault is to see if the page works in Chrome on Android:
if it works in Chrome on Android but not in the WebView then set targetSdkVersion to 19 and try disabling WebSettings, changing your layout to fixed size, etc.. to see what's causing the problem. Maybe start from the other end - by making a super trivial WebView app that just loads the page - confirm that works and then slowly introduce changes to see which one causes the problem,
if it doesn't work in Chrome on Android then problem is the difference in viewport meta tag support between pre-KK WebView and Chrome on Android - this means you'll have to fix your content,
If you're still stuck post a zip that contains sources with a repro (doesn't have to be the full app, just the minimum to demonstrate the problem) and I can try and help you more from there.
Just had a run through of this after not quite being sure of the answer myself.
http://www.gauntface.co.uk/blog/2013/11/29/desktop-site-and-the-viewport/
You want a viewport without an initial-scale if you only want the webpage to fit the WebView's width.
Things that will affect the WebView:
Ensure you have setUseWideViewport() enabled so the page can be larger than the devices width: http://developer.android.com/reference/android/webkit/WebSettings.html#setUseWideViewPort(boolean)
Ensure you targetSDKVersion=19 to ensure you aren't getting any compatibilities for the old webview
If you want to prevent the user from zooming in or out, use user-scalable=no in the viewport rather than set a min and max.
I have a very weird problem that is not consistent. I have a header in my webview page that is regular html from my site. The images are linked to pages. Sometimes the links don't work and sometimes they do. If I move my finger below the image, sometimes you see the rectangular highlight press color box show up but way off from the actual image. It will just be in a random spot but always below the image somewhere. So the link href and the image are getting out of sync per say. If I reload the page it will be in the correct position again and the image/button works. It doesn't always happen. Works fine in desktop and mobile browsers. Just weird in webview. Anyway, have a suggestion or experience this and why its so random?
Use it like this
String s="<head><meta name=viewport content=target-densitydpi=medium-dpi, width=device-width/></head>";
webview.loadDataWithBaseURL(null,s+htmlContent,"text/html" , "utf-8",null);
For more reference
http://developer.android.com/guide/webapps/targeting.html
And in Samsung s3 like phones, sometimes this will not work .For that create a separate layout for xhdpi phones and change the webview's height to 40dp or something depending on your requirement for avoiding white space.
The problem wasn't with just webview it is mobile in general, specifically Android Browser which I believe webview uses. My header was position:fixed and after a lot of research I found that position:fixed is glitchy on mobile and causes weird things to happen. This was causing the clickable location of the links getting out of place when you scrolled even though the images never moved. So when you clicked on the image/link it didn't work because the location of the link was somewhere else on the page, usually under the image somewhere.
As noted on this blog solution which described my issue.
http://suratpyari.wordpress.com/2011/09/30/fixed-position-problem-with-android-webkit/
However the solution I went with was not to use position:fixed at all as I didn't want css hacks and to use the solution used at the SO link below using position:absolute to make the inner div scrollable. It actually works quite well and the scrolling is even more smooth and fluid now.
CSS 100% Height, and then Scroll DIV not page
So anyone else that may have this problem, it might be your fixed header. And it is "real" problem for the person who down voted my question. :/
I use a android.webkit.WebView to display some HTML formatted info to the user. Whenever I "page" in my application, I reuse all the graphical elements on screen and just fill them with different content. A WebView will by default increase its size to fit the contents, but won't decrease if the content shrinks.
To fix this, I call webView.clearView() to clear the view and then webView.loadDataWithBaseURL(null, html, "text/html", "utf-8", null)to reload it with data. It works, but it creates a very strange behavior where the view starts to flicker persistently. The flickering area seems to be the same size as what would have been left empty after filling it with smaller content.
I can't describe this better with words, so I created a short video to illustrate the problem:
http://www.youtube.com/watch?v=yL7tQpRSFe0
The WebView is the yellow box on the lower part of the screen.
Am I doing something wrong, or is it a bug?
If this is an Android bug, is there a better way to resize the view as to circumvent this problem?
I have an application that displays html pages from resource assets in a WebView. The WebView was chosen in order to permit navigation links on the page, and all navigation action is handled in a WebView Client class by interrupting new page requests and returning the required local asset. The activity that contains the WebView supports both portrait and landscape orientations, and the WebView is configured ("setInitialScale" and "WebSettings") in "onCreate". Pages are displayed to fit inside the width and vertically scrollable. This has worked fine until the ICS update.
Under ICS the initial page selected still displays as before, but further page links that are displayed are wider than the screen width (and include a horizontal scroll bar). This occurs if the device is in portrait or landscape orientation when the initial page is loaded. Rotating the device to landscape and back to portrait solves the problem (causing a re-load of the activity as if the displayed page were the first one), but navigating back to previous pages while in portrait orientation causes them to again have widths that exceed the device display, even when returning to the primary page which was displaying correctly.
This is mostly an annoyance - but the inconsistent behavior is worrying. Unfortunately, there are several other "tweaks" associated with this code (mostly to re-size images within the html to fit the screen and retain the WebView scroll position when the orientation changes). While these could be a source of the current problems, a quick log output of their results shows they are working as expected, suggesting it is the ICS WebView behavior has changed.
I have searched for any similar postings of the problem without finding any direct reference, so my question is really open. Has anyone else seen anything like this in the ICS WebView class, or should I be looking for another source for the changed behavior?
Update:
After eliminating one line of code after another for hours (grrrr), I have identified the problem.
When running under android api 14 or higher, the WebView has unpredictable behavior after setting the view scale with "setInitialScale" to values larger than 100% when the viewport is fixed at the device width (using the meta tag name="viewport" content="width=device-width" in the html css). The initial page load seems to respect the device width, but subsequent page loads may or may not render with the viewport wider than requested, almost randomly.
This may be the expected behavior, although the unpredictability suggests that it is not (and if it is, then it is a fix from the behavior under previous versions).
The code used was setting the scale to allow the user to adjust the text display size in preferences, with the size of page images being "fixed" to a value in code before the page is loaded. This has been replaced by maintaining the page scale at 100%, and setting the text size from the user's preferences using "WebSettings.setDefaultFontSize", which has removed the rendering problems.
I am developing a mobile site, so I'm using CSS to make things as liquid as possible.
I'm having an odd difficulty. Within a div container, I have a <p> that is supposed to fill the width of the div. I've tried width:auto, width:100%...nothing seems to work on Android Browser. Here are examples:
iOS (Correct):
Android (Incorrect; not fully spreading; added more text than iOS version so you can see what I'm talking about):
Both screenshots taken from respective emulators.
Here is the odd thing, though... If I give the class applied to these <p>'s a background color, the Android browser then allows the <p> to fill the full width of its parent div (looks identical to iOS). The really odd part, though, is that if I make the background color transparent (I thought I had it tricked lol), then it goes back to doing as shown in the example.
So, I have a <p> only properly referencing its CSS if it has a background-color applied... am I stupidly overlooking something, or is this some issue with Android Browser? Any ideas how to fix it?
Thanks for your time.
While it may not be the best solution, I finally just made an "invisible" transparent png and set it as the <p>'s background, and that fixed the issue... if you can call it fixing. :) I have to assume it is some kind of error in Android's Browser, as I tried this in every browser, desktop and mobile.
It is the intended behavior of Android phones. It will enhance the readability of copy text, since you are not forced to scroll sideways if you pinch zoom the page.
It can be managed on your own phone maybe in the browser's settings, but that is not the solution you want.
It can be 'fixed' by the workaround of applying a background-image to the element you want.
This can be done with a base64 encoded data url:
background: url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7);
In your mobile browser's settings, look for something called "Auto Fit Pages" and disable it. This setting (in Android) is ON by default. Turn it off and your text will flow as it should.
the div or any element above this could be the issue.
if you give fixed width to the p element, does it work well ?