Contents
  1. 1. 为 Apple TV 开发 tvOS App Part 2

原文链接=http://jamesonquave.com/blog/developing-tvos-apps-for-apple-tv-part-2/
作者=Jameson Quave
原文日期=2015/09/10
译者=ray16897188
校对=千叶知风
定稿=
发布时间=

为 Apple TV 开发 tvOS App Part 2

本文是tvOS教程的第二部分。如果你还没按照第一部分(译文链接)的流程做过一遍的话,我还是建议你先做一遍。

######增加交互事件

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

1
2
3
4
5
6
7
8
9
10
11
<document>
<alertTemplate>
<title>Hello tvOS!</title>
<button>
<text>A Button</text>
</button>
<button>
<text>A Second Button</text>
</button>
</alertTemplate>
</document>

这是一个带有几个button的告警提示(alert),现在这些button还什么都做不了。这个告警提示还很特殊,比较难编写,所以在操作中生成XML可能会更好一些,在JS中我们能轻松做到这点。我们在main.js文件中加一个新的函数,把这个告警封装成一个更简单的告警提示,仅有一个OK button。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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的string,它包含了TVML的内容,表示一个带着单一button的简单告警提示。而针对description我们是用TVJS string串联起${variable}来插入str的值。

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

最后,我们就能用navigationDocument的presentModal方法将DOM元素模态的呈现出来。navigationDocument是一个全局定义的变量,一直带有根导航文件(root navigation document)。

现在,在我们的onLaunch函数中把之前的代码移除,简单的调用一个告警提示…

1
2
3
App.onLaunch = function(options) {
alert("Hello!");
}

Hello警告

运行app,你会看到一个炫酷的”Hello!” tvOS告警提示。但是点击OK什么都不会发生。那么我们该怎么处理像touch这样的事件呢?

基本上,如果要一直留在JavaScript和TVML之中,你就会希望给DOM元素加一个事件监听者(event listener)。比如我们可以给alert函数添加第二个参数,把OK button发送”点选”事件时所调用的那个函数作为参数传进去。我们加上这个参数,叫它doneCallback。按照下面这么做来添加这个事件监听者:

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

在更新完整个函数之后,它看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 screen。这么做之前我们再加一个getDocumentContents函数,也是类似的,在装载完成之后实施一个回调函数,该回调函数的唯一参数在装载完成时被赋予XMLHttpRequest对象的响应结果。这么做会让我们更容易的装载多种类型的TVML文件。

1
2
3
4
5
6
7
8
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方法几乎一样,除了这里是异步操作,而且不会把任何东西推送给view。

现在有个这个函数,我们就能执行这个调用,然后在OK button被点击时在屏幕上替换掉告警提示。

1
2
3
4
5
6
7
8
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是给一组有标题和图片的内容元素做布局的一种好方法。下面例子是我在我自己的演示中所用到的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<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是顶部的banner,collectionList就是一个包含许多shelf 对象的东西,而shelf 对象则包含一些section 对象,section 对象又包含了lockup 对象,后者才是真正包含我们图片和标题的东西。在我的这个例子中我在我的目录下加了一些要用到的图片,分别是nina.png和coltrane.png。

你更喜欢哪个艺术家?

在Twitter上follow原作者

Contents
  1. 1. 为 Apple TV 开发 tvOS App Part 2