為 Apple TV 開發(fā) tvOS App Part 2

作者:Jameson Quave,原文鏈接,原文日期:2015/09/10
譯者:ray16897188;校對:千葉知風(fēng);定稿:shanks

本文是 tvOS 教程的第二部分。如果你還沒看過第一部分(譯文鏈接),我建議你先看那篇。

增加交互事件

在第一部分中我們創(chuàng)建了一個簡單的 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)界面,目前這些按鈕沒有任何作用。這段代碼直接硬編碼了具體內(nèi)容,更好的方式是使用代碼生成 XML,在 JS 中很容易實現(xiàn)。我們在main.js文件中添加一個新函數(shù),把上面的代碼封裝成一個更簡單的警告界面,它只包含一個 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);
}

這里創(chuàng)建了一個alertXMLString字符串,它表示的是包含一個按鈕的簡單警告界面所對應(yīng)的 TVML。description節(jié)點比較特殊,我們使用 TVJS 的內(nèi)嵌字符串語法${variable}來插入str的值。

接下來,創(chuàng)建一個新的DOMParser對象,把這個字符串轉(zhuǎn)換成一個實際的 XML DOM 元素。

最后,我們用navigationDocumentpresentModal方法展示一個模態(tài)框,內(nèi)容就是上一步的 DOM 元素。navigationDocument是一個全局變量,它永遠(yuǎn)指向 XML 文檔的根節(jié)點。

現(xiàn)在,刪除onLaunch函數(shù)中之前的代碼,直接調(diào)用剛才創(chuàng)建的函數(shù)……

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

運行應(yīng)用,你會看到一個炫酷的"Hello!" tvOS 警告。但是點擊 OK 沒有任何反應(yīng)。我們該怎么處理像觸摸之類的事件呢?

通常來說,在 JavaScript 和 TVML 的世界中,你需要給 DOM 元素添加一個事件監(jiān)聽器(event listener)。舉個例子,我們可以給alert函數(shù)添加第二個參數(shù),把 OK 按鈕觸發(fā)select事件時需要調(diào)用的函數(shù)作為參數(shù)傳入。下面我們就加入這個名為doneCallback的參數(shù):

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

更新后的完整函數(shù)如下:

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

現(xiàn)在我們可以修改之前的onLaunch函數(shù),添加一個回調(diào)函數(shù)來顯示一個 TVML 頁面。在此之前,我們需要再添加一個getDocumentContents函數(shù),它會在頁面加載完畢之后調(diào)用回調(diào)函數(shù)。這個回調(diào)函數(shù)只有一個參數(shù),用來接收 XMLHttpRequest 對象的響應(yīng)內(nèi)容。這樣我們就可以輕松地加載多種 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方法幾乎一樣,區(qū)別是這里是異步操作,而且不會在界面上顯示任何內(nèi)容。

有個這個函數(shù),我們就能執(zhí)行下面的調(diào)用,當(dāng) OK 按鈕被點擊時替換屏幕上的警告內(nèi)容。

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非常適合用來展示一組包含標(biāo)題和圖片的列表內(nèi)容。下面是本例用到的內(nèi)容:

<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是頂部的橫幅內(nèi)容,collectionList包含許多shelf對象,而shelf對象則包含許多section對象,section對象又包含許多lockup對象,最后這個才真正包含我們的圖片和標(biāo)題。在本例中我向目錄中添加了一些圖片,它們是nina.pngcoltrane.png

你更喜歡哪個藝術(shù)家?
你更喜歡哪個藝術(shù)家?

在Twitter上follow原作者

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,525評論 19 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,828評論 25 709
  • 2017年2月17日 星期五 仁壽 晴 奕含:復(fù)習(xí)《易經(jīng)》履卦第十 跟讀《莊子》逍遙游第一第1節(jié) 跟讀《新...
    朱砂紅塵閱讀 510評論 4 1
  • Redis 客戶端與服務(wù)端之間的通信協(xié)議是在 TCP 協(xié)議上構(gòu)建的。Redis 定義了 RESP(Redis Se...
    某尤閱讀 1,131評論 0 0
  • 5投射 金堂沱江夜景美麗,看到不一樣的風(fēng)景,遇見可愛的人和可愛的事,一家子快樂和諧。 感賞 昨天想去一個沒去過的地...
    媽媽隨筆閱讀 312評論 1 3

友情鏈接更多精彩內(nèi)容