Udostępnij za pośrednictwem


Praca z widokami kolekcji tvOS na platformie Xamarin

Widoki kolekcji umożliwiają wyświetlanie grupy zawartości przy użyciu dowolnych układów. Dzięki wbudowanej obsłudze umożliwiają łatwe tworzenie układów przypominających siatkę lub liniową, a także obsługę układów niestandardowych.

Przykładowy widok kolekcji

Widok kolekcji przechowuje kolekcję elementów przy użyciu delegata i źródła danych w celu zapewnienia interakcji użytkownika i zawartości kolekcji. Ponieważ widok kolekcji jest oparty na podsystemie układu, który jest niezależny od samego widoku, zapewnienie innego układu może łatwo zmienić prezentację danych widoku kolekcji na bieżąco.

Informacje o widokach kolekcji

Jak wspomniano powyżej, widok kolekcji (UICollectionView) zarządza uporządkowaną kolekcją elementów i przedstawia te elementy z dostosowywalnymi układami. Widoki kolekcji działają podobnie do widoków tabel (UITableView), z wyjątkiem układów do prezentowania elementów w więcej niż jednej kolumnie.

W przypadku korzystania z widoku kolekcji w systemie tvOS aplikacja jest odpowiedzialna za dostarczanie danych skojarzonych z kolekcją przy użyciu źródła danych (UICollectionViewDataSource). Dane widoku kolekcji można opcjonalnie organizować i przedstawiać w różnych grupach (sekcjach).

Widok kolekcji przedstawia poszczególne elementy na ekranie przy użyciu komórki (UICollectionViewCell), która udostępnia prezentację danego elementu informacji z kolekcji (na przykład obrazu i jego tytułu).

Opcjonalnie można dodać widoki dodatkowe do prezentacji widoku kolekcji, aby działać jako nagłówki i stopki dla sekcji i komórek. Układ widoku kolekcji jest odpowiedzialny za zdefiniowanie umieszczania tych widoków wraz z poszczególnymi komórkami.

Widok kolekcji może reagować na interakcję użytkownika przy użyciu delegata (UICollectionViewDelegate). Ten delegat jest również odpowiedzialny za określenie, czy dana komórka może uzyskać fokus, jeśli komórka została wyróżniona lub czy została wybrana. W niektórych przypadkach delegat określa rozmiar poszczególnych komórek.

Układy widoku kolekcji

Kluczową funkcją widoku kolekcji jest rozdzielenie danych, które prezentuje i jego układ. Układ widoku kolekcji (UICollectionViewLayout) jest odpowiedzialny za udostępnianie organizacji i lokalizacji komórek (oraz wszelkich widoków uzupełniających) w prezentacji ekranowej widoku kolekcji.

Poszczególne komórki są tworzone przez widok kolekcji na podstawie dołączonego źródła danych, a następnie są rozmieszczane i wyświetlane przez dany układ widoku kolekcji.

Układ widoku kolekcji jest zwykle udostępniany podczas tworzenia widoku kolekcji. Można jednak w dowolnym momencie zmienić układ widoku kolekcji, a prezentacja ekranowa danych widoku kolekcji zostanie automatycznie zaktualizowana przy użyciu nowego układu.

Układ widoku kolekcji zawiera kilka metod, których można użyć do animowania przejścia między dwoma różnymi układami (domyślnie nie jest wykonywana żadna animacja). Ponadto układy widoku kolekcji mogą współpracować z funkcjami rozpoznawania gestów, aby jeszcze bardziej animować interakcję użytkownika, która powoduje zmianę układu.

Tworzenie komórek i widoków dodatkowych

Źródło danych widoku kolekcji jest nie tylko odpowiedzialne za dostarczanie danych zapasowych elementu kolekcji, ale także komórek używanych do wyświetlania zawartości.

Ponieważ widoki kolekcji zostały zaprojektowane tak, aby obsługiwały duże kolekcje elementów, poszczególne komórki można odseprzeć i użyć ponownie, aby nie ograniczać limitów pamięci. Istnieją dwie różne metody usuwania widoków w kolejce:

  • DequeueReusableCell — Tworzy lub zwraca komórkę danego typu (jak określono w scenorysie aplikacji).
  • DequeueReusableSupplementaryView — Tworzy lub zwraca dodatkowy widok danego typu (jak określono w scenorysie aplikacji).

Przed wywołaniem jednej z tych metod należy zarejestrować klasę, scenorys lub .xib plik użyty do utworzenia widoku komórki za pomocą widoku kolekcji. Na przykład:

public CityCollectionView (IntPtr handle) : base (handle)
{
    // Initialize
    RegisterClassForCell (typeof(CityCollectionViewCell), CityViewDatasource.CardCellId);
    ...
}

Gdzie typeof(CityCollectionViewCell) udostępnia klasę, która obsługuje widok i CityViewDatasource.CardCellId udostępnia identyfikator używany podczas kolejki komórki (lub widoku).

Po usunięciu komórki należy ją skonfigurować przy użyciu danych dla elementu, który reprezentuje, i powrócić do widoku kolekcji do wyświetlenia.

Informacje o kontrolerach widoku kolekcji

Kontroler widoku kolekcji (UICollectionViewController) to wyspecjalizowany kontroler widoku (UIViewController), który zapewnia następujące zachowanie:

  • Jest on odpowiedzialny za ładowanie widoku kolekcji z jego scenorysu lub .xib pliku i utworzenie wystąpienia widoku. Jeśli został utworzony w kodzie, automatycznie tworzy nowy, nieskonfigurowany widok kolekcji.
  • Po załadowaniu widoku kolekcji kontroler podejmie próbę załadowania źródła danych i delegata z scenorysu lub .xib pliku. Jeśli żadna z nich nie jest dostępna, ustawia się jako źródło obu tych elementów.
  • Gwarantuje, że dane zostaną załadowane przed wypełnieniem widoku kolekcji po raz pierwszy, a następnie ponownie załaduj i wyczyść zaznaczenie na każdym kolejnym ekranie.

Ponadto kontroler widoku kolekcji udostępnia metody, które mogą służyć do zarządzania cyklem życia widoku kolekcji, takich jak AwakeFromNib i ViewWillDisplay.

Widoki kolekcji i scenorysy

Najprostszym sposobem pracy z widokiem kolekcji w aplikacji Xamarin.tvOS jest dodanie go do scenorysu. W krótkim przykładzie utworzymy przykładową aplikację, która przedstawia obraz, tytuł i przycisk wyboru. Jeśli użytkownik kliknie przycisk wyboru, zostanie wyświetlony widok kolekcji, który umożliwi użytkownikowi wybranie nowego obrazu. Po wybraniu obrazu widok kolekcji zostanie zamknięty, a zostanie wyświetlony nowy obraz i tytuł.

Wykonajmy następujące czynności:

  1. Uruchom nową aplikację tvOS z jednym widokiem w Visual Studio dla komputerów Mac.

  2. W Eksplorator rozwiązań kliknij Main.storyboard dwukrotnie plik i otwórz go w Projektant systemu iOS.

  3. Dodaj widok obrazu, etykietę i przycisk do istniejącego widoku i skonfiguruj je tak, aby wyglądały tak:

    Przykładowy układ

  4. Przypisz nazwę do widoku obrazu i etykietę na karcieWidżet Eksploratora właściwości. Na przykład:

    Ustawianie nazwy

  5. Następnie przeciągnij kontroler widoku kolekcji na scenorys:

    Kontroler widoku kolekcji

  6. Przeciągnij kontrolkę z przycisku do kontrolera widoku kolekcji i wybierz pozycję Wypchnij z wyskakującego okienka:

    Wybierz pozycję Wypchnij z wyskakującego okienka

  7. Po uruchomieniu aplikacji spowoduje to, że widok kolekcji będzie wyświetlany za każdym razem, gdy użytkownik kliknie przycisk.

  8. Wybierz widok kolekcji i wprowadź następujące wartości na karcie Układ Eksploratora właściwości:

    Eksplorator właściwości

  9. Steruje to rozmiarem poszczególnych komórek i obramowania między komórkami a zewnętrzną krawędzią widoku kolekcji.

  10. Wybierz kontroler widoku kolekcji i ustaw jego klasę na CityCollectionViewController karcie Widżet:

    Ustaw klasę na CityCollectionViewController

  11. Wybierz widok kolekcji i ustaw jej klasę na CityCollectionView karcie Widżet:

    Ustaw klasę na CityCollectionView

  12. Wybierz komórkę Widok kolekcji i ustaw jej klasę na CityCollectionViewCell karcie Widżet:

    Ustaw klasę na CityCollectionViewCell

  13. Na karcie Widżet upewnij się, że układ jest Flow i kierunek przewijania jest Vertical przeznaczony dla widoku kolekcji:

    Karta Widżet

  14. Wybierz komórkę Widoku kolekcji i ustaw jej tożsamość na CityCell wartość na karcie Widżet:

    Ustawianie wartości Identity na CityCell

  15. Zapisz zmiany.

Gdybyśmy wybrali Custom układ widoku kolekcji, moglibyśmy określić układ niestandardowy. Firma Apple udostępnia wbudowane UICollectionViewFlowLayout i UICollectionViewDelegateFlowLayout umożliwia łatwe prezentowanie danych w układzie opartym na siatce (są one używane przez flow styl układu).

Aby uzyskać więcej informacji na temat pracy z scenorysami, zobacz przewodnik Szybki start dotyczący funkcji Hello, tvOS.

Dostarczanie danych dla widoku kolekcji

Po dodaniu widoku kolekcji (i kontrolera widoku kolekcji) do scenorysu musimy podać dane dla kolekcji.

Model danych

Najpierw utworzymy model dla naszych danych, który przechowuje nazwę pliku obrazu do wyświetlenia, tytuł i flagę umożliwiającą wybranie miasta.

Utwórz klasę CityInfo i utwórz ją tak, jakby wyglądała następująco:

using System;

namespace tvCollection
{
    public class CityInfo
    {
        #region Computed Properties
        public string ImageFilename { get; set; }
        public string Title { get; set; }
        public bool CanSelect{ get; set; }
        #endregion

        #region Constructors
        public CityInfo (string filename, string title, bool canSelect)
        {
            // Initialize
            this.ImageFilename = filename;
            this.Title = title;
            this.CanSelect = canSelect;
        }
        #endregion
    }
}

Komórka widoku kolekcji

Teraz musimy zdefiniować sposób prezentowania danych dla każdej komórki. Zmodyfikuj plik (utworzony automatycznie z pliku Scenorysu CityCollectionViewCell.cs ) i utwórz go w następujący sposób:

using System;
using Foundation;
using UIKit;
using CoreGraphics;

namespace tvCollection
{
    public partial class CityCollectionViewCell : UICollectionViewCell
    {
        #region Private Variables
        private CityInfo _city;
        #endregion

        #region Computed Properties
        public UIImageView CityView { get ; set; }
        public UILabel CityTitle { get; set; }

        public CityInfo City {
            get { return _city; }
            set {
                _city = value;
                CityView.Image = UIImage.FromFile (City.ImageFilename);
                CityView.Alpha = (City.CanSelect) ? 1.0f : 0.5f;
                CityTitle.Text = City.Title;
            }
        }
        #endregion

        #region Constructors
        public CityCollectionViewCell (IntPtr handle) : base (handle)
        {
            // Initialize
            CityView = new UIImageView(new CGRect(22, 19, 320, 171));
            CityView.AdjustsImageWhenAncestorFocused = true;
            AddSubview (CityView);

            CityTitle = new UILabel (new CGRect (22, 209, 320, 21)) {
                TextAlignment = UITextAlignment.Center,
                TextColor = UIColor.White,
                Alpha = 0.0f
            };
            AddSubview (CityTitle);
        }
        #endregion


    }
}

W przypadku naszej aplikacji tvOS będziemy wyświetlać obraz i opcjonalny tytuł. Jeśli nie można wybrać danego miasta, wygasimy widok obrazu przy użyciu następującego kodu:

CityView.Alpha = (City.CanSelect) ? 1.0f : 0.5f;

Gdy komórka zawierająca obraz zostanie sprowadzona przez użytkownika, chcemy użyć wbudowanego efektu parallax, aby ustawić następującą właściwość:

CityView.AdjustsImageWhenAncestorFocused = true;

Aby uzyskać więcej informacji na temat nawigacji i koncentracji uwagi, zapoznaj się z dokumentacją Praca z nawigacją i fokusem oraz kontrolerami zdalnymi Siri i Bluetooth.

Widok kolekcji Dostawca danych

Po utworzeniu modelu danych i zdefiniowanym układzie komórki utwórzmy źródło danych dla naszego widoku kolekcji. Źródło danych będzie odpowiedzialne nie tylko za dostarczanie danych zapasowych, ale także w kolejce komórek w celu wyświetlenia poszczególnych komórek na ekranie.

Utwórz klasę CityViewDatasource i utwórz ją tak, jakby wyglądała następująco:

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;
using ObjCRuntime;

namespace tvCollection
{
    public class CityViewDatasource : UICollectionViewDataSource
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Static Constants
        public static NSString CardCellId = new NSString ("CityCell");
        #endregion

        #region Computed Properties
        public List<CityInfo> Cities { get; set; } = new List<CityInfo>();
        public CityCollectionView ViewController { get; set; }
        #endregion

        #region Constructors
        public CityViewDatasource (CityCollectionView controller)
        {
            // Initialize
            this.ViewController = controller;
            PopulateCities ();
        }
        #endregion

        #region Public Methods
        public void PopulateCities() {

            // Clear existing cities
            Cities.Clear();

            // Add new cities
            Cities.Add(new CityInfo("City01.jpg", "Houses by Water", false));
            Cities.Add(new CityInfo("City02.jpg", "Turning Circle", true));
            Cities.Add(new CityInfo("City03.jpg", "Skyline at Night", true));
            Cities.Add(new CityInfo("City04.jpg", "Golden Gate Bridge", true));
            Cities.Add(new CityInfo("City05.jpg", "Roads by Night", true));
            Cities.Add(new CityInfo("City06.jpg", "Church Domes", true));
            Cities.Add(new CityInfo("City07.jpg", "Mountain Lights", true));
            Cities.Add(new CityInfo("City08.jpg", "City Scene", false));
            Cities.Add(new CityInfo("City09.jpg", "House in Winter", true));
            Cities.Add(new CityInfo("City10.jpg", "By the Lake", true));
            Cities.Add(new CityInfo("City11.jpg", "At the Dome", true));
            Cities.Add(new CityInfo("City12.jpg", "Cityscape", true));
            Cities.Add(new CityInfo("City13.jpg", "Model City", true));
            Cities.Add(new CityInfo("City14.jpg", "Taxi, Taxi!", true));
            Cities.Add(new CityInfo("City15.jpg", "On the Sidewalk", true));
            Cities.Add(new CityInfo("City16.jpg", "Midnight Walk", true));
            Cities.Add(new CityInfo("City17.jpg", "Lunchtime Cafe", true));
            Cities.Add(new CityInfo("City18.jpg", "Coffee Shop", true));
            Cities.Add(new CityInfo("City19.jpg", "Rustic Tavern", true));
        }
        #endregion

        #region Override Methods
        public override nint NumberOfSections (UICollectionView collectionView)
        {
            return 1;
        }

        public override nint GetItemsCount (UICollectionView collectionView, nint section)
        {
            return Cities.Count;
        }

        public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
        {
            var cityCell = (CityCollectionViewCell)collectionView.DequeueReusableCell (CardCellId, indexPath);
            var city = Cities [indexPath.Row];

            // Initialize city
            cityCell.City = city;

            return cityCell;
        }
        #endregion
    }
}

Przyjrzyjmy się szczegółowo tej klasie. Najpierw dziedziczymy UICollectionViewDataSource i udostępniamy skrót do identyfikatora komórek (który przypisano w Projektant systemu iOS):

public static NSString CardCellId = new NSString ("CityCell");

Następnie udostępniamy magazyn danych zbieranych i udostępniamy klasę do wypełniania danych:

public List<CityInfo> Cities { get; set; } = new List<CityInfo>();
...

public void PopulateCities() {

    // Clear existing cities
    Cities.Clear();

    // Add new cities
    Cities.Add(new CityInfo("City01.jpg", "Houses by Water", false));
    Cities.Add(new CityInfo("City02.jpg", "Turning Circle", true));
    ...
}

Następnie zastąpimy metodę NumberOfSections i zwrócimy liczbę sekcji (grup elementów), które ma nasz widok kolekcji. W tym przypadku jest tylko jeden:

public override nint NumberOfSections (UICollectionView collectionView)
{
    return 1;
}

Następnie zwracamy liczbę elementów w kolekcji przy użyciu następującego kodu:

public override nint GetItemsCount (UICollectionView collectionView, nint section)
{
    return Cities.Count;
}

Na koniec zdejmujemy z kolejki komórkę wielokrotnego użytku, gdy żądanie Widoku kolekcji z następującym kodem:

public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
    var cityCell = (CityCollectionViewCell)collectionView.DequeueReusableCell (CardCellId, indexPath);
    var city = Cities [indexPath.Row];

    // Initialize city
    cityCell.City = city;

    return cityCell;
}

Po pobraniu komórki widoku kolekcji naszego CityCollectionViewCell typu wypełniamy ją danym elementem.

Reagowanie na zdarzenia użytkownika

Ponieważ chcemy, aby użytkownik mógł wybrać element z kolekcji, musimy podać delegata widoku kolekcji, aby obsłużyć tę interakcję. Musimy zapewnić sposób, aby poinformować nasz widok wywołujący o tym, który element został wybrany przez użytkownika.

Delegat aplikacji

Potrzebujemy sposobu powiązania aktualnie wybranego elementu z widoku kolekcji z powrotem do widoku wywołującego. Będziemy używać właściwości niestandardowej w naszym AppDelegateobiekcie . AppDelegate.cs Edytuj plik i dodaj następujący kod:

public CityInfo SelectedCity { get; set;} = new CityInfo("City02.jpg", "Turning Circle", true);

Definiuje właściwość i ustawia domyślne miasto, które będzie początkowo wyświetlane. Później użyjemy tej właściwości, aby wyświetlić wybór użytkownika i zezwolić na zmianę zaznaczenia.

Delegat widoku kolekcji

Następnie dodaj nową CityViewDelegate klasę do projektu i utwórz ją w następujący sposób:

using System;
using System.Collections.Generic;
using UIKit;
using Foundation;
using CoreGraphics;

namespace tvCollection
{
    public class CityViewDelegate : UICollectionViewDelegateFlowLayout
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructors
        public CityViewDelegate ()
        {
        }
        #endregion

        #region Override Methods
        public override CGSize GetSizeForItem (UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
        {
            return new CGSize (361, 256);
        }

        public override bool CanFocusItem (UICollectionView collectionView, NSIndexPath indexPath)
        {
            if (indexPath == null) {
                return false;
            } else {
                var controller = collectionView as CityCollectionView;
                return controller.Source.Cities[indexPath.Row].CanSelect;
            }
        }

        public override void ItemSelected (UICollectionView collectionView, NSIndexPath indexPath)
        {
            var controller = collectionView as CityCollectionView;
            App.SelectedCity = controller.Source.Cities [indexPath.Row];

            // Close Collection
            controller.ParentController.DismissViewController(true,null);
        }
        #endregion
    }
}

Przyjrzyjmy się bliżej tej klasie. Najpierw dziedziczymy z UICollectionViewDelegateFlowLayout. Powodem, dla którego dziedziczymy z tej klasy, a nie UICollectionViewDelegate jest to, że używamy wbudowanego UICollectionViewFlowLayout elementu do prezentowania elementów, a nie niestandardowego typu układu.

Następnie zwracamy rozmiar poszczególnych elementów przy użyciu tego kodu:

public override CGSize GetSizeForItem (UICollectionView collectionView, UICollectionViewLayout layout, NSIndexPath indexPath)
{
    return new CGSize (361, 256);
}

Następnie decydujemy, czy dana komórka może skupić się na użyciu następującego kodu:

public override bool CanFocusItem (UICollectionView collectionView, NSIndexPath indexPath)
{
    if (indexPath == null) {
        return false;
    } else {
        var controller = collectionView as CityCollectionView;
        return controller.Source.Cities[indexPath.Row].CanSelect;
    }
}

Sprawdzamy, czy dany fragment danych zapasowych ma jego CanSelect flagę ustawioną na true i zwracaną wartość. Aby uzyskać więcej informacji na temat nawigacji i koncentracji uwagi, zapoznaj się z dokumentacją Praca z nawigacją i fokusem oraz kontrolerami zdalnymi Siri i Bluetooth.

Na koniec odpowiemy użytkownikowi, wybierając element za pomocą następującego kodu:

public override void ItemSelected (UICollectionView collectionView, NSIndexPath indexPath)
{
    var controller = collectionView as CityCollectionView;
    App.SelectedCity = controller.Source.Cities [indexPath.Row];

    // Close Collection
    controller.ParentController.DismissViewController(true,null);
}

W tym miejscu ustawiliśmy SelectedCity właściwość elementu AppDelegate wybranego przez użytkownika i zamkniemy kontroler widoku kolekcji, wracając do widoku, który nas nazwał. Nie zdefiniowaliśmy ParentController jeszcze właściwości widoku kolekcji. Zrobimy to dalej.

Konfigurowanie widoku kolekcji

Teraz musimy edytować nasz widok kolekcji i przypisać nasze źródło danych i delegata. Zmodyfikuj plik (utworzony automatycznie z naszego scenorysu CityCollectionView.cs ) i utwórz go w następujący sposób:

using System;
using Foundation;
using UIKit;

namespace tvCollection
{
    public partial class CityCollectionView : UICollectionView
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Computed Properties
        public CityViewDatasource Source {
            get { return DataSource as CityViewDatasource;}
        }

        public CityCollectionViewController ParentController { get; set;}
        #endregion

        #region Constructors
        public CityCollectionView (IntPtr handle) : base (handle)
        {
            // Initialize
            RegisterClassForCell (typeof(CityCollectionViewCell), CityViewDatasource.CardCellId);
            DataSource = new CityViewDatasource (this);
            Delegate = new CityViewDelegate ();
        }
        #endregion

        #region Override Methods
        public override nint NumberOfSections ()
        {
            return 1;
        }

        public override void DidUpdateFocus (UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
        {
            var previousItem = context.PreviouslyFocusedView as CityCollectionViewCell;
            if (previousItem != null) {
                Animate (0.2, () => {
                    previousItem.CityTitle.Alpha = 0.0f;
                });
            }

            var nextItem = context.NextFocusedView as CityCollectionViewCell;
            if (nextItem != null) {
                Animate (0.2, () => {
                    nextItem.CityTitle.Alpha = 1.0f;
                });
            }
        }
        #endregion
    }
}

Najpierw udostępniamy skrót do uzyskiwania dostępu do naszego elementu AppDelegate:

public static AppDelegate App {
    get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
}

Następnie udostępniamy skrót do źródła danych widoku kolekcji i właściwości w celu uzyskania dostępu do kontrolera widoku kolekcji (używanego przez naszego pełnomocnika powyżej w celu zamknięcia kolekcji, gdy użytkownik dokona wyboru):

public CityViewDatasource Source {
    get { return DataSource as CityViewDatasource;}
}

public CityCollectionViewController ParentController { get; set;}

Następnie użyjemy następującego kodu, aby zainicjować widok kolekcji i przypisać klasę komórek, źródło danych i delegata:

public CityCollectionView (IntPtr handle) : base (handle)
{
    // Initialize
    RegisterClassForCell (typeof(CityCollectionViewCell), CityViewDatasource.CardCellId);
    DataSource = new CityViewDatasource (this);
    Delegate = new CityViewDelegate ();
}

Na koniec chcemy, aby tytuł pod obrazem był widoczny tylko wtedy, gdy użytkownik ma wyróżnione (fokus). Robimy to za pomocą następującego kodu:

public override void DidUpdateFocus (UIFocusUpdateContext context, UIFocusAnimationCoordinator coordinator)
{
    var previousItem = context.PreviouslyFocusedView as CityCollectionViewCell;
    if (previousItem != null) {
        Animate (0.2, () => {
            previousItem.CityTitle.Alpha = 0.0f;
        });
    }

    var nextItem = context.NextFocusedView as CityCollectionViewCell;
    if (nextItem != null) {
        Animate (0.2, () => {
            nextItem.CityTitle.Alpha = 1.0f;
        });
    }
}

Ustawiamy transparencję poprzedniego elementu tracąc fokus na zero (0), a transparencja następnego elementu zyskuje fokus na 100%. Te przejścia również są animowane.

Konfigurowanie kontrolera widoku kolekcji

Teraz musimy wykonać ostateczną konfigurację w widoku kolekcji i zezwolić kontrolerowi na ustawienie zdefiniowanej właściwości, aby widok kolekcji mógł zostać zamknięty po wybraniu przez użytkownika.

Zmodyfikuj plik (utworzony automatycznie na podstawie naszego scenorysu CityCollectionViewController.cs ) i utwórz go w następujący sposób:

// This file has been autogenerated from a class added in the UI designer.

using System;

using Foundation;
using UIKit;

namespace tvCollection
{
    public partial class CityCollectionViewController : UICollectionViewController
    {
        #region Computed Properties
        public CityCollectionView Collection {
            get { return CollectionView as CityCollectionView; }
        }
        #endregion

        #region Constructors
        public CityCollectionViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void AwakeFromNib ()
        {
            base.AwakeFromNib ();

            // Save link to controller
            Collection.ParentController = this;
        }
        #endregion
    }
}

Łączenie tego wszystkiego

Teraz, gdy wszystkie części zostały połączone, aby wypełnić i kontrolować widok kolekcji, musimy wprowadzić ostateczne zmiany w naszym głównym widoku, aby połączyć wszystko.

Zmodyfikuj plik (utworzony automatycznie na podstawie naszego scenorysu ViewController.cs ) i utwórz go w następujący sposób:

using System;
using Foundation;
using UIKit;
using tvCollection;

namespace MySingleView
{
    public partial class ViewController : UIViewController
    {
        #region Application Access
        public static AppDelegate App {
            get { return (AppDelegate)UIApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructors
        public ViewController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void ViewDidLoad ()
        {
            base.ViewDidLoad ();
            // Perform any additional setup after loading the view, typically from a nib.
        }

        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);

            // Update image with the currently selected one
            CityView.Image = UIImage.FromFile(App.SelectedCity.ImageFilename);
            BackgroundView.Image = CityView.Image;
            CityTitle.Text = App.SelectedCity.Title;
        }

        public override void DidReceiveMemoryWarning ()
        {
            base.DidReceiveMemoryWarning ();
            // Release any cached data, images, etc that aren't in use.
        }
        #endregion
    }
}

Poniższy kod początkowo wyświetla wybrany element z SelectedCity właściwości AppDelegate i redisplays go, gdy użytkownik dokonał wyboru z widoku kolekcji:

public override void ViewWillAppear (bool animated)
{
    base.ViewWillAppear (animated);

    // Update image with the currently selected one
    CityView.Image = UIImage.FromFile(App.SelectedCity.ImageFilename);
    BackgroundView.Image = CityView.Image;
    CityTitle.Text = App.SelectedCity.Title;
}

Testowanie aplikacji

Jeśli tworzysz i uruchamiasz aplikację, widok główny jest wyświetlany z domyślnym miastem:

Ekran główny

Jeśli użytkownik kliknie przycisk Wybierz widok , zostanie wyświetlony widok kolekcji:

Widok kolekcji

Każde miasto, które ma właściwość CanSelect ustawioną na false , zostanie wyświetlone wygaszone, a użytkownik nie będzie mógł ustawić fokusu. Gdy użytkownik wyróżni element (ustawić go w fokusie), tytuł jest wyświetlany i może użyć efektu parallax, aby subtelnie przechylić obraz w 3D.

Gdy użytkownik kliknie wybrany obraz, widok kolekcji zostanie zamknięty, a widok główny zostanie ponownie wyświetlony przy użyciu nowego obrazu:

Nowy obraz na ekranie głównym

Tworzenie niestandardowego układu i zmienianie kolejności elementów

Jedną z kluczowych funkcji korzystania z widoku kolekcji jest możliwość tworzenia układów niestandardowych. Ponieważ system tvOS dziedziczy z systemu iOS, proces tworzenia układu niestandardowego jest taki sam. Aby uzyskać więcej informacji, zobacz dokumentację Wprowadzenie do widoków kolekcji.

Ostatnio dodane do widoków kolekcji dla systemu iOS 9 było możliwość łatwego zezwalania na zmienianie kolejności elementów w kolekcji. Ponownie, ponieważ system tvOS 9 jest podzbiorem systemu iOS 9, odbywa się to w taki sam sposób. Aby uzyskać więcej informacji, zobacz nasz dokument Dotyczący zmian widoku kolekcji.

Podsumowanie

W tym artykule opisano projektowanie i pracę z widokami kolekcji w aplikacji platformy Xamarin.tvOS. Po pierwsze omówił wszystkie elementy tworzące widok kolekcji. Następnie pokazano, jak projektować i implementować widok kolekcji przy użyciu scenorysu. Na koniec udostępnia linki do informacji na temat tworzenia układów niestandardowych i zmieniania kolejności elementów.