Just as it’s important for an Android developer to understand how to support multiple screen sizes, so too is it important to understand how the Android framework handles the scaling of the content in a WebView.
To demonstrate the scaling that takes place within a webview, I’m going to use a basic example of a webview that displays a local image and some text underneath it – as some additional information, the device used in this example is a Galaxy Nexus with an xhdpi screen (320 dpi) and resolution of 1280×720. Below is the HTML and CSS used and the result of the app run on the said device:
<
html
>
<
head
>
<
link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"sample.css"
/>
</
head
>
<
body
>
<
img
src
=
"localImage.png"
/>
<
p
>
Lorem ipsum dolor sit amet, consectetur adipisicing elit<
br
>
bla bla bla
</
p
>
</
body
>
</
html
>
|
the CSS…
img
{
display
:
block
;
margin-left
:
auto
;
margin-right
:
auto
;
}
p
{
background-color
:
#E4E4E4
;
padding
:
1em
;
margin
:
0.5em
;
border-radius:
15px
;
font-size
:
1em
;
}
|
and finally the result…
Immediately it becomes obvious that the 300×200 local image has been scaled up considering the resolution of the device. Essentially what the Android framework is doing is assuming that the web content is targeted at an mdpi density (which Android treats as the base density), and as a result scales the content up accordingly for the xhdpi test device so that the drawn elements match the physical size they would appear on an mdpi display. Unless you explicitly specify the density you are targeting, Android will scale up/down accordingly.
To adjust the scaling performed by the Android framework, one can use the viewport
meta tag to specify properties regarding screen density support:
<meta name="viewport" content="target-densitydpi=device-dpi" />
The Android docs explain the target-densitydpi property as follows:
You can use this to specify the target density for which the web page is designed, using the following values:
device-dpi
– Use the device’s native dpi as the target dpi. Default scaling never occurs.high-dpi
– Use hdpi as the target dpi. Medium and low density screens scale down as appropriate.medium-dpi
– Use mdpi as the target dpi. High density screens scale up and low density screens scale down. This is also the default behavior.low-dpi
– Use ldpi as the target dpi. Medium and high density screens scale up as appropriate.– Specify a dpi value to use as the target dpi (accepted values are 70-400).
So if we use this information and modify our HTML to prevent default scaling:
<
html
>
<
head
>
<
link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"sample.css"
/>
<
meta
name
=
"viewport"
content
=
"target-densitydpi=device-dpi"
/>
</
head
>
<
body
>
<
img
src
=
"localImage.png"
/>
<
p
>
Lorem ipsum dolor sit amet, consectetur adipisicing elit<
br
>
bla bla bla
</
p
>
</
body
>
</
html
>
|
and run the test app again, we get:
One can now see that no scaling has taken place; the image is displayed as one would expect a 300×200 image on such a device, and the text is significantly smaller. Without the scaling it becomes obvious that the graphic and styles used are not suitable for the xhdpi device, so these would ultimately need to change yet still cater for other densities.
In many simple cases like our example, all we want is to be able to develop and test the web content against a specific test device to ensure that it looks correct, and then allow Android to scale up/down from there. To achieve this, one can declare the specific target density (or even the exact dpi) for which your content is being designed. The following demonstrates this using our example designed for the Galaxy Nexus (320 dpi):
<
html
>
<
head
>
<
link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"sample.css"
/>
<
meta
name
=
"viewport"
content
=
"target-densitydpi=320"
/>
</
head
>
<
body
>
<
img
src
=
"localImage.png"
/>
<
p
>
Lorem ipsum dolor sit amet, consectetur adipisicing elit<
br
>
bla bla bla
</
p
>
</
body
>
</
html
>
|
img
{
display
:
block
;
margin-left
:
auto
;
margin-right
:
auto
;
}
p
{
background-color
:
#E4E4E4
;
padding
:
1em
;
margin
:
0.5em
;
border-radius:
15px
;
font-size
:
2em
;
}
|
With the CSS modified a bit for the higher density and a new higher resolution graphic, we see the following result:
We are now happy with the look of the web content on our device, and because we have told the Android framework the specific density we are targeting it will automatically scale up or down for devices with higher or lower densities respectively. The following is a screenshot of the same HTML/CSS and graphic on a lower density emulator:
Having said all of this, YMMV with this basic approach. Allowing Android to perform scaling like this may have undesirable results with certain aspects, such as image quality. A more in-depth method for dealing with web content and multiple screen sizes and densities is to provide specific styles/graphics for different densities using the CSS media
feature; more information about this can be seen here.
Very useful article… saved me a lot of anguish. Thanks. And lucky you living in Cape Town!