Using StageWebView within a UIComponent in Mobile

StageWebView is the name given to the class that displays the native browser of a mobile device in your mobile app. Since it’s not actually native to AIR it floats above your app. This is a nice gift from the AIR team but as it is you must manually size, position and control the visibility. Well not anymore!

The WebView class adds those features. It wraps the StageWebView up in a UIComponent wrapper. This allows it to be sized, positioned and so on like any other Flex component.

It also exposes the StageWebView snapshot feature. This is a flag that when set to true displays captures snapshot of the Stage Web View at the time the property is set. It then hides the actual StageWebView instance. Setting this property to false removes the snapshot and displays the live web view again. This allows you to display Flex components on top of the web view snapshot. It also helps you to integrate the web view into the display list for animations, transitions, etc.

All updates
• June 2011 – I’ve made a complete rewrite of it. This release exposes the rest of the StageWebView methods and properties and adds snapshot mode and HTML content wrapping.
• July 2011 – I’ve added a few bug fixes and implemented commit properties and measure. Added properties for keyCode for history back and forward. Webview maintains state. Key navigation can be disabled properly. This version is not as tested as much as the last. Let me know of any issues. July 28 release (early release)
• Nov 2011 – Feel free to modify and post this or derivatives on your own site.
• Dec 2011 – I’ve been working on an update. The first thing I’ve fixed is that webview visibility is bound to the UIComponent visible property instead of the developer manually hiding and showing it.
• Jan 2012 – Created a mobile example project showing loading a local URL, remote URL, HTML markup, HTML page markup and snapshot mode.
• Feb 2012 – I’ve uploaded the class and example to my Google Code mobile library.
• Jan 2012 – LATEST STABLE – This is the latest stable download for Jan 2012 Release and Example Project
• Feb 2013 – LATEST BETA – A new beta version that supports runtime DPI and adds more support for JavaScript is available in the GitHub repository here. I’ve added StyleableWebView that has some usage examples. I haven’t had time to create a zip or example project for the this version but it’s being used in production. To use this you can manually download the class files you need from GitHub or you will have to checkout the MainLibrary and MobileLibrary projects from GitHub and then import those into FlashBuilder to create the SWC. Once you’ve added the SWC to your own project you can then create instances of a WebView component.

To use:

<!-- StageWebView is only available for Flex SDK Mobile (Flex 4.5) -->
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:components="com.flexcapacitor.components.*">

	<fx:Script>
		<![CDATA[
			protected function button1_clickHandler(event:MouseEvent):void {
				event.currentTarget.selected ? webView.loadString("Hello world") : webView.load("http://google.com");
			}

			protected function togglebutton1_clickHandler(event:MouseEvent):void {
				webView.snapshotMode = event.currentTarget.selected;
			}

		]]>
	</fx:Script>

	<s:HGroup>
		<s:ToggleButton label="HTML/URL" click="button1_clickHandler(event)"
						width="150" height="64"/>
		<s:ToggleButton label="Snapshot" click="togglebutton1_clickHandler(event)"
						width="150" height="64"/>
		<s:ToggleButton label="Add/Remove" click="button2_clickHandler(event)"
				  width="150" height="64"/>
	</s:HGroup>

	<components:WebView id="webView" top="100" source="http://google.com" width="100%" height="100%"/>

	<s:Label top="100" width="100%"
			 text="This label is only visible when a non interactive snapshot is being displayed."
			 fontWeight="bold" fontSize="24"
			 backgroundColor="#ffffff" lineBreak="toFit" />
</s:Application>
This entry was posted in AIR, Flash, Flex, Mobile, Tips. Bookmark the permalink.

149 Responses to Using StageWebView within a UIComponent in Mobile

  1. Margo says:

    Awesome class! Quick question on memory management.
    I am just starting on mobile development and reading up on the importance of memory management in mobile apps. My usage is an app with a list (that pushes a stage web view and then pops it to return to the list). I was wondering why you did not remove event listeners when the component was removed from the stage. I changed the event listeners to use weak references and added to the method removedFromStageHandler the removal of all event listeners that were created. Is there a reason why this was omitted? – it appears everything operates appropriately within the emulator.

    • Judah says:

      Are you referring to the example project? Unless you needed the webview to persist then you’re correct. You’d want to remove the listeners. You’d also want to call the dispose method as well.

  2. I have just completed the first version of an app for our membership. When seeing this code I thought that this would solve the problem of displaying html within the app. And it does, however a couple of questions.

    1. The local file works fine in the emulator, bt does not work on mt android, any ideas? This what I originally wanted to do was to keep all the html local so an internet connection was not nessasary. Before seeing this I couldn’t figure out how to do this.

    2. I noticed on the Android when I touched the page to scroll it, I notices a the zoom controls. Bit it would only zoom in closer, how can I make it zoom out?

    As you probally guessed I’m new to Flex and Flex Mobile.

    Thanks, I look forward to getting rid of the need to use the devices browser.

    Rich

  3. Raja says:

    Hi,

    Im using StageWebView to display a webpage on my Android Application…..Can any one please help me , how to change the Default WHITE Background color of the StageWebView….

    Thanks,
    Rajkumar

  4. Rich says:

    What I mean is when you touch the screen to scroll a little Magnifying glas shows up with a plus and another one with a minus sign. Touch the plus it moves in, but can’t zoom out any further.

    Hope that clarifies it.

  5. Raja says:

    Hi,
    Is Flex Stage Web View supports Gesture Events?

    Thanks,
    Rajkumar

    • Judah says:

      The stage web view accepts gesture events but it does not pass them on to your Flex application. If you put the component in bitmap mode you can capture gesture events, if your device supports it, but the events would not be seen by the stage web view (since it is hidden).

  6. Angelo says:

    Thanks so much, it’s pretty neat!

    Question: if I use the class for showing web view in a mobile application, the StageWebView renders the content into its own layer. How can I use it as part of a Group, HGroup or VGroup with scrolling?

    • Judah says:

      You would use it as normal component. If you need to clip the content then once you load the page set the component to snapshot mode.

      • I tried playing with this, but the rendering goes beyond the confined scroll area when hitting the top or bottom whilst swiping.

        Would like to see some working example.

        • Judah says:

          Hi Matthias,
          The content will always be on top as long as the web view is live. In live mode you’ll have to set the web component to a fixed height or set the top or bottom constraints or vertical position and let the web view create it’s own scroll bars.

          Alternatively, and if possible, you could at some point, possibly mouse down (see if you can capture the mouse event via bubble or capture phase of the stage listener) or mouse down and also mouse move slightly, then set the snapshot mode to true to turn it into a bitmap image (done automatically on the UIComponent). Then in snapshot mode the view will play nicely with the scroll bars. Not sure if it will autosize to the web content height or if you’ll have to determine that yourself and then set the web component instance to that height before calling snapshot mode.

          I don’t have time at the moment to create an example of this or see if it would work but you could ask on stackoverflow.com, mention this post and see if they may be able to help find a solution.

  7. Celso Wo says:

    Thanks very much for this component, it helped me a lot!

  8. roberta says:

    great component!!!very helpful!!thank you!!

  9. Lee says:

    Any planned updates for maintenance or additions to your component Judah?

    Great implementation by the way!

  10. Paul says:

    I’m having an issue where a basic WebView control, with a source defined, is constantly reloading the web page.

    I even copied the code from your example project (which runs fine on its own) and I still get the odd behaviour.

    Here is my code:

    <?xml version="1.0" encoding="utf-8"?>
    <s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
    		xmlns:s="library://ns.adobe.com/flex/spark"
    		xmlns:components="com.flexcapacitor.components.*"
    		xmlns:controls="com.flexcapacitor.controls.*"
    		actionBarVisible="false" overlayControls="false" tabBarVisible="false"
    		height="100%" width="100%"
    		>
    	<controls:WebView id="webView2" width="100%" height="100%" source="http://google.com"/>
    </s:View>

    this is loaded from a previous view, using “navigator.pushView(views.webview);”

  11. Hey! First of all, congrats for this great component!

    I just downloaded it, and started playing with it, and i got an ArgumentError at WebView.as:193, because bitmap size was different from actual viewport size, so i replaced the code at line 192 from

    snapshotBitmapData = new BitmapData(unscaledWidth, unscaledHeight);

    to

    snapshotBitmapData = new BitmapData(webView.viewPort.width, webView.viewPort.height);

    And that corrected the problem!

    I just wanted to share this, in the case anyone is facing this issue.

    Also it’s important to point that if the applicationDPI is fixed (so Flex is scaling all for you) the snapshot will be oversized when added to component, so you should not use scaling, or apply a patch to resize this bitmap taking in account the current scaling. Starting with something like

    var currentFlexScalingFactor:Number = FlexGlobals.topLevelApplication.runtimeDPI / FlexGlobals.topLevelApplication.applicationDPI;

    Well i hope this helps someone, if i add a patch for myself, i will send it to you maybe to incorporate it to the source.

    And thanks again for sharing this component!

    • Judah says:

      Thanks. I have an updated version that may have some of these fixes in them. It’s available in the repository here, https://github.com/monkeypunch3/flexcapacitor/tree/master/MainMobileLibrary/src/com/flexcapacitor/controls. I added StyleableWebView that has some usage examples.

    • Thanks for this hint! To get it to work, I first tried

      var currentFlexScalingFactor:Number = FlexGlobals.topLevelApplication.runtimeDPI / FlexGlobals.topLevelApplication.applicationDPI;
      snapshotBitmapData = new BitmapData(webView.viewPort.width / currentFlexScalingFactor, webView.viewPort.height / currentFlexScalingFactor);

      But that still gave the error you reported.

      My solution was to scale the bitmap itself:

      var currentFlexScalingFactor:Number = FlexGlobals.topLevelApplication.runtimeDPI / FlexGlobals.topLevelApplication.applicationDPI;
      snapshotBitmapData = new BitmapData(webView.viewPort.width, webView.viewPort.height);
      webView.drawViewPortToBitmapData(snapshotBitmapData);
      webViewBitmap = new Bitmap(snapshotBitmapData);
      webViewBitmap.scaleX = webViewBitmap.scaleY = 1/currentFlexScalingFactor;

      @Judah, thanks for the component!

  12. Jonathan says:

    Sorry if this has been asked before. But is Javascript enabled in the component? If it isn’t then how do I enable it?

    Many Thanks

    Jonathan

Leave a Reply

Your email address will not be published. Required fields are marked *

Wrap your code before posting! Click the links below:

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">