3

I made a dialog with both Enter and Exit slow animations. But the dialog contains a webview myMsg (that loads a local file, so no delay) and messes up the animation.

With the code below (no webview), the dialog works perfectly, animating both at Enter and at Exit. However, if I uncomment the line //builder.setView(myMsg), the Exit animation still works perfectly, but the Enter animation is not performed (or performed too fast). Funny thing, if I minimize the app and maximize it again, the Enter dialog animation is performed fine.

It's like the webview load messes the Enter animation. I tried to show the dialog after the webview is loaded, with the same results.

Isn't that crazy?? Any clue of what is happening, and how to solve it? Any help would be appreciated.

Here's the relevant part of the code:

    WebView myMsg = new WebView(context);
    myMsg.loadUrl("file:///android_asset/page.html");

    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setIcon(R.drawable.ic_launcher);
    //builder.setView(myMsg);
    builder.setTitle("Some Title");
    final AlertDialog dialog = builder.create();

    WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
    lp.windowAnimations = R.style.AnimateDialog;

    dialog.show();
    dialog.getWindow().setAttributes(lp);

and in styles,

<style name="AnimateDialog">
    <item name="android:windowEnterAnimation">@anim/in_left</item>
    <item name="android:windowExitAnimation">@anim/out_left</item>
</style>

EDIT

I tried with a setWebViewClient, but without luck (without the line dialog.getWindow().setLayout... the Enter animation simply does not work):

    WebView myMsg = new WebView(context);
    myMsg.getSettings().setJavaScriptEnabled(true);
    myMsg.loadUrl("file:///android_asset/" + page);
    myMsg.setBackgroundColor(0);
    myMsg.setSoundEffectsEnabled(true);

    AlertDialog.Builder builder = new AlertDialog.Builder(context);
    builder.setIcon(R.drawable.ic_launcher);
    builder.setTitle("SomeTitle");
    builder.setView(myMsg);
    final AlertDialog dialog = builder.create();

    myMsg.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            dialog.show();
            dialog.getWindow().setWindowAnimations(R.style.AnimateDialog);
            dialog.getWindow().setLayout(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.FILL_PARENT);
        }
    }

EDIT2

I also tried with Dialog instead of AlertDialog, with an xml layout, getting identical problems (tried also WebView.loadData instead of WebView.loadUrl, same problems):

    final Dialog d = new Dialog(context);
    d.setContentView(R.layout.viewhtml);
    d.setTitle("SomeTitle");
    // Without this, Enter animation does not work
    d.getWindow().setLayout(WindowManager.LayoutParams.FILL_PARENT,
            WindowManager.LayoutParams.FILL_PARENT);
    WebView wv = (WebView) d.findViewById(R.id.webview);
    wv.loadUrl("file:///android_asset/" + page);
    wv.setBackgroundColor(0);
    d.getWindow().setWindowAnimations(R.style.AnimateDialog);
    wv.setWebViewClient(new WebViewClient() {
        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            d.show();
        }
    });

and this is Dialog xml layout file:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

<WebView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/webview"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:soundEffectsEnabled="true" >
</WebView>

</LinearLayout>

EDIT3

I just realized that the same problem happens when using a TextView with TextView.setText(Html.fromHTML...) instead of a WebView. Moreover, if I add dialog.getWindow().setLayout(600,800) after dialog.show(), the animation is performed as expected. So it seems that the problem is that the animation is not performed without knowing beforehand the dialog size?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Luis A. Florit
  • 2,169
  • 1
  • 33
  • 58

2 Answers2

0

I have a similar problem but instead of putting animation, I want to disable it because it is messing up with the apparent load time of my Dialog with WebView. I was actually able to disable the main window animation Enter/Exit as it is no longer fading in/out but the problem is the content of the WebView is most of the time delayed by the Slide animation of the Dialog which I am also trying to disable (I really thought if you disable the window animation, all animations should be disabled).

Based on my tests, this is actually a Jellybean bug but it is most obvious in Android 4.3 and the extra animation is messing up my popups. There is no problem with ICS though.

If you try to increase the default animation time via Android Settings -> Developer Options -> Window animation scale, say to 5 or even 10, you will notice that the content is now even further delayed in showing. But if you turn off the animation, the display will be fast. I believe your animation might work too if the default animation is disabled.

I think this behavior is a Jelly bean bug which is only present when you use a WebView inside a Dialog. The dialog puts the WebView content after the animation time even though it should already had been disabled sliding it as it grows in height.

Another solution I tried is to cache the Dialog so that it can be reused. My problem goes away but it is sometimes not resizing properly to the actual HTML content. Now if your content is mostly the same length when displayed, you could probably just cache your Dialog.

I hope I have given you much clues.

  • I have the same problem in ICS and JB, so it is not JB problem. Two more questions regarding your answer: How do I disable the default animation? How do I cache my webview? Some weird behaviour I have is that if I set `dialog.getWindow().setLayout(WindowManager.LayoutParams.FILL_PARENT, WindowManager.LayoutParams.FILL_PARENT)` then the animation is performed ok. But with `WRAP_CONTENT` is not. Thanks a lot for taking time to write your detailed answer. – Luis A. Florit Aug 05 '13 at 00:18
  • Another problem that I have, even with `WindowManager.LayoutParams.FILL_PARENT`, is that the webview content is loaded after the animation ends (0.15s), unless I ask for a long animation time (0.5s). – Luis A. Florit Aug 05 '13 at 01:22
  • I have made additional tests with real devices and found out the behavior I had discussed is only present in Android 4.3 (my former tests with old versions of Jelly bean is only with the Emulator which is very slow). If the behavior you had with animations is also present in ICS and JB, then it could be a different problem. – user2647899 Aug 05 '13 at 09:00
0

The reason why your dialog animation seemed to be messed up by the WebView is the asynchronous nature of the loading of WebView's content. So putting the loadUrl, loadData or even loadDataWithBaseURL before dialog.show() is not a guarantee that the content is already fully loaded even if the content comes from local file or string. There is still a slight delay (normally split of a second or less than a second).

If you want to truly display the dialog only after the WebView content is fully loaded, you will have to show the dialog inside onPageFinished of WebViewClient. I have tested this and it worked fine with ICS, but of course with a slight delay from the time the user activated the dialog and the availability of WebView content. If the slight delay is fine then this solution could be for you.

You could modify your code this way (Updated to include setWebViewClient):

WebView myMsg = new WebView(context);

AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setIcon(R.drawable.ic_launcher);
builder.setView(myMsg);
builder.setTitle("Some Title");
final AlertDialog dialog = builder.create();

// hook a listener for page load complete
WebViewClient webviewclient = new WebViewClient() {
    @Override  
    public void onPageFinished(WebView view, String url) {
        super.onPageFinished(view, url);
        dialog.show(); // show the dialog here
    }
};
myMsg.setWebViewClient(webviewclient);

myMsg.loadUrl("file:///android_asset/page.html");
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();
lp.windowAnimations = R.style.AnimateDialog;

//dialog.show(); // do not show until content is truly available
dialog.getWindow().setAttributes(lp);

I have tested it with my Nexus 7 with Android 4.3, but the showing of the content is still delayed by the system animation time just like I had discussed in my previous suggestion so you will have to solve the same problem I had on Android 4.3.

  • Yes, I have tried the `onPageFinished` (you forgot to attach the `WebViewClient` to the `WebView`, right?). But the problem persists. And now the Entry animation simply does not work, even with `WindowManager.LayoutParams.FILL_PARENT`, unless you put it inside the `WebViewClient`. Please, take a look at the EDIT of my original post to see the only thing that makes the animation works (but still only with `WindowManager.LayoutParams.FILL_PARENT` and still asynchronous). Any idea how to disable the default animation first? – Luis A. Florit Aug 05 '13 at 14:00
  • Actually, after executing the Dialog action, the LogCat shows two lines at the end: `WebView(17458): onSizeChanged - w:582 h:0` and `WebView(17458): onSizeChanged - w:582 h:708`. So why does it begin with 0 height, but nonzero width? – Luis A. Florit Aug 05 '13 at 14:23
  • Ah, yes I forgot to copy the code that attaches the WebViewClient to the WebView as I am using my own code. In my own code, I am actually using an XML layout with WebView having FILL_PARENT for layout_width and WRAP_CONTENT for height so I do not have to set in in code. Can you try doing the same? The default animation is supposed to be replaced when you set the Dialog animation. – user2647899 Aug 06 '13 at 05:06
  • Regarding the Dialog width starting nonzero while the height zero, I think it is because the dialog grows vertically with the length of the content. – user2647899 Aug 06 '13 at 05:20
  • Or maybe, inside `onPageFinished`, you can try to put the call to `show` after the layout has been set if you do not want to put the layout in an XML file. – user2647899 Aug 06 '13 at 07:21
  • Thanks again for your time and the suggestions. I tried all (look at the new Edit, please): (1) Using a XML gives identical problems, even with a Dialog instead of AlertDialog. (2) I also tried before putting inside `onPageFinished` the `dialog.show` at the end: I get the same bad behaviour, but now with the added problem that the dialog crashes when orientation is changed, because of this: http://stackoverflow.com/questions/1111980/how-to-handle-screen-orientation-change-when-progress-dialog-and-background-thre – Luis A. Florit Aug 06 '13 at 16:42