ng-animate is not working in android WebView of Sa

2019-07-22 06:07发布

问题:

I'm trying to implement an animation with ng-animate for a button in an Android hybrid app in which I use WebView.

The animated button is like this:

<div class="dish-like dish-like-animater">
    <img ng-hide="page.liked" class="dish-like-unliked" src="http://dev.fotodish.com/img/dish_like_icon@2x.png" ng-click="Like()">
    <img ng-show="page.liked" class="dish-like-liked-up" src="http://dev.fotodish.com/img/dish_liked_bg@2x.png">
    <img ng-show="page.liked" class="dish-like-liked-down" src="http://dev.fotodish.com/img/dish_liked_icon@2x.png" ng-click="Unlike()">
</div>

Please check this fiddle for details: http://jsfiddle.net/QcH8m/

I've tested the animation on desktop Chrome, a Samsung Galaxy S4, and a Moto G. And currently, the animation works fine in all the following environments:

  • desktop Chrome,
  • Android Browser ("Internet") on this Galaxy S4,
  • Chrome on this Galaxy S4,
  • Chrome on this Moto G,
  • WebView on this Moto G

However, when I tried to run it in the WebView on this Galaxy S4, its behavior was quite weird. At the very beginning, before I clicked on it, it looked ok, whether page.liked was true or false. However, when I clicked on it, everything just disappeared. And an error occured. The stack trace was like this:

03-21 16:40:32.412    6019-6019/com.fotodish.android E/Web Console﹕ TypeError: undefined is not a function
        at file:///android_asset/www/bower_components/angular/angular.js:11330:9
        at afterReflow (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:1092:11)
        at Object.fn (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:1585:13)
        at file:///android_asset/www/bower_components/angular-animate/angular-animate.js:450:46
        at Array.forEach (native)
        at forEach (file:///android_asset/www/bower_components/angular/angular.js:322:11)
        at run (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:438:11)
        at Object.before (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:471:13)
        at performAnimation (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:897:16)
        at Object.removeClass (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:702:11):9509
03-21 16:40:32.432    6019-6019/com.fotodish.android E/Web Console﹕ TypeError: undefined is not a function
        at file:///android_asset/www/bower_components/angular/angular.js:11330:9
        at afterReflow (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:1092:11)
        at Object.fn (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:1585:13)
        at file:///android_asset/www/bower_components/angular-animate/angular-animate.js:450:46
        at Array.forEach (native)
        at forEach (file:///android_asset/www/bower_components/angular/angular.js:322:11)
        at run (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:438:11)
        at Object.before (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:471:13)
        at performAnimation (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:897:16)
        at Object.removeClass (file:///android_asset/www/bower_components/angular-animate/angular-animate.js:702:11):9509

I'm using angular 1.2.14 and angular-animate 1.2.14. An other animation regarding ng-view works fine at the same time...

The WebView settings are like:

    mWebView = (WebView) findViewById(R.id.webview);
    WebSettings webSettings = mWebView.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setAllowUniversalAccessFromFileURLs(true);
    webSettings.setDatabasePath("/data/data/" + this.getPackageName() + "/databases/");
    webSettings.setDomStorageEnabled(true);
    mWebView.setWebChromeClient(new WebChromeClient());

The Galaxy S4 runs Android 4.3, the original Samsung one. The Moto G also runs Android 4.3.

The UserAgent string of this Galaxy S4 is:

Mozilla/5.0 (Linux; U; Android 4.3; en-us; SAMSUNG-SGH-I337 Build/JSS15J) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30

Anyone has an idea what has happened?

回答1:

As I inspected, ng-animate seems very incompatible with the WebView of Samsung Galaxy mobile phones with Android 4.3 or lower. Android 4.4 Galaxies with Chrome WebView seem fine. It seems that it's something wrong with ng-animate's auto-reflow.

With ng-animate enabled, the strange things are:

  • For ng-switch and ng-show / ng-hide, after the animation, the element leaving is gone, but the element entering does not appear.
  • For ng-view, when a new page enters, it behaves like that the old one is still there, although not visible. When you try to click on the page, it behaves like that you are actually clicking on the old page.

My current and temporary solution:

Turn off $animate service for Samsung Galaxy phone users. When $animate is disabled, they can use the functions normally, thought without animations. Add the following code into .run function:

var s = ((function isSamsungWebkit(ua) {
    return (ua.indexOf('SAMSUNG') != -1 || ua.indexOf('SGH') != -1 || ua.indexOf('SCH') != -1 || ua.indexOf('GT-I') != -1) && ua.indexOf('534.30') != -1;
})($window.navigator.userAgent));
console.log("Samsung Hack", s);
$animate.enabled(!s);

It's not the best solution, but one solution.