Neste artigo, vou mostrar como trabalhar com lista de itens, exibindo textos e imagens em lista roláveis usando a view ListView e apresentando alguns dos seus recursos. Vamos criar uma pequena aplicação que acessa a base de filmes da Netflix.
Na primeira parte do artigo, criamos o projeto Xamarin Forms no VS 2015, definimos o modelo de domínio, incluímos as referências aos pacotes do Json e o HttpClient no projeto e criamos a classe de serviço que irá acessar a base de filmes do Netflix.
Vamos, agora, cuidar da interface com o usuário e para isso vamos definir as páginas:
- MoviesPage – Página que vai exibir os filmes para um ator em um ListView;
- MovieDetailsPage – Página que vai exibir os detalhes de um filme selecionado;
Abaixo, temos como devem se comportar cada uma das páginas:
Criando a interface com o usuário
Abra o projeto AppRouletteNetFlix, criado na primeira parte do artigo, no Visual Studio Community 2015.
Selecione o projeto compartilhado AppRouletteNetFlix e, no menu Project, clique em Add New Item.
Selecione o item Cross-Plataform e, a seguir, Forms Xaml Page. Informe o nome MoviesPage e clique em Add.
Repita o procedimento acima e crie a página MovieDetailsPage.
Você verá na janela Solution Explorer os arquivos MoviesPage.xaml e MovieDetailsPage.xaml que representam o arquivo onde o código XAML, que geralmente define o comportamento da interface do usuário. Ele é colocado e os arquivos code-behind MoviesPage.xaml.cs e MovieDetailsPage.xaml.cs, que representam os arquivos onde o código C# é usado para alterar o comportamento e tratar eventos.
Definindo a interface para exibir os filmes na página MoviesPage
Abra o arquivo MoviesPage.xaml e inclua seguir o código abaixo:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="AppRouletteNetFlix.MoviesPage" Title="Filmes"> <StackLayout> <SearchBar Placeholder="Buscar filmes por ator..." TextColor="Black" TextChanged="SearchBar_TextChanged"/> <Label x:Name="lblmsg" TextColor="Red" FontSize="20" IsVisible="False" HorizontalOptions="Center" VerticalOptions="Center"/> <ListView x:Name="lvwMovies" IsVisible="False" ItemSelected="lvwMovies_ItemSelected"> <ListView.ItemTemplate> <DataTemplate> <ImageCell Text="{Binding Title}" Detail="{Binding ReleaseYear}" ImageSource="{Binding ImageUrl}" /> </DataTemplate> </ListView.ItemTemplate> </ListView> </StackLayout> </ContentPage>
Estamos usando um StackLayout para empilhar verticalmente (o padrão) as demais views que são:
- SearchBar – Definimos o evento TextChanged nesta view para tratar a digitação do usuário;
- Label – xName=lblmsg – Vamos usar essa label para exibir mensagens ao usuário;
- ListView – xName=lvwMovies – Definimos o evento ItemSelected para capturar o filme selecionado pelo usuário;
- DataTemplate – Definimos um DataTemplate para exibir os dados dos filmes usando um ImageCell e os recursos do DataBinding.
Definindo o código C# no arquivo MoviesPage.xaml.cs
Vamos agora definir o código que vai tratar os eventos da interface como a digitação do usuário, acessar o serviço REST da Netflix e exibir as informações no ListView.
Abra o arquivo MoviesPage.xaml.cs e inclua o código a seguir:
using AppRouletteNetFlix.Model; using AppRouletteNetFlix.Service; using System.Collections.Generic; using Xamarin.Forms; namespace AppRouletteNetFlix { public partial class MoviesPage : ContentPage { MovieService servico = new MovieService(); public MoviesPage() { InitializeComponent(); } private async void SearchBar_TextChanged(object sender, TextChangedEventArgs e) { //verifica a quantidade de caracteres digitados if (e.NewTextValue.Length > 5) { List<Movie> filmes = await servico.LocalizaFilmesPorAtor(e.NewTextValue); if (filmes == null || filmes.Count == 0) { //esconde o listview e exibe o label //exibe a mensagem no label lvwMovies.IsVisible = false; lblmsg.IsVisible = true; lblmsg.Text = "Não foi possível retornar a lista de filmes"; lblmsg.TextColor = Color.Red; } else { //exibe o listview e esconde o label //exibe a lista de filmes lvwMovies.IsVisible = true; lblmsg.IsVisible = false; lvwMovies.ItemsSource = filmes; } } else { //esconde o listview e exibe o label coma mensagem lvwMovies.IsVisible = false; lblmsg.IsVisible = true; lblmsg.Text = "Digite pelo menos 6 caracteres."; } } private async void lvwMovies_ItemSelected(object sender, SelectedItemChangedEventArgs e) { if (e.SelectedItem == null) return; //obtem o item selecionado var filme = e.SelectedItem as Movie; //deseleciona o item do listview lvwMovies.SelectedItem = null; //chama a pagina MovieDetailsPage await Navigation.PushAsync(new MovieDetailsPage(filme)); } } }
Vamos entender o código:
Criamos uma instância da nossa classe MovieService para poder acessar o serviço REST : MovieService servico = new MovieService(). A seguir, temos o tratamento do evento TextChanged da view SearchBar:
- Neste evento, verificamos se a quantidade de caracteres digitada pelo usuário é maior que 5 : e.NewTextValue.Length > 5;
- Neste caso, usamos o método LocalizaFilmesPorAtor() da classe MovieService e retornamos uma lista de filmes:
List<Movie> filmes = await servico.LocalizaFilmesPorAtor(e.NewTextValue); - Se houver filmes retornados, então, exibimos no controle ListView : lvwMovies.ItemsSource = filmes;
- Caso contrário, exibimos uma mensagem ao usuário na view Label : lblmsg.Text = “Não foi possível retornar a lista de filmes”.
A seguir, temos o tratamento do evento ItemSelected da view ListView:
- Verificamos se existe um item selecionado e obtemos o item convertendo-o para o tipo Movie: var filme = e.SelectedItem as Movie;
- Desmarcamos o item selecionado na listview : lvwMovies.SelectedItem = null;
- Chamamos a página MovieDetailsPage(), passando como parâmetro o filme selecionado: await Navigation.PushAsync(new MovieDetailsPage(filme)).
Dessa forma, esta página está pronta para receber e exibir as informações dos filmes obtidas a partir do serviço REST.
Na terceira parte do artigo vamos implementar as funcionalidades da página MovieDetailsPage para exibir os detalhes de um filme.