Compartilhar via


Trabalhando com exibições de tabela do tvOS no Xamarin

Este artigo aborda o design e o trabalho com Modos de Exibição de Tabela e Controladores de Exibição de Tabela dentro de um aplicativo Xamarin.tvOS.

No tvOS, uma Exibição de Tabela é apresentada como uma única coluna de linhas de rolagem que podem ser organizadas opcionalmente em grupos ou seções. As Exibições de Tabela devem ser usadas quando você precisar exibir uma grande quantidade de dados de forma eficiente para o usuário, de forma clara e compreensível.

Normalmente, as Exibições de Tabela são exibidas em um lado de uma Exibição Dividida como navegação, com os detalhes do item selecionado exibidos no lado oposto:

Exemplo de exibição de tabela

Sobre modos de exibição de tabela

A UITableView exibe uma única coluna de linhas roláveis como uma lista hierárquica de informações que podem ser organizadas opcionalmente em grupos ou seções:

Um item selecionado

A Apple tem as seguintes sugestões para trabalhar com tabelas:

  • Esteja ciente da largura - Tente encontrar o equilíbrio correto nas larguras da tabela. Se a tabela for muito larga, pode ser difícil digitalizar à distância e pode tirar da área de conteúdo disponível. Se a tabela for muito estreita, isso pode fazer com que as informações sejam truncadas ou quebradas, novamente isso pode ser difícil para o usuário ler do outro lado da sala.
  • Mostrar conteúdo da tabela rapidamente - Para grandes listas de dados, carregue o conteúdo com preguiça e comece a mostrar informações assim que a tabela for apresentada ao usuário. Se a tabela demorar muito para carregar, o usuário pode perder o interesse em seu aplicativo ou achar que ele está bloqueado.
  • Informar o usuário sobre cargas longas de conteúdo - Se um longo tempo de carregamento da tabela for inevitável, apresente uma Barra de progresso ou um indicador de atividade para que ele saiba que o aplicativo não foi bloqueado.

Tipos de célula de exibição de tabela

A UITableViewCell é usado para representar as Linhas de dados individuais no Modo de Exibição de Tabela. A Apple definiu vários tipos de células de tabela padrão:

  • Padrão - Esse tipo apresenta uma opção Imagem no lado esquerdo da Célula e Título alinhado à esquerda à direita.
  • Subtítulo - Este tipo apresenta um Título alinhado à esquerda na primeira linha e um Legenda menor alinhado à esquerda na próxima linha.
  • Valor 1 - Esse tipo apresenta um Título alinhado à esquerda com uma Legenda de cor mais clara e alinhada à direita na mesma linha.
  • Valor 2 - Esse tipo apresenta um Título alinhado à direita com uma Legenda de cor mais clara e alinhada à esquerda na mesma linha.

Todos os tipos de célula de exibição de tabela padrão também oferecem suporte a elementos gráficos, como indicadores de divulgação ou marcas de seleção.

Além disso, você pode definir um tipo de célula de exibição de tabela personalizada e apresentar uma célula de protótipo, que você cria no Designer de Interface ou via código.

A Apple tem as seguintes sugestões para trabalhar com células de visualização de tabela:

  • Evite o recorte de texto - Mantenha as linhas individuais de texto curtas para que não acabem truncadas. Palavras ou frases truncadas são difíceis de serem analisadas pelo usuário do outro lado da sala.
  • Considere o Estado da Linha Focada - Como uma Linha se torna maior, com cantos mais arredondados quando em foco, você precisa testar a aparência da Célula em todos os estados. As imagens ou o texto podem ficar cortados ou parecer incorretos no estado Focalizado.
  • Use tabelas editáveis com moderação - Mover ou excluir linhas de tabela é mais demorado no tvOS do que no iOS. Você precisa decidir cuidadosamente se esse recurso irá adicionar ou distrair do seu aplicativo tvOS.
  • Criar tipos de célula personalizados quando apropriado - Embora os tipos de célula de exibição de tabela internos sejam ótimos para muitas situações, considere a criação de tipos de célula personalizados para informações não padrão para fornecer maior controle e apresentar melhor as informações ao usuário.

Trabalhando com modos de exibição de tabela

A maneira mais fácil de trabalhar com Exibições de Tabela em um aplicativo Xamarin.tvOS é criar e modificar sua aparência no Designer de Interface.

Para começar, faça o seguinte:

  1. No Visual Studio para Mac, inicie um novo projeto de aplicativo tvOS e selecione Aplicativo tvOS>>Aplicativo de Exibição Única e clique no botão Avançar:

    Selecione Aplicativo de Exibição Única

  2. Insira um Nome para o aplicativo e clique em Avançar:

    Insira um Nome para o aplicativo

  3. Ajuste o Nome do Projeto e o Nome da Solução ou aceite os padrões e clique no botão Criar para criar a nova solução:

    O nome do projeto e o nome da solução

  4. No Solution Pad, clique duas vezes no Main.storyboard arquivo para abri-lo no iOS Designer:

    O arquivo Main.storyboard

  5. Selecione e exclua o Controlador de Exibição Padrão:

    Selecionar e excluir o controlador de exibição padrão

  6. Selecione um Controlador de Visualização Dividida na Caixa de Ferramentas e arraste-o para a Superfície de Design.

  7. Por padrão, você obterá um Split View com um Navigation View Controller e um Table View Controller no lado esquerdo e um View Controller no lado direito. Esta é a sugestão de uso da Apple de uma exibição de tabela no tvOS:

    Adicionar um modo de exibição dividido

  8. Você precisará selecionar cada parte do Modo de Exibição de Tabela e atribuir a ele um Nome de Classe personalizado na guia Widget do Gerenciador de Propriedades para que você possa acessá-lo posteriormente no código C#. Por exemplo, o Controlador de Exibição de Tabela:

    Atribuir um nome de classe

  9. Certifique-se de criar uma classe personalizada para o Controlador de Exibição de Tabela, o Modo de Exibição de Tabela e quaisquer Células de Protótipo. O Visual Studio para Mac adicionará as classes personalizadas à Árvore do Projeto à medida que forem criadas:

    As classes personalizadas na árvore do projeto

  10. Em seguida, selecione o Modo de Exibição de Tabela na Superfície de Design e ajuste suas propriedades conforme necessário. Como o número de células de protótipo e o estilo (simples ou agrupado):

    A guia widget

  11. Para cada Célula de Protótipo, selecione-a e atribua um Identificador exclusivo na guia Widget do Gerenciador de Propriedades. Esta etapa é muito importante , pois você precisará desse Identificador mais tarde quando preencher a tabela. Por exemplo: AttrCell

    A guia Widget

  12. Você também pode optar por apresentar a Célula como um dos Tipos de Célula de Exibição de Tabela Padrão por meio do menu suspenso Estilo ou defini-la como Personalizada e usar a Superfície de Design para esquematizar a Célula arrastando outros widgets da interface do usuário da Caixa de Ferramentas:

    O layout da célula

  13. Atribua um Nome exclusivo a cada elemento da interface do usuário no design da Célula de Protótipo na guia Widget do Gerenciador de Propriedades para que você possa acessá-los posteriormente no código C#:

    Atribuir um nome

  14. Repita a etapa acima para todas as células de protótipo no modo de exibição de tabela.

  15. Em seguida, atribua classes personalizadas ao restante do design da interface do usuário, esquematize o modo de exibição Detalhes e atribua Nomes exclusivos a cada elemento da interface do usuário no modo de exibição Detalhes para que você possa acessá-los também em C#. Por exemplo:

    O layout da interface do usuário

  16. Salve suas alterações no storyboard.

Criando um modelo de dados

Para facilitar o trabalho com as informações que o Modo de Exibição de Tabela exibirá e facilitar a apresentação de informações detalhadas (à medida que o usuário seleciona ou realça Linhas no Modo de Exibição de Tabela), crie uma classe ou classes personalizadas para atuar como o Modelo de Dados para as informações apresentadas.

Veja o exemplo de um aplicativo de reserva de viagens que contém uma lista de Cidades, cada uma contendo uma lista exclusiva de Atrações que o usuário pode selecionar. O usuário poderá marcar uma atração como Favorita, selecionar para obter Direções para uma atração e Reservar um Voo para uma determinada cidade.

Para criar o Modelo de Dados para uma Atração, clique com o botão direito do mouse no Nome do Projeto no Painel de Soluções e selecione Adicionar>Novo Arquivo.... Digite AttractionInformation o Nome e clique no botão Novo:

Insira AttractionInformation para o nome

Edite o AttractionInformation.cs arquivo e faça com que ele tenha a seguinte aparência:

using System;
using Foundation;

namespace tvTable
{
    public class AttractionInformation : NSObject
    {
        #region Computed Properties
        public CityInformation City { get; set;}
        public string Name { get; set;}
        public string Description { get; set;}
        public string ImageName { get; set;}
        public bool IsFavorite { get; set;}
        public bool AddDirections { get; set;}
        #endregion

        #region Constructors
        public AttractionInformation (string name, string description, string imageName)
        {
            // Initialize
            this.Name = name;
            this.Description = description;
            this.ImageName = imageName;
        }
        #endregion
    }
}

Essa classe fornece as propriedades para armazenar as informações sobre uma determinada atração.

Em seguida, clique com o botão direito do mouse no Nome do Projeto no Painel de Soluções novamente e selecione Adicionar>Novo Arquivo.... Digite CityInformation o Nome e clique no botão Novo:

Insira CityInformation para o nome

Edite o CityInformation.cs arquivo e faça com que ele tenha a seguinte aparência:

using System;
using System.Collections.Generic;
using Foundation;

namespace tvTable
{
    public class CityInformation : NSObject
    {
        #region Computed Properties
        public string Name { get; set; }
        public List<AttractionInformation> Attractions { get; set;}
        public bool FlightBooked { get; set;}
        #endregion

        #region Constructors
        public CityInformation (string name)
        {
            // Initialize
            this.Name = name;
            this.Attractions = new List<AttractionInformation> ();
        }
        #endregion

        #region Public Methods
        public void AddAttraction (AttractionInformation attraction)
        {
            // Mark as belonging to this city
            attraction.City = this;

            // Add to collection
            Attractions.Add (attraction);
        }

        public void AddAttraction (string name, string description, string imageName)
        {
            // Create attraction
            var attraction = new AttractionInformation (name, description, imageName);

            // Mark as belonging to this city
            attraction.City = this;

            // Add to collection
            Attractions.Add (attraction);
        }
        #endregion
    }
}

Esta classe contém todas as informações sobre uma cidade de destino, uma coleção de atrações para essa cidade e fornece dois métodos auxiliares (AddAttraction) para facilitar a adição de atrações à cidade.

A fonte de dados do Modo de Exibição de Tabela

Cada Modo de Exibição de Tabela requer uma Fonte de Dados (UITableViewDataSource) para fornecer os dados para a Tabela e gerar as Linhas necessárias, conforme exigido pelo Modo de Exibição de Tabela.

Para o exemplo dado acima, clique com o botão direito do mouse no Nome do Projeto no Gerenciador de Soluções, selecione Adicionar>Novo Arquivo... e chame-o AttractionTableDatasource e clique no botão Novo para criar. Em seguida, edite o AttractionTableDatasource.cs arquivo e torne-o parecido com o seguinte:

using System;
using System.Collections.Generic;
using UIKit;

namespace tvTable
{
    public class AttractionTableDatasource : UITableViewDataSource
    {
        #region Constants
        const string CellID = "AttrCell";
        #endregion

        #region Computed Properties
        public AttractionTableViewController Controller { get; set;}
        public List<CityInformation> Cities { get; set;}
        #endregion

        #region Constructors
        public AttractionTableDatasource (AttractionTableViewController controller)
        {
            // Initialize
            this.Controller = controller;
            this.Cities = new List<CityInformation> ();
            PopulateCities ();
        }
        #endregion

        #region Public Methods
        public void PopulateCities ()
        {
            // Clear existing
            Cities.Clear ();

            // Define cities and attractions
            var Paris = new CityInformation ("Paris");
            Paris.AddAttraction ("Eiffel Tower", "Is a wrought iron lattice tower on the Champ de Mars in Paris, France.", "EiffelTower");
            Paris.AddAttraction ("Musée du Louvre", "is one of the world's largest museums and a historic monument in Paris, France.", "Louvre");
            Paris.AddAttraction ("Moulin Rouge", "French for 'Red Mill', is a cabaret in Paris, France.", "MoulinRouge");
            Paris.AddAttraction ("La Seine", "Is a 777-kilometre long river and an important commercial waterway within the Paris Basin.", "RiverSeine");
            Cities.Add (Paris);

            var SanFran = new CityInformation ("San Francisco");
            SanFran.AddAttraction ("Alcatraz Island", "Is located in the San Francisco Bay, 1.25 miles (2.01 km) offshore from San Francisco.", "Alcatraz");
            SanFran.AddAttraction ("Golden Gate Bridge", "Is a suspension bridge spanning the Golden Gate strait between San Francisco Bay and the Pacific Ocean", "GoldenGateBridge");
            SanFran.AddAttraction ("San Francisco", "Is the cultural, commercial, and financial center of Northern California.", "SanFrancisco");
            SanFran.AddAttraction ("Telegraph Hill", "Is primarily a residential area, much quieter than adjoining North Beach.", "TelegraphHill");
            Cities.Add (SanFran);

            var Houston = new CityInformation ("Houston");
            Houston.AddAttraction ("City Hall", "It was constructed in 1938-1939, and is located in Downtown Houston.", "CityHall");
            Houston.AddAttraction ("Houston", "Is the most populous city in Texas and the fourth most populous city in the US.", "Houston");
            Houston.AddAttraction ("Texas Longhorn", "Is a breed of cattle known for its characteristic horns, which can extend to over 6 ft.", "LonghornCattle");
            Houston.AddAttraction ("Saturn V Rocket", "was an American human-rated expendable rocket used by NASA between 1966 and 1973.", "Rocket");
            Cities.Add (Houston);
        }
        #endregion

        #region Override Methods
        public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            // Get cell
            var cell = tableView.DequeueReusableCell (CellID) as AttractionTableCell;

            // Populate cell
            cell.Attraction = Cities [indexPath.Section].Attractions [indexPath.Row];

            // Return new cell
            return cell;
        }

        public override nint NumberOfSections (UITableView tableView)
        {
            // Return number of cities
            return Cities.Count;
        }

        public override nint RowsInSection (UITableView tableView, nint section)
        {
            // Return the number of attractions in the given city
            return Cities [(int)section].Attractions.Count;
        }

        public override string TitleForHeader (UITableView tableView, nint section)
        {
            // Get the name of the current city
            return Cities [(int)section].Name;
        }
        #endregion
    }
}

Vamos dar uma olhada em algumas seções da classe em detalhes.

Primeiro, definimos uma constante para manter o Identificador exclusivo da Célula do Protótipo (este é o mesmo Identificador atribuído no Designer de Interface acima), adicionamos um atalho de volta ao Controlador de Exibição de Tabela e criamos armazenamento para nossos dados:

const string CellID = "AttrCell";
public AttractionTableViewController Controller { get; set;}
public List<CityInformation> Cities { get; set;}

Em seguida, salvamos o Controlador de Exibição de Tabela e, em seguida, compilamos e preenchemos nossa fonte de dados (usando os Modelos de Dados definidos acima) quando a classe é criada:

public AttractionTableDatasource (AttractionTableViewController controller)
{
    // Initialize
    this.Controller = controller;
    this.Cities = new List<CityInformation> ();
    PopulateCities ();
}

Por exemplo, o PopulateCities método simplesmente cria objetos de Modelo de Dados na memória, no entanto, eles podem ser facilmente lidos de um banco de dados ou serviço Web em um aplicativo real:

public void PopulateCities ()
{
    // Clear existing
    Cities.Clear ();

    // Define cities and attractions
    var Paris = new CityInformation ("Paris");
    Paris.AddAttraction ("Eiffel Tower", "Is a wrought iron lattice tower on the Champ de Mars in Paris, France.", "EiffelTower");
    ...
}

O NumberOfSections método retorna o número de seções na tabela:

public override nint NumberOfSections (UITableView tableView)
{
    // Return number of cities
    return Cities.Count;
}

Para Exibições de Tabela com estilo simples , sempre retorne 1.

O RowsInSection método retorna o número de linhas na seção atual:

public override nint RowsInSection (UITableView tableView, nint section)
{
    // Return the number of attractions in the given city
    return Cities [(int)section].Attractions.Count;
}

Novamente, para Exibições de Tabela sem Formatação , retorne o número total de itens na fonte de dados.

O TitleForHeader método retorna o Title para determinada seção:

public override string TitleForHeader (UITableView tableView, nint section)
{
    // Get the name of the current city
    return Cities [(int)section].Name;
}

Para um tipo de Modo de Exibição de Tabela sem Formatação , deixe o título em branco ("").

Finalmente, quando solicitado pelo Modo de Exibição de Tabela, crie e preencha uma Célula de Protótipo usando o GetCell método:

public override UITableViewCell GetCell (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    // Get cell
    var cell = tableView.DequeueReusableCell (CellID) as AttractionTableCell;

    // Populate cell
    cell.Attraction = Cities [indexPath.Section].Attractions [indexPath.Row];

    // Return new cell
    return cell;
}

Para obter mais informações sobre como trabalhar com um UITableViewDatasource, consulte a documentação UITableViewDatasource da Apple.

O delegado do Modo de Exibição de Tabela

Cada Modo de Exibição de Tabela requer um Representante (UITableViewDelegate) para responder à interação do usuário ou a outros eventos do sistema na Tabela.

Para o exemplo dado acima, clique com o botão direito do mouse no Nome do Projeto no Gerenciador de Soluções, selecione Adicionar>Novo Arquivo... e chame-o AttractionTableDelegate e clique no botão Novo para criar. Em seguida, edite o AttractionTableDelegate.cs arquivo e torne-o parecido com o seguinte:

using System;
using System.Collections.Generic;
using UIKit;

namespace tvTable
{
    public class AttractionTableDelegate : UITableViewDelegate
    {
        #region Computed Properties
        public AttractionTableViewController Controller { get; set;}
        #endregion

        #region Constructors
        public AttractionTableDelegate (AttractionTableViewController controller)
        {
            // Initializw
            this.Controller = controller;
        }
        #endregion

        #region Override Methods
        public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            var attraction = Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row];
            attraction.IsFavorite = (!attraction.IsFavorite);

            // Update UI
            Controller.TableView.ReloadData ();
        }

        public override bool CanFocusRow (UITableView tableView, Foundation.NSIndexPath indexPath)
        {
            // Inform caller of highlight change
            RaiseAttractionHighlighted (Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row]);
            return true;
        }
        #endregion

        #region Events
        public delegate void AttractionHighlightedDelegate (AttractionInformation attraction);
        public event AttractionHighlightedDelegate AttractionHighlighted;

        internal void RaiseAttractionHighlighted (AttractionInformation attraction)
        {
            // Inform caller
            if (this.AttractionHighlighted != null) this.AttractionHighlighted (attraction);
        }
        #endregion
    }
}

Vamos dar uma olhada em várias seções desta classe em detalhes.

Primeiro, criamos um atalho para o Table View Controller quando a classe é criada:

public AttractionTableViewController Controller { get; set;}
...

public AttractionTableDelegate (AttractionTableViewController controller)
{
    // Initialize
    this.Controller = controller;
}

Em seguida, quando uma linha é selecionada (o usuário clica na superfície de toque do Apple Remote), queremos marcar a Atração representada pela Linha selecionada como Favorita:

public override void RowSelected (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    var attraction = Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row];
    attraction.IsFavorite = (!attraction.IsFavorite);

    // Update UI
    Controller.TableView.ReloadData ();
}

Em seguida, quando o usuário realçar uma Linha (dando-lhe Foco usando o Apple Remote Touch Surface), queremos apresentar os Detalhes da Atração representada por essa Linha na seção Detalhes do nosso Controlador Split View:

public override bool CanFocusRow (UITableView tableView, Foundation.NSIndexPath indexPath)
{
    // Inform caller of highlight change
    RaiseAttractionHighlighted (Controller.Datasource.Cities [indexPath.Section].Attractions [indexPath.Row]);
    return true;
}
...

public delegate void AttractionHighlightedDelegate (AttractionInformation attraction);
public event AttractionHighlightedDelegate AttractionHighlighted;

internal void RaiseAttractionHighlighted (AttractionInformation attraction)
{
    // Inform caller
    if (this.AttractionHighlighted != null) this.AttractionHighlighted (attraction);
}

O CanFocusRow método é chamado para cada linha que está prestes a obter foco no modo de exibição de tabela. Retorne true se a Linha puder obter Foco, caso contrário, retorne false. No caso deste exemplo, criamos um evento personalizado AttractionHighlighted que será gerado em cada Linha à medida que ela recebe o Foco.

Para obter mais informações sobre como trabalhar com um UITableViewDelegate, consulte a documentação UITableViewDelegate da Apple.

A célula do modo de exibição de tabela

Para cada Célula de Protótipo adicionada ao Modo de Exibição de Tabela no Designer de Interface, você também criou uma instância personalizada da Célula de Exibição de Tabela (UITableViewCell) para permitir que você preencha a nova célula (Linha) à medida que ela é criada.

Para o aplicativo de exemplo, clique duas vezes no AttractionTableCell.cs arquivo para abri-lo para edição e torná-lo parecido com o seguinte:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionTableCell : UITableViewCell
    {
        #region Private Variables
        private AttractionInformation _attraction = null;
        #endregion

        #region Computed Properties
        public AttractionInformation Attraction {
            get { return _attraction; }
            set {
                _attraction = value;
                UpdateUI ();
            }
        }
        #endregion

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

        #region Private Methods
        private void UpdateUI ()
        {
            // Trap all errors
            try {
                Title.Text = Attraction.Name;
                Favorite.Hidden = (!Attraction.IsFavorite);
            } catch {
                // Since the UI might not be fully loaded, ignore
                // all errors at this point
            }
        }
        #endregion
    }
}

Essa classe fornece armazenamento para o objeto Attraction Data Model (AttractionInformation conforme definido acima) exibido na linha fornecida:

private AttractionInformation _attraction = null;
...

public AttractionInformation Attraction {
    get { return _attraction; }
    set {
        _attraction = value;
        UpdateUI ();
    }
}

O UpdateUI método preenche os widgets da interface do usuário (que foram adicionados ao protótipo da célula no Designer de Interface) conforme necessário:

private void UpdateUI ()
{
    // Trap all errors
    try {
        Title.Text = Attraction.Name;
        Favorite.Hidden = (!Attraction.IsFavorite);
    } catch {
        // Since the UI might not be fully loaded, ignore
        // all errors at this point
    }
}

Para obter mais informações sobre como trabalhar com um UITableViewCell, consulte a documentação UITableViewCell da Apple.

O controlador de exibição de tabela

Um Controlador de Exibição de Tabela (UITableViewController) gerencia um Modo de Exibição de Tabela que foi adicionado a um Storyboard por meio do Designer de Interface.

Para o aplicativo de exemplo, clique duas vezes no AttractionTableViewController.cs arquivo para abri-lo para edição e torná-lo parecido com o seguinte:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionTableViewController : UITableViewController
    {
        #region Computed Properties
        public AttractionTableDatasource Datasource {
            get { return TableView.DataSource as AttractionTableDatasource; }
        }

        public AttractionTableDelegate TableDelegate {
            get { return TableView.Delegate as AttractionTableDelegate; }
        }
        #endregion

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

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

            // Setup table
            TableView.DataSource = new AttractionTableDatasource (this);
            TableView.Delegate = new AttractionTableDelegate (this);
            TableView.ReloadData ();
        }
        #endregion
    }
}

Vamos dar uma olhada mais de perto nesta classe. Primeiro, criamos atalhos para facilitar o acesso ao Modo de Exibição de Tabela e DataSourceTableDelegateao . Vamos usá-los posteriormente para nos comunicarmos entre o Modo de Exibição de Tabela no lado esquerdo do Modo de Exibição Dividido e o Modo de Exibição de Detalhes à direita.

Finalmente, quando o Modo de Exibição de Tabela é carregado na memória, criamos instâncias do AttractionTableDatasource e AttractionTableDelegate (ambos criados acima) e os anexamos ao Modo de Exibição de Tabela.

Para obter mais informações sobre como trabalhar com um UITableViewController, consulte a documentação UITableViewController da Apple.

Puxando tudo junto

Conforme indicado no início deste documento, as Exibições de Tabela são normalmente exibidas em um lado de um Modo de Exibição Dividido como navegação, com os detalhes do item selecionado exibidos no lado oposto. Por exemplo:

Execução de aplicativo de exemplo

Como este é um padrão padrão no tvOS, vamos ver as etapas finais para reunir tudo e fazer com que os lados esquerdo e direito do Split View interajam entre si.

A Vista de Detalhes

Para o exemplo do aplicativo de viagem apresentado acima, uma classe personalizada (AttractionViewController) é definida para o View Controller padrão apresentado no lado direito do Split View como o Detail View:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class AttractionViewController : UIViewController
    {
        #region Private Variables
        private AttractionInformation _attraction = null;
        #endregion

        #region Computed Properties
        public AttractionInformation Attraction {
            get { return _attraction; }
            set {
                _attraction = value;
                UpdateUI ();
            }
        }

        public MasterSplitView SplitView { get; set;}
        #endregion

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

        #region Public Methods
        public void UpdateUI ()
        {
            // Trap all errors
            try {
                City.Text = Attraction.City.Name;
                Title.Text = Attraction.Name;
                SubTitle.Text = Attraction.Description;

                IsFlighBooked.Hidden = (!Attraction.City.FlightBooked);
                IsFavorite.Hidden = (!Attraction.IsFavorite);
                IsDirections.Hidden = (!Attraction.AddDirections);
                BackgroundImage.Image = UIImage.FromBundle (Attraction.ImageName);
                AttractionImage.Image = BackgroundImage.Image;
            } catch {
                // Since the UI might not be fully loaded, ignore
                // all errors at this point
            }
        }
        #endregion

        #region Override Methods
        public override void ViewWillAppear (bool animated)
        {
            base.ViewWillAppear (animated);

            // Ensure the UI Updates
            UpdateUI ();
        }
        #endregion

        #region Actions
        partial void BookFlight (NSObject sender)
        {
            // Ask user to book flight
            AlertViewController.PresentOKCancelAlert ("Book Flight",
                                                      string.Format ("Would you like to book a flight to {0}?", Attraction.City.Name),
                                                      this,
                                                      (ok) => {
                Attraction.City.FlightBooked = ok;
                IsFlighBooked.Hidden = (!Attraction.City.FlightBooked);
            });
        }

        partial void GetDirections (NSObject sender)
        {
            // Ask user to add directions
            AlertViewController.PresentOKCancelAlert ("Add Directions",
                                                     string.Format ("Would you like to add directions to {0} to you itinerary?", Attraction.Name),
                                                     this,
                                                     (ok) => {
                                                         Attraction.AddDirections = ok;
                                                         IsDirections.Hidden = (!Attraction.AddDirections);
                                                     });
        }

        partial void MarkFavorite (NSObject sender)
        {
            // Flip favorite state
            Attraction.IsFavorite = (!Attraction.IsFavorite);
            IsFavorite.Hidden = (!Attraction.IsFavorite);

            // Reload table
            SplitView.Master.TableController.TableView.ReloadData ();
        }
        #endregion
    }
}

Aqui, fornecemos a Atração (AttractionInformation) que está sendo exibida como uma propriedade e criamos um UpdateUI método que preenche os Widgets da Interface do Usuário adicionados à Exibição no Designer de Interface.

Também definimos um atalho para o Controlador de Exibição Dividida (SplitView) que usaremos para comunicar as alterações de volta ao Modo de Exibição de Tabela (AcctractionTableView).

Finalmente, Ações personalizadas (eventos) foram adicionadas às três UIButton instâncias criadas no Designer de Interface, que permitem ao usuário marcar uma atração como Favorita, obter Direções para uma atração e Reservar um Voo para uma determinada cidade.

O controlador de exibição de navegação

Como o Controlador de Modo de Exibição de Tabela está aninhado em um Controlador de Modo de Exibição de Navegação no lado esquerdo do Modo de Exibição Difundido, o Controlador de Modo de Exibição de Navegação recebeu uma classe personalizada (MasterNavigationController) no Designer de Interface e foi definido da seguinte maneira:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class MasterNavigationController : UINavigationController
    {
        #region Computed Properties
        public MasterSplitView SplitView { get; set;}
        public AttractionTableViewController TableController {
            get { return TopViewController as AttractionTableViewController; }
        }
        #endregion

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

Novamente, essa classe apenas define alguns atalhos para facilitar a comunicação entre os dois lados do Controlador de Exibição Dividida:

  • SplitView - É um link para o Controlador de Visualização Dividida (MainSpiltViewController) ao qual o Controlador de Visualização de Navegação pertence.
  • TableController - Obtém o Controlador de Exibição de Tabela (AttractionTableViewController) que é apresentado como o Modo de Exibição Superior no Controlador de Modo de Exibição de Navegação.

O controlador Split View

Como o Split View Controller é a base do nosso aplicativo, criamos uma classe personalizada (MasterSplitViewController) para ele no Interface Designer e a definimos da seguinte maneira:

using System;
using Foundation;
using UIKit;

namespace tvTable
{
    public partial class MasterSplitView : UISplitViewController
    {
        #region Computed Properties
        public AttractionViewController Details {
            get { return ViewControllers [1] as AttractionViewController; }
        }

        public MasterNavigationController Master {
            get { return ViewControllers [0] as MasterNavigationController; }
        }
        #endregion

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

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

            // Initialize
            Master.SplitView = this;
            Details.SplitView = this;

            // Wire-up events
            Master.TableController.TableDelegate.AttractionHighlighted += (attraction) => {
                // Display new attraction
                Details.Attraction = attraction;
            };
        }
        #endregion
    }
}

Primeiro, criamos atalhos para o lado Detalhes do Modo de Exibição Dividido (AttractionViewController) e para o lado Mestre (MasterNavigationController). Mais uma vez, isso facilita a comunicação entre os dois lados mais tarde.

Em seguida, quando o Split View é carregado na memória, anexamos o Split View Controller aos dois lados do Split View e respondemos ao usuário destacando uma atração no Table View (AttractionHighlighted) exibindo a nova atração no lado Details do Split View.

Exibições de tabela em detalhes

Como o tvOS é baseado no iOS, as Visualizações de Tabela e os Controladores de Exibição de Tabela são projetados e se comportam de maneira semelhante. Para obter informações mais detalhadas sobre como trabalhar com o Modo de Exibição de Tabela em um aplicativo Xamarin, consulte nossa documentação Trabalhando com tabelas e células do iOS.

Resumo

Este artigo abordou o design e o trabalho com Exibições de Tabela dentro de um aplicativo Xamarin.tvOS. E apresentou um exemplo de como trabalhar com uma Vista de Tabela dentro de uma Vista dividida, que é a utilização típica de uma Vista de Tabela numa aplicação tvOS.