Developer diary

[How to] Fixed page width on Android WebView or Cordova/PhoneGap (and disabling double click/tap to zoom)

The problem

While working on Scan Wars / Alien Blitz I came across a problem with fixed HTML page width in a WebView (and later on I had the same problem with PhoneGap).

Basically what I want in my UI is to have a fixed 800px width, so the screen should be stretched accordingly to the true mobile screen resolution.

I don’t want to use responsive design as I think it’s pretty useless for a UI constructed with images. It is very useful if your UI is made mostly thanks to CSS, but when using images everywhere (all the buttons, frames, … are made using 9 patch images) then you have to deliver resized images for all DPI (basically 3-4 sets of images resized to different resolution). It’s a lot of work, and it’s pretty useless.

The “solution”

Theoretically setting the page width is very easy, just google that problem, solution is to add a viewport meta tag in HTML:

<meta name="viewport" content="width=800"/>

And all should go smoothly on PhoneGap, default WebView users must also add this to their Java code:

WebSettings settings = myWebView.getSettings();
settings.setUseWideViewPort(true);

Ok, so everything’s fine… no ?

Welcome to the wonderful world of Android development

No, everything’s not fine at all, the major problem is that enabling the UseWideViewPort option will also enable… double tap to zoom… Why ? I have no idea, it doesn’t make any sense to me.

Activating fixed width on all devices

Basically we will try to activate fixed page width by every mean possible, I will focus on Cordova/PhoneGap, if you are using a WebView it is almost the same code, just a bit simplified (change reference of CordovaWebView to WebView, remove Cordova/PhoneGap specific code)

There are two methods provided, you should try the “defaultFixedViewport” solution first and see if it suits your needs. I personally had trouble with it on Android 4.4 when the page is larger than viewport width (ie when I want some horizontal scrolling), and the  “forceFixedViewport” works better in this case.

Setting WebView configuration

    private int getScale()
    {
        Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
        int width = display.getWidth();
        Double val = new Double(width) / 800d;
        val = val * 100d;
        return val.intValue();
    }

    private void forceFixedViewport()
    {
        CordovaWebView myWebView = appView;
        WebSettings settings = myWebView.getSettings();

        settings.setLoadWithOverviewMode(false);
        // Activating viewport on Android 2.x will deactivate stretching
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.HONEYCOMB)
        {
            // Set default zoom to unzoom, no setting this will sometimes trigger zoom 100% on some phone (like double tap)
            // It seems to glitch on Android 2.x, a white screen will appear after enabling this option
            //settings.setDefaultZoom(WebSettings.ZoomDensity.FAR);
            // Force using viewport html statement, sadly it activates double tap to zoom
            settings.setUseWideViewPort(true);
        }
        // Try not to use default zoom (useful ?)
        settings.setSupportZoom(false);
        settings.setBuiltInZoomControls(false);
        // Set scale on devices that supports it
        myWebView.setPadding(0, 0, 0, 0);

        //Enable DOM storage, and tell Android where to save the Database
        //settings.setDatabasePath("/data/data/" + this.getPackageName() + "/databases/");

        int percentScale = getScale();
        myWebView.setInitialScale(percentScale);
    }

    private void defaultFixedViewport()
    {
        CordovaWebView myWebView = appView;
        WebSettings settings = myWebView.getSettings();
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);
    }

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        this.init();
        super.loadUrl(Config.getStartUrl());
        
        //Choose between two methods
        defaultFixedViewport();
        //forceFixedViewport();
    }

On PhoneGap the file to be modified is located in /platforms/android/src/…/, it’s called HelloWorld.java by default
This modification is local, and can’t be used with remote building directly

Deactivating double click/tap to zoom

To deactivate double click you will quickly find a solution on Google that makes use of a custom GestureListener, problem is it is not 100% reliable, sometimes zoom will still be triggered, I don’t know why (seems to happens randomly, more often if two thumbs are on screen, and it seems to be ok if selection is disabled). The other problem is that if user clicks a lot on something, all clicks will be ignored, and I don’t want that for Alien Blitz (I want the user to be able to click a lot on the “buy ammo” button for example, some clicks can be ignored, but not all).

In case everything fails (which shouldn’t happen), we will also detect zoom change and revert zoom when it occurs. Problem is that sometimes it will mess up with the UI (especially on VM), and it’s a bad user experience (page will zoom in and quickly zoom out)

PhoneGap/Cordova : override default WebView

First we need to extend the generic WebView (or CordovaWebView), it can be done easily if you are not using PhoneGap/Cordova. On these platforms you need to override the init method

    @Override
    public void init()
    {
        CordovaWebView webView = new SWWebView(this);
        CordovaWebViewClient webViewClient;
        webViewClient = new SWWebViewClient(this, webView);
        this.init(webView, webViewClient, new CordovaChromeClient(this, webView));
    }

Custom WebView

Create a new class (named SWWebView in our example) that extends WebView or CordovaWebView. I will let you work on the details (default constructor,…) and we will override the onTouchEvent function:

    private long    lastEventTime        = -1;

    @Override
    public boolean onTouchEvent(MotionEvent ev)
    {
        long eventTime = ev.getEventTime();
        int action = ev.getAction();

        switch (action)
        {
        case MotionEvent.ACTION_MOVE:
        {
            return super.onTouchEvent(ev);
        }
        case MotionEvent.ACTION_DOWN:
        {
            return super.onTouchEvent(ev);
        }
        case MotionEvent.ACTION_UP:
        {
            if (System.currentTimeMillis() - lastEventTime < 1000)
            {
                //Cancel all touch actions
                ev.setAction(MotionEvent.ACTION_CANCEL);
                super.onTouchEvent(ev);
                //Restart the current action
                ev.setAction(MotionEvent.ACTION_DOWN);
                super.onTouchEvent(ev);
            }
            ev.setAction(MotionEvent.ACTION_UP);
            lastEventTime = System.currentTimeMillis();
            return super.onTouchEvent(ev);
        }
        return super.onTouchEvent(ev);
    }

This should cancel all double tap events, preventing zooming. This code will send a cancel event to the WebView whenever two taps occur within 1000ms (We don’t use ViewConfiguration.getDoubleTapTimeout() as it doesn’t really seem reliable). As all events have been canceled a down event is sent back before restoring the original up event. This means all information about the previous down event (position,…) are lost in the process. This could be improved but I didn’t have the need to do it.

Custom WebViewClient

Second thing to do is to make sure the zoom is canceled whenever it is triggered (even if it shouldn’t be)

Create a new class named SWWebViewClient in this example, it must extends WebViewClient or CordovaWebViewClient. Do the details (constructor,…) and let’s override the onScaleChanged function:

    @Override
    public void onScaleChanged(WebView view, float oldScale, float newScale)
    {
        view.zoomOut();
    }

It should reset zoom whenever it is changed, with some little drawbacks (interface might be badly updated, bad user experience).

Conclusion

As far as I know this code should work on all 2.3+ devices. But it still needs some more testing and as not been widely tested, so I will update this post accordingly whenever I encounter a problem/solution.

Like all my posts on this blog comments are disabled (I got tired of having to deal with Spam), but you can contact me on Twitter if you need some more info : @Haedri
My email should also be available somewhere on this website (in the About section)

Source sample (Cordova/PhoneGap)

Here is a sample of the above modifications on the default HelloWorld project of PhoneGap

Download sample source folder

These 3 files are supposed to go to the /platforms/android/src folder. This will activate fixed width + deactivate double tap to zoom.
Warning! If you want to apply these modifications manually on your own project don’t forget to change the “super.init();” to “this.init();” of the default onCreate method.

PDF

Download the PDF version of this page here : android-fixed-width-20140131

Document history

2014-02-02

I noticed some problems with the easy solution, on Android 4.4 when the page is larger than viewport width (when there should be horizontal scrolling) then the viewport width seems to be ignored. So I’ve restored old solution and you can now choose between both.

There are still problems on Samsung devices…

2014-01-31

Added current PDF + sample source zip.

2014-01-30

Changed the code to lock page width; after some more testing it seems this new code works even better (and I can’t reproduce anymore the old problems I had on some devices, I have absolutely no idea why).
In case you get some errors don’t hesitate to contact me with your test reports, I’ve saved the old page in this PDF : android-fixed-width-20140130

2014-01-29

It seems this page is interesting for some people, so I’ve decided to put a license text (bottom of the page). It’s just a simple CC-by-attribution license, do what you want with this tutorial, but please give me some credit.

2013-12-06

Typo

2013-11-29

Spent a few hours digging the Android SDK source, and finally came up with a reliable solution to disable double tap to zoom, and not losing events (previous solution forbade tapping twice in less than 500ms, the webview was receiving only one tap event). We use a cancel event when needed to cancel all previous events.

2013-11-26

Added some links and a better explanation for GestureListener problem

Added a correct double tap delay using ViewConfiguration.getDoubleTapTimeout()

2013-11-24

Corrected code for Android 2.x, activating viewport on Android 2.x seems to deactivate completely stretching, and the viewport tag seems to be ignored.

I’ve also removed the default zoom on Android 2.x, once activated it displays a white screen instead of the page (which can be removed by tapping )

2013-11-21

First version

License

Creative Commons License
This page is licensed under a Creative Commons Attribution 4.0 International License.

Basically you can do almost anything you want as long as you give the correct attribution (link to my domain, my twitter, or this page for example)

The code itself (classes, functions,…) is not copyrighted (CC0), you can do whatever you want with it

Read more

Alien Blitz, menu update in progress

Small news, I just wanted to say that I’m currently working on the new menu system for Alien Blitz. In a screenshot you can’t really tell the difference, but at usage it’s a lot nicer :

  • There are animations everywhere : when opening windows, clicking stuff, removing money,…
  • All the windows can now scroll, it makes creating new window and adding content to them A LOT easier
  • I’m also reviewing all the menus, to make them nicer and to add some tooltips

I think this will be completed within 2 weeks, next update will include these changes, and as I don’t want it to be only a cosmetic update I will also add 4 maps to the full version (available at anytime)

Here’s what it looks like at the moment :

Capture d'écran - 18112013 - 19:54:07

Capture d'écran - 18112013 - 19:54:00

 

Read more

Progress / random news / new projects

Some uncategorized/random news 🙂

ScanWars

Some nice progress have been made, sadly we are kinda changing a lot of the gameplay every time we have a meeting, so development is quite chaotic. And we are seriously laking a graphic designer.

I doubt this game will ever be finished at this point, so I am beginning to consider working on something else. The main problem being I am the only one working full time on it, which make things hard (and I won’t be full time after February anymore). But I will be able to reuse stuffs I have developed for other projects, so everything is not “lost”.

Alien Blitz

I am currently working on rewriting the menus of Alien Blitz, I am reusing the UI framework I developed for ScanWars. This will make menus a lot nicer (lots of animations, use of some touch events,…) and I will be able to add more information/update UI a lot more easily.

Basically the UI is written in JavaScript/HTML/CSS, and it will call Java to get/update information. I won’t port this new UI to the desktop version, it will be only for Alien Blitz.

Other projects I have in mind / will work on

  • A space exploration game
    • Mobile only (maybe also browser later)
    • Inspired by games I loved : Space Trader (palmOS) / Eve online / FTL / SPAZ
    • Multiplayer content (no real time interactions, but you will visit/attack other players, actions you do have an impact on the whole universe for all players,…)
    • Multiple jobs : merchant, miner & fighter
    • Customization : big ships choice, and lots of upgrades (weapons, mining lasers, cargo space,…)
    • Good (fight pirates,…) or evil choices (buy/sell narcotics/weapons, mine in forbidden areas, fight merchants,…)
    • Long (solo) main quest, lots of side quests
    • Will reuse ScanWars code (server & client side)
    • F2P : with an online shop (misc stuffs, maybe DLC)
  • A “snake” game
    • Mobile only
    • Inspired by Kleum for Windows & Kleum
    • Solo game, lots of levels (100+ I hope)
    • Puzzle/exploration style
    • Score sharing, best score,…
    • Weekly/monthly new levels
    • Will reuse AlienBlitz engine & resources
    • F2P : with an online shop (new maps or map packs)
  • A strategy game
    • PC only (maybe mobile latter)
    • Mixed between settlers/dungeon keeper/…
    • Lots of RPG elements (quests, huge adventure, lots of magic…)
    • I have a friend working on the background, there is a very nice story/world so far. It could lead to a lot of other game later on

Read more

September news

I have been working a lot lately, but couldn’t post that much as there’s nothing nice to show yet, here’s a quick summary 🙂

Scan Wars

I’ve been mainly focusing on Scan Wars lately, the next game I am working on with some friends. Made very good progress and I now have a great toolbox for mobile games/UI that I could reuse.

There is almost no graphics yet (only placeholders), so I can’t post any screenshots, but I hope I will be able soon. The public beta should also be available within next weeks.

It’s a multiplayer mobile game (Android/iOS) inspired by pokemon, it will be F2P (with some in-app-purchase)

Snorms

Nothing done or planned on Snorms, I got pretty much zero success with press releases, and only one bundle creator answered me. So I don’t really know what to do now, I might continue trying or just give up (it’s working ok so there’s nothing to develop anyway, I would just give up on trying to contact press for now).

I might make a post about it, but basically I guess the main reason of the failure is that even if Snorms is a fun game to play it lakes good graphics (going isometric was a bad idea it limits a lot possibilities, I should have gone fully 3d, or fully 2d like Alien Blitz), and there’s nothing “new” about it that could help promotion.
Of course if I was better with marketing stuff it could have helped me and I could have made some money out of it. But the main problem is the game itself, it doesn’t stand out the thousands of indie games produced every year. I guess it is ok for a first game, we learn from our mistakes 🙂

Alien Blitz

During this month I will make some updates to Alien Blitz, mainly to make it more mobile friendly:

  • I will reuse the UI framework I made for Scan Wars, it’s basically a Javascript/HTML/CSS framework very easy to use. It will make creating UI screens a lot easier and nicer.
  • I am thinking on adding a new difficulty setting “insane” a lot harder than everything you have seen before
  • I might also add some “fun stuff”: destructible walls, quick reload, infinite ammos,… they will not allow you to complete levels (they won’t unlock next levels) and they will not give any experience, it’s just some fun stuffs to play with that will be unlocked when completing some achievements
  • I will try to add some sort of “fog of war”: undiscovered areas will be fully opaque, I don’t know if it will render nicely or is even useful, it’s just something to try out
  • I will also add some shortcuts to go to my store page and rate my game

Snake game (no title yet)

I don’t know if I will really work on this, but I am thinking on doing an advanced snake game that will reuse a lot of Alien Blitz stuffs (meaning there will be complicated levels/puzzle, with keys, buttons and such).

It would be very touch screen friendly (almost no control on screen) and with lots of cool stuff in it. It shouldn’t be much work technically as the prototype for my game engine was actually a snake game, so I will reuse lot of this old work.

I think this game will be completely free (the complete main story), with something like 30-50 levels included, but with in-app-purchase you could get some DLC (level packs).
And if I can make it I would love to add a “one level a day” challenge: one new level to download every day, everyone can play and high scores are saved (launch day high scores, and all time high score). It would be some simple levels, partially randomly generated.

Secret game

I am currently planning another game with some friends (currently one graphic designer and one story writer/game designer) , it’s just a plan at the moment, but it could become reality in the future.

Basically it would use an advanced version of my current engine (fully 3d) and it will be a strategy game (inspired by dungeon keeper/settlers) with an heavy RPG background (really well written story, quests, NPC, magical stuff,…). It’s planned for PC/Mac, but might also be available (simplified) on mobile.

I’m pretty sure I will work on it (99% sure) but it’s quite a lot of work and I already have some work-in-progress, so there might be some delay. I might also try to do a crowdfunding campaign in order to have some money to be able to work on it.

Read more

Snorms & Alien Blitz updated: title screen, viewport stretching

Snorms & Alien Blitz have been updated:

  • (update) new title screen, main menu is loaded in the background while title screen is being displayed (click anywhere, press any key or wait 4 second to close title screen)
  • (update) new pre-rendered screens at end of episode 1 & 3
  • (update) (pc) added an option to stretch viewport (experimental), when activated it will zoom-in to make elements bigger (especially useful on screens with very high resolution)
  • (update) (android) added a brightness option, you can change from full brightness to default system brightness. By default the game will now be full brightness.

Update has been uploaded and accepted on all distribution services (Google Play, this website, Desura & IGS).

mainchar

Read more

New artworks

Ok, I’ve finally completed some new artworks: promotional stuffs, boxshots, title screens, icons,…

googleplay_image_1024x500

preview_image

I will update Snorms & Alien blitz soon

Read more

More blender

Something else I tried with blender:

box

It might suit well for boxshot or title for Snorms/Alien Blitz. I will try to play with that.

I’ve also done 2 raytrace rendered images that will be included in transition screen for Snorms/Alien Blitz (end of episode 1 & end of episode 3)

Read more

Page 20 of 38« First...10...1819202122...30...Last »