Frage

I have a strange problem with a WebView I want to use to display an image and make it zoomable. I have the following method within my Activity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_manual);

    WebView webView = (WebView)findViewById(R.id.webView);      
    webView.loadUrl("file:///android_res/drawable/some_image.jpg");
    webView.setInitialScale(getScale());
    webView.getSettings().setBuiltInZoomControls(true);
}

The getScale() method computes a scale I can use with webView.setInitialScale() to exactly scale my image to full screen width, and it works. The builtin zoom controls also work to some extent, but:

After I zoomed into the image, I can't zoom out back to my initial scale, I assume because the minimum scale is greater than my initial scale.

Setting the zoom density using WebSettings doesn't help, and I think even if it did on my phone it wouldn't on another.

What I also tried: I made an HTML-Page containing the image as only child of the body element. I set its width to 100% and also got it scaled right that way. However if I zoom in again, the image immediately is resized to again fit the screen width.

I found some answers, but none of them really helped:

    webView.getSettings().setLoadWithOverviewMode(true);
    webView.getSettings().setDefaultZoom(ZoomDensity.FAR);
    webView.getSettings().setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);

One solution mentioned employing reflection to change the WebView class to ignore the limits, but I fear this could break my app on some older versions of Android. I have to be compatible with devices down to API level 9.

War es hilfreich?

Lösung

I think I found a solution for most situations like this, as long as we just want to load a single image. It's kind of a workaround, and loses some image details as it resizes the image. Nevertheless it should work on most if not all devices out there.

I followed the approach to embed the image into a basic HTML page, and filled the <img> tag with the width of the screen in pixels. For simplicity I skipped loading the HTML from a file and just generated it inside my Java code:

private String generatePage() {
    Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); 
    int displayWidth = display.getWidth();

    String result =
            "<html>"
            + "<meta name=\"viewport\" content=\"target-densitydpi=device-dpi,width=device-width\">"
            + "<head>"
            + " <title>Title</title>"
            + "</head>"
            + "<body>"
            + "<image id=\"myImage\" src=\"drawable/image.jpg\" width=\"" + displayWidth + "px\" />"
            + "</body>"
            + "</html>";
    return result;
}

I added this method to my Activity and used it to generate the code matching the device it runs on. The onCreate() method now can be pretty straightforward:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_manual);

    WebView webView = (WebView)findViewById(R.id.webView);

    webView.loadDataWithBaseURL("file:///android_res/", generatePage(), "text/html", "utf-8", null);
    webView.getSettings().setBuiltInZoomControls(true);
}

Important note: There are two details that you need to keep in mind, or it won't work.

  1. You need to use the method webView.loadDataWithBaseURL(...), otherwise you can't access the local android ressources inside the HTML. This way the src attribute couldn't point to your image file.

  2. You need the tag <meta name="viewport" content="..."> inside your HTML code, and it has to include target-densitydpi=device-dpi inside its content attribute. Otherwise the size of the image may still not match your viewport.

Note: You also can specify a minimal-scale inside the viewporttag, and this really affected my webview. The bad thing: At least on my Galaxy S3 mini running Jelly Bean 4.1.2 a minimal-scale of less than 1.0 had no effect.

Andere Tipps

May be this is what your are searching

settings.setBuiltInZoomControls(true);
settings.setSupportZoom(true);
settings.setUseWideViewPort(true);
settings.setJavaScriptEnabled(true);
settings.setJavaScriptCanOpenWindowsAutomatically(true);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top