在移动应用程序中显示 HTML 内容

Adobe AIR AIR 2.5 和更高版本

StageWebView 类在移动设备上使用系统浏览器控件显示 HTML 内容,在桌面计算机上使用标准 Adobe® AIR® HTMLLoader 控件显示 HTML 内容。检查 StageWebView.isSupported 属性以确定当前设备是否支持该类。不保证在移动配置文件中为所有设备提供支持。

在所有配置文件中,StageWebView 类仅支持 HTML 内容和应用程序其他内容之间的有限交互。您可以控制导航,但不允许脚本交叉或直接交换数据。您可以从本地或远程 URL 加载内容,或者传入 HTML 字符串。

StageWebView 对象

StageWebView 对象不是显示对象,无法添加到显示列表。相反,它作为直接附加到舞台的视口工作。StageWebView 内容在任何显示列表内容的前面绘制。无法控制多个 StageWebView 对象的绘制顺序。

要显示 StageWebView 对象,您对将显示此对象的舞台赋予 StageWebView 的 Stage 属性。使用 viewPort 属性设置显示的大小。

viewPort 属性的 x 和 y 坐标设置为介于 -8192 至 8191 之间的值。舞台宽度和高度的最大值为 8191。如果大小超出了最大值,将引发异常。

以下示例创建一个 StageWebView 对象,设置 StageviewPort 属性,并显示 HTML 字符串:

var webView:StageWebView = new StageWebView(); 
webView.viewPort = new Rectangle( 0, 0, this.stage.stageWidth, this .stage.stageHeight); 
webView.stage = this.stage; 
var htmlString:String = "<!DOCTYPE HTML>" + 
                        "<html><body>" + 
                        "<p>King Philip could order five good steaks.</p>" + 
                        "</body></html>"; 
webView.loadString( htmlString );

要隐藏 StageWebView 对象,请将其 stage 属性设置为 null。要彻底销毁对象,请调用 dispose() 方法。调用 dispose() 是可选的,但调用它有助于垃圾回收器尽快回收对象使用的内存。

内容

您可以使用两个方法将内容加载到 StageWebView 对象:loadURL()loadString()

loadURL() 方法在指定的 URL 上加载资源。您可以使用系统 Web 浏览器控件支持的任何 URI 方案,包括 data:、file:、http:、https: 和 JavaScript:。不支持 app: 和 app-storage: 方案。AIR 不验证 URL 字符串。

loadString() 方法加载包含 HTML 内容的文本字符串。使用此方法加载的页面的位置表示为:
  • 在桌面操作系统上:about:blank

  • 在 iOS 上:htmlString

  • 在 Android 上:编码的 htmlString 的数据 URI 格式

URI 方案确定加载嵌入内容或数据的规则。

URI 方案

加载本地资源

加载远程资源

本地 XMLHttpRequest

远程 XMLHttpRequest

数据:

文件:

http:,https:

同一域

关于:(loadString() 方法)

注: 如果舞台的 displayState 属性设置为 FULL_SCR EN,则在桌面操作系统中,您不能在 StageWebView 中显示的文本字段中键入内容。但是,在 iOS 和 Android 中,即使舞台的 displayState 设置为 FULL_SCR EN,您也可以在 StageWebView 上的文本字段中键入内容。

下面的示例使用 StageWebView 对象显示 Adobe 的网站:

package  { 
    import flash.display.MovieClip; 
    import flash.media.StageWebView; 
    import flash.geom.Rectangle; 
     
    public class StageWebViewExample extends MovieClip{ 
 
        var webView:StageWebView = new StageWebView(); 
         
        public function StageWebViewExample() { 
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); 
            webView.loadURL( "http://www.adobe.com" ); 
        } 
    } 
}

在 Android 设备上,您必须指定 Android INTERNET 权限才能使应用程序成功加载远程资源。

JavaScript URI

可以使用 JavaScript URI 来调用在 HTML 页中定义并由 StageWebView 对象加载的函数。使用 JavaScript URI 调用的函数将在所加载网页的上下文中运行。以下示例使用 StageWebView 对象调用一个 JavaScript 函数:

package { 
    import flash.display.*; 
    import flash.geom.Rectangle; 
    import flash.media.StageWebView; 
    public class WebView extends Sprite 
    { 
        public var webView:StageWebView = new StageWebView(); 
        public function WebView() 
        {     
            var htmlString:String = "<!DOCTYPE HTML>" + 
            "<html><script type=text/javascript>" + 
            "function callURI(){" + 
            "alert(\"You clicked me!!\");"+ 
            "}</script><body>" + 
            "<p><a href=javascript:callURI()>Click Me</a></p>" + 
            "</body></html>"; 
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); 
            webView.loadString( htmlString ); 
        } 
    } 
}

导航事件

当用户单击 HTML 中的链接时,StageWebView 对象调度一个 locationChanging 事件。您可以调用事件对象的 preventDefault() 方法停止导航。否则,StageWebView 对象将导航到新页面并调度一个 locationChange 事件。当页面加载完成时,StageWebView 调度一个 complete 事件。

locationChanging 事件会在每次 HTML 重定向时调度。在适当的时间调度 locationChangecomplete 事件。

在 iOS 上,除了首个 loadURL() 或 loadString() 方法以外,locationChanging 事件会在 locationChange 事件之前调度。通过 iFrame 和 Frame 进行导航更改时,也会调度 locationChange 事件。

以下示例显示如何防止位置更改,并在系统浏览器中打开新页面。

package  { 
    import flash.display.MovieClip; 
    import flash.media.StageWebView; 
    import flash.events.LocationChangeEvent; 
    import flash.geom.Rectangle; 
    import flash.net.navigateToURL; 
    import flash.net.URLRequest; 
     
    public class StageWebViewNavEvents extends MovieClip{ 
        var webView:StageWebView = new StageWebView(); 
         
        public function StageWebViewNavEvents() { 
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); 
        webView.addEventListener( LocationChangeEvent.LOCATION_CHANGING, onLocationChanging ); 
            webView.loadURL( "http://www.adobe.com" ); 
        } 
        private function onLocationChanging( event:LocationChangeEvent ):void 
        { 
            event.preventDefault(); 
            navigateToURL( new URLRequest( event.location ) ); 
        } 
    } 
}

历史记录

当用户单击在 StageWebView 对象中显示的内容中的链接时,控件会保存向前和向后的历史记录堆栈。以下示例显示如何通过二个历史记录堆栈导航。示例使用“后退”(Back) 和“搜索”(Search) 软键。

package  { 
    import flash.display.MovieClip; 
    import flash.media.StageWebView; 
    import flash.geom.Rectangle; 
    import flash.events.KeyboardEvent; 
    import flash.ui.Keyboard; 
     
    public class StageWebViewExample extends MovieClip{ 
 
        var webView:StageWebView = new StageWebView(); 
         
        public function StageWebViewExample() 
        { 
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle( 0, 0, stage.stageWidth, stage.stageHeight ); 
            webView.loadURL( "http://www.adobe.com" ); 
             
            stage.addEventListener( KeyboardEvent.KEY_DOWN, onKey ); 
        } 
         
        private function onKey( event:KeyboardEvent ):void 
        { 
            if( event.keyCode == Keyboard.BACK && webView.isHistoryBackEnabled ) 
            { 
                trace("back"); 
                webView.historyBack(); 
                event.preventDefault(); 
            } 
            if( event.keyCode == Keyboard.SEARCH && webView.isHistoryForwardEnabled ) 
            { 
                trace("forward"); 
                webView.historyForward(); 
            } 
        } 
    } 
}

焦点

尽管 StageWebView 类不是显示对象,但它包含的成员允许您管理控件的焦点进出。

当 StageWebView 对象获得焦点时,它调度一个 focusIn 事件。您使用此事件管理应用程序中的焦点元素(如果需要)。

当 StageWebView 放弃焦点时,它调度一个 focusOut 事件。当用户使用设备轨迹球或方向箭头以 Tab 键方式向上通过页面上的第一个或向下通过最后一个控件时,StageWebView 实例会放弃焦点。事件对象的 direction 属性告诉您焦点移动方向是向上通过页面的顶部还是向下通过页面的底部。使用此信息将焦点赋予 StageWebView 上方或下方适当的显示对象上。

在 iOS 上,不能通过编程方式设置焦点。StageWebView 会调度 focusInfocusOut 事件,并将 FocusEvent 的 direction 属性设置为 none。如果用户触摸 StageWebView 内部,将调度 focusIn 事件。如果用户触摸 StageWebView 外部,将调度 focusOut 事件。

以下示例显示焦点如何从 StageWebView 对象传递到 Flash 显示对象:

package  { 
    import flash.display.MovieClip; 
    import flash.media.StageWebView; 
    import flash.geom.Rectangle; 
    import flash.events.KeyboardEvent; 
    import flash.ui.Keyboard; 
    import flash.text.TextField; 
    import flash.text.TextFieldType; 
    import flash.events.FocusEvent; 
    import flash.display.FocusDirection; 
    import flash.events.LocationChangeEvent; 
     
    public class StageWebViewFocusEvents extends MovieClip{ 
        var webView:StageWebView = new StageWebView(); 
        var topControl:TextField = new TextField(); 
        var bottomControl:TextField = new TextField(); 
         
        public function StageWebViewFocusEvents() 
        { 
            trace("Starting"); 
            topControl.type = TextFieldType.INPUT; 
            addChild( topControl ); 
            topControl.height = 60; 
            topControl.width = stage.stageWidth; 
            topControl.background = true; 
            topControl.text = "One control on top."; 
            topControl.addEventListener( FocusEvent.FOCUS_IN, flashFocusIn ); 
            topControl.addEventListener( FocusEvent.FOCUS_OUT, flashFocusOut ); 
             
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle( 0, 60, stage.stageWidth, stage.stageHeight 
- 120 ); 
            webView.addEventListener( FocusEvent.FOCUS_IN, webFocusIn ); 
            webView.addEventListener(FocusEvent.FOCUS_OUT, webFocusOut ); 
            webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, 
                                     function( event:LocationChangeEvent ):void 
                                     { 
                                         event.preventDefault(); 
                                     } ); 
            webView.loadString("<form action='#'><input/><input/><input/></form>"); 
            webView.assignFocus(); 
             
            bottomControl.type = TextFieldType.INPUT; 
            addChild( bottomControl ); 
            bottomControl.y = stage.stageHeight - 60; 
            bottomControl.height = 60; 
            bottomControl.width = stage.stageWidth; 
            bottomControl.background = true; 
            bottomControl.text = "One control on the bottom.";             
            bottomControl.addEventListener( FocusEvent.FOCUS_IN, flashFocusIn ); 
            bottomControl.addEventListener( FocusEvent.FOCUS_OUT, flashFocusOut );        } 
         
        private function webFocusIn( event:FocusEvent ):void 
        { 
            trace("Web focus in"); 
        } 
         
        private function webFocusOut( event:FocusEvent ):void 
        { 
            trace("Web focus out: " + event.direction); 
            if( event.direction == FocusDirection.TOP ) 
            { 
                stage.focus = topControl; 
            } 
            else 
            { 
                stage.focus = bottomControl; 
            } 
        } 
 
        private function flashFocusIn( event:FocusEvent ):void 
        { 
            trace("Flash focus in"); 
            var textfield:TextField = event.target as TextField; 
            textfield.backgroundColor = 0xff5566; 
        } 
         
        private function flashFocusOut( event:FocusEvent ):void 
        { 
            trace("Flash focus out"); 
            var textfield:TextField = event.target as TextField; 
            textfield.backgroundColor = 0xffffff; 
        } 
         
    } 
}

位图捕获

StageWebView 对象会在所有显示列表内容之上呈现。您不能在 StageWebView 对象之上添加内容。例如,您不能在 StageWebView 之上展开一个下拉列表。要解决此问题,请捕获 StageWebView 的快照。然后,隐藏 StageWebView 并添加替代的位图快照。

以下示例演示了如何使用 drawViewPortToBitmapData 方法捕获 StageWebView 对象的快照。该示例通过将舞台设置为 null 来隐藏 StageWebView 对象。完全加载网页后,该示例调用了一个捕获并显示位图的函数。运行时,此代码会显示两个标签:Google 和 Facebook。点击标签将捕获相应的网页,并将其在舞台上作为快照显示。

package 
{ 
    import flash.display.Bitmap; 
    import flash.display.BitmapData; 
    import flash.display.Sprite; 
    import flash.events.*; 
    import flash.geom.Rectangle; 
    import flash.media.StageWebView; 
    import flash.net.*; 
    import flash.text.TextField; 
    public class stagewebview extends Sprite 
    { 
        public var webView:StageWebView=new StageWebView(); 
        public var textGoogle:TextField=new TextField(); 
        public var textFacebook:TextField=new TextField(); 
        public function stagewebview() 
        { 
            textGoogle.htmlText="<b>Google</b>"; 
            textGoogle.x=300; 
            textGoogle.y=-80;         
            addChild(textGoogle); 
            textFacebook.htmlText="<b>Facebook</b>"; 
            textFacebook.x=0; 
            textFacebook.y=-80; 
            addChild(textFacebook); 
            textGoogle.addEventListener(MouseEvent.CLICK,goGoogle); 
            textFacebook.addEventListener(MouseEvent.CLICK,goFaceBook); 
            webView.stage = this.stage; 
            webView.viewPort = new Rectangle(0, 0, stage.stageWidth, stage.stageHeight); 
        } 
    public function goGoogle(e:Event):void 
        { 
            webView.loadURL("http://www.google.com"); 
            webView.stage = null; 
            webView.addEventListener(Event.COMPLETE,handleLoad); 
        } 
     
    public function goFaceBook(e:Event):void 
        { 
            webView.loadURL("http://www.facebook.com"); 
            webView.stage = null; 
            webView.addEventListener(Event.COMPLETE,handleLoad); 
        } 
    public function handleLoad(e:Event):void 
        { 
            var bitmapData:BitmapData = new BitmapData(webView.viewPort.width, webView.viewPort.height); 
            webView.drawViewPortToBitmapData(bitmapData); 
            var webViewBitmap:Bitmap=new Bitmap(bitmapData); 
            addChild(webViewBitmap); 
        } 
    } 
}

显示广告

可以使用 StageWebView 类来显示提供 JavaScript/HTML 接口的广告服务的广告。设置 StageWebView 对象视口以覆盖应用程序中要显示广告的区域。然后加载包含请求和显示广告的代码的 HTML 页。

下面的示例显示了加载 Admob JavaScript 库并请求显示广告的 HTML 页。类似机制也适用于其他广告服务。若要使用此示例请求测试广告,必须首先注册一个 Admob 帐户,并将您的 Admob 发行商 id 分配给 pubid 变量。

<html> 
<head> 
<title>Ad jig</title> 
<script type="text/javascript"> 
    var admob_vars = { 
    pubid: 'admob_pubID', // change to your publisher id 
    bgcolor: 'ffffff', // background color (hex) 
    text: '000000', // font-color (hex) 
    test: true, // test mode, set to false if non-test mode 
    manual_mode: true 
}; 
 
function showAd() 
{ 
    _admob.fetchAd(document.getElementById('adspace')); 
} 
</script> 
<script type="text/javascript" src="http://mm.admob.com/static/iphone/iadmob.js"></script> 
<style type="text/css"> 
    body { 
    margin-left: 0px; 
    margin-top: 0px; 
    margin-right: 0px; 
    margin-bottom: 0px; 
} 
</style> 
</head> 
<body onload="showAd()"> 
<div id="adspace"></div> 
</body> 
</html>

下面的 ActionScript 代码在移动 AIR 应用程序中显示广告页。已对该示例的格式进行了设置,可以在 Flash Professional 中的时间轴上使用。如果使用的是 Flash Builder 或创建了一个类,则需要相应地修改示例代码。

当用户点击广告时,可以在应用程序中显示广告目标页,也可以使用 navigateToURL() 在设备的 Web 浏览器中显示目标页。此示例使用 navigateToURL(),该方法适用于 http: 链接和 market: 链接。

在移动设备上,基本 Web 控件处理由代码启动的位置更改以了解 URI 方案,而无需调度 locationChanging 事件。由于 Admob JavaScript API 更改了页面位置,因此该示例将处理 locationChanginglocationChange 事件,以便应用程序可以采取适当的措施,而不必考虑 StageWebView 对象的位置是如何更改的。

可以取消 locationChanging 事件,因此该示例调用事件的 preventDefault() 方法并基于 event location 属性启动设备 Web 浏览器。无法取消 locationChange 事件。在这种情况下,该示例使用 navigateToURL() 启动新位置并重新加载广告显示页。

//Set up web view object 
var webView:StageWebView = new StageWebView(); 
webView.stage = this.stage; 
var adViewPort = new Rectangle( 0, 0, this.stage.stageWidth, 60 ); 
webView.viewPort = adViewPort; 
webView.addEventListener(ErrorEvent.ERROR, onWebViewError ); 
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGING, onWebViewLocChanging ); 
webView.addEventListener(LocationChangeEvent.LOCATION_CHANGE, onWebViewLocChange ); 
 
//Copy the html file outside the app directory 
var templateFile:File = File.applicationDirectory.resolvePath( "adview.html" ); 
var workingFile:File = File.createTempFile(); 
templateFile.copyTo( workingFile, true ); 
 
try 
{ 
    webView.loadURL( workingFile.url ); 
} 
catch (e:Error) 
{ 
    trace( e ); 
} 
 
function onWebViewLocChange( event:LocationChangeEvent ):void 
{ 
    trace( "Change to" + event.location ); 
    if( event.location != workingFile.url ) 
    {   
        //Reset location back to our ad display page 
        navigateToURL( new URLRequest( event.location ) ); 
        try 
        { 
            webView.loadURL( workingFile.url ); 
        } 
        catch (e:Error) 
        { 
            trace( e ); 
        } 
    } 
} 
 
function onWebViewLocChanging( event:LocationChangeEvent ):void 
{ 
    trace( "Changing " + event.location ); 
    event.preventDefault(); 
    navigateToURL( new URLRequest( event.location ) ); 
} 
 
function onWebViewError( error:ErrorEvent ):void 
{ 
    trace( error ); 
}
注: 由于本地与远程沙箱的限制,该示例无法在桌面应用程序中使用,也无法在桌面上测试移动应用程序时使用。在桌面上,StageWebView 对象具有对应于桌面操作系统的安全约束。在移动设备上,StageWebView 对象使用标准 Web 控件和由移动设备操作系统强制实施的安全约束。在这种情况下,本地加载的文件 (adview.html) 可以访问移动设备上的远程资源(广告服务),但不能访问桌面上的资源。