(Част 5 от 5)

Това е последната част от нашия урок за tvOS. Моля, разгледайте предишните страници, за да научите повече за тази серия.

catalogTemplate е един от 18-те шаблона, които са достъпни за използване от разработчиците на tvOS. Целта на шаблона е да показва информация за групи от подобни продукти, което е идеално за показване на вашите видеоклипове въз основа на техните категории! CatologTemplate има много интересни елементи:

Банер — Този елемент се използва за показване на информация в горната част на страницата на приложението за шаблон. Състои се от няколко прости елемента като заглавие, фон и т.н.

Нека започнем да го изграждаме, отидете до нашата директория client и създайте две нови папки в папката js и ги наименувайте images и templates съответно. Вашата клиентска папка вече трябва да има следните папки.

Ще ви трябват изображения, за да попълните клетките в шаблона на каталога. Щракнете тук, за да ги изтеглите, събрах ги за вас с помощта на някои уебсайтове за обучение. След като ги изтеглите, прехвърлете изображенията в папката images, която сте създали във вашата client директория.

Сега ще покажете изображенията на екрана! Създайте нов JavaScript файл, наречен HighlightsTemplate.xml.js, във вашата папка templates.

Добавете следното към HighlightsTemplate.xml.js:

var Template = function() { return `<?xml version="1.0" encoding="UTF-8" ?>
  <document>
    <catalogTemplate>
      <banner>
        <title>Highlights</title>
      </banner>
    </catalogTemplate>
  </document>`
}

Засега ще се опитаме да покажем само банера на шаблона на каталога.

И накрая, последният ни Javascript файл, ResourceLoader.jsкойто ни помага да уведомим другите файлове за съществуването на шаблонния файл.

ResourceLoader

Създайте нов JavaScript файл, наименувайте го ResourceLoader.js и го запазете в папката js заедно с вашите application.js и Presenter.js файлове.

Добавете следното към ResourceLoader.js:

 
function ResourceLoader(baseurl) {
  this.BASEURL = baseurl;
}
 
ResourceLoader.prototype.loadResource = function(resource, callback) {
  var self = this;
  evaluateScripts([resource], function(success) {
    if(success) {
      var resource = Template.call(self);
      callback.call(self, resource);
    } else {
      var title = "Resource Loader Error",
          description = `Error loading resource '${resource}'. \n\n Try again later.`,
          alert = createAlert(title, description);
      navigationDocument.presentModal(alert);
    }
  }); 
}

Не прекарвайте много време в анализиране на този файл, просто знайте, че този файл се използва за зареждане на шаблонни файлове.

Сега нека опитаме да заменим нашия сигнал „Hello World“ с новосъздадения ни HighlightsTemplate като основен екран. Отворете application.js и направете следните промени във файла:

// 1
var resourceLoader;
 
App.onLaunch = function(options) {
  // 2
  var javascriptFiles = [
    `${options.BASEURL}js/ResourceLoader.js`, 
    `${options.BASEURL}js/Presenter.js`
  ];
 
  evaluateScripts(javascriptFiles, function(success) {
    if(success) {
      // 3
      resourceLoader = new ResourceLoader(options.BASEURL);
      resourceLoader.loadResource(`${options.BASEURL}templates/HighlightsTemplate.xml.js`, function(resource) {
        var doc = Presenter.makeDocument(resource);
        Presenter.pushDocument(doc);
      });
    } else {
      var errorDoc = createAlert("Evaluate Scripts Error", "Error attempting to evaluate external JavaScript files.");
      navigationDocument.presentModal(errorDoc);
    }
  });
}

// Leave createAlert alone

Обяснение за кода:

  1. Декларира променлива resourceLoader.
  2. Добавен ResourceLoader.js към списъка с файлове, които искаме да изложим.
  3. Използвах променливата resourceLoader от 1, за да заредя TVML шаблона и използвах Presenter, за да го представя на екрана.

Създайте и стартирайте проекта и се уверете, че нямате грешки. Чувствайте се свободни да оставите коментар или да пишете на моя имейл адрес в случай на грешки/съмнения.

Поздравления, вече можете да заредите TVML от файл, вместо да го кодирате твърдо във вашия Javascript!

Създайте още малко TVML

Вярвате или не, но почти сте готови. Едно от най-красивите неща за TVML tvOS приложенията е, че е много лесно да добавяте елементи на потребителския интерфейс.

var Template = function() { return `<?xml version="1.0" encoding="UTF-8" ?>
  <document>
    <catalogTemplate>
      <banner>
        <title>Highlights</title>
      </banner>
  //1
      <list>
        <section> 
  //2
      <listItemLockup>
        <title>Inspiration Videos</title>
        <decorationLabel>13</decorationLabel>
  //3
        <relatedContent>
          <grid>
            <section>
  //4
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/ray.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/ryan.png" width="500" height="308" />
          </lockup>
              <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/matthijs.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/vicki.png" width="500" height="308" />
          </lockup>
              <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/alexis.png" width="500" height="308" />
              </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/marin.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/chris.png" width="500" height="308" />
              </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/cesare.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/ellen.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/jake.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/kim.png" width="500" height="308" />
          </lockup>
              <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/tammy.png" width="500" height="308" />
          </lockup>
          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
            <img src="${this.BASEURL}images/saul.png" width="500" height="308" />
          </lockup>
        </section>
          </grid>
        </relatedContent>
      </listItemLockup>
  
        <listItemLockup>
          <title>Funny Videos</title>
          <decorationLabel>3</decorationLabel>
          <relatedContent>
            <grid>
              <section>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/kim.png" width="500" height="308" />
                      </lockup>
                          <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/tammy.png" width="500" height="308" />
                      </lockup>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/saul.png" width="500" height="308" />
                      </lockup>
  
          </section>
            </grid>
          </relatedContent>
        </listItemLockup>
  
          <listItemLockup>
            <title>Educational Videos</title>
            <decorationLabel>4</decorationLabel>
            <relatedContent>
              <grid>
                <section>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/cesare.png" width="500" height="308" />
                      </lockup>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/ellen.png" width="500" height="308" />
                      </lockup>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/jake.png" width="500" height="308" />
                      </lockup>
                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                        <img src="${this.BASEURL}images/kim.png" width="500" height="308" />
                      </lockup>
    
            </section>
              </grid>
            </relatedContent>
          </listItemLockup>
  
            <listItemLockup>
              <title>Anime Videos</title>
              <decorationLabel>3</decorationLabel>
              <relatedContent>
                <grid>
                  <section>
                                  <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                                    <img src="${this.BASEURL}images/vicki.png" width="500" height="308" />
                                  </lockup>
                                      <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                                    <img src="${this.BASEURL}images/alexis.png" width="500" height="308" />
                                      </lockup>
                                  <lockup videoURL="https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8">
                                    <img src="${this.BASEURL}images/marin.png" width="500" height="308" />
                                  </lockup>
      
              </section>
                </grid>
              </relatedContent>
            </listItemLockup>
  
        </section>
      </list>
    </catalogTemplate>
  </document>`
}

Обяснение на кода:

  1. Областта Списък, която обхваща останалото съдържание на екрана.
  2. listItemLockup — представлява клетка от раздел. Всяка клетка е представена с помощта на таг listItemLockup. Декларирахме различни раздели като видеоклипове за вдъхновение, забавни видеоклипове, образователни видеоклипове и аниме видеоклипове.
  3. relatedContent —Този етикет се отнася до съседната област на първия раздел.
  4. lockup — Този етикет се отнася до клетка в мрежата. Включили сме свойство на videoURL за всеки блокиращ маркер. Това ще е необходимо за поточно предаване на видеоклиповете.

Изградете и стартирайте, купили сте приложението си за живот.

Сега, след като имаме много различни клетки, с които да си играем, нека изведем дистанционното управление в симулатора (Когато прозорецът на симулатора е активен, щракнете върху прозореца и покажете дистанционното управление на AppleTV). Можете да се движите из клетките, като просто задържите клавиша option и преместите курсора върху отдалечения прозорец.

Поточно предаване на видеото

Досега началният екран е попълнен и изглежда страхотно. Apple наистина свърши страхотна работа, като абстрахира всички детайли, като ни предостави тези фантастични шаблони, с които да работим. Само си представете колко време би отнело проектирането на всичко това с помощта на UIKit.

Нека преминем към следващата част и внедрим последните две функции на това приложение: избор на клетка и възпроизвеждане на мултимедия.

Събития за избор

Може би вече сте забелязали, че натискането на клавиша enter или щракването върху дистанционното управление на Apple TV дава натисната анимация, но нищо не се случва. Сега ще внедрим необходимия код за реализиране на селекция от клетки.

Както вече знаем, класът Presenter ще се справи с тази част. Добавете следния код към класа Presenter:

load: function(event) {
  //1
  var self = this,
  ele = event.target,
  videoURL = ele.getAttribute("videoURL")
  if(videoURL) {
    //2
    var player = new Player();
    var playlist = new Playlist();
    var mediaItem = new MediaItem("video", videoURL);

    player.playlist = playlist;
    player.playlist.push(mediaItem);
    player.present();
  }
}

Обяснение на кода:

Нека направим сравнително проучване за по-добро разбиране на кода.

  1. зареждане —Този метод отговаря за избора на клетки. Той е подобен на @IBAction,и аргументът event е подобен наподателяна IBAction. Всяко събитие има цел,и целта се отнася за всеки блокиращ елемент. [ЗАБЕЛЕЖКА: заключването представлява всяка клетка в нашия раздел, с видео миниатюра и всяка от тях има свойство videoURL]
  2. Плейър —Този клас на TVJS рамката предоставя цялата функционалност за възпроизвеждане на мултимедия. Просто трябва да добавите плейлист и да поставите mediaItem в плейлиста и накрая player.present() ще възпроизведе видеоклипа на екрана .

След като внедрихме логиката за реагиране на събития за избор, е време всъщност да я свържем към всяка клетка. За последен път се върнете към файла application.js и добавете следния ред към метода App.onLaunch.

App.onLaunch = function(options) {
  //...
  //inside resourceLoader.loadResource...
  var doc = Presenter.makeDocument(resource);
  doc.addEventListener("select", Presenter.load.bind(Presenter)); //add this line
  Presenter.pushDocument(doc);
  //...
}

Методът addEventListener е подобен на свързване на бутон към @IBActionизход. Създайте и стартирайте своя проект и сега, когато щракнете върху клетка, ще се възпроизведе съответното видео.

ура! Изминахме много дълъг път. Сега е време за купон, потупайте се по гърба и започнете да изпробвате различни шаблони.

Не само за грешки, ще се радвам също да чуя от вас, така че не се колебайте да споделите отзивите си в секцията за коментари или на моя имейл адрес [email protected] и аз със сигурност ще се свържа с ти възможно най-скоро.

Това е всичко засега, ще ви наваксам със следващата си статия за tvOS, използвайки собствения UIKit, ще създадем приложение, подобно на OTT платформа.

Референтни връзки:





https://www.kodeco.com/home