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

Adobe AIR 2.5 和更高版本

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

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

Adobe 推荐的资源

AIR2.5 StageWebView 演示 – OAuth 支持

Mark Doherty
Evangelist Mark Doherty 将演示如何使用 StageWebView 类登录到受 OAuth 保护的网站,例如 Twitter。

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_SCREEN,则在桌面操作系统中,您不能在 StageWebView 中显示的文本字段中键入内容。但是,在 iOS 和 Android 中,即使舞台的 displayState 设置为 FULL_SCREEN,您也可以在 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 权限才能使应用程序成功加载远程资源。

在 Android 3.0 以上的版本中,应用程序必须在 AIR 应用程序描述符的 Android manifestAdditions 元素中启用硬件加速,才能在 StageWebView 对象中显示插件内容。请参阅在 StageWebView 对象中启用 Flash Player 和其他插件

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); 
        } 
    } 
}