How to improve performance of JS draggable menu in WebView on Android
Asked Answered
G

5

16

We have a web application shown in WebView on Android and we have performance issue on older Android tablets that we really need to deal with

  • We are using iScroll-lite for javascript dragging
  • We set hardware acceleration to true, set rendering priority to high and the WebView lets through only one MOVE touch event in 80ms interval

Is there anything more we can do?
Is there maybe some faster alternative to iScroll-lite?

We don't know what exactly makes it so slow. It for example runs on phone Sony Erricson with 1 GHz, 512 MB RAM with Android 2.3 smoothly but on tablet Qualcomm 1GHz, 512 RAM with Android 4.0 you make a drag and you actually have to wait to see any outcome. The only difference I see in Android version and screen resolution.

Geesey answered 29/12, 2012 at 17:46 Comment(1)
You might find some answers here: touchpunch.furf.comUnlike
H
2

It might not be the Javascript after all. Android WebViews tend to have quite unexpected performance issues.

Try to deactivate all unnecessary CSS and see if performance improves. If so, you can re-add the CSS styles iteratively to locate the culprit.

And do not use any kind of animated GIFs. Our experience is that this (strangely enough) drags down performance drastically.

Halide answered 1/1, 2013 at 13:58 Comment(0)
T
2

My suggestion is that you write the drag by yourself. It's not difficult. The key part of code looks like below:

var yourDomElement = document.getElementById("demoDrag");
yourDomElement.addEventListener("touchstart", function (e) {
    e.preventDefault();
    //todo
});
yourDomElement.addEventListener("touchmove", function (e) {
    //todo: 
});
yourDomElement.addEventListener("touchend", function (e) {
    //todo
});

You can find many sample code here (e.g. /assets/www/scripts/novas/framwork/nova.Carousel.js, also the scroller.js). You should read the sample code to learn how to write your own "drag".

If you still have no idea, you can contact our team to finish your task for you. We make phonegap apps with very good performance.

Tomtit answered 8/1, 2013 at 2:28 Comment(1)
Possibly, you can write no more than 100 lines of code to do a high-performance dragging.Tomtit
C
2

What about using div with overflow set to auto and then applying this fix so that elements can be scrolled

http://chris-barr.com/index.php/entry/scrolling_a_overflowauto_element_on_a_touch_screen_device/

Short extract:

function touchScroll(id){
    var el=document.getElementById(id);
    var scrollStartPos=0;

    document.getElementById(id).addEventListener("touchstart", function(event) {
        scrollStartPos=this.scrollTop+event.touches[0].pageY;
        event.preventDefault();
    },false);

    document.getElementById(id).addEventListener("touchmove", function(event) {
        this.scrollTop=scrollStartPos-event.touches[0].pageY;
        event.preventDefault();
    },false);
}
Consent answered 8/1, 2013 at 3:14 Comment(0)
M
1

We have tried to get iScroll to work smoothly in a phonegap-app on the iPad(2/3), but we were not able to make that happen. Get anywhere near an acceptable in performance even though all stand-alone examples ran super smooth. We finally ended up using -webkit-overflow-scrolling:touch have you looked into that one yet? I know you need this for Android so I cannot say if it is as good there as on iOS6, but on the iPad it worked like a charm.

Mendelism answered 5/1, 2013 at 3:55 Comment(1)
-webkit-overflow-scrolling:touch is not implemented on android webview - you can neither make an iframe nor any other overflowing content touch-scrollable at all, only complete pages. So far, for Android there's the need for Js libraries like appframework's scroller plugin, iScroll, Leo Cai's solution below, or *younameit*... in order to achieve touchscrolling.Carny
S
0

If you want to REALLY make a difference, I'd suggest you my approach:

I did a JavaScript-callable function for creating another WebView ("child webview") that I would use like an Iframe and fill with content, so from the JS application I could do:

insertWebView (x,y,w,h,"<div>.......</div>").

You have to do some one-time work to stabilish a way to comunicate both webviews, but you get the idea. Please find below attached the source of my insertWebView function for inspiration.

The improvement was awesome, as those tiny iframe-webviews not only performed awesome, but stuff like the glowing overscroll, multitouch (now they are different webviews!) etc provided a near-native experience.

I also did an extension to use native drag and drop between webviews.

Probably it was not very efficient memory-wise, but in terms of user experience believe me it was worth the effort, thousand times.

good luck!

public void insertWebView(int code, int x0, int y0, int w, int h, String url, int vertical, String initContent, String params, int alpha, int rot, int screenId) {

        PlasmaWebView webview1 = getWebView(code);

        if (webview1 != null) {
            if (Conf.LOG_ON) Log.d(TAG, "WEBVIEW: Reusing  webview " + code + " at " + x0 + "," + y0 + "," + w + "," + h + " vertical " + vertical+", rot="+rot);
            webview1.setVerticalScrollBarEnabled(vertical == 1);
            webview1.setHorizontalScrollBarEnabled(vertical != 1);
            webview1.move(x0, y0, w, h, Funq.this);
            if ((alpha>0) && (alpha<100)) webview1.setAlpha((float)alpha/100);
            webview1.setRotation((float)rot/10);
            webview1.handleTemplateLoad(url, initContent);
            return;
        } 

        if (Conf.LOG_ON) Log.d(TAG, "WEBVIEW: Insert webview " + code + " at " + x0 + "," + y0 + "," + w + "," + h + " vertical " + vertical + " url " + url+" alpha "+alpha+", rot="+rot);

        webview1 = new PlasmaWebView(Funq.this.getBaseContext(), code, vertical==1, useHardware, jvs, screenId);
        if ((alpha>0) && (alpha<100)) webview1.setAlpha((float)alpha/100);
        webview1.setRotation((float)rot/10);

        RelativeLayout.LayoutParams p=webview1.createLayout(x0, y0, w, h, Funq.this);
        layerContainer.addView(webview1, p);
        webview1.handleTemplateLoad(url, initContent);
    }
Smell answered 12/5, 2013 at 1:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.