为 Apple TV 开发 tvOS App Part 2

作者:Jameson Quave,原文链接,原文日期:2015/09/10
译者:ray16897188;校对:千叶知风;定稿:shanks

本文是 tvOS 教程的第二部分。如果你还没看过第一部分(译文链接),我建议你先看那篇。

增加交互事件

在第一部分中我们创建了一个简单的 TVML document,里面有几个按钮。这个document看起来是这样的:

<document>
    <alertTemplate>
        <title>Hello tvOS!</title>
        <button>
            <text>A Button</text>
        </button>
        <button>
            <text>A Second Button</text>
        </button>
    </alertTemplate>
</document>

这是一个带按钮的警告(alert)界面,目前这些按钮没有任何作用。这段代码直接硬编码了具体内容,更好的方式是使用代码生成 XML,在 JS 中很容易实现。我们在main.js文件中添加一个新函数,把上面的代码封装成一个更简单的警告界面,它只包含一个 OK 按钮。

function alert(str) {
    var alertXMLString = `<?xml version="1.0" encoding="UTF-8" ?>
    <document>
        <alertTemplate>
            <title>Hey Listen!</title>
            <description>${str}</description>
            <button>
                <text>OK</text>
        </button>
    </alertTemplate>
</document>`
var parser = new DOMParser();
var alertDOMElement = parser.parseFromString(alertXMLString, "application/xml");
navigationDocument.presentModal(alertDOMElement);
}

这里创建了一个alertXMLString字符串,它表示的是包含一个按钮的简单警告界面所对应的 TVML。description节点比较特殊,我们使用 TVJS 的内嵌字符串语法${variable}来插入str的值。

接下来,创建一个新的DOMParser对象,把这个字符串转换成一个实际的 XML DOM 元素。

最后,我们用navigationDocumentpresentModal方法展示一个模态框,内容就是上一步的 DOM 元素。navigationDocument是一个全局变量,它永远指向 XML 文档的根节点。

现在,删除onLaunch函数中之前的代码,直接调用刚才创建的函数……

App.onLaunch = function(options) {
    alert("Hello!");
}
Hello 警告
Hello 警告

运行应用,你会看到一个炫酷的"Hello!" tvOS 警告。但是点击 OK 没有任何反应。我们该怎么处理像触摸之类的事件呢?

通常来说,在 JavaScript 和 TVML 的世界中,你需要给 DOM 元素添加一个事件监听器(event listener)。举个例子,我们可以给alert函数添加第二个参数,把 OK 按钮触发select事件时需要调用的函数作为参数传入。下面我们就加入这个名为doneCallback的参数:

alertDOMElement.addEventListener("select", function() { doneCallback }, false);

更新后的完整函数如下:

function alert(str, doneCallback) {
    var alertXMLString = `<?xml version="1.0" encoding="UTF-8" ?>
    <document>
        <alertTemplate>
            <title>Hey Listen!</title>
            <description>${str}</description>
            <button>
                <text>OK</text>
            </button>
        </alertTemplate>
</document>`
var parser = new DOMParser();
var alertDOMElement = parser.parseFromString(alertXMLString, "application/xml");
alertDOMElement.addEventListener("select", doneCallback, false);
navigationDocument.presentModal(alertDOMElement);
}

现在我们可以修改之前的onLaunch函数,添加一个回调函数来显示一个 TVML 页面。在此之前,我们需要再添加一个getDocumentContents函数,它会在页面加载完毕之后调用回调函数。这个回调函数只有一个参数,用来接收 XMLHttpRequest 对象的响应内容。这样我们就可以轻松地加载多种 TVML 文件。

function getDocumentContents(url, loadCallback) {
    var templateXHR = new XMLHttpRequest();
    templateXHR.responseType = "document";
    templateXHR.addEventListener("load", function() { loadCallback(templateXHR) }, false);
    templateXHR.open("GET", url, true);
    templateXHR.send();
    return templateXHR;
}

代码和之前定义的getDocument方法几乎一样,区别是这里是异步操作,而且不会在界面上显示任何内容。

有个这个函数,我们就能执行下面的调用,当 OK 按钮被点击时替换屏幕上的警告内容。

App.onLaunch = function(options) {
    alert("Hello!", function() {
      var helloDocument = getDocumentContents("http://localhost:8000/hello.tvml", function(xhr) {
        navigationDocument.dismissModal();
        navigationDocument.pushDocument(xhr.responseXML);
      });
    });
}

我们使用stackTemplate模板来改写hello.tvml文件,这样界面会更有趣。stackTemplate非常适合用来展示一组包含标题和图片的列表内容。下面是本例用到的内容:

<document>
    <stackTemplate>
        <banner>
            <title>Which Artist Do You Prefer?</title>
        </banner>
        <collectionList>
            <shelf>
                <section>
                    <lockup>
                        <img src="http://localhost:8000/nina.png" width="256" height="256" />
                        <title>Nina Simone</title>
                    </lockup>
                    <lockup>
                        <img src="http://localhost:8000/coltrane.png" width="256" height="256" />
                        <title>John Coltrane</title>
                    </lockup>
                </section>
            </shelf>
        </collectionList>
    </stackTemplate>
</document>

这基本上就是stackTemplate的布局方式,banner是顶部的横幅内容,collectionList包含许多shelf对象,而shelf对象则包含许多section对象,section对象又包含许多lockup对象,最后这个才真正包含我们的图片和标题。在本例中我向目录中添加了一些图片,它们是nina.pngcoltrane.png

你更喜欢哪个艺术家?
你更喜欢哪个艺术家?

在Twitter上follow原作者

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,951评论 19 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 176,034评论 25 709
  • 2017年2月17日 星期五 仁寿 晴 奕含:复习《易经》履卦第十 跟读《庄子》逍遥游第一第1节 跟读《新...
    朱砂紅塵阅读 3,297评论 4 1
  • Redis 客户端与服务端之间的通信协议是在 TCP 协议上构建的。Redis 定义了 RESP(Redis Se...
    某尤阅读 4,705评论 0 0
  • 5投射 金堂沱江夜景美丽,看到不一样的风景,遇见可爱的人和可爱的事,一家子快乐和谐。 感赏 昨天想去一个没去过的地...
    妈妈随笔阅读 1,855评论 1 3

友情链接更多精彩内容