Escolar Documentos
Profissional Documentos
Cultura Documentos
Xamarin.Forms
Introdução
Requisitos
Instalação
Criar seu primeiro aplicativo
Início rápido de página única
Início rápido de várias páginas
Início rápido do banco de dados local
Início rápido de estilos
Aprofundamento
XAML
Controles XAML
Noções básicas de XAML
Parte 1. Introdução ao XAML
Parte 2. Sintaxe essencial do XAML
Parte 3. Extensões de marcação do XAML
Parte 4. Conceitos básicos da associação de dados
Parte 5. De associações de dados a MVVM
Compilação de XAML
Caixa de ferramentas do XAML
Visualizador do XAML
Dados do tempo de design
Controles personalizados
Namespaces XAML
Esquemas personalizados de namespace do XAML
Prefixos recomendados de namespace do XAML
Extensões de marcação do XAML
Consumo de extensões de marcação do XAML
Criação de extensões de marcação do XAML
Modificadores de campo
Passando argumentos
Propriedades associáveis
Propriedades anexadas
Dicionários de recurso
XAML Standard (Versão prévia)
Controles
Carregar XAML em tempo de execução
Conceitos básicos de aplicativo
Acessibilidade
Propriedades de automação
Navegação por teclado
Classe de aplicativo
Ciclo de vida do aplicativo
Indexação de aplicativo e vinculação profunda
Comportamentos
Introdução
Comportamentos anexados
Comportamentos do Xamarin.Forms
Comportamentos reutilizáveis
EffectBehavior
EventToCommandBehavior
Renderizadores personalizados
Introdução
Classes base de renderizador e controles nativos
Personalizando uma entrada
Personalizando uma ContentPage
Personalizando um mapa
Personalizando um marcador de mapa
Realçando uma área circular em um mapa
Realçando uma região em um mapa
Realçando uma rota em um mapa
Personalizando uma ListView
Personalizando um ViewCell
Implementando uma exibição
Implementando um HybridWebView
Implementando um player de vídeo
Criando os players de vídeo da plataforma
Reproduzindo um vídeo da Web
Associando fontes de vídeo ao player
Carregando vídeos de recursos do aplicativo
Acessando a biblioteca de vídeos do dispositivo
Controles de transporte de vídeo personalizado
Posicionamento de vídeo personalizado
Associação de dados
Associações básicas
Modo de associação
Formação de cadeia de caracteres
Caminho de associação
Associação de conversores de valor
Associação de fallbacks
A interface de comando
Associações compiladas
DependencyService
Introdução
Implementando a conversão de texto em fala
Verificando a orientação do dispositivo
Verificando o status da bateria
Selecionando da biblioteca de fotos
Efeitos
Introdução
Criação de efeitos
Passar parâmetros
Parâmetros como propriedades CLR
Parâmetros como propriedades anexadas
Invocação de eventos
Arquivos
Gestos
Toque
Fixar
Panorâmica
Passar o dedo
Localização
Localização de cadeias de caracteres e imagens
Localização da direita para a esquerda
Bancos de dados locais
MessagingCenter
Navegação
Navegação hierárquica
TabbedPage
CarouselPage
MasterDetailPage
Páginas modais
Exibindo pop-ups
Shell
Modelos
Modelos de controle
Introdução
Criação do modelo de controle
Associações de modelo
Modelos de dados
Introdução
Criação de modelo de dados
Seleção de modelo de dados
Gatilhos
Interface do Usuário
Animação
Animação
Animações simples
Funções de easing
Animações personalizadas
BoxView
Botão
CollectionView
Dados
Layout
Seleção
EmptyView
Rolagem
Cores
Referência de Controles
Pages (Páginas)
Layouts
Exibições
Células
DataPages
Introdução
Referência de Controles
DatePicker
Elementos gráficos com SkiaSharp
Imagens
ImageButton
Layouts
StackLayout
AbsoluteLayout
RelativeLayout
Grade
FlexLayout
ScrollView
LayoutOptions
Margem e preenchimento
Orientação do dispositivo
Tablet e desktop
Layouts associáveis
Criando um layout personalizado
Compactação de Layout
ListView
Data Sources
Aparência de célula
Aparência de lista
Interatividade
Desempenho
Mapas
Seletor
Definir a propriedade ItemsSource de um seletor
Adicionar dados à coleção de itens do seletor
Controle deslizante
Passador
Estilos
Aplicar estilo a aplicativos do Xamarin.Forms usando os estilos do XAML
Introdução
Estilos explícitos
Estilos implícitos
Estilos globais
Herança de estilo
Estilos dinâmicos
Estilos de dispositivo
Classes de estilos
Aplicar estilo a aplicativos do Xamarin.Forms usando as CSS (folhas de estilos em
cascata)
TableView
Texto
Rotular
Entrada
Editor
Fontes
Estilos
Temas
Tema claro
Tema escuro
Criar um tópico personalizado
TimePicker
Visual
Visual material
Criar um renderizador visual
Gerenciador de Estado Visual
WebView
Recursos da plataforma
Android
AppCompat e Design de material
Botão de sombras e preenchimento
Opções do IME de entrada
Sombras de ImageButton
Rolagem rápida de ListView
Altura da barra de NavigationPage
Eventos de ciclo de vida da página
Modo de entrada do teclado virtual
Passar o dedo na página TabbedPage
Animações de transição da página TabbedPage
Cor e posicionamento da barra de ferramentas TabbedPage
Elevação de VisualElement
Modo de cor herdado de VisualElement
Conteúdo misto de WebView
Classe de dispositivo
iOS
Cor da tela de fundo da célula
Cor do cursor de entrada
Tamanho da fonte de entrada
Formatação
Estilo de apresentação da página modal do iPad
Títulos de página grandes
Estilo do cabeçalho de grupo de ListView
Animações em linha de ListView
Estilo do separador de ListView
Atualizações de controle do thread principal
Separador da barra de NavigationPage
Modo de cor do texto da barra de NavigationPage
Translucência da barra de NavigationPage
Visibilidade da barra de status da página
Seleção de item do seletor
Guia do Layout da Área de Segurança
Toques de conteúdo de ScrollView
Reconhecimento de gesto de panorâmica simultâneo
Toque do elevador de controle deslizante
Desfoque de VisualElement
Sombras de VisualElement
Modo de cor herdado de VisualElement
Formulários nativos
Exibições nativas
Exibições nativas em XAML
Exibições nativas em C#
Outras plataformas
GTK#
Mac
Tizen
WPF
Especificações da plataforma
Windows
Sentido de leitura de InputView
SelectionMode de ListView
Barra de navegação de MasterDetailPage
Posicionamento da barra de ferramentas da página
Instalação da plataforma
Verificação ortográfica de SearchBar
Ícones de TabbedPage
Chaves de acesso de VisualElement
Modo de cor herdado de VisualElement
Alertas do JavaScript de WebView
Xamarin.Essentials
Introdução
Acelerômetro
Informações do aplicativo
Barômetro
Bateria
Área de Transferência
Conversores de cor
Bússola
Conectividade
Detectar movimento
Informações sobre DeviceDisplay
Informações sobre o dispositivo
Email
Auxiliares do sistema de arquivos
Lanterna
Geocódigo
Geolocalização
Giroscópio
Inicializador
Magnetômetro
Thread principal
Mapas
Abrir navegador
Sensor de orientação
Discagem telefônica
Extensões da plataforma (tamanho, retângulo, ponto)
Preferências
Armazenamento seguro
Compartilhar
SMS
Conversão de texto em fala
Conversores de unidade
Monitoramento de versões
Vibrar
Solução de problemas
Serviços de dados e de nuvem
Noções básicas de exemplo
Consumo de serviços Web
ASMX
WCF
REST
Aplicativos móveis do Azure
Autenticar o acesso aos serviços Web
REST
OAuth
Aplicativos móveis do Azure
Azure Active Directory B2C
Integração do Azure Active Directory B2C com Aplicativos Móveis do Azure
Sincronizar dados com Serviços Web
Aplicativos móveis do Azure
Enviar notificações por push
Azure
Armazenar arquivos na nuvem
Armazenamento do Azure
Pesquisar dados na nuvem
Azure Search
Aplicativos sem servidor
Verificação de
Armazenar dados em um banco de dados de documento
Consumo de um banco de dados de documento do Azure Cosmos DB
Autenticar usuários com um banco de dados de documento do Azure Cosmos DB
Adicionar inteligência com Serviços Cognitivos
Reconhecimento de fala
Verificação ortográfica
Tradução de texto
Reconhecimento de emoção
Implantação e Teste
Como publicar aplicativos iOS
Como publicar aplicativos Android
Como publicar aplicativos UWP
Como publicar aplicativos Mac
Desempenho
Testes automatizados no Visual Studio App Center
Conceitos avançados e recursos internos
Resolução de dependência
Renderizadores Rápidos
.NET Standard
Solução de problemas
Perguntas frequentes
Posso atualizar o modelo padrão Xamarin.Forms para um pacote NuGet mais
recente?
Por que o designer XAML do Visual Studio não funciona para arquivos XAML do
Xamarin.Forms?
Erro de build do Android: The "LinkAssemblies" task failed unexpectedly
Por que meu projeto Android Xamarin.Forms.Maps falha com
COMPILETODALVIK: UNEXPECTED TOP-LEVEL ERROR?
Notas sobre a versão
Exemplos
Criação de aplicativos móveis com Xamarin.Forms Book
Livro eletrônico de padrões de aplicativo empresarial
Elementos gráficos de SkiaSharp em Xamarin.Forms
Requisitos do Xamarin.Forms
12/04/2019 • 3 minutes to read • Edit Online
Plataformas de destino
Aplicativos Xamarin.Forms podem ser gravados para os seguintes sistemas operacionais:
iOS 8 ou superior
Android 4.4 (API 19) ou superior (mais detalhes)
Plataforma Universal do Windows do Windows 10 (mais detalhes)
Presume-se que os desenvolvedores estejam familiarizados com o .NET Standard e com Projetos
Compartilhados.
Suporte adicional da plataforma
O status dessas plataformas está disponível no GitHub do Xamarin.Forms:
Samsung Tizen
macOS
GTK#
WPF
Plataformas de versões anteriores
Não há suporte para uso do Xamarin.Forms 3.0 nas seguintes plataformas:
WinRT do Windows 8.1/Windows Phone 8.1
Windows Phone 8 Silverlight
Android
Você precisa ter a plataforma das Ferramentas do SDK do Android e da API do Android mais recente instalada. É
possível atualizar para as versões mais recentes usando o Gerenciador de SDK do Android.
Além disso, a versão de destino/compilação para projetos do Android deve ser definida como Usar a plataforma
mais recente instalada. No entanto, a versão mínima pode ser definida como API 19, de modo que você pode
continuar dando suporte a dispositivos que usam Android 4.4 e mais recentes. Esses valores são definidos nas
Opções de Projeto:
Visual Studio
Visual Studio para Mac
Opções do projeto > aplicativo > Propriedades do aplicativo
Requisitos do sistema de desenvolvimento
Aplicativos Xamarin.Forms podem ser desenvolvidos no macOS e no Windows. No entanto, o Windows e o
Visual Studio são necessários para produzir versões do Windows do aplicativo.
NOTE
Aplicativos do Windows não podem ser desenvolvidos no macOS.
Como configurar o Visual Studio e Xamarin para começar a criar aplicativos móveis com o .NET.
Dependendo de qual edição do Visual Studio de 2019 que você está instalando, o processo de instalação
pode levar muito tempo para ser concluída. Você pode usar as barras de progresso para monitorar a
instalação:
5. Quando a instalação do Visual Studio de 2019 for concluída, clique no inicie botão para iniciar o Visual
Studio:
Adicionando o Xamarin ao Visual Studio de 2019
Se o Visual Studio de 2019 já estiver instalado, adicionar o Xamarin executando novamente o instalador do Visual
Studio de 2019 para modificar as cargas de trabalho (consulte modificar o Visual Studio para obter detalhes). Em
seguida, siga as etapas listadas acima para instalar o Xamarin.
Para obter mais informações sobre como baixar e instalar o Visual Studio de 2019, consulte instalar o Visual
Studio 2019.
4. Enquanto Desenvolvimento móvel com .NET estiver selecionado, veja o painel Detalhes da
instalação à direita. Nele, é possível anular a seleção das opções de desenvolvimento móvel que você não
deseja instalar.
5. Quando estiver pronto para começar a instalação do Visual Studio 2017, clique no botão Instalar no canto
inferior direito:
Dependendo da edição do Visual Studio 2017 que você estiver instalando, o processo de instalação poderá
levar muito tempo para ser concluído. Você pode usar as barras de progresso para monitorar a instalação:
6. Quando a instalação do Visual Studio 2017 for concluída, clique no botão Iniciar para iniciá-lo:
Links relacionados
Desinstalando o Xamarin
Instruções de configuração de firewall do Xamarin
Compilar seu primeiro aplicativo Xamarin.Forms
18/04/2019 • 5 minutes to read • Edit Online
Assista a este vídeo e acompanhe-o para compilar seu primeiro aplicativo móvel com Xamarin.Forms.
2. Pesquise por "Xamarin" ou escolha Mobile da tipo de projeto menu. Selecione o aplicativo móvel
(xamarin. Forms) tipo de projeto:
3. Escolha um nome de projeto – o exemplo usa "AwesomeApp":
5. Aguarde até que os pacotes do NuGet sejam restaurados (a mensagem "Restauração concluída" será
exibida na barra de status).
6. Inicie o Android Emulator pressionando o botão de depuração (ou o item de menu Depurar > Iniciar
Depuração).
7. Edite MainPage.xaml, adicionando este XAML antes do final de </StackLayout> :
<Button Text="Click Me" Clicked="Button_Clicked" />
int count = 0;
void Button_Clicked(object sender, System.EventArgs e)
{
count++;
((Button)sender).Text = $"You clicked {count} times.";
}
TIP
É possível compilar e depurar o aplicativo iOS no Visual Studio com um computador Mac em rede. Veja as instruções
de instalação para obter mais informações.
3. Aguarde até que os pacotes do NuGet sejam restaurados (a mensagem "Restauração concluída" será
exibida na barra de status).
4. Inicie o Android Emulator pressionando o botão de depuração (ou o item de menu Depurar > Iniciar
Depuração).
5. Edite MainPage.xaml, adicionando este XAML antes do final de </StackLayout> :
int count = 0;
void Button_Clicked(object sender, System.EventArgs e)
{
count++;
((Button)sender).Text = $"You clicked {count} times.";
}
2. Certifique-se de que Android e iOS estejam selecionados, com compartilhamento de código .NET
Standard:
3. Restaure os pacotes do NuGet clicando com o botão direito do mouse na solução:
4. Inicie o Android Emulator pressionando o botão de depuração (ou Executar > Iniciar Depuração).
5. Edite MainPage.xaml, adicionando este XAML antes do final de </StackLayout> :
int count = 0;
void Handle_Clicked(object sender, System.EventArgs e)
{
count++;
((Button)sender).Text = $"You clicked {count} times.";
}
Próximas etapas
Único Page Quickstart – compilar um aplicativo mais funcional.
Exemplos de Xamarin.Forms – baixe e execute exemplos de código e de aplicativos.
Livro eletrônico Creating Mobile Apps (Criando aplicativos móveis) – capítulos detalhados que ensinam o
desenvolvimento de Xamarin.Forms, disponível em PDF e incluindo centenas de exemplos adicionais.
Criar um aplicativo xamarin. Forms de página única
12/04/2019 • 24 minutes to read • Edit Online
Pré -requisitos
Visual Studio 2019 (versão mais recente), com o desenvolvimento móvel com .NET carga de trabalho
instalada.
Dados de Conhecimento da C#.
(opcional) Um Mac emparelhado para compilar o aplicativo no iOS.
Para obter mais informações sobre esses pré-requisitos, consulte instalando o Xamarin. Para obter informações
sobre como conectar o Visual Studio de 2019 para um host de build do Mac, consulte emparelhar com Mac para
desenvolvimento do xamarin. IOS.
3. No configurar seu novo projeto janela, defina as nome do projeto para notas, escolha um local
adequado para o projeto e clique no criar botão:
IMPORTANT
Os snippets C# e XAML neste início rápido requerem que a solução seja nomeada como Notas. O uso de um nome
diferente resultará em erros de build ao copiar o código deste início rápido para a solução.
4. No novo aplicativo de plataforma cruzada caixa de diálogo, clique em aplicativo em brancoe clique
no Okey botão:
Para obter mais informações sobre a biblioteca .NET Standard criada, confira Anatomia de um aplicativo
Xamarin.Forms em Aprofundamento do Início Rápido do Xamarin.Forms.
5. No Gerenciador de Soluções, no projeto Notas, clique duas vezes em MainPage.xaml para abri-lo:
6. Em MainPage.xaml, remova todo o código de modelo e substitua-o pelo código a seguir:
Esse código define declarativamente a interface do usuário para a página, que consiste em uma Label para
exibir texto, uma Editor para entrada de texto e dois Button instâncias que direcionam o aplicativo para
salvar ou excluir um arquivo. As duas instâncias de Button são dispostas horizontalmente em uma Grid ,
com o Label , o Editor e a Grid dispostos verticalmente em um StackLayout . Para obter mais
informações sobre como criar a interface do usuário, consulte interface do usuário na aprofundamento de
início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml ao pressionar CTRL+S e feche o arquivo.
7. No Gerenciador de Soluções, no projeto Notas, expanda MainPage.xaml e clique duas vezes em
MainPage.xaml.cs para abri-lo:
8. Em MainPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
namespace Notes
{
public partial class MainPage : ContentPage
{
string _fileName =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.txt");
public MainPage()
{
InitializeComponent();
if (File.Exists(_fileName))
{
editor.Text = File.ReadAllText(_fileName);
}
}
Esse código define um campo _fileName , que referencia um arquivo chamado notes.txt que armazenará
os dados de notas na pasta de dados local do aplicativo. Quando o construtor de página for executado o
arquivo será lido, caso exista, e exibido no Editor . Quando o Button Salvar for pressionado, o
manipulador de eventos OnSaveButtonClicked será executado, salvando no arquivo o conteúdo do Editor .
Quando o Button Excluir for pressionado, o manipulador de eventos OnDeleteButtonClicked será
executado, excluindo o arquivo, caso ele exista, e removendo todo o texto do Editor . Para obter mais
informações sobre a interação do usuário, consulte responder à interação do usuário na aprofundamento
de início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml.cs ao pressionar CTRL+S e feche o arquivo.
Criando o Início Rápido
1. No Visual Studio, selecione o item de menu Criar > Criar Solução (ou pressione F6). A solução será criada
e uma mensagem de êxito será exibida na barra de status do Visual Studio:
Se houver erros, repita as etapas anteriores e corrija-os até que a solução seja compilada com êxito.
2. Na barra de ferramentas do Visual Studio, pressione o botão Iniciar (o botão triangular que se parece com
o botão Reproduzir) para iniciar o aplicativo em seu emulador Android escolhido:
NOTE
As etapas a seguir deverão ser realizadas somente se você tiver um Mac emparelhado que atenda aos requisitos do
sistema para o desenvolvimento no Xamarin.Forms.
3. Na barra de ferramentas do Visual Studio, clique com o botão direito do mouse no projeto Notes.iOS e
selecione Definir como projeto de inicialização.
4. Na barra de ferramentas do Visual Studio, pressione o botão Iniciar (o botão triangular que se parece com
o botão Reproduzir) para iniciar o aplicativo em seu Simulador remoto do iOS escolhido:
Para obter mais informações sobre esses pré-requisitos, consulte instalando o Xamarin. Para obter informações
sobre como conectar o Visual Studio de 2019 para um host de build do Mac, consulte emparelhar com Mac para
desenvolvimento do xamarin. IOS.
2. Na caixa de diálogo Novo Projeto, clique em Multiplataforma, selecione o modelo Aplicativo Móvel
(Xamarin.Forms), defina o Nome como Notas, escolha um local adequado para o projeto e clique no
botão OK:
IMPORTANT
Os snippets C# e XAML neste início rápido requerem que a solução seja nomeada como Notas. O uso de um nome
diferente resultará em erros de build ao copiar o código deste início rápido para a solução.
Esse código define declarativamente a interface do usuário para a página, que consiste em uma Label para
exibir texto, uma Editor para entrada de texto e dois Button instâncias que direcionam o aplicativo para
salvar ou excluir um arquivo. As duas instâncias de Button são dispostas horizontalmente em uma Grid ,
com o Label , o Editor e a Grid dispostos verticalmente em um StackLayout . Para obter mais
informações sobre como criar a interface do usuário, consulte interface do usuário na aprofundamento de
início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml ao pressionar CTRL+S e feche o arquivo.
6. No Gerenciador de Soluções, no projeto Notas, expanda MainPage.xaml e clique duas vezes em
MainPage.xaml.cs para abri-lo:
7. Em MainPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
namespace Notes
{
public partial class MainPage : ContentPage
{
string _fileName =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.txt");
public MainPage()
{
InitializeComponent();
if (File.Exists(_fileName))
{
editor.Text = File.ReadAllText(_fileName);
}
}
Esse código define um campo _fileName , que referencia um arquivo chamado notes.txt que armazenará
os dados de notas na pasta de dados local do aplicativo. Quando o construtor de página for executado o
arquivo será lido, caso exista, e exibido no Editor . Quando o Button Salvar for pressionado, o
manipulador de eventos OnSaveButtonClicked será executado, salvando no arquivo o conteúdo do Editor .
Quando o Button Excluir for pressionado, o manipulador de eventos OnDeleteButtonClicked será
executado, excluindo o arquivo, caso ele exista, e removendo todo o texto do Editor . Para obter mais
informações sobre a interação do usuário, consulte responder à interação do usuário na aprofundamento
de início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml.cs ao pressionar CTRL+S e feche o arquivo.
Criando o Início Rápido
1. No Visual Studio, selecione o item de menu Criar > Criar Solução (ou pressione F6). A solução será criada
e uma mensagem de êxito será exibida na barra de status do Visual Studio:
Se houver erros, repita as etapas anteriores e corrija-os até que a solução seja compilada com êxito.
2. Na barra de ferramentas do Visual Studio, pressione o botão Iniciar (o botão triangular que se parece com
o botão Reproduzir) para iniciar o aplicativo em seu emulador Android escolhido:
NOTE
As etapas a seguir deverão ser realizadas somente se você tiver um Mac emparelhado que atenda aos requisitos do
sistema para o desenvolvimento no Xamarin.Forms.
3. Na barra de ferramentas do Visual Studio, clique com o botão direito do mouse no projeto Notes.iOS e
selecione Definir como projeto de inicialização.
4. Na barra de ferramentas do Visual Studio, pressione o botão Iniciar (o botão triangular que se parece com
o botão Reproduzir) para iniciar o aplicativo em seu Simulador remoto do iOS escolhido:
3. Na caixa de diálogo Configurar seu aplicativo de formulários em branco, nomeie o novo aplicativo
como Notas, selecione o botão de opção Usar .NET Standard e clique no botão Avançar:
4. Na caixa de diálogo Configurar seu novo aplicativo de formulários em branco, deixe os nomes do
Projeto e da Solução definidos como Notas, escolha um local adequado para o projeto e clique no botão
Criar para criá-lo:
IMPORTANT
Os snippets C# e XAML neste início rápido requerem que a solução e o projeto sejam nomeados como Notas. O uso
de um nome diferente resultará em erros de build ao copiar o código deste início rápido para o projeto.
Para obter mais informações sobre a biblioteca .NET Standard criada, confira Anatomia de um aplicativo
Xamarin.Forms em Aprofundamento do Início Rápido do Xamarin.Forms.
5. No Painel de Soluções, no projeto Notas, clique duas vezes em MainPage.xaml para abri-lo:
Esse código define declarativamente a interface do usuário para a página, que consiste em uma Label para
exibir texto, uma Editor para entrada de texto e dois Button instâncias que direcionam o aplicativo para
salvar ou excluir um arquivo. As duas instâncias de Button são dispostas horizontalmente em uma Grid ,
com o Label , o Editor e a Grid dispostos verticalmente em um StackLayout . Para obter mais
informações sobre como criar a interface do usuário, consulte interface do usuário na aprofundamento de
início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml ao escolher Arquivo > Salvar (ou ao pressionar ⌘ + S ) e feche o
arquivo.
7. No Painel de Soluções, no projeto Notas, expanda MainPage.xaml e clique duas vezes em
MainPage.xaml.cs para abri-lo:
8. Em MainPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
namespace Notes
{
public partial class MainPage : ContentPage
{
string _fileName =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "notes.txt");
public MainPage()
{
InitializeComponent();
if (File.Exists(_fileName))
{
editor.Text = File.ReadAllText(_fileName);
}
}
Esse código define um campo _fileName , que referencia um arquivo chamado notes.txt que armazenará
os dados de notas na pasta de dados local do aplicativo. Quando o construtor de página for executado o
arquivo será lido, caso exista, e exibido no Editor . Quando o Button Salvar for pressionado, o
manipulador de eventos OnSaveButtonClicked será executado, salvando no arquivo o conteúdo do Editor .
Quando o Button Excluir for pressionado, o manipulador de eventos OnDeleteButtonClicked será
executado, excluindo o arquivo, caso ele exista, e removendo todo o texto do Editor . Para obter mais
informações sobre a interação do usuário, consulte responder à interação do usuário na aprofundamento
de início rápido de xamarin. Forms.
Salve as alterações em MainPage.xaml.cs ao escolher Arquivo > Salvar (ou ao pressionar ⌘ + S ) e
feche o arquivo.
Criando o Início Rápido
1. No Visual Studio para Mac, selecione o item de menu Compilar > Compilar Tudo (ou pressione ⌘ + B ).
Os projetos serão criados e uma mensagem de êxito será exibida na barra de ferramentas do Visual Studio
para Mac.
Se houver erros, repita as etapas anteriores e corrija-os até que os projetos sejam compilados com êxito.
2. No painel de soluções, selecione o Notes.iOS projeto, o botão direito do mouse e selecione definir
como projeto de inicialização:
3. Na barra de ferramentas do Visual Studio para Mac, pressione o botão Iniciar (o botão triangular que se
parece com o botão Reproduzir) para iniciar o aplicativo no Simulador do iOS escolhido:
5. Na barra de ferramentas do Visual Studio para Mac, pressione o botão Iniciar (o botão triangular que se
parece com o botão Reproduzir) para iniciar o aplicativo em seu emulador Android escolhido:
Próximas etapas
Neste início rápido, você aprendeu como:
Crie um aplicativo de plataforma cruzada xamarin. Forms.
Defina a interface do usuário para uma página usando a linguagem de marcação de aplicativo extensível
(XAML ).
Interagir com elementos de interface do usuário XAML do código.
Para ativar esse aplicativo de página única em um aplicativo de várias página, continue para o próximo início
rápido.
Avançar
Links relacionados
Anotações (amostra)
Aprofundamento de início rápido do xamarin. Forms
Executar a navegação em um aplicativo xamarin.
Forms de várias páginas
12/04/2019 • 26 minutes to read • Edit Online
Pré -requisitos
Você deve concluir com êxito a guia de início rápido anterior antes de tentar este início rápido. Como alternativa,
baixe o exemplo de início rápido anterior e usá-lo como ponto de partida para este início rápido.
5. No Adicionar Novo Item caixa de diálogo, selecione Visual C# itens > classe, nomeie o novo arquivo
Observaçãoe clique no adicionar botão:
Isso adicionará uma classe chamada Observação para o modelos pasta dos notas projeto.
6. Na Note.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
namespace Notes.Models
{
public class Note
{
public string Filename { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
}
}
Essa classe define um Note modelo que armazenará os dados sobre cada Observação no aplicativo.
Salve as alterações em Note.cs pressionando CTRL + Se feche o arquivo.
7. No Gerenciador de soluções, clique com botão direito no notas do projeto e selecione Adicionar >
Novo Item... . No Adicionar Novo Item caixa de diálogo, selecione Visual C# itens > xamarin. Forms
> página de conteúdo, nomeie o novo arquivo NoteEntryPagee clique no Adicionar botão:
Isso adicionará uma nova página chamada NoteEntryPage para a pasta raiz do projeto. Esta página será a
segunda página do aplicativo.
8. Na NoteEntryPage.xaml, remova todo o código de modelo e substitua-o pelo código a seguir:
<?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="Notes.NoteEntryPage"
Title="Note Entry">
<StackLayout Margin="20">
<Editor Placeholder="Enter your note"
Text="{Binding Text}"
HeightRequest="100" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save"
Clicked="OnSaveButtonClicked" />
<Button Grid.Column="1"
Text="Delete"
Clicked="OnDeleteButtonClicked"/>
</Grid>
</StackLayout>
</ContentPage>
Esse código define declarativamente a interface do usuário para a página, que consiste em uma Editor
para entrada de texto e dois Button instâncias que direcionam o aplicativo para salvar ou excluir um
arquivo. Os dois Button instâncias são dispostas horizontalmente em uma Grid , com o Editor e Grid
sendo dispostos verticalmente em um StackLayout . Além disso, o Editor usa associação de dados para
associar ao Text propriedade do Note modelo. Para obter mais informações sobre associação de dados,
consulte vinculação de dados na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NoteEntryPage.xaml pressionando CTRL + Se feche o arquivo.
9. Na NoteEntryPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
using Notes.Models;
namespace Notes
{
public partial class NoteEntryPage : ContentPage
{
public NoteEntryPage()
{
InitializeComponent();
}
if (string.IsNullOrWhiteSpace(note.Filename))
{
// Save
var filename = Path.Combine(App.FolderPath, $"{Path.GetRandomFileName()}.notes.txt");
File.WriteAllText(filename, note.Text);
}
else
{
// Update
File.WriteAllText(note.Filename, note.Text);
}
await Navigation.PopAsync();
}
if (File.Exists(note.Filename))
{
File.Delete(note.Filename);
}
await Navigation.PopAsync();
}
}
}
Este código armazena uma Note instância, que representa uma anotação única, em de BindingContext da
página. Quando o salve Button é pressionado a OnSaveButtonClicked manipulador de eventos é
executado, o que seja salva o conteúdo do Editor para um novo arquivo com um nome de arquivo gerado
aleatoriamente, ou para um arquivo existente se uma anotação está sendo atualizada. Em ambos os casos, o
arquivo é armazenado na pasta de dados do aplicativo local para o aplicativo. Em seguida, o método navega
de volta para a página anterior. Quando o exclua Button é pressionado a OnDeleteButtonClicked
manipulador de eventos é executado, o que exclui o arquivo, desde que ela existe e navega de volta para a
página anterior. Para obter mais informações sobre navegação, consulte navegação na aprofundamento de
início rápido de xamarin. Forms.
Salve as alterações em NoteEntryPage.xaml.cs pressionando CTRL + Se feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
10. No Gerenciador de soluções, clique com botão direito no notas do projeto e selecione Adicionar >
Novo Item... . No Adicionar Novo Item caixa de diálogo, selecione Visual C# itens > xamarin. Forms
> página de conteúdo, nomeie o novo arquivo NotesPagee clique no adicionar botão.
Isso adicionará uma página chamada NotesPage para a pasta raiz do projeto. Esta página será a página
raiz do aplicativo.
11. Na NotesPage.xaml, remova todo o código de modelo e substitua-o pelo código a seguir:
Esse código define declarativamente a interface do usuário para a página, que consiste em uma ListView e
uma ToolbarItem . O ListView usa dados de associação para exibir todas as anotações são recuperadas
pelo aplicativo e selecionando uma observação navegará até o NoteEntryPage em que a anotação pode ser
modificada. Como alternativa, uma nova anotação pode ser criada, pressionando o ToolbarItem . Para obter
mais informações sobre associação de dados, consulte vinculação de dados na aprofundamento de início
rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml pressionando CTRL + Se feche o arquivo.
12. Na NotesPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Xamarin.Forms;
using Notes.Models;
namespace Notes
{
public partial class NotesPage : ContentPage
{
public NotesPage()
{
InitializeComponent();
}
listView.ItemsSource = notes
.OrderBy(d => d.Date)
.ToList();
}
Esse código define a funcionalidade para o NotesPage . Quando a página for exibida, o OnAppearing método
é executado, que preenche a ListView com as observações que foram recuperadas da pasta de dados do
aplicativo local. Quando o ToolbarItem é pressionado a OnNoteAddedClicked manipulador de eventos é
executado. Esse método navega para o NoteEntryPage , definindo o BindingContext dos NoteEntryPage para
um novo Note instância. Quando um item na ListView está selecionado o OnListViewItemSelected
manipulador de eventos é executado. Esse método navega para o NoteEntryPage , definindo o
BindingContext dos NoteEntryPage para selecionado Note instância. Para obter mais informações sobre
navegação, consulte navegação na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml.cs pressionando CTRL + Se feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
13. Na Gerenciador de soluções, clique duas vezes em App.xaml.cs para abri-lo. Em seguida, substitua o
código existente pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
namespace Notes
{
public partial class App : Application
{
public static string FolderPath { get; private set; }
public App()
{
InitializeComponent();
FolderPath =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
MainPage = new NavigationPage(new NotesPage());
}
...
}
}
Esse código adiciona uma declaração de namespace para o System.IO namespace e adiciona uma
declaração para um estático FolderPath propriedade do tipo string . O FolderPath propriedade é usada
para armazenar o caminho no dispositivo onde Observe que os dados serão armazenados. Além disso, o
código inicializa o FolderPath propriedade no App construtor e inicializa o MainPage propriedade seja
uma NavigationPage que hospeda um instância do NotesPage . Para obter mais informações sobre
navegação, consulte navegação na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em App.xaml.cs ao pressionar CTRL + S e feche o arquivo.
14. Na Gerenciador de soluções, no notas do projeto, clique com botão direito MainPage. XAMLe
selecione excluir. Na caixa de diálogo que aparece pressione a Okey botão para remover o arquivo de
disco rígido.
Isso remove uma página que não é mais usada.
15. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Depois de salvar a nota o aplicativo será navegue de volta para o NotesPage.
Insira um número de observações, de comprimento variado, para observar o comportamento do aplicativo.
2. No painel de soluções, selecione o notas projeto, o botão direito do mouse e selecione Adicionar >
nova pasta:
5. No novo arquivo caixa de diálogo, selecione geral > classe vazia, nomeie o novo arquivo Observaçãoe
clique no novo botão:
Isso adicionará uma classe chamada Observação para o modelos pasta dos notas projeto.
6. Na Note.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
namespace Notes.Models
{
public class Note
{
public string Filename { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
}
}
Essa classe define um Note modelo que armazenará os dados sobre cada Observação no aplicativo.
Salve as alterações em Note.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche o arquivo.
7. No painel de soluções, selecione o notas projeto, o botão direito do mouse e selecione Adicionar >
novo arquivo... . No novo arquivo caixa de diálogo, selecione formulários > formulários ContentPage
XAML, nomeie o novo arquivo NoteEntryPagee clique no novo botão:
Isso adicionará uma nova página chamada NoteEntryPage para a pasta raiz do projeto. Esta página será a
segunda página do aplicativo.
8. Na NoteEntryPage.xaml, remova todo o código de modelo e substitua-o pelo código a seguir:
<?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="Notes.NoteEntryPage"
Title="Note Entry">
<StackLayout Margin="20">
<Editor Placeholder="Enter your note"
Text="{Binding Text}"
HeightRequest="100" />
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Save"
Clicked="OnSaveButtonClicked" />
<Button Grid.Column="1"
Text="Delete"
Clicked="OnDeleteButtonClicked"/>
</Grid>
</StackLayout>
</ContentPage>
Esse código define declarativamente a interface do usuário para a página, que consiste em uma Editor
para entrada de texto e dois Button instâncias que direcionam o aplicativo para salvar ou excluir um
arquivo. Os dois Button instâncias são dispostas horizontalmente em uma Grid , com o Editor e Grid
sendo dispostos verticalmente em um StackLayout . Além disso, o Editor usa associação de dados para
associar ao Text propriedade do Note modelo. Para obter mais informações sobre associação de dados,
consulte vinculação de dados na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NoteEntryPage.xaml escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e
feche o arquivo.
9. Na NoteEntryPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
using Notes.Models;
namespace Notes
{
public partial class NoteEntryPage : ContentPage
{
public NoteEntryPage()
{
InitializeComponent();
}
if (string.IsNullOrWhiteSpace(note.Filename))
{
// Save
var filename = Path.Combine(App.FolderPath, $"{Path.GetRandomFileName()}.notes.txt");
File.WriteAllText(filename, note.Text);
}
else
{
// Update
File.WriteAllText(note.Filename, note.Text);
}
await Navigation.PopAsync();
}
if (File.Exists(note.Filename))
{
File.Delete(note.Filename);
}
await Navigation.PopAsync();
}
}
}
Este código armazena uma Note instância, que representa uma anotação única, em de BindingContext da
página. Quando o salve Button é pressionado a OnSaveButtonClicked manipulador de eventos é
executado, o que seja salva o conteúdo do Editor para um novo arquivo com um nome de arquivo gerado
aleatoriamente, ou para um arquivo existente se uma anotação está sendo atualizada. Em ambos os casos, o
arquivo é armazenado na pasta de dados do aplicativo local para o aplicativo. Em seguida, o método navega
de volta para a página anterior. Quando o exclua Button é pressionado a OnDeleteButtonClicked
manipulador de eventos é executado, o que exclui o arquivo, desde que ela existe e navega de volta para a
página anterior. Para obter mais informações sobre navegação, consulte navegação na aprofundamento de
início rápido de xamarin. Forms.
Salve as alterações em NoteEntryPage.xaml.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e
feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
10. No painel de soluções, selecione o notas projeto, o botão direito do mouse e selecione Adicionar >
novo arquivo... . No novo arquivo caixa de diálogo, selecione formulários > formulários ContentPage
XAML, nomeie o novo arquivo NotesPagee clique no novo botão.
Isso adicionará uma página chamada NotesPage para a pasta raiz do projeto. Esta página será a página
raiz do aplicativo.
11. Na NotesPage.xaml, remova todo o código de modelo e substitua-o pelo código a seguir:
Esse código define declarativamente a interface do usuário para a página, que consiste em uma ListView e
uma ToolbarItem . O ListView usa dados de associação para exibir todas as anotações são recuperadas
pelo aplicativo e selecionando uma observação navegará até o NoteEntryPage em que a anotação pode ser
modificada. Como alternativa, uma nova anotação pode ser criada, pressionando o ToolbarItem . Para obter
mais informações sobre associação de dados, consulte vinculação de dados na aprofundamento de início
rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche o
arquivo.
12. Na NotesPage.xaml.cs, remova todo o código de modelo e substitua-o pelo código a seguir:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Xamarin.Forms;
using Notes.Models;
namespace Notes
{
public partial class NotesPage : ContentPage
{
public NotesPage()
{
InitializeComponent();
}
listView.ItemsSource = notes
.OrderBy(d => d.Date)
.ToList();
}
Esse código define a funcionalidade para o NotesPage . Quando a página for exibida, o OnAppearing método
é executado, que preenche a ListView com as observações que foram recuperadas da pasta de dados do
aplicativo local. Quando o ToolbarItem é pressionado a OnNoteAddedClicked manipulador de eventos é
executado. Esse método navega para o NoteEntryPage , definindo o BindingContext dos NoteEntryPage para
um novo Note instância. Quando um item na ListView está selecionado o OnListViewItemSelected
manipulador de eventos é executado. Esse método navega para o NoteEntryPage , definindo o
BindingContext dos NoteEntryPage para selecionado Note instância. Para obter mais informações sobre
navegação, consulte navegação na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e
feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
13. No painel de soluções, clique duas vezes em App.xaml.cs para abri-lo. Em seguida, substitua o código
existente pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
namespace Notes
{
public partial class App : Application
{
public static string FolderPath { get; private set; }
public App()
{
InitializeComponent();
FolderPath =
Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData));
MainPage = new NavigationPage(new NotesPage());
}
...
}
}
Esse código adiciona uma declaração de namespace para o System.IO namespace e adiciona uma
declaração para um estático FolderPath propriedade do tipo string . O FolderPath propriedade é usada
para armazenar o caminho no dispositivo onde Observe que os dados serão armazenados. Além disso, o
código inicializa o FolderPath propriedade no App construtor e inicializa o MainPage propriedade seja
uma NavigationPage que hospeda um instância do NotesPage . Para obter mais informações sobre
navegação, consulte navegação na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em App.xaml.cs escolhendo Arquivo > Salvar (ou pressionando ⌘ + S ) e feche o
arquivo.
14. No painel de soluções, no notas do projeto, clique com botão direito MainPage. XAMLe selecione
remover. Na caixa de diálogo que aparece pressione a excluir botão para remover o arquivo de disco
rígido.
Isso remove uma página que não é mais usada.
15. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Depois de salvar a nota o aplicativo será navegue de volta para o NotesPage.
Insira um número de observações, de comprimento variado, para observar o comportamento do aplicativo.
Próximas etapas
Neste início rápido, você aprendeu como:
Adicione páginas adicionais a uma solução do xamarin. Forms.
Execute a navegação entre páginas.
Use a ligação de dados para sincronizar dados entre elementos de interface do usuário e sua fonte de dados.
Para modificar o aplicativo para que ele armazena seus dados em um banco de dados local SQLite.NET, continue
para o próximo início rápido.
Avançar
Links relacionados
Anotações (amostra)
Aprofundamento de início rápido do xamarin. Forms
Store dados em um banco de dados Local
SQLite.NET
16/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
Neste início rápido, você aprenderá como:
Use o Gerenciador de pacotes do NuGet para adicionar um pacote do NuGet a um projeto.
Store dados localmente em um banco de dados SQLite.NET.
O guia de início rápido orienta como armazenar dados em um banco de dados local do SQLite.NET. O aplicativo
final é mostrado abaixo:
Pré -requisitos
Você deve concluir com êxito a guia de início rápido anterior antes de tentar este início rápido. Como alternativa,
baixe o exemplo de início rápido anterior e usá-lo como ponto de partida para este início rápido.
NOTE
Há diversos pacotes NuGet com nomes semelhantes. O pacote correto tem estes atributos:
Autor(es): Frank A. Krueger
Id: sqlite-net-pcl
Link do NuGet: sqlite-net-pcl
Apesar do nome do pacote, este pacote NuGet pode ser usado em projetos do .NET Standard.
Este pacote será usado para incorporar operações de banco de dados ao aplicativo.
4. Na Gerenciador de soluções, no notas projeto, abra Note.cs no modelos pasta e substitua o existente
de código com o o código a seguir:
using System;
using SQLite;
namespace Notes.Models
{
public class Note
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
}
}
Essa classe define um Note modelo que armazenará os dados sobre cada Observação no aplicativo. O ID
propriedade é marcada com PrimaryKey e AutoIncrement atributos para garantir que cada Note instância
no banco de dados SQLite.NET terá uma id exclusiva fornecida pelo SQLite.NET.
Salve as alterações em Note.cs pressionando CTRL + Se feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
5. Na Gerenciador de soluções, adicione uma nova pasta chamada dados para o notas projeto.
6. Na Gerenciador de soluções, no notas do projeto, adicione uma nova classe denominada
NoteDatabase para o dados pasta.
7. Na NoteDatabase.cs, substitua o código existente pelo código a seguir:
using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
using Notes.Models;
namespace Notes.Data
{
public class NoteDatabase
{
readonly SQLiteAsyncConnection _database;
Essa classe contém código para criar o banco de dados, ler dados a partir dele, gravação de dados e exclua
dados dele. O código usa APIs SQLite.NET assíncronas que movem operações de banco de dados para
threads de segundo plano. Além disso, o construtor NoteDatabase usa o caminho para o arquivo de banco
de dados como um argumento. Esse caminho será fornecido pelo App classe na próxima etapa.
Salve as alterações em NoteDatabase.cs pressionando CTRL + Se feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
8. Na Gerenciador de soluções, no notas do projeto, clique duas vezes em App.xaml.cs para abri-lo. Em
seguida, substitua o código existente pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
using Notes.Data;
namespace Notes
{
public partial class App : Application
{
static NoteDatabase database;
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new NotesPage());
}
...
}
}
Esse código define uma Database que cria uma nova propriedade NoteDatabase instância como um
singleton, passando o nome do arquivo do banco de dados como o argumento para o NoteDatabase
construtor. A vantagem de expor o banco de dados como um singleton é que uma conexão de banco de
dados individual criada é mantida aberta enquanto o aplicativo é executado, evitando, portanto, o trabalho
de abrir e fechar o arquivo de banco de dados cada vez que uma operação de banco de dados é realizada.
Salve as alterações em App.xaml.cs ao pressionar CTRL + S e feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
9. Na Gerenciador de soluções, no notas do projeto, clique duas vezes em NotesPage.xaml.cs para abri-
lo. Em seguida, substitua o OnAppearing método com o código a seguir:
10. Na Gerenciador de soluções, clique duas vezes em NoteEntryPage.xaml.cs para abri-lo. Em seguida,
substitua os OnSaveButtonClicked e OnDeleteButtonClicked métodos com o código a seguir:
O NoteEntryPage armazena um Note instância, que representa uma anotação única, nas BindingContext
da página. Quando o OnSaveButtonClicked manipulador de eventos é executado, o Note instância é salva
no banco de dados e o aplicativo navega de volta à página anterior. Quando o OnDeleteButtonClicked
manipulador de eventos é executado, o Note instância é excluída do banco de dados e o aplicativo navega
de volta à página anterior.
Salve as alterações em NoteEntryPage.xaml.cs pressionando CTRL + Se feche o arquivo.
11. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Depois de salvar a nota o aplicativo será navegue de volta para o NotesPage.
Insira um número de observações, de comprimento variado, para observar o comportamento do aplicativo.
NOTE
Há diversos pacotes NuGet com nomes semelhantes. O pacote correto tem estes atributos:
Autor: Frank A. Krueger
Id: sqlite-net-pcl
Link do NuGet: sqlite-net-pcl
Apesar do nome do pacote, este pacote NuGet pode ser usado em projetos do .NET Standard.
Este pacote será usado para incorporar operações de banco de dados ao aplicativo.
4. No painel de soluções, no notas projeto, abra Note.cs no modelos pasta e substitua o código existente
pelo seguinte código:
using System;
using SQLite;
namespace Notes.Models
{
public class Note
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
public string Text { get; set; }
public DateTime Date { get; set; }
}
}
Essa classe define um Note modelo que armazenará os dados sobre cada Observação no aplicativo. O ID
propriedade é marcada com PrimaryKey e AutoIncrement atributos para garantir que cada Note instância
no banco de dados SQLite.NET terá uma id exclusiva fornecida pelo SQLite.NET.
Salve as alterações em Note.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
5. No painel de soluções, adicione uma nova pasta chamada dados para o notas projeto.
6. No painel de soluções, no notas do projeto, adicione uma nova classe denominada NoteDatabase para
o dados pasta.
7. Na NoteDatabase.cs, substitua o código existente pelo código a seguir:
using System.Collections.Generic;
using System.Threading.Tasks;
using SQLite;
using Notes.Models;
namespace Notes.Data
{
public class NoteDatabase
{
readonly SQLiteAsyncConnection _database;
Essa classe contém código para criar o banco de dados, ler dados a partir dele, gravação de dados e exclua
dados dele. O código usa APIs SQLite.NET assíncronas que movem operações de banco de dados para
threads de segundo plano. Além disso, o construtor NoteDatabase usa o caminho para o arquivo de banco
de dados como um argumento. Esse caminho será fornecido pelo App classe na próxima etapa.
Salve as alterações em NoteDatabase.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche
o arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
8. No painel de soluções, no notas do projeto, clique duas vezes em App.xaml.cs para abri-lo. Em seguida,
substitua o código existente pelo código a seguir:
using System;
using System.IO;
using Xamarin.Forms;
using Notes.Data;
namespace Notes
{
public partial class App : Application
{
static NoteDatabase database;
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new NotesPage());
}
...
}
}
Esse código define uma Database que cria uma nova propriedade NoteDatabase instância como um
singleton, passando o nome do arquivo do banco de dados como o argumento para o NoteDatabase
construtor. A vantagem de expor o banco de dados como um singleton é que uma conexão de banco de
dados individual criada é mantida aberta enquanto o aplicativo é executado, evitando, portanto, o trabalho
de abrir e fechar o arquivo de banco de dados cada vez que uma operação de banco de dados é realizada.
Salve as alterações em App.xaml.cs escolhendo Arquivo > Salvar (ou pressionando ⌘ + S ) e feche o
arquivo.
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
9. No painel de soluções, no notas do projeto, clique duas vezes em NotesPage.xaml.cs para abri-lo. Em
seguida, substitua o OnAppearing método com o código a seguir:
WARNING
A tentativa de compilar o aplicativo neste ponto resultará em erros que serão corrigidos em etapas subsequentes.
10. No painel de soluções, clique duas vezes em NoteEntryPage.xaml.cs para abri-lo. Em seguida,
substitua os OnSaveButtonClicked e OnDeleteButtonClicked métodos com o código a seguir:
O NoteEntryPage armazena um Note instância, que representa uma anotação única, nas BindingContext
da página. Quando o OnSaveButtonClicked manipulador de eventos é executado, o Note instância é salva
no banco de dados e o aplicativo navega de volta à página anterior. Quando o OnDeleteButtonClicked
manipulador de eventos é executado, o Note instância é excluída do banco de dados e o aplicativo navega
de volta à página anterior.
Salve as alterações em NoteEntryPage.xaml.cs escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e
feche o arquivo.
11. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Depois de salvar a nota o aplicativo será navegue de volta para o NotesPage.
Insira um número de observações, de comprimento variado, para observar o comportamento do aplicativo.
Próximas etapas
Neste início rápido, você aprendeu como:
Use o Gerenciador de pacotes do NuGet para adicionar um pacote do NuGet a um projeto.
Store dados localmente em um banco de dados SQLite.NET.
Para definir o estilo de aplicativo com os estilos XAML, continue para o próximo início rápido.
Avançar
Links relacionados
Notas (exemplo)
Aprofundamento de início rápido do xamarin. Forms
Definir o estilo de um aplicativo xamarin. Forms de
plataforma cruzada
12/04/2019 • 10 minutes to read • Edit Online
Baixar o exemplo
Neste início rápido, você aprenderá como:
Um aplicativo xamarin. Forms usando os estilos XAML de estilo.
O guia de início rápido explica como definir o estilo de um aplicativo de plataforma cruzada xamarin. Forms com
estilos XAML. O aplicativo final é mostrado abaixo:
Pré -requisitos
Você deve concluir com êxito a guia de início rápido anterior antes de tentar este início rápido. Como alternativa,
baixe o exemplo de início rápido anterior e usá-lo como ponto de partida para este início rápido.
<Thickness x:Key="PageMargin">20</Thickness>
</Application.Resources>
</Application>
Esse código define uma Thickness de valor, uma série de Color valores e estilos implícitos para o
NavigationPage e ContentPage . Observe que esses estilos, que estão no nível do aplicativo
ResourceDictionary , podem ser consumidos em todo o aplicativo. Para obter mais informações sobre
estilos de XAML, consulte estilos na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em App. XAML pressionando CTRL + Se feche o arquivo.
3. Na Gerenciador de soluções, no notas do projeto, clique duas vezes em NotesPage.xaml para abri-lo.
Em seguida, substitua o código existente pelo código a seguir:
<?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="Notes.NotesPage"
Title="Notes">
<ContentPage.Resources>
<!-- Implicit styles -->
<Style TargetType="{x:Type ListView}">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Text="+"
Clicked="OnNoteAddedClicked" />
</ContentPage.ToolbarItems>
<ListView x:Name="listView"
Margin="{StaticResource PageMargin}"
ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Text}"
Detail="{Binding Date}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Este código adiciona um estilo implícito para o ListView para o nível de página ResourceDictionary e
define o ListView.Margin propriedade com um valor definido no nível do aplicativo ResourceDictionary .
Observe que o ListView estilo implícito foi adicionado ao nível da página ResourceDictionary , porque ele
só é consumido pelo NotesPage . Para obter mais informações sobre estilos de XAML, consulte estilos na
aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml pressionando CTRL + Se feche o arquivo.
4. No painel de soluções, no notas do projeto, clique duas vezes em NoteEntryPage.xaml para abri-lo. Em
seguida, substitua o código existente pelo código a seguir:
<?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="Notes.NoteEntryPage"
Title="Note Entry">
<ContentPage.Resources>
<!-- Implicit styles -->
<Style TargetType="{x:Type Editor}">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
<Style TargetType="Button"
ApplyToDerivedTypes="True"
CanCascade="True">
<Setter Property="FontSize" Value="Medium" />
<Setter Property="BackgroundColor" Value="LightGray" />
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderRadius" Value="5" />
</Style>
</ContentPage.Resources>
</ContentPage>
Esse código adiciona os estilos implícitos para o Editor e Button modos de exibição para o nível de
página ResourceDictionary e define o StackLayout.Margin propriedade com um valor definido no nível do
aplicativo ResourceDictionary . Observe que o Editor e Button estilos implícitos foram adicionados ao
nível da página ResourceDictionary , porque eles são consumidos somente pelo NoteEntryPage . Para obter
mais informações sobre estilos de XAML, consulte estilos na aprofundamento de início rápido de xamarin.
Forms.
Salve as alterações em NoteEntryPage.xaml pressionando CTRL + Se feche o arquivo.
5. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Em cada página, observe como o estilo foi alterado de início rápido anterior.
<Thickness x:Key="PageMargin">20</Thickness>
</Application.Resources>
</Application>
Esse código define uma Thickness de valor, uma série de Color valores e estilos implícitos para o
NavigationPage e ContentPage . Observe que esses estilos, que estão no nível do aplicativo
ResourceDictionary , podem ser consumidos em todo o aplicativo. Para obter mais informações sobre
estilos de XAML, consulte estilos na aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em App. XAML escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche o
arquivo.
3. Na Gerenciador de soluções, no notas do projeto, clique duas vezes em NotesPage.xaml para abri-lo.
Em seguida, substitua o código existente pelo código a seguir:
<?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="Notes.NotesPage"
Title="Notes">
<ContentPage.Resources>
<!-- Implicit styles -->
<Style TargetType="{x:Type ListView}">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
</ContentPage.Resources>
<ContentPage.ToolbarItems>
<ToolbarItem Text="+"
Clicked="OnNoteAddedClicked" />
</ContentPage.ToolbarItems>
<ListView x:Name="listView"
Margin="{StaticResource PageMargin}"
ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Text}"
Detail="{Binding Date}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Este código adiciona um estilo implícito para o ListView para o nível de página ResourceDictionary e
define o ListView.Margin propriedade com um valor definido no nível do aplicativo ResourceDictionary .
Observe que o ListView estilo implícito foi adicionado ao nível da página ResourceDictionary , porque ele
só é consumido pelo NotesPage . Para obter mais informações sobre estilos de XAML, consulte estilos na
aprofundamento de início rápido de xamarin. Forms.
Salve as alterações em NotesPage.xaml escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e feche o
arquivo.
4. Na Gerenciador de soluções, no notas do projeto, clique duas vezes em NoteEntryPage.xaml para
abri-lo. Em seguida, substitua o código existente pelo código a seguir:
<?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="Notes.NoteEntryPage"
Title="Note Entry">
<ContentPage.Resources>
<!-- Implicit styles -->
<Style TargetType="{x:Type Editor}">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
<Style TargetType="Button"
ApplyToDerivedTypes="True"
CanCascade="True">
<Setter Property="FontSize" Value="Medium" />
<Setter Property="BackgroundColor" Value="LightGray" />
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderRadius" Value="5" />
</Style>
</ContentPage.Resources>
</ContentPage>
Esse código adiciona os estilos implícitos para o Editor e Button modos de exibição para o nível de
página ResourceDictionary e define o StackLayout.Margin propriedade com um valor definido no nível do
aplicativo ResourceDictionary . Observe que o Editor e Button estilos implícitos foram adicionados ao
nível da página ResourceDictionary , porque eles são consumidos somente pelo NoteEntryPage . Para obter
mais informações sobre estilos de XAML, consulte estilos na aprofundamento de início rápido de xamarin.
Forms.
Salve as alterações em NoteEntryPage.xaml escolhendo arquivo > Salvar (ou pressionando ⌘ + S ) e
feche o arquivo.
5. Compile e execute o projeto em cada plataforma. Para obter mais informações, consulte criando o guia de
início rápido.
Sobre o NotesPage pressione a + botão para navegar para o NoteEntryPage e insira uma observação.
Em cada página, observe como o estilo foi alterado de início rápido anterior.
Próximas etapas
Neste início rápido, você aprendeu como:
Um aplicativo xamarin. Forms usando os estilos XAML de estilo.
Para saber mais sobre os conceitos básicos do desenvolvimento de aplicativos usando o xamarin. Forms, continue
o aprofundamento do guia de início rápido.
Avançar
Links relacionados
Notas (exemplo)
Aprofundamento de início rápido do xamarin. Forms
Aprofundamento de início rápido do
xamarin. Forms
12/04/2019 • 35 minutes to read • Edit Online
No início rápido do xamarin. Forms, o aplicativo de anotações foi criado. Este artigo analisa o que
foi criado para entender os fundamentos de como os aplicativos Xamarin.Forms funcionam.
Os projetos são:
Notas – esse projeto é o projeto de biblioteca .NET Standard que contém todos os códigos
compartilhados e a interface do usuário compartilhada.
Notes.Android – esse projeto contém código específico do Android e é o ponto de entrada
para o aplicativo Android.
Notes.iOS – esse projeto contém código específico do iOS e é o ponto de entrada para o
aplicativo iOS.
Notes.UWP – esse projeto contém o código específico da plataforma Universal do Windows
(UWP ) e é o ponto de entrada para o aplicativo UWP.
Os projetos são:
Notas – esse projeto é o projeto de biblioteca .NET Standard que contém todos os códigos
compartilhados e a interface do usuário compartilhada.
Notes.Android – esse projeto contém código específico do Android e é o ponto de entrada
para aplicativos Android.
Notes.iOS – esse projeto contém código específico do iOS e é o ponto de entrada para
aplicativos iOS.
namespace Notes
{
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new NotesPage());
}
...
}
}
Esse código define a MainPage propriedade do App de classe para um NavigationPage instância
cujo conteúdo é um NotesPage instância.
Além disso, o AssemblyInfo.cs arquivo contém um atributo único aplicativo, que é aplicado no
nível de assembly:
using Xamarin.Forms.Xaml;
[assembly: XamlCompilation(XamlCompilationOptions.Compile)]
namespace Notes.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init();
LoadApplication(new App());
return base.FinishedLaunching(app, options);
}
}
}
Android
Para iniciar a página inicial do xamarin. Forms no Android, o projeto Notes.Android inclui código
que cria um com o MainLauncher atributo, com a atividade herdando a
Activity
FormsAppCompatActivity classe:
namespace Notes.Droid
{
[Activity(Label = "Notes",
Icon = "@mipmap/icon",
Theme = "@style/MainTheme",
MainLauncher = true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
}
Xamarin.Forms.Forms.Init (e);
if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
{
...
}
namespace Notes.UWP
{
public sealed partial class MainPage
{
public MainPage()
{
this.InitializeComponent();
this.LoadApplication(new Notes.App());
}
}
}
Interface do usuário
Há quatro grupos de controle principal usados para criar a interface do usuário de um aplicativo
xamarin. Forms:
1. Páginas – as páginas do Xamarin.Forms representam telas de aplicativos móveis de
plataforma cruzada. O aplicativo de anotações usa o ContentPage classe para exibir telas
únicas. Para saber mais sobre páginas, consulte Xamarin.Forms Pages (Páginas do
Xamarin.Forms).
2. Exibições – as exibições do Xamarin.Forms são os controles exibidos na interface do usuário,
como rótulos, botões e caixas de entrada de texto. O aplicativo de anotações concluído usa o
ListView , Editor , e Button modos de exibição. Para saber mais sobre exibições, consulte
Xamarin.Forms Views (Exibições do Xamarin.Forms).
3. Layouts – os layouts do Xamarin.Forms são contêineres usados para compor exibições em
estruturas lógicas. O aplicativo de anotações usa o StackLayout classe para organizar os
modos de exibição em uma pilha vertical e o Grid classe para organizar botões
horizontalmente. Para saber mais sobre layouts, consulte Xamarin.Forms Layouts (Layouts do
Xamarin.Forms).
4. Células – as células do Xamarin.Forms são elementos especializados usados para itens em
uma lista e descrevem como cada item em uma lista deve ser desenhado. O aplicativo de
anotações usa o TextCell para exibir dois itens para cada linha na lista. Para saber mais sobre
células, consulte Xamarin.Forms Cells (Células do Xamarin.Forms).
No tempo de execução, cada controle será mapeado para seu equivalente nativo, que é o que
será renderizado.
Layout
O aplicativo de anotações usa o StackLayout para simplificar o desenvolvimento de aplicativos
de plataforma cruzada organizando automaticamente os modos de exibição na tela,
independentemente do tamanho da tela. Os elementos filho são posicionados um após o outro,
horizontalmente ou verticalmente, na ordem em que foram adicionados. A quantidade de espaço
que o StackLayout usará dependerá de como as propriedades HorizontalOptions e
VerticalOptions forem definidas, mas por padrão o StackLayout tentará usar a tela inteira.
Por padrão o StackLayout assume uma orientação vertical. No entanto, ela pode ser alterada
para uma orientação horizontal, definindo a StackLayout.Orientation propriedade para o
StackOrientation.Horizontal membro de enumeração.
NOTE
O tamanho dos modos de exibição pode ser definido por meio de HeightRequest e WidthRequest
propriedades.
NOTE
O arquivo code-behind de uma classe XAML pode acessar um objeto definido em XAML usando o nome
atribuído a ele com o atributo x:Name . O valor atribuído a esse atributo tem as mesmas regras que
variáveis C#, no sentido de que deve começar com uma letra ou um sublinhado e não conter espaços.
Listas
O ListView é responsável por exibir uma coleção de itens verticalmente em uma lista. Cada item
no ListView estará contido em uma única célula.
O seguinte exemplo de código mostra a ListView da NotesPage :
<ListView x:Name="listView"
Margin="{StaticResource PageMargin}"
ItemSelected="OnListViewItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Text}"
Detail="{Binding Date}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
O ItemSelected evento pode acessar o objeto que foi associado à célula por meio de
e.SelectedItem propriedade.
Para obter mais informações sobre o ListView da classe, consulte ListView.
Navegação
o Xamarin.Forms oferece uma série de experiências de navegação de página diferentes,
dependendo do tipo do Page sendo usado. Para ContentPage navegação de instâncias pode ser
modal ou hierárquica. Para obter informações sobre navegação modal, consulte páginas modais
do xamarin. Forms.
NOTE
As classes CarouselPage , MasterDetailPage e TabbedPage oferecem experiências de navegação
alternativas. Para obter mais informações, veja Navegação.
No painel de Navegação hierárquica, o NavigationPage classe é usada para navegar por meio de
uma pilha de ContentPage objetos, frente e para trás, conforme desejado. A classe implementa
navegação como uma pilha UEPS (último a entrar, primeiro a sair) de objetos Page . Para mover-
se de uma página para outra, um aplicativo enviará por push uma nova página para a pilha de
navegação, na qual ela se tornará a página ativa. Para retornar à página anterior, o aplicativo
removerá o item mais recente, que é a página atual da pilha de navegação, então a nova página
de nível mais alto se tornará a página ativa.
A classe NavigationPage também adicionará uma barra de navegação à parte superior da página
que exibe um título e um botão Voltar apropriado para a plataforma, que retornará à página
anterior.
A primeira página adicionada a uma pilha de navegação é conhecida como o raiz página do
aplicativo e o exemplo de código a seguir mostra como isso é feito no aplicativo de anotações:
public App ()
{
...
MainPage = new NavigationPage (new NotesPage ());
}
Todas as instâncias do ContentPage têm uma propriedade Navigation que expõe métodos para
modificar a pilha de páginas. Esses métodos devem ser invocados somente se o aplicativo incluir
um NavigationPage . Para navegar até o NoteEntryPage , é necessário invocar o método
PushAsync conforme demonstrado no exemplo de código abaixo:
Isso faz com que o novo NoteEntryPage objeto a ser enviado para a pilha de navegação, em que
ele se torna a página ativa.
A página ativa pode ser removida como o item mais recente da pilha de navegação pressionando
o botão Voltar no dispositivo, independentemente de este ser um botão físico no dispositivo ou
um botão na tela. Para retornar programaticamente à página original, o objeto NoteEntryPage
deve invocar o método PopAsync , conforme demonstrado no exemplo de código abaixo:
await Navigation.PopAsync();
Para obter mais informações sobre navegação hierárquica, veja Navegação hierárquica.
Associação de dados
Vinculação de dados é usada para simplificar como um aplicativo Xamarin.Forms exibe e
interage com seus dados. Ela estabelece uma conexão entre a interface do usuário e o aplicativo
subjacente. A classe BindableObject contém a maior parte da infraestrutura para dar suporte à
vinculação de dados.
A vinculação de dados conecta dois objetos, chamados de a origem e o destino. O objeto origem
fornece os dados. O objeto destino consumirá (e geralmente exibirá) dados do objeto de origem.
Por exemplo, um Editor (destino objeto) normalmente associará sua Text propriedade para
um público string propriedade em um código -fonte objeto. O diagrama a seguir ilustra essa
relação de associação:
O principal benefício da vinculação de dados é que você não precisa se preocupar sobre a
sincronização de dados entre suas exibições e a fonte de dados. As alterações no objeto de
origem são enviadas automaticamente para o objeto de destino nos bastidores pela estrutura de
associação, enquanto as alterações no objeto de destino podem ser opcionalmente enviadas de
volta para o objeto de origem.
Estabelecimento de dados de associação é um processo em duas etapas:
A propriedade BindingContext do objeto de destino deve ser definida como a origem.
Uma associação deve ser estabelecida entre o destino e a origem. Em XAML, isso é obtido
usando a extensão de marcação Binding .
Estilo
Aplicativos xamarin. Forms geralmente contêm vários elementos visuais que têm uma aparência
idêntica. Definir a aparência de cada elemento visual pode ser repetitiva e sujeito a erros. Em vez
disso, podem ser criados estilos que definem a aparência e, em seguida, aplicada aos elementos
visuais necessários.
O Style classe agrupa uma coleção de valores de propriedade em um único objeto, em seguida,
pode ser aplicado a várias instâncias do elemento visual. Estilos são armazenados em uma
ResourceDictionary , no nível do aplicativo, o nível de página ou o nível de exibição. Escolhendo
onde definir um Style impactos em que ele pode ser usado:
Style instâncias definidas no nível do aplicativo podem ser aplicadas em todo o aplicativo.
Style instâncias definidas no nível de página podem ser aplicadas para a página e seus
filhos.
Style instâncias definidas no nível de exibição podem ser aplicadas para o modo de exibição
e seus filhos.
IMPORTANT
Todos os estilos que são usados em todo o aplicativo são armazenados no dicionário de recursos do
aplicativo para evitar a duplicação. No entanto, o XAML que é específico para uma página não deve ser
incluído no dicionário de recursos do aplicativo, como os recursos então serão analisados na inicialização
do aplicativo em vez de quando exigido por uma página.
Cada Style instância contém uma coleção de um ou mais Setter objetos, com cada Setter
tendo um Property e uma Value . O Property é o nome da propriedade associável do elemento
de estilo é aplicado, e o Value é o valor que é aplicado à propriedade. O exemplo de código a
seguir mostra um estilo de NoteEntryPage :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Notes.NoteEntryPage"
Title="Note Entry">
<ContentPage.Resources>
<!-- Implicit styles -->
<Style TargetType="{x:Type Editor}">
<Setter Property="BackgroundColor"
Value="{StaticResource AppBackgroundColor}" />
</Style>
...
</ContentPage.Resources>
...
</ContentPage>
NOTE
Definir o estilo de um aplicativo xamarin. Forms tradicionalmente é realizado usando estilos XAML. No
entanto, o xamarin. Forms também dá suporte a elementos visuais de estilo usando folhas de estilo em
cascata (CSS). Para obter mais informações, consulte aplicativos de estilo de xamarin. Forms usando
folhas de estilo em cascata (CSS).
Para obter mais informações sobre estilos XAML, consulte estilos aplicativos xamarin. Forms
usando os estilos XAML.
Fornecer estilos específicos de plataforma
O OnPlatform extensões de marcação permitem que você personalize a aparência da interface do
usuário em uma base por plataforma:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Notes.App">
<Application.Resources>
...
<Color x:Key="iOSNavigationBarColor">WhiteSmoke</Color>
<Color x:Key="AndroidNavigationBarColor">#2196F3</Color>
<Color x:Key="iOSNavigationBarTextColor">Black</Color>
<Color x:Key="AndroidNavigationBarTextColor">White</Color>
Teste e implantação
Tanto o Visual Studio para Mac quanto o Visual Studio oferecem várias opções para testar e
implantar um aplicativo. Depurar aplicativos é uma parte comum do ciclo de vida de
desenvolvimento de aplicativo e ajuda a diagnosticar problemas de código. Para saber mais,
consulte Definir um ponto de interrupção, Percorrer o código e Enviar as informações para a
janela de log.
Simuladores são um bom lugar para começar a implantar e testar um aplicativo e eles
apresentam recursos úteis para testar aplicativos. No entanto, os usuários não consumirão o
aplicativo final em um simulador, assim, os aplicativos devem ser testados em dispositivos reais
antecipadamente e com frequência. Para saber mais sobre o provisionamento de dispositivo iOS,
consulte Provisionamento de Dispositivo. Para saber mais sobre o provisionamento de
dispositivo Android, consulte Configurar o dispositivo para desenvolvimento.
Próximas etapas
Essa informação aprofundada examinou os conceitos básicos do desenvolvimento de aplicativos
usando o xamarin. Forms. As próximas etapas sugeridas incluem ler sobre as seguintes
funcionalidades:
Há quatro grupos de controle principais usados para criar a interface do usuário de um
aplicativo Xamarin.Forms. Para obter mais informações, confira Referência de controles.
A associação de dados é uma técnica para vincular propriedades de dois objetos para que as
alterações em uma propriedade sejam automaticamente refletidas na outra propriedade. Para
obter mais informações, confira Associação de dados.
O Xamarin.Forms oferece uma série de experiências de navegação de página diferentes,
dependendo do tipo de página sendo usado. Para obter mais informações, veja Navegação.
Estilos ajudam a reduzir as marcações repetitivas e permitem que a aparência de aplicativos
seja alterada com mais facilidade. Para obter mais informações, confira Definindo o estilo de
aplicativos Xamarin.Forms.
As extensões de marcação XAML estendem a eficiência e a flexibilidade do XAML permitindo
que os atributos do elemento sejam definidos de fontes que não sejam cadeias de caracteres
de texto literal. Para obter mais informações, confira Extensões de marcação XAML.
Os modelos de dados fornecem a capacidade de definir a apresentação de dados em exibições
com suporte. Para saber mais, veja Modelos de dados.
Cada página, layout e exibição é renderizado diferentemente em cada plataforma usando uma
classe Renderer , que por sua vez cria um controle nativo, organiza sua disposição na tela e
adiciona o comportamento especificado no código compartilhado. Os desenvolvedores
podem implementar suas próprias classes Renderer personalizadas para personalizar a
aparência e/ou o comportamento de um controle. Para obter mais informações, veja
Renderizadores personalizados.
Efeitos também permitem que os controles nativos em cada plataforma sejam personalizados.
Os efeitos são criados em projetos específicos da plataforma aplicando subclasses à classe
PlatformEffect e consumidos anexando-os a um controle Xamarin.Forms apropriado. Para
obter mais informações, veja Efeitos.
O código compartilhado pode acessar a funcionalidade nativa por meio da classe
DependencyService . Para obter mais informações, consulte Acessar recursos nativos com
DependencyService.
Como alternativa, veja Criando aplicativos móveis com Xamarin.Forms, um livro de Charles
Petzold, é uma ótima opção para saber mais sobre o Xamarin.Forms. O livro está disponível em
PDF ou em vários formatos de livro eletrônico.
Links relacionados
Linguagem de marcação de aplicativo extensível (XAML )
Associação de dados
Referência de Controles
Extensões de marcação XAML
Exemplos do Xamarin.Forms
Exemplos de Introdução
Referência de API de xamarin. Forms
Aprendizado autodirigido gratuito (vídeo)
Linguagem de marcação de aplicativo extensível
(XAML)
12/04/2019 • 6 minutes to read
XAML é uma linguagem de marcação declarativa que pode ser usada para definir interfaces do usuário. A
interface do usuário é definida em um arquivo XML usando a sintaxe XAML, enquanto o comportamento de
tempo de execução é definido em um arquivo code-behind separado.
NOTE
Experimente o visualização padrão de XAML
Controles XAML
Todas as exibições que são definidas no xamarin. Forms podem ser referenciadas em arquivos XAML.
Compilação de XAML
Opcionalmente, XAML pode ser compilado direto na IL (linguagem intermediária) com o compilador XAML
(XAMLC ). Este artigo descreve como usar o XAMLC e seus benefícios.
Visualizador do XAML
O XAML pré-visualizador renderiza uma visualização dinâmica de uma página lado a lado com a marcação XAML,
permitindo que você veja sua interface do usuário renderizado conforme você digita.
Namespaces XAML
XAML usa a xmlns atributo XML para declarações de namespace. Este artigo apresenta a sintaxe do namespace
XAML e demonstra como declarar um namespace XAML para um tipo de acesso.
Modificadores de campo
O x:FieldModifier atributo namespace Especifica o nível de acesso para os campos gerados para elementos
nomeados do XAML.
Passando argumentos
XAML pode ser usado para passar argumentos para os construtores não padrão ou a métodos de fábrica. Este
artigo demonstra como usar os atributos XAML que podem ser usados para passar argumentos para construtores,
para chamar métodos de fábrica e para especificar o tipo de um argumento genérico.
Propriedades associáveis
No xamarin. Forms, a funcionalidade de propriedades comuns de runtime (CLR ) de linguagem é estendida por
propriedades associáveis. Uma propriedade associável é um tipo especial de propriedade, em que o valor da
propriedade é controlado pelo sistema de propriedades de xamarin. Forms. Este artigo fornece uma introdução a
propriedades associáveis e demonstra como criar e consumi-los.
Propriedades anexadas
Uma propriedade anexada é um tipo especial de propriedade associável, definido em uma classe, mas anexado a
outros objetos e reconhecível no XAML como um atributo que contém uma classe e um nome de propriedade
separados por um período. Este artigo fornece uma introdução para propriedades anexadas e demonstra como
criar e consumi-los.
Dicionários de recurso
Recursos XAML são definições de objetos que podem ser usados mais de uma vez. Um ResourceDictionary
permite que os recursos sejam definidos em um único local e reutilizadas em todo um aplicativo xamarin. Forms.
Este artigo demonstra como criar e consumir um ResourceDictionary e como mesclar um ResourceDictionary em
outro.
BoxView
<BoxView Color="Accent"
Exibe um retângulo de uma cor específica. WidthRequest="150"
HeightRequest="150"
HorizontalOptions="Center">
API / guia
Image
<Image Source="https://aka.ms/campus.jpg"
Exibe um bitmap. Aspect="AspectFit"
HorizontalOptions="Center" />
API / guia
Rotular
<Label Text="Hello, Xamarin.Forms!"
Exibe um ou mais linhas de texto. FontSize="Large"
FontAttributes="Italic"
HorizontalTextAlignment="Center" />
API / guia
Mapa
<maps:Map ItemsSource="{Binding Locations}" />
Exibe um mapa.
API / guia
WebView
<WebView
Exibe as páginas da Web ou conteúdo HTML. Source="https://docs.microsoft.com/xamarin/"
VerticalOptions="FillAndExpand" />
API / guia
Botão
<Button Text="Click Me!"
Exibe o texto em um objeto retangular. Font="Large"
BorderWidth="1"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Clicked="OnButtonClicked" />
API / guia
ImageButton
<ImageButton Source="XamarinLogo.png"
Exibe uma imagem em um objeto retangular. HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Clicked="OnImageButtonClicked" />
API / guia
SearchBar
<SearchBar Placeholder="Xamarin.Forms Property"
Exibe uma barra de pesquisa, para executar uma pesquisa.
SearchButtonPressed="OnSearchBarButtonPressed" />
API
Modos de exibição para definir valores
Controle deslizante
<Slider Minimum="0"
Permite a seleção de um double valor de um intervalo Maximum="100"
contínuo. VerticalOptions="CenterAndExpand" />
API / guia
Passador
<Stepper Minimum="0"
Permite a seleção de um double valor de um intervalo de Maximum="10"
incremental. Increment="0.1"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
API / guia
Alternar
<Switch IsToggled="false"
Permite a seleção de um boolean valor. HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
API
DatePicker
<DatePicker Format="D"
Permite a seleção de uma data. VerticalOptions="CenterAndExpand" />
API / guia
TimePicker
<TimePicker Format="T"
Permite a seleção de uma hora. VerticalOptions="CenterAndExpand" />
API / guia
Entrada
<Entry Keyboard="Email"
Permite que uma única linha de texto a ser inserido e editadas. Placeholder="Enter email address"
VerticalOptions="CenterAndExpand" />
API / guia
Editor
<Editor VerticalOptions="FillAndExpand" />
Permite que várias linhas de texto a ser inserido e editado.
API / guia
ActivityIndicator
<ActivityIndicator IsRunning="True"
Exibe uma animação para mostrar que o aplicativo está
envolvido em uma atividade demorada, sem fornecer VerticalOptions="CenterAndExpand" />
nenhuma indicação de progresso.
API
ProgressBar
<ProgressBar Progress=".5"
Exibe uma animação para mostrar que o aplicativo está em VerticalOptions="CenterAndExpand" />
andamento através de uma atividade demorada.
API
CollectionView
<CollectionView ItemsSource="{Binding Monkeys}">
Exibe uma lista rolável de itens selecionáveis de dados, usando ItemTemplate="{StaticResource
as especificações de layout diferente. MonkeyTemplate}"
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical"
Span="2" />
</CollectionView.ItemsLayout>
</CollectionView/>
Guia
ListView
<ListView ItemsSource="{Binding Monkeys}">
Exibe uma lista rolável de itens de dados podem ser ItemTemplate="{StaticResource
selecionados. MonkeyTemplate}" />
API / guia
Seletor
<Picker Title="Select a monkey"
Exibe o item de seleção de uma lista de cadeias de caracteres TitleColor="Red">
de texto. <Picker.ItemsSource<
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
API / guia
TableView
<TableView Intent="Settings">
Exibe uma lista de linhas interativas. <TableRoot>
<TableSection Title="Ring">
<SwitchCell Text="New Voice Mail" />
<SwitchCell Text="New Mail" On="true"
/>
</TableSection>
</TableRoot>
API / guia </TableView>
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Exemplos do Xamarin.Forms
Documentação da API de xamarin. Forms
Noções básicas de XAML de xamarin. Forms
12/04/2019 • 7 minutes to read
Tópicos XAML são abordados mais detalhadamente nos vários capítulos do livro, incluindo:
Visão geral
XAML é uma linguagem baseada em XML criada pela Microsoft como uma alternativa ao código de programação
para instanciar e inicializando objetos e organizar os objetos em hierarquias pai-filho. XAML tem foram
adaptados para várias tecnologias dentro do .NET framework, mas encontrou sua utilidade maior na definição do
layout de interfaces do usuário dentro do Windows Presentation Foundation (WPF ), Silverlight, o tempo de
execução do Windows e o Windows Universal UWP (plataforma).
XAML também é parte do xamarin. Forms, a plataforma cruzada nativamente com base em interface de
programação para iOS, Android e UWP dispositivos móveis. Dentro do arquivo XAML, o desenvolvedor de
xamarin. Forms pode definir interfaces do usuário usando todos os o xamarin. Forms exibições, layouts e páginas,
como classes de cliente. O arquivo XAML pode ser compilado ou incorporado no executável. De qualquer forma,
as informações de XAML são analisadas no momento da compilação para localizar objetos nomeados e
novamente em tempo de execução para instanciar e inicializar objetos e para estabelecer links entre esses objetos
e o código de programação.
XAML tem várias vantagens sobre o código equivalente:
XAML geralmente é mais sucinta e legíveis que o código equivalente.
A hierarquia pai-filho inerente no XML permite que o XAML simular com maior clareza visual a hierarquia pai-
filho de objetos de interface do usuário.
XAML pode ser facilmente manuscritas por programadores, mas também serve para ser compatível com
ferramentas e geradas por ferramentas de design visual.
Obviamente, também há desvantagens, relacionadas principalmente às limitações que são intrínsecas para
linguagens de marcação:
XAML não pode conter código. Todos os manipuladores de eventos devem ser definidos em um arquivo de
código.
XAML não pode conter loops para processamento repetitivo. (No entanto, vários objetos visuais do xamarin.
Forms — mais notoriamente ListView — pode gerar vários filhos com base nos objetos no seu ItemsSource
coleção.)
XAML não pode conter processamento condicional (no entanto, uma associação de dados pode fazer
referência a um conversor de associação baseada em código que permite efetivamente que algum
processamento condicional.)
XAML geralmente não é possível instanciar classes que definem um construtor sem parâmetros. (No entanto,
há algumas vezes, uma solução alternativa para essa restrição.)
XAML geralmente não é possível chamar métodos. (Novamente, essa restrição pode, às vezes, ser superada.)
Não há ainda um designer visual para gerar o XAML em aplicativos xamarin. Forms. Todos os XAML deve ser
escrito manualmente, mas há uma XAML pré-visualizador. Os programadores novo XAML talvez queira
frequentemente compilar e executar seus aplicativos, especialmente após qualquer coisa que podem não estar
corretas, obviamente. Os desenvolvedores até mesmo com muita experiência em XAML sabem que
experimentação é gratificante.
XAML é, basicamente, XML, mas a XAML tem alguns recursos exclusivos de sintaxe. Os mais importantes são:
Elementos de propriedade
Propriedades anexadas
Extensões de marcação
Esses recursos estão não extensões XML. XAML é XML inteiramente legal. Mas esses recursos de sintaxe XAML
usam XML de maneiras exclusivas. Eles serão discutidos em detalhes nos artigos a seguir, que terminam com uma
introdução ao uso do XAML para implementar o MVVM.
Requisitos
Este artigo pressupõe que esteja familiarizado com o xamarin. Forms. Este artigo também pressupõe alguma
familiaridade com XML, inclusive a entender o uso de declarações de namespace XML e os termos elemento,
marca, e atributo.
Quando você estiver familiarizado com o xamarin. Forms e XML, começar a ler parte 1. Introdução ao XAML .
Links relacionados
XamlSamples
Criar o catálogo de aplicativos móveis
Exemplos do Xamarin.Forms
Parte 1. Introdução ao XAML
12/04/2019 • 30 minutes to read
baixar o exemplo
Em um aplicativo xamarin. Forms, o XAML é usado principalmente para definir o conteúdo visual de uma página
e funciona em conjunto com um C# arquivo code-behind.
O arquivo code-behind fornece suporte de código para a marcação. Juntos, esses dois arquivos contribuem para
uma nova definição de classe que inclui modos de exibição filho e inicialização de propriedade. Dentro do arquivo
XAML, classes e propriedades são referenciadas com atributos e elementos XML e links entre a marcação e
código são estabelecidas.
Criando a solução
Para começar a editar seu primeiro arquivo XAML, use o Visual Studio ou Visual Studio para Mac para criar uma
nova solução xamarin. Forms. (Selecione a guia abaixo correspondentes ao seu ambiente.)
Visual Studio
Visual Studio para Mac
No Windows, use o Visual Studio para selecionar arquivo > Novo > projeto no menu. No novo projeto caixa
de diálogo, selecione Visual C# > plataforma cruzada à esquerda e, em seguida, aplicativo móvel (xamarin.
Forms) na lista no centro.
Selecione um local para a solução, dê um nome de XamlSamples (ou acordo com sua preferência) e pressione
Okey.
Na próxima tela, selecione a aplicativo em branco modelo e o .NET Standard estratégia de compartilhamento
de código:
Pressione Okey.
Quatro projetos são criados na solução: o XamlSamples .NET Standard library, XamlSamples.Android,
XamlSamples.iOSe a plataforma Universal do Windows solução, XamlSamples.UWP.
Depois de criar o XamlSamples solução, você talvez queira testar seu ambiente de desenvolvimento,
selecionando os vários projetos de plataforma como o projeto de inicialização da solução e criar e implantar o
aplicativo simples criado por o modelo de projeto em emuladores de telefone ou em dispositivos reais.
A menos que você precisa escrever código específico da plataforma, compartilhado XamlSamples projeto de
biblioteca .NET Standard é onde você vai gastar praticamente todo seu tempo programação. Estes artigos não
serão se aventurar fora desse projeto.
Anatomia de um arquivo XAML
Dentro de XamlSamples biblioteca .NET Standard são um par de arquivos com os seguintes nomes:
App. XAML, o arquivo XAML; e
App.XAML.CS, um C# de lógica arquivo associado ao arquivo XAML.
Você precisará clicar na seta ao lado App. XAML para ver o arquivo code-behind.
Ambos App. XAML e App.xaml.cs contribuem para uma classe denominada App que deriva de Application . A
maioria das outras classes com arquivos XAML contribuem para uma classe que deriva de ContentPage ; esses
arquivos usam XAML para definir o conteúdo visual de uma página inteira. Isso é verdadeiro para os outros dois
arquivos na XamlSamples projeto:
MainPage. XAML, o arquivo XAML; e
MainPage.xaml.cs, o C# arquivo code-behind.
O MainPage. XAML arquivo tem esta aparência (embora a formatação pode ser um pouco diferente):
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.MainPage">
<StackLayout>
<!-- Place new controls here -->
<Label Text="Welcome to Xamarin Forms!"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
O namespace XML de dois ( xmlns ) declarações façam referência URIs, a primeira aparentemente no site de web
do Xamarin e o segundo da Microsoft. Não se preocupe em que ponto os URIs para a verificação. Não há nada.
Eles são simplesmente URIs pertencentes a Xamarin e a Microsoft e eles basicamente funcionam como
identificadores de versão.
A primeira declaração de namespace XML significa que marcas definidas dentro do arquivo XAML sem prefixo se
referem às classes no xamarin. Forms, por exemplo ContentPage . A segunda declaração de namespace define um
prefixo de x . Isso é usado para vários elementos e atributos que são intrínsecos para XAML em si e que são
compatíveis com outras implementações de XAML. No entanto, esses elementos e atributos são ligeiramente
diferentes dependendo do ano inserido no URI. Xamarin. Forms dá suporte à especificação do XAML 2009, mas
nem tudo dela.
O local declaração de namespace permite que você acesse outras classes do projeto de biblioteca do .NET
Standard.
No final da primeira marca, o x prefixo é usado para um atributo chamado Class . Porque o uso deste x
prefixo é praticamente universal para o namespace XAML, atributos XAML, como Class quase sempre são
chamados de x:Class .
O x:Classatributo especifica um nome de classe totalmente qualificado do .NET: o MainPage classe o
XamlSamples namespace. Isso significa que esse arquivo XAML define uma nova classe chamada MainPage no
XamlSamples namespace que deriva ContentPage — a marca na qual o x:Class atributo é exibido.
O x:Class atributo só pode aparecer no elemento raiz de um arquivo XAML para definir um derivada C# classe.
Esta é a classe somente novo definido no arquivo XAML. Em vez disso, tudo o que aparece no arquivo XAML é
instanciado a partir de classes existentes-las simplesmente e inicializado.
O MainPage.xaml.cs arquivo tem esta aparência (além de não utilizados using diretivas):
using Xamarin.Forms;
namespace XamlSamples
{
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
}
O MainPage classe deriva ContentPage , mas observe o partial definição de classe. Isso sugere que deve haver
outra definição de classe parcial para MainPage , mas onde ele está? E o que é isso InitializeComponent método?
Quando o Visual Studio compila o projeto, ele analisa o arquivo XAML para gerar um C# arquivo de código. Se
você olhar o XamlSamples\XamlSamples\obj\Debug diretório, você encontrará um arquivo chamado
XamlSamples.MainPage.xaml.g.cs. 'g' significa gerado. Isso é outra definição de classe parcial de MainPage
que contém a definição do InitializeComponent método chamado do MainPage construtor. Esses dois parcial
MainPage definições de classe podem ser compiladas juntos. Dependendo se o XAML é compilado ou não, o
arquivo XAML ou um formato binário do arquivo XAML é incorporado no executável.
No tempo de execução de código nas chamadas de projeto de plataforma em particular uma LoadApplication
método, passando a ele uma nova instância do App classe na biblioteca do .NET Standard. O App cria uma
instância do construtor de classe MainPage . Chama o construtor da classe InitializeComponent , que chama o
LoadFromXaml método que extrai o arquivo XAML (ou seu binário compilado) da biblioteca do .NET Standard.
LoadFromXaml inicializa todos os objetos definidos no arquivo XAML, conecta tudo isso junto em relações pai-
filho, anexa os manipuladores de eventos definidos no código aos eventos definido no arquivo XAML e define a
árvore resultante de objetos, como o conteúdo da página.
Embora você normalmente não precisa gastar muito tempo com arquivos de código gerados, às vezes, tempo de
execução exceções são geradas em código em arquivos gerados, portanto, você deve estar familiarizado com eles.
Quando você compilar e executar este programa, o Label elemento aparece no centro da página, como sugere o
XAML:
Para visuais mais interessantes, tudo o que você precisa é mais interessante de XAML.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
O ContentPage.Content marcas fazem parte da sintaxe de XAML exclusivo. Primeiro, elas podem parecer ser um
XML inválido, mas são válidas. O período não é um caractere especial em XML.
O ContentPage.Content marcas são chamadas elemento de propriedade marcas. Content é uma propriedade de
ContentPage e geralmente é definido como um modo de exibição único ou um layout com modos de exibição
filho. Normalmente propriedades tornam-se atributos em XAML, mas ele seria difícil de definir um Content de
atributo para um objeto complexo. Por esse motivo, a propriedade é expressa como um elemento XML que
consiste em nome de classe e o nome da propriedade separados por um período. Agora o Content propriedade
pode ser definida entre o ContentPage.Content marcas, como este:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.HelloXamlPage"
Title="Hello XAML Page">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
O HorizontalTextAlignment propriedade é do tipo TextAlignment , que é uma enumeração. Para uma propriedade
de qualquer tipo de enumeração, tudo o que você precisa fornecer é um nome de membro.
Para propriedades de tipos mais complexos, no entanto, conversores são usados para analisar o XAML. Essas são
classes no xamarin. Forms que derivam de TypeConverter . Muitos são classes públicas, mas alguns não são. Para
esse arquivo XAML específico, várias dessas classes desempenham um papel nos bastidores:
LayoutOptionsConverter para o VerticalOptions propriedade
FontSizeConverter para o FontSize propriedade
ColorTypeConverter para o TextColor propriedade
Cada uma das letras pouco é um dígito hexadecimal. Aqui está como um canal alfa está incluído:
TextColor="#aarrggbb">
Para o canal alfa, tenha em mente que FF é totalmente opaca e 00 é totalmente transparente.
Dois outros formatos permitem que você especifique apenas um dígito hexadecimal para cada canal:
TextColor="#rgb" TextColor="#argb"
Nesses casos, o dígito é repetido para formar o valor. Por exemplo, #CF3 é a cor RGB FF -CC -33.
Navegação de página
Quando você executa o XamlSamples programa, o MainPage é exibida. Para ver o novo HelloXamlPage você
pode definir que, como a inicialização de novo, página em de App.xaml.cs do arquivo ou navegue para a nova
página de MainPage .
Para implementar a navegação, primeiro altere o código na App.xaml.cs construtor para que um NavigationPage
objeto é criado:
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
}
No MainPage.xaml.cs construtor, você pode criar um simples Button e use o manipulador de eventos para
navegar até HelloXamlPage :
public MainPage()
{
InitializeComponent();
Content = button;
}
Definindo o Content propriedade da página substitui a configuração do Content propriedade no arquivo XAML.
Quando você compila e implanta a nova versão deste programa, um botão aparece na tela. Pressioná-lo navega
para HelloXamlPage . Aqui está a página resultante no iPhone, Android e UWP:
Você pode navegar de volta para MainPage usando o < volta botão no iOS, usando a seta para a esquerda na
parte superior da página ou na parte inferior do telefone no Android, ou na seta à esquerda na parte superior da
página no Windows 10.
Fique à vontade fazer experiências com o XAML para diferentes maneiras renderizar o Label . Se você precisar
inserir quaisquer caracteres Unicode em texto, você pode usar a sintaxe XML padrão. Por exemplo, para colocar a
saudação aspas inglesas, use:
<Label Text="“Hello, XAML!”" … />
Aqui está o que se parece com:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<StackLayout>
<Slider VerticalOptions="CenterAndExpand" />
Esse arquivo XAML é sintaticamente completo, e aqui está o que se parece com:
No entanto, você provavelmente considere este programa seja funcionalmente deficientes. Talvez o Slider deve
fazer com que o Label para exibir o valor atual e o Button provavelmente se destina a fazer algo dentro do
programa.
Como você verá no parte 4. Noções básicas de vinculação de dados, o trabalho de exibição de um Slider valor
usando um Label possam ser manipulados inteiramente em XAML com uma associação de dados. Mas é útil ver
a solução de código pela primeira vez. Mesmo assim, tratando o Button clique definitivamente requer código.
Isso significa que o arquivo code-behind para XamlPlusCodePage deve conter os manipuladores para o
ValueChanged eventos da Slider e o Clicked evento do Button . Vamos adicioná-los:
namespace XamlSamples
{
public partial class XamlPlusCodePage
{
public XamlPlusCodePage()
{
InitializeComponent();
}
}
}
}
Observe que a atribuição de um manipulador a um evento tem a mesma sintaxe atribuindo um valor a uma
propriedade.
Se o manipulador para o ValueChanged eventos do Slider usará o Label para exibir o valor atual, o
manipulador precisa fazer referência a esse objeto de código. O Label precisa de um nome, o que é especificado
com o x:Name atributo.
<Label x:Name="valueLabel"
Text="A simple Label"
Font="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
Ou, o manipulador foi possível obter o Slider objeto que está gerando esse evento do sender argumento e
obter o Value propriedade de que:
Quando você executa o programa, o Label não exibe as Slider valor porque o ValueChanged evento ainda não
foi acionado. Mas qualquer manipulação do Slider faz com que o valor a ser exibido:
Agora, para o Button . Vamos simular uma resposta a um Clicked evento exibindo um alerta com o Text do
botão. O manipulador de eventos pode seguramente os sender argumento para um Button e, em seguida,
acessar suas propriedades:
O método é definido como async porque o DisplayAlert método é assíncrono e devem ser precedido com o
await operador, que retorna quando o método for concluído. Porque esse método obtém o Button acionar o
evento a partir de sender argumento, o mesmo manipulador pode ser usado para vários botões.
Você já viu que um objeto definido em XAML pode acionar um evento que é processado no arquivo code-behind,
e que o arquivo code-behind pode acessar um objeto definido em XAML usando o nome atribuído a ele com o
x:Name atributo. Essas são as duas maneiras fundamentais que interagem de código e XAML.
Algumas informações adicionais em como funciona o XAML pode ser obtida, examinando o recém-gerado
arquivo XamlPlusCode.xaml.g.cs, que agora inclui qualquer nome atribuído a qualquer x:Name atributo como
um campo particular. Aqui está uma versão simplificada do arquivo:
A declaração desse campo permite que a variável para ser usados livremente em qualquer lugar dentro do
XamlPlusCodePage arquivo de classe parcial em sua jurisdição. Em tempo de execução, o campo é atribuído depois
que o XAML foi analisado. Isso significa que o valueLabel campo é null quando o XamlPlusCodePage construtor
começa válido, mas depois InitializeComponent é chamado.
Depois de InitializeComponent retorna controle volta para o construtor, os elementos visuais da página foram
construídos como se eles tinham instanciados e inicializados no código. O arquivo XAML não desempenha
qualquer função na classe. Você pode manipular esses objetos na página de qualquer forma que desejar, por
exemplo, adicionando modos de exibição para o StackLayout , configuração ou o Content propriedade da página
para algo mais inteiramente. Você pode "percorrer a árvore" Examinando o Content propriedade da página e os
itens a Children coleções de layouts. Você pode definir propriedades em modos de exibição acessados dessa
maneira, ou atribuir manipuladores de eventos a elas dinamicamente.
Fique à vontade. É sua página e o XAML é apenas uma ferramenta para criar seu conteúdo.
Resumo
Com essa introdução, você viu como um arquivo XAML e o arquivo de código contribuem para uma definição de
classe, e como os arquivos XAML e código interagem. Mas XAML também tem seus próprios recursos exclusivos
de sintáticos que permitem que ele seja usado de maneira muito flexível. Você pode começar a explorar em parte
2. Sintaxe XAML essencial.
Links relacionados
XamlSamples
Parte 2. Sintaxe essencial de XAML
Parte 3. Extensões de Marcação XAML
Parte 4. Conceitos básicos da associação de dados
Parte 5. De associação de dados a MVVM
Parte 2. Sintaxe XAML essencial
12/04/2019 • 17 minutes to read
baixar o exemplo
XAML é projetado principalmente para instanciar e inicializar objetos. Muitas vezes, mas propriedades devem ser
definidas para objetos complexos que não podem ser facilmente representados como cadeias de caracteres XML
e, às vezes, as propriedades definidas por uma classe devem ser definidas em uma classe filha. Essas duas
necessidades exigem os recursos de sintaxe XAML essencial de elementos de propriedade e propriedades
anexadas.
Elementos de propriedade
No XAML, as propriedades das classes normalmente são definidas como atributos XML:
No entanto, há uma maneira alternativa de definir uma propriedade em XAML. Para tentar essa alternativa com
TextColor , primeiro exclua o existente TextColor configuração:
</Label>
Dentro dessas marcas, adicione marcas de início e término que consistem em nome de classe e um nome de
propriedade separados por um período:
</Label.TextColor>
</Label>
Defina o valor da propriedade como conteúdo dessas novas marcas, como este:
<Label Text="Hello, XAML!"
VerticalOptions="Center"
FontAttributes="Bold"
FontSize="Large">
<Label.TextColor>
Aqua
</Label.TextColor>
</Label>
Essas duas maneiras para especificar o TextColor propriedade são funcionalmente equivalentes, mas não use as
duas formas para a mesma propriedade, porque que seriam efetivamente ser definindo a propriedade duas vezes
e pode ser ambíguo.
Com essa nova sintaxe, terminologia úteis pode ser introduzida:
Label é um elemento de objeto. Ele é um objeto de xamarin. Forms expressado como um elemento XML.
Text , VerticalOptions , FontAttributes e FontSize são atributos da propriedade. Elas são expressadas como
atributos XML de propriedades de xamarin. Forms.
Esse trecho de código final, TextColor tornou-se um elemento de propriedade. É uma propriedade de
xamarin. Forms, mas agora é um elemento XML.
A definição de propriedade elementos podem parecer a princípio ser uma violação da sintaxe XML, mas não é. O
período não tem nenhum significado especial em XML. Um decodificador de XML, Label.TextColor é
simplesmente um elemento filho normal.
No XAML, no entanto, essa sintaxe é muito especial. Uma das regras para elementos de propriedade é que nada
mais pode aparecer no Label.TextColor marca. O valor da propriedade é sempre definido como o conteúdo
entre o elemento de propriedade marcas de início e término.
Você pode usar a sintaxe de elemento de propriedade em mais de uma propriedade:
A princípio, sintaxe de elemento de propriedade pode parecer uma substituição longos desnecessária para algo
bastante comparativamente simples, e nesses exemplos, certamente, esse é o caso.
No entanto, a sintaxe de elemento de propriedade se torna essencial quando o valor de uma propriedade é muito
complexo para ser expresso como uma cadeia de caracteres simple. Dentro das marcas de elemento de
propriedade, você pode criar uma instância de outro objeto e defina suas propriedades. Por exemplo, você pode
definir explicitamente uma propriedade como VerticalOptions para um LayoutOptions valor com as
configurações de propriedade:
<Label>
...
<Label.VerticalOptions>
<LayoutOptions Alignment="Center" />
</Label.VerticalOptions>
</Label>
Outro exemplo: O Grid tem duas propriedades chamadas RowDefinitions e ColumnDefinitions . Essas duas
propriedades são do tipo RowDefinitionCollection e ColumnDefinitionCollection , que são coleções de
RowDefinition e ColumnDefinition objetos. Você precisa usar a sintaxe de elemento de propriedade para definir
essas coleções.
Aqui está o início do arquivo XAML para um GridDemoPage classe, mostrando as marcas de elemento de
propriedade para o RowDefinitions e ColumnDefinitions coleções:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.GridDemoPage"
Title="Grid Demo Page">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
...
</Grid>
</ContentPage>
Propriedades anexadas
Você acabou de ver que o Grid exige que os elementos de propriedade para o RowDefinitions e
ColumnDefinitions coleções para definir as linhas e colunas. No entanto, também deve haver alguma forma para
o programador indicar a linha e coluna em que cada filho do Grid reside.
Dentro da marca para cada filho do Grid especifique a linha e coluna dos filho usando os seguintes atributos:
Grid.Row
Grid.Column
Os valores padrão desses atributos são 0. Você também pode indicar se um filho abrange mais de uma linha ou
coluna com esses atributos:
Grid.RowSpan
Grid.ColumnSpan
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="100" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<BoxView Color="Silver"
HeightRequest="0"
Grid.Row="0" Grid.Column="1" />
<BoxView Color="Teal"
Grid.Row="1" Grid.Column="0" />
</Grid>
</ContentPage>
O Grid.Row e Grid.Column configurações de 0 não são necessárias, mas são geralmente é incluídas para fins de
esclarecimento.
Aqui está o que se parece com:
A julgar unicamente com a sintaxe, essas Grid.Row , Grid.Column , Grid.RowSpan , e Grid.ColumnSpan atributos
aparecem como campos estáticos ou propriedades de Grid , mas é interessante Grid não define nada chamado
Row , Column , RowSpan , ou ColumnSpan .
Em vez disso, Grid define quatro propriedades vinculáveis chamadas RowProperty , ColumnProperty ,
RowSpanProperty , e ColumnSpanProperty . Estes são tipos especiais de propriedades vinculáveis conhecidos como
propriedades anexadas. Elas são definidas pelo Grid classe definida, mas nos filhos do Grid .
Quando você deseja usar essas propriedades anexadas em código, o Grid classe fornece métodos estáticos
denominados SetRow , GetColumn e assim por diante. Mas no XAML, essas propriedades anexadas são definidas
como atributos nos filhos do Grid usando nomes de propriedades simples.
Propriedades anexadas são sempre reconhecidas em arquivos XAML como atributos, contendo uma classe e um
nome de propriedade separados por um período. Eles são chamados propriedades anexadas porque eles são
definidos por uma classe (nesse caso, Grid ), mas anexado a outros objetos (nesse caso, os filhos do Grid ).
Durante o layout, o Grid pode interrogar os valores dessas propriedades anexadas saber onde colocar cada filho.
O AbsoluteLayout classe define duas propriedades anexadas denominadas LayoutBounds e LayoutFlags . Aqui
está um padrão quadriculado realizados usando o posicionamento proporcional e os recursos de
dimensionamento do AbsoluteLayout :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.AbsoluteDemoPage"
Title="Absolute Demo Page">
<AbsoluteLayout BackgroundColor="#FF8080">
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0.33, 0, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="1, 0, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0, 0.33, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0.67, 0.33, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0.33, 0.67, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="1, 0.67, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0, 1, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
<BoxView Color="#8080FF"
AbsoluteLayout.LayoutBounds="0.67, 1, 0.25, 0.25"
AbsoluteLayout.LayoutFlags="All" />
</AbsoluteLayout>
</ContentPage>
E aqui está:
Para algo como isso, você poderá questionar a sabedoria da usando XAML. Certamente, a repetição e
regularidade do LayoutBounds retângulo sugere que ele pode ser melhor realizado no código.
Certamente, que é uma preocupação legítima e não há nenhum problema com o uso de código e marcação de
balanceamento, ao definir as interfaces do usuário. É fácil definir alguns dos elementos visuais em XAML e, em
seguida, use o construtor do arquivo code-behind para adicionar mais alguns visuais que podem ser gerados de
melhor em loops.
Propriedades de Conteúdo
Nos exemplos anteriores, o StackLayout , Grid , e AbsoluteLayout objetos são definidos com o Content
propriedade do ContentPage , e os filhos desses layouts são, na verdade, os itens no Children coleção. Embora
essas Content e Children propriedades estão em nenhum lugar no arquivo XAML.
Você certamente pode incluir a Content e Children propriedades como elementos de propriedade, como na
XamlPlusCode exemplo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.XamlPlusCodePage"
Title="XAML + Code Page">
<ContentPage.Content>
<StackLayout>
<StackLayout.Children>
<Slider VerticalOptions="CenterAndExpand"
ValueChanged="OnSliderValueChanged" />
<Label x:Name="valueLabel"
Text="A simple Label"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
A pergunta real é: por que são esses elementos de propriedade não necessárias no arquivo XAML?
Os elementos definidos no xamarin. Forms para uso em XAML podem ter uma propriedade sinalizada no
ContentProperty atributo na classe. Se você pesquisar o ContentPage classe na documentação online do xamarin.
Forms, você verá esse atributo:
[Xamarin.Forms.ContentProperty("Content")]
public class ContentPage : TemplatedPage
Isso significa que o Content marcas de elemento de propriedade não são necessárias. Qualquer conteúdo XML
que aparece entre o início e término ContentPage marcas é considerado a ser atribuído ao Content propriedade.
StackLayout , Grid , AbsoluteLayout , e RelativeLayout todos os derivam Layout<View> , e se você pesquisar
Layout<T> na documentação do xamarin. Forms, você verá outra ContentProperty atributo:
[Xamarin.Forms.ContentProperty("Children")]
public abstract class Layout<T> : Layout ...
Que permite que o conteúdo do layout a ser adicionado automaticamente para o Children coleção sem explícita
Children marcas de elemento de propriedade.
Outras classes também têm ContentProperty definições de atributo. Por exemplo, a propriedade de conteúdo do
Label é Text . Verifique a documentação da API para outras pessoas.
Você também pode fazer algo semelhante em XAML usando o OnPlatform e On classes. Primeiro, inclua os
elementos de propriedade para o Padding propriedade próximo à parte superior da página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
</ContentPage.Padding>
...
</ContentPage>
Dentro dessas marcas incluem um OnPlatform marca. OnPlatform é uma classe genérica. Você precisa especificar
o argumento de tipo genérico, nesse caso, Thickness , que é o tipo de Padding propriedade. Felizmente, há um
atributo XAML especificamente para definir argumentos genéricos chamados x:TypeArguments . Isso deve
corresponder ao tipo da propriedade que você está configurando:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
OnPlatform tem uma propriedade chamada Platforms que é um IList de On objetos. Use as marcas de
elemento de propriedade para essa propriedade:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<OnPlatform.Platforms>
</OnPlatform.Platforms>
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
Agora, adicione On elementos. Para cada um deles definir a Platform propriedade e o Value propriedade a
marcação para o Thickness propriedade:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<OnPlatform.Platforms>
<On Platform="iOS" Value="0, 20, 0, 0" />
<On Platform="Android" Value="0, 0, 0, 0" />
<On Platform="UWP" Value="0, 0, 0, 0" />
</OnPlatform.Platforms>
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
Essa marcação pode ser simplificada. A propriedade de conteúdo do OnPlatform é Platforms , portanto, essas
marcas de elemento de propriedade podem ser removidas:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 20, 0, 0" />
<On Platform="Android" Value="0, 0, 0, 0" />
<On Platform="UWP" Value="0, 0, 0, 0" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
O Platform propriedade de On é do tipo IList<string> , portanto, você pode incluir várias plataformas, se os
valores são os mesmos:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 20, 0, 0" />
<On Platform="Android, UWP" Value="0, 0, 0, 0" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
Android e UWP estejam definidas para o valor padrão de Padding , que marca pode ser removida:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 20, 0, 0" />
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
Essa é a maneira padrão para definir um dependente de plataforma Padding propriedade em XAML. Se o Value
configuração não pode ser representada por uma única cadeia de caracteres, você pode definir os elementos de
propriedade para ele:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="...">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS">
<On.Value>
0, 20, 0, 0
</On.Value>
</On>
</OnPlatform>
</ContentPage.Padding>
...
</ContentPage>
Resumo
Com elementos de propriedade e propriedades anexadas, grande parte da sintaxe XAML básica estabelecida. No
entanto, às vezes, você precisa definir propriedades para objetos de uma maneira indireta, por exemplo, a partir
de um dicionário de recursos. Essa abordagem é abordada na próxima parte, parte 3. Extensões de marcação
XAML.
Links relacionados
XamlSamples
Parte 1. Introdução ao XAML
Parte 3. Extensões de Marcação XAML
Parte 4. Conceitos básicos da associação de dados
Parte 5. De associação de dados a MVVM
Parte 3. Extensões de marcação XAML
12/04/2019 • 21 minutes to read
baixar o exemplo
Extensões de marcação XAML constituem um recurso importante no XAML que permitem que as propriedades
sejam definidas para objetos ou valores que são referenciados indiretamente de outras fontes. Extensões de
marcação XAML são particularmente importantes para compartilhamento de objetos e fazendo referência
constantes usadas em todo um aplicativo, mas que encontrar seu utilitário maior de associações de dados.
Recursos compartilhados
Algumas páginas XAML contêm vários modos de exibição com propriedades definidas para os mesmos valores.
Por exemplo, várias das configurações de propriedade para esses Button objetos forem os mesmos:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BorderWidth="3"
Rotation="-15"
TextColor="Red"
FontSize="24" />
</StackLayout>
</ContentPage>
Se uma dessas propriedades precisa ser alterado, talvez você prefira fazer a alteração apenas uma vez, em vez de
três vezes. Se esse fosse o código, você provavelmente usarão constantes e os objetos estáticos somente leitura
para ajudar a manter esses valores, consistente e fácil de modificar.
No XAML, uma solução popular é armazenar esses valores ou objetos em um dicionário de recursos. O
VisualElement classe define uma propriedade chamada Resources do tipo ResourceDictionary , que é um
dicionário com chaves de tipo string e valores do tipo object . Você pode colocar os objetos nesse Dictionary
e, em seguida, referenciá-los a partir de marcação, tudo em XAML.
Para usar um dicionário de recursos em uma página, inclua um par de Resources marcas de elemento de
propriedade. É mais conveniente para colocá-las na parte superior da página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
</ContentPage.Resources>
...
</ContentPage>
<ContentPage.Resources>
<ResourceDictionary>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Agora os objetos e valores de vários tipos podem ser adicionados ao dicionário de recursos. Esses tipos devem
ser instanciáveis. Eles não podem ser classes abstratas, por exemplo. Esses tipos também devem ter um
construtor público sem parâmetros. Cada item requer uma chave de dicionário especificada com o x:Key
atributo. Por exemplo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Esses dois itens são valores do tipo estrutura LayoutOptions e cada um tem uma chave exclusiva e uma ou duas
propriedades definidas. No código e marcação, é muito mais comum usar os campos estáticos de LayoutOptions
, mas aqui é mais conveniente definir as propriedades.
Agora, é necessário definir as HorizontalOptions e VerticalOptions propriedades desses botões para esses
recursos, e isso é feito com o StaticResource extensão de marcação XAML:
O StaticResource extensão de marcação é sempre delimitada com chaves e inclui a chave do dicionário.
O nome StaticResourcedistingue de DynamicResource , que o xamarin. Forms também oferece suporte.
DynamicResource é para as chaves de dicionário associadas aos valores que podem ser alterados durante o
tempo de execução, enquanto StaticResource acessa os elementos do dicionário de apenas uma vez quando os
elementos na página são construídos.
Para o BorderWidth propriedade, é necessário armazenar um valor double no dicionário. XAML
convenientemente define marcas para tipos de dados comuns, como x:Double e x:Int32 :
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">
3
</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
Você não precisa colocá-lo em três linhas. Essa entrada de dicionário para o ângulo de rotação usa apenas uma
linha para cima:
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">
3
</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
Esses dois recursos podem ser referenciados da mesma forma como o LayoutOptions valores:
Para recursos do tipo Color , você pode usar as mesmas representações de cadeia de caracteres que você usa ao
atribuir diretamente atributos desses tipos. Conversores de tipo são invocados quando o recurso é criado. Aqui
está um recurso do tipo Color :
<Color x:Key="textColor">Red</Color>
Agora todas as propriedades, exceto Text são definidos pelas configurações de recursos:
Também é possível usar OnPlatform no dicionário de recursos para definir valores diferentes para as
plataformas. Aqui está como um OnPlatform objeto pode ser parte do dicionário de recursos para as cores de
texto diferente:
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="UWP" Value="#80FF80" />
</OnPlatform>
Observe que OnPlatform obtém tanto um x:Key porque ele é um objeto no dicionário de atributo e um
x:TypeArguments atributo porque é uma classe genérica. O iOS , Android , e UWP atributos são convertidos em
Color valores quando o objeto é inicializado.
Aqui está o arquivo XAML completo final com três botões acessando seis valores compartilhados:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SharedResourcesPage"
Title="Shared Resources Page">
<ContentPage.Resources>
<ResourceDictionary>
<LayoutOptions x:Key="horzOptions"
Alignment="Center" />
<LayoutOptions x:Key="vertOptions"
Alignment="Center"
Expands="True" />
<x:Double x:Key="borderWidth">3</x:Double>
<x:Double x:Key="rotationAngle">-15</x:Double>
<OnPlatform x:Key="textColor"
x:TypeArguments="Color">
<On Platform="iOS" Value="Red" />
<On Platform="Android" Value="Aqua" />
<On Platform="UWP" Value="#80FF80" />
</OnPlatform>
<x:Double x:Key="fontSize">24</x:Double>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<Button Text="Do this!"
HorizontalOptions="{StaticResource horzOptions}"
VerticalOptions="{StaticResource vertOptions}"
BorderWidth="{StaticResource borderWidth}"
Rotation="{StaticResource rotationAngle}"
TextColor="{StaticResource textColor}"
FontSize="{StaticResource fontSize}" />
</StackLayout>
</ContentPage>
<StackLayout>
<StackLayout.Resources>
<ResourceDictionary>
<Color x:Key="textColor">Blue</Color>
</ResourceDictionary>
</StackLayout.Resources>
...
</StackLayout>
Você descobrirá que a cor do texto dos botões agora é azul. Basicamente, sempre que o analisador XAML
encontra uma StaticResource extensão de marcação, ele pesquisa a árvore visual e usa a primeira
ResourceDictionary encontra contendo essa chave.
Um dos tipos mais comuns de objetos armazenados em dicionários de recursos é o xamarin. Forms Style , que
define uma coleção de configurações de propriedade. Estilos são discutidos neste artigo estilos.
Às vezes, os desenvolvedores de novos no XAML esteja se perguntando se eles podem colocar um elemento
visual, como Label ou Button em um ResourceDictionary . Embora seja certamente possível, ele não faz muito
sentido. A finalidade de ResourceDictionary é compartilhar objetos. Um elemento visual não pode ser
compartilhado. A mesma instância não pode aparecer duas vezes em uma única página.
Até agora, isso não seja muito impressionante. Mas o x:Static extensão de marcação pode também fazer
referência a campos estáticos ou propriedades de seu próprio código. Por exemplo, aqui está um AppConstants
classe que contém alguns campos estáticos que você talvez queira usar em várias páginas em um aplicativo:
using System;
using Xamarin.Forms;
namespace XamlSamples
{
static class AppConstants
{
public static readonly Thickness PagePadding;
static AppConstants()
{
switch (Device.RuntimePlatform)
{
case Device.iOS:
PagePadding = new Thickness(5, 20, 5, 0);
TitleFont = Font.SystemFontOfSize(35, FontAttributes.Bold);
break;
case Device.Android:
PagePadding = new Thickness(5, 0, 5, 0);
TitleFont = Font.SystemFontOfSize(40, FontAttributes.Bold);
break;
case Device.UWP:
PagePadding = new Thickness(5, 0, 5, 0);
TitleFont = Font.SystemFontOfSize(50, FontAttributes.Bold);
break;
}
}
}
}
Para fazer referência os campos estáticos dessa classe no arquivo XAML, você precisará de uma forma de indicar
dentro do arquivo XAML em que esse arquivo está localizado. Você pode fazer isso com uma declaração de
namespace XML.
Lembre-se de que os arquivos XAML criados como parte do modelo de XAML de xamarin. Forms padrão
contêm duas declarações de namespace XML: um para acesso de classes xamarin. Forms e outro para fazer
referência a marcas e atributos intrínsecos ao XAML:
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
Você precisará de declarações de namespace XML adicionais para acessar outras classes. Cada declaração de
namespace XML adicional define um novo prefixo. Para acessar classes locais para a biblioteca .NET Standard de
aplicativo compartilhado, como AppConstants , os programadores XAML geralmente usam o prefixo local . A
declaração de namespace deve indicar o nome do namespace CLR (Common Language Runtime), também
conhecido como o nome de namespace de .NET, que é o nome que aparece em um C# namespace definição ou
em um using diretiva:
xmlns:local="clr-namespace:XamlSamples"
Você também pode definir as declarações de namespace XML para namespaces do .NET em qualquer assembly
que faz referência a biblioteca .NET Standard. Por exemplo, aqui está uma sys prefixo para o .NET standard
System namespace, que está no mscorlib assembly, que representava uma vez "Microsoft Common Library do
objeto de tempo de execução", mas agora significa "Multilanguage padrão Objeto em tempo de execução
biblioteca comum." Como esse é outro assembly, você deve também especificar o nome do assembly, neste caso
mscorlib:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Observe que a palavra-chave clr-namespace é seguido por dois-pontos e, em seguida, o nome do namespace
.NET, seguido por um ponto e vírgula, a palavra-chave assembly , um sinal de igual e o nome do assembly.
Sim, seguido por dois pontos clr-namespace , mas o sinal de igual segue assembly . A sintaxe foi definida desta
maneira deliberadamente: A maioria das declarações de namespace XML fazem referência a um URI que
começa um nome de esquema URI, como http , que é sempre seguido por dois-pontos. O clr-namespace parte
dessa cadeia de caracteres destina-se para simular que a convenção.
As duas declarações de namespace esses estão incluídas na StaticConstantsPage exemplo. Observe que o
BoxView dimensões são definidas como Math.PI e Math.E , mas em escala por um fator de 100:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="XamlSamples.StaticConstantsPage"
Title="Static Constants Page"
Padding="{x:Static local:AppConstants.PagePadding}">
<StackLayout>
<Label Text="Hello, XAML!"
TextColor="{x:Static local:AppConstants.BackgroundColor}"
BackgroundColor="{x:Static local:AppConstants.ForegroundColor}"
Font="{x:Static local:AppConstants.TitleFont}"
HorizontalOptions="Center" />
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.RelativeLayoutPage"
Title="RelativeLayout Page">
<RelativeLayout>
Talvez a lição mais importante que você deve executar este exemplo é a sintaxe de extensão de marcação: Sem
aspas devem aparecer dentro das chaves de uma extensão de marcação. Ao digitar a extensão de marcação em
um arquivo XAML, é natural deseja colocar os valores das propriedades entre aspas. Resista à tentação!
Aqui está o programa em execução:
Resumo
As extensões de marcação XAML mostradas aqui oferecem suporte importante para arquivos XAML. Mas talvez
seja a extensão de marcação XAML mais valiosa Binding , que será abordado na próxima parte desta série,
parte 4. Noções básicas de vinculação de dados.
Links relacionados
XamlSamples
Parte 1. Introdução ao XAML
Parte 2. Sintaxe essencial de XAML
Parte 4. Conceitos básicos da associação de dados
Parte 5. De associação de dados a MVVM
Parte 4. Noções básicas de vinculação de dados
12/04/2019 • 21 minutes to read
baixar o exemplo
Associações de dados permitem que as propriedades de dois objetos a serem vinculadas para que a alteração
de uma causa uma alteração no outro. Essa é uma ferramenta muito valiosa, e enquanto as associações de
dados podem ser definidas inteiramente no código, XAML fornece atalhos e conveniência. Consequentemente,
uma das extensões de marcação mais importantes no xamarin. Forms é associação.
Associações de dados
Associações de dados se conectar a propriedades de dois objetos, chamados de fonte e o destino. No código,
são necessárias duas etapas: O BindingContext propriedade do objeto de destino deve ser definida para o
objeto de origem e o SetBinding método (geralmente usado em conjunto com o Binding classe) deve ser
chamado no objeto de destino para associar uma propriedade desse objeto para uma propriedade da fonte
objeto.
A propriedade de destino deve ser uma propriedade vinculável, o que significa que o objeto de destino deve
derivar de BindableObject . A documentação do xamarin. Forms online indica quais propriedades são
propriedades associáveis. Uma propriedade de Label , como Text associado com a propriedade associável
TextProperty .
Na marcação, você também deve executar as mesmas duas etapas que são necessárias no código, exceto pelo
fato do Binding extensão de marcação ocupa o lugar do SetBinding chamar e o Binding classe.
No entanto, quando você define vinculações de dados no XAML, há várias maneiras de definir o
BindingContext do objeto de destino. Às vezes, ele é definido do arquivo code-behind, às vezes, usando um
StaticResource ou x:Static extensão de marcação e às vezes, como o conteúdo de BindingContext marcas
de elemento de propriedade.
Associações são usadas com mais frequência para conectar os elementos visuais de um programa com um
modelo de dados subjacente, geralmente em uma realização da arquitetura MVVM (Model-View -ViewModel)
do aplicativo, conforme discutido em parte 5. De associações de dados a MVVM, mas outros cenários são
possíveis.
<StackLayout>
<Label Text="ROTATION"
BindingContext="{x:Reference Name=slider}"
Rotation="{Binding Path=Value}"
FontAttributes="Bold"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="CenterAndExpand" />
O Slider contém uma x:Name atributo que é referenciado pelas duas Label exibições usando o x:Reference
extensão de marcação.
O x:Reference extensão de associação define uma propriedade chamada Name para definir como o nome do
elemento referenciado, nesse caso, slider . No entanto, o ReferenceExtension classe que define o
x:Reference extensão de marcação também define um ContentProperty de atributo para Name , que significa
que não é explicitamente necessário. Apenas para a variedade, a primeira x:Reference inclui "nome =", mas
não o segundo:
BindingContext="{x:Reference Name=slider}"
…
BindingContext="{x:Reference slider}"
O Binding extensão de marcação em si pode ter várias propriedades, assim como o BindingBase e Binding
classe. O ContentProperty para Binding é Path , mas o "caminho =" parte da extensão de marcação pode ser
omitido se o caminho é o primeiro item no Binding extensão de marcação. O exemplo primeiro tem "caminho
=", mas o segundo exemplo omite a ele:
Rotation="{Binding Path=Value}"
…
Text="{Binding Value, StringFormat='The angle is {0:F0} degrees'}"
Text="{Binding Value,
StringFormat='The angle is {0:F0} degrees'}"
O modo de ligação
Uma única exibição pode ter associações de dados em várias de suas propriedades. No entanto, cada modo de
exibição pode ter apenas um BindingContext , portanto, várias associações de dados nessa exibição devem
todas as propriedades do mesmo objeto de referência.
A solução para esse e outros problemas envolve a Mode propriedade, que é definida como um membro do
BindingMode enumeração:
Default
OneWay — valores que são transferidos da origem ao destino
OneWayToSource — valores que são transferidos do destino para a fonte
TwoWay — valores são transferidos ambas as direções entre origem e destino
OneTime — dados vão da fonte para o destino, mas somente quando o BindingContext alterações
O programa a seguir demonstra um uso comum de OneWayToSource e TwoWay modos de ligação. Quatro
Slider modos de exibição destinam -se ao controle de Scale , Rotate , RotateX , e RotateY propriedades de
um Label . A princípio, parece como se essas quatro propriedades do Label deve ser destinos de vinculação
de dados, porque cada um está sendo definida um Slider . No entanto, o BindingContext de Label pode ser
apenas um objeto, e há quatro controles deslizantes diferentes.
Por esse motivo, todas as associações são definidas aparentemente com versões anteriores maneiras: O
BindingContext de cada um dos quatro controles deslizantes é definido como o Label , e as associações são
definidas no Value propriedades dos controles deslizantes. Usando o OneWayToSource e TwoWay modos, essas
Value propriedades podem definir as propriedades da fonte, que são os Scale , Rotate , RotateX , e RotateY
propriedades do Label :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="XamlSamples.SliderTransformsPage"
Padding="5"
Title="Slider Transforms Page">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
As associações em três da Slider modos de exibição são OneWayToSource , o que significa que o Slider valor
faz com que uma alteração na propriedade do seu BindingContext , que é o Label chamado label . Esses três
Slider modos de exibição causam alterações para o Rotate , RotateX , e RotateY propriedades do Label .
No entanto, a associação para o Scale é de propriedade TwoWay . Isso ocorre porque o Scale propriedade
tem um valor padrão de 1 e usando um TwoWay associação faz com que o Slider inicial do valor a ser
definido em 1 em vez de 0. Se essa associação foram OneWayToSource , o Scale propriedade inicialmente seria
definida como 0 do Slider valor padrão. O Label não seria visível e que pode causar alguma confusão ao
usuário.
NOTE
O VisualElement classe também tem ScaleX e ScaleY propriedades, que dimensionarem o VisualElement no
eixo x e y respectivamente.
Associações e coleções
Nada ilustra o poder do XAML e associações de dados melhores do que com um modelo ListView .
ListView define uma ItemsSource propriedade do tipo IEnumerable , e exibe os itens dessa coleção. Esses
itens podem ser objetos de qualquer tipo. Por padrão, ListView usa o ToString método de cada item para
exibir o item. Às vezes, é isso que você deseja, mas em muitos casos, ToString retorna somente o nome de
classe totalmente qualificado do objeto.
No entanto, os itens a ListView coleção pode ser exibida como quiser com o uso de um modelo, que envolve
uma classe que deriva de Cell . O modelo for clonado para todos os itens a ListView , e as associações de
dados que foram definidas no modelo são transferidas para os clones individuais.
Com muita frequência, você desejará criar uma célula personalizada para esses itens usando o ViewCell
classe. Esse processo é um pouco confuso no código, mas no XAML torna-se muito simples.
O XamlSamples projeto há também uma classe chamada NamedColor . Cada NamedColor objeto tem Name e
FriendlyName propriedades do tipo string e um Color propriedade do tipo Color . Além disso, NamedColor
tem 141 campos estáticos somente leitura do tipo Color correspondente para as cores definidas no xamarin.
Forms Color classe. Um construtor estático cria um IEnumerable<NamedColor> coleção que contém NamedColor
objetos correspondentes a esses campos estáticos e o atribui a seu público estático All propriedade.
Configuração estática NamedColor.All propriedade para o ItemsSource de uma ListView é fácil usando o
x:Static extensão de marcação:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
x:Class="XamlSamples.ListViewDemoPage"
Title="ListView Demo Page">
</ContentPage>
Muito melhor. Agora tudo o que precisamos é aprimorar o modelo de item com mais informações e a cor real.
Para dar suporte a esse modelo, alguns valores e os objetos foram definidos no dicionário de recursos da
página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.ListViewDemoPage"
Title="ListView Demo Page">
<ContentPage.Resources>
<ResourceDictionary>
<OnPlatform x:Key="boxSize"
x:TypeArguments="x:Double">
<On Platform="iOS, Android, UWP" Value="50" />
</OnPlatform>
<OnPlatform x:Key="rowHeight"
x:TypeArguments="x:Int32">
<On Platform="iOS, Android, UWP" Value="60" />
</OnPlatform>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Orientation="Horizontal"
Spacing="0">
<Label Text="{Binding Color.R,
Converter={StaticResource intConverter},
ConverterParameter=255,
StringFormat='R={0:X2}'}" />
Observe o uso de OnPlatform para definir o tamanho de um BoxView e a altura do ListView linhas. Embora
os valores para todas as plataformas são os mesmos, a marcação pode facilmente ser adaptada para outros
valores ajustar a exibição.
namespace XamlSamples
{
class DoubleToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, CultureInfo culture)
{
double multiplier;
O ConvertBack método não desempenham um papel nesse programa porque as associações são apenas uma
maneira de origem ao destino.
Uma associação faz referência a um conversor de associação com o Converter propriedade. Um conversor de
associação também pode aceitar um parâmetro especificado com o ConverterParameter propriedade. Para
alguns versatilidade, isso é como o multiplicador é especificado. O conversor de associação verifica se o
parâmetro de conversor para válido double valor.
O conversor é instanciado no dicionário de recursos para que ele possa ser compartilhado entre várias
associações:
Associações de dados de três fazer referência a essa única instância. Observe que o Binding extensão de
marcação contém inserida StaticResource extensão de marcação:
Se as propriedades dos itens em si são alteradas durante o tempo de execução, então os itens na coleção
devem implementar o INotifyPropertyChanged alterações de interface e o sinal para valores de propriedade
usando o PropertyChanged eventos. Isso é demonstrado na próxima parte desta série, parte 5. De associação
de dados a MVVM.
Resumo
Associações de dados fornecem um mecanismo poderoso para vincular as propriedades entre dois objetos
dentro de uma página ou entre objetos visuais e os dados subjacentes. Mas quando o aplicativo começa a
trabalhar com fontes de dados, um padrão de arquitetura de aplicativo populares começa a surgir como um
paradigma úteis. Isso é abordado em parte 5. De associações de dados a MVVM.
Links relacionados
XamlSamples
Parte 1. Introdução ao XAML (amostra)
Parte 2. Sintaxe essencial de XAML (amostra)
Parte 3. Extensões de marcação de XAML (amostra)
Parte 5. De associação de dados a MVVM (amostra)
Parte 5. De associações de dados a MVVM
12/04/2019 • 21 minutes to read
baixar o exemplo
O padrão de arquitetura do Model-View -ViewModel (MVVM ) foi inventado com XAML em mente. O padrão
impõe uma separação entre três camadas de software — a interface do usuário XAML, chamada de exibição;
os dados subjacentes, chamados de modelo; e um intermediário entre o modo de exibição e o modelo,
chamado o ViewModel. O View e ViewModel são frequentemente conectadas por meio de ligações de dados
definidas no arquivo XAML. O BindingContext para o modo de exibição geralmente é uma instância do
ViewModel.
Um ViewModel Simple
Como uma introdução aos ViewModels, vamos primeiro examinar um programa sem uma. Anteriormente,
você viu como definir uma nova declaração de namespace XML para permitir que um arquivo XAML para
classes de referência em outros assemblies. Este é um programa que define uma declaração de namespace
XML para o System namespace:
xmlns:sys="clr-namespace:System;assembly=mscorlib"
O programa pode usar x:Static para obter a data e hora atuais do estático DateTime.Now propriedade e
defina-as DateTime de valor para o BindingContext em um StackLayout :
BindingContext é uma propriedade muito especial: quando você define o BindingContext em um elemento, ela
é herdada por todos os filhos desse elemento. Isso significa que todos os filhos do StackLayout ter esse
mesmo BindingContext , e podem conter associações simples às propriedades desse objeto.
No DateTime One-Shot programa, dois dos filhos contém associações a propriedades desse DateTime valor,
mas dois outros filhos contenham associações que parecem estar faltando um caminho de associação. Isso
significa que o DateTime próprio valor é usado para o StringFormat :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="XamlSamples.OneShotDateTimePage"
Title="One-Shot DateTime Page">
</StackLayout>
</ContentPage>
É claro, o grande problema é que a data e hora são definidos após a criação de quando a página é pela primeira
vez e nunca alteração:
Um arquivo XAML pode exibir um relógio que sempre mostra a hora atual, mas ele precisa de algum código
para ajudar. Ao pensar em termos de MVVM, o Model e ViewModel são classes escritas inteiramente no
código. O modo de exibição geralmente é um arquivo XAML que faz referência a propriedades definidas no
ViewModel por meio de ligações de dados.
Um modelo apropriado é com ignorância de ViewModel e um ViewModel adequado é com ignorância da
exibição. No entanto, com muita frequência um programador personalizam os tipos de dados expostos pelo
ViewModel para os tipos de dados associados a interfaces de usuário específico. Por exemplo, se um modelo de
acessar um banco de dados que contém cadeias de caracteres do caractere de 8 bits ASCII, o ViewModel
precisa converter entre essas cadeias de caracteres para cadeias de caracteres Unicode para acomodar o uso
exclusivo do Unicode na interface do usuário.
Nos exemplos simples do MVVM (como aqueles mostrados aqui), geralmente, não há nenhum modelo e o
padrão envolve apenas um modo de exibição e ViewModel vinculado com associações de dados.
Aqui está um ViewModel para um relógio com apenas uma única propriedade chamada DateTime , mas quais
atualizações que DateTime propriedade cada segundo:
using System;
using System.ComponentModel;
using Xamarin.Forms;
namespace XamlSamples
{
class ClockViewModel : INotifyPropertyChanged
{
DateTime dateTime;
public ClockViewModel()
{
this.DateTime = DateTime.Now;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
this.DateTime = DateTime.Now;
return true;
});
}
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("DateTime"));
}
}
}
get
{
return dateTime;
}
}
}
}
ViewModels geralmente implementa o INotifyPropertyChanged interface, o que significa que a classe dispara
um PropertyChanged evento sempre que uma de suas propriedades é alterada. O mecanismo de ligação de
dados no xamarin. Forms anexa um manipulador a este PropertyChanged eventos para que ele possa ser
notificado quando uma propriedade é alterada e mantenha o destino atualizado com o novo valor.
Um relógio com base nesse ViewModel pode ser tão simple como este:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
x:Class="XamlSamples.ClockPage"
Title="Clock Page">
Observe como o ClockViewModel é definido como o BindingContext da Label usando marcas de elemento de
propriedade. Como alternativa, você pode instanciar a ClockViewModel em um Resources coleção e defini-lo
como o BindingContext por meio de um StaticResource extensão de marcação. Ou então, o arquivo code-
behind pode instanciar o ViewModel.
O Binding extensão de marcação na Text propriedade da Label formatos o DateTime propriedade. Aqui
está a exibição:
MVVM interativo
MVVM é frequentemente usada com ligações de dados bidirecional para uma exibição interativa com base em
um modelo de dados subjacente.
Aqui está uma classe chamada HslViewModel que converte um Color valor na Hue , Saturation ,e Luminosity
valores e vice-versa:
using System;
using System.ComponentModel;
using Xamarin.Forms;
using Xamarin.Forms;
namespace XamlSamples
{
public class HslViewModel : INotifyPropertyChanged
{
double hue, saturation, luminosity;
Color color;
Hue = value.Hue;
Saturation = value.Saturation;
Luminosity = value.Luminosity;
}
}
get
{
return color;
}
}
void SetNewColor()
{
Color = Color.FromHsla(Hue, Saturation, Luminosity);
}
Altera para o Hue , Saturation , e Luminosity propriedades causa o Color propriedade a ser alterada e as
alterações Color faz com que as outras três propriedades alterar. Isso pode parecer um loop infinito, exceto
que a classe não chamar o PropertyChanged evento, a menos que a propriedade realmente foram alterados.
Isso acaba com o loop de comentários caso contrário incontrolável.
Contém o arquivo XAML a seguir um BoxView cujos Color propriedade está associada a Color propriedade
de ViewModel e três Slider e três Label modos de exibição associado ao Hue , Saturation e Luminosity
propriedades:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
x:Class="XamlSamples.HslColorScrollPage"
Title="HSL Color Scroll Page">
<ContentPage.BindingContext>
<local:HslViewModel Color="Aqua" />
</ContentPage.BindingContext>
Com exceção do SearchBar e ListView elemento, esses elementos definem duas propriedades:
Command do tipo System.Windows.Input.ICommand
CommandParameter do tipo Object
O ViewModel pode definir as propriedades de tipo ICommand . Em seguida, você pode associar essas
propriedades para o Command propriedade de cada Button ou outro elemento, ou talvez uma exibição
personalizada que implementa essa interface. Opcionalmente, você pode definir as CommandParameter
propriedade para identificar individuais Button objetos (ou outros elementos) que estão associados a essa
propriedade de ViewModel. Internamente, o Button chamadas a Execute método sempre que o usuário toca
o Button , passando para o Execute método seu CommandParameter .
O CanExecute método e CanExecuteChanged são usados para casos em que um Button tap pode ser válido no
momento, caso em que o Button deve desabilitar em si. O Button chamadas CanExecute quando o Command
propriedade é definida pela primeira vez e sempre que o CanExecuteChanged evento é disparado. Se
CanExecute retorna false , o Button desabilita a mesmo e não gera Execute chamadas.
Para obter ajuda sobre como adicionar comandos aos seus ViewModels, xamarin. Forms define duas classes
que implementam ICommand : Command e Command<T> onde T é o tipo dos argumentos para Execute e
CanExecute . Essas duas classes definem vários construtores além de um ChangeCanExecute método que o
ViewModel pode chamar para forçar o Command objeto para acionar o CanExecuteChanged eventos.
Aqui está um ViewModel para um teclado simple que é destinado para inserir números de telefone. Observe
que o Execute e CanExecute método são definidos como diretamente de funções lambda no construtor:
using System;
using System.ComponentModel;
using System.Windows.Input;
using Xamarin.Forms;
namespace XamlSamples
{
class KeypadViewModel : INotifyPropertyChanged
{
string inputString = "";
string displayText = "";
char[] specialChars = { '*', '#' };
// Constructor
public KeypadViewModel()
{
AddCharCommand = new Command<string>((key) =>
{
// Add the key to the input string.
InputString += key;
});
// Public properties
public string InputString
{
protected set
{
{
if (inputString != value)
{
inputString = value;
OnPropertyChanged("InputString");
DisplayText = FormatText(inputString);
// ICommand implementations
public ICommand AddCharCommand { protected set; get; }
Esse ViewModel supõe que o AddCharCommand propriedade está associada a Command propriedade de vários
botões (ou qualquer outra coisa que tenha uma interface de comando), cada um deles é identificada pelo
CommandParameter . Esses botões adicionam caracteres para um InputString propriedade, que é formatada
como um número de telefone para o DisplayText propriedade.
Também há uma segunda propriedade do tipo ICommand chamado DeleteCharCommand . Isso é associado a um
botão back espaçamento, mas o botão deve ser desabilitado se houver caracteres a serem excluídos.
O teclado a seguir não é tão visualmente sofisticado quanto poderia ser. Em vez disso, a marcação foi reduzida
ao mínimo para demonstrar mais claramente o uso da interface de comando:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples;assembly=XamlSamples"
x:Class="XamlSamples.KeypadPage"
Title="Keypad Page">
<Grid HorizontalOptions="Center"
VerticalOptions="Center">
<Grid.BindingContext>
<local:KeypadViewModel />
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
<ColumnDefinition Width="80" />
</Grid.ColumnDefinitions>
<Frame Grid.Column="0"
OutlineColor="Accent">
<Label Text="{Binding DisplayText}" />
</Frame>
<Button Text="⇦"
Command="{Binding DeleteCharCommand}"
Grid.Column="1"
BorderWidth="0" />
</Grid>
<Button Text="1"
Command="{Binding AddCharCommand}"
CommandParameter="1"
Grid.Row="1" Grid.Column="0" />
<Button Text="2"
Command="{Binding AddCharCommand}"
CommandParameter="2"
Grid.Row="1" Grid.Column="1" />
<Button Text="3"
Command="{Binding AddCharCommand}"
CommandParameter="3"
Grid.Row="1" Grid.Column="2" />
<Button Text="4"
Command="{Binding AddCharCommand}"
CommandParameter="4"
Grid.Row="2" Grid.Column="0" />
<Button Text="5"
Command="{Binding AddCharCommand}"
CommandParameter="5"
Grid.Row="2" Grid.Column="1" />
<Button Text="6"
Command="{Binding AddCharCommand}"
CommandParameter="6"
Grid.Row="2" Grid.Column="2" />
<Button Text="7"
Command="{Binding AddCharCommand}"
CommandParameter="7"
Grid.Row="3" Grid.Column="0" />
<Button Text="8"
Command="{Binding AddCharCommand}"
CommandParameter="8"
Grid.Row="3" Grid.Column="1" />
<Button Text="9"
Command="{Binding AddCharCommand}"
CommandParameter="9"
Grid.Row="3" Grid.Column="2" />
<Button Text="*"
Command="{Binding AddCharCommand}"
CommandParameter="*"
Grid.Row="4" Grid.Column="0" />
<Button Text="0"
Command="{Binding AddCharCommand}"
CommandParameter="0"
Grid.Row="4" Grid.Column="1" />
<Button Text="#"
Command="{Binding AddCharCommand}"
CommandParameter="#"
Grid.Row="4" Grid.Column="2" />
</Grid>
</ContentPage>
O Command propriedade do primeiro Button que aparece neste marcação está associada ao DeleteCharCommand
; o restante são associados ao AddCharCommand com um CommandParameter que é o mesmo como o caractere que
aparece no Button face. Aqui está o programa em ação:
Invocar métodos assíncronos
Comandos também podem invocar métodos assíncronos. Isso é feito usando o async e await palavras-chave
ao especificar o Execute método:
Isso indica que o DownloadAsync método é um Task e deve ser colocada em espera:
void Download ()
{
...
}
static PageDataViewModel()
{
All = new List<PageDataViewModel>
{
// Part 1. Getting Started with XAML
new PageDataViewModel(typeof(HelloXamlPage), "Hello, XAML",
"Display a Label with many properties set"),
O arquivo XAML para MainPage define uma ListBox cuja ItemsSource estiver definida como que All
propriedade e que contém um TextCell para exibir o Title e Description propriedades de cada página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:XamlSamples"
x:Class="XamlSamples.MainPage"
Padding="5, 0"
Title="XAML Samples">
if (args.SelectedItem != null)
{
PageDataViewModel pageData = args.SelectedItem as PageDataViewModel;
Page page = (Page)Activator.CreateInstance(pageData.Type);
await Navigation.PushAsync(page);
}
}
Vídeo
Xamarin Evolve 2016: MVVM simplificada com o xamarin. Forms e Prism
Resumo
XAML é uma ferramenta poderosa para a definição de interfaces do usuário em aplicativos xamarin. Forms,
especialmente quando a associação de dados e MVVM são usados. O resultado é uma representação limpa,
elegante e potencialmente editável de uma interface do usuário com todo o suporte de plano de fundo no
código.
Links relacionados
XamlSamples
Parte 1. Introdução ao XAML
Parte 2. Sintaxe essencial de XAML
Parte 3. Extensões de Marcação XAML
Parte 4. Conceitos básicos da associação de dados
Compilação de XAML no xamarin. Forms
12/04/2019 • 2 minutes to read
Pode ser compilado, opcionalmente, o XAML diretamente em linguagem intermediária (IL ) com o compilador
XAML (XAMLC ).
Compilação de XAML oferece vários benefícios:
Executa verificação de tempo de compilação de XAML, notificando o usuário de quaisquer erros.
Elimina parte da carga e do tempo de instanciação para elementos XAML.
Ajuda a reduzir o tamanho do arquivo do assembly final não incluindo mais arquivos .XAML.
Compilação de XAML está desabilitada por padrão, para garantir a compatibilidade com versões anteriores. Ele
pode ser habilitado no nível de classe e do assembly adicionando a XamlCompilation atributo.
O exemplo de código a seguir demonstra como habilitar compilação de XAML no nível de assembly:
using Xamarin.Forms.Xaml;
...
[assembly: XamlCompilation (XamlCompilationOptions.Compile)]
namespace PhotoApp
{
...
}
Neste exemplo, a verificação de todas as do XAML contido dentro do assembly de tempo de compilação será
executado, com erros XAML que está sendo relatados no tempo de compilação em vez de tempo de execução.
Portanto, o assembly de prefixo para o XamlCompilation atributo especifica que o atributo se aplica a todo o
assembly.
NOTE
O XamlCompilation atributo e o XamlCompilationOptions enumeração residem no Xamarin.Forms.Xaml namespace,
que deve ser importado para usá-los.
O exemplo de código a seguir demonstra como habilitar compilação de XAML no nível da classe:
using Xamarin.Forms.Xaml;
...
[XamlCompilation (XamlCompilationOptions.Compile)]
public class HomePage : ContentPage
{
...
}
Neste exemplo, a verificação de que o XAML para o tempo de compilação a HomePage classe será executado e
erros são relatados como parte do processo de compilação.
NOTE
Associações compiladas podem ser habilitadas para melhorar o desempenho de associação de dados em aplicativos
xamarin. Forms. Para obter mais informações, consulte compilado associações.
Links relacionados
XamlCompilation
XamlCompilationOptions
Caixa de ferramentas do xamarin. Forms XAML
12/04/2019 • 2 minutes to read
Visual Studio 2017 versão 15,8 e o Visual Studio para Mac 7.6 agora tem uma caixa de ferramentas está disponível
ao editar arquivos XAML de xamarin. Forms. A caixa de ferramentas contém todos os controles internos do
xamarin. Forms e layouts, que podem ser arrastados para o editor XAML.
Visual Studio
Visual Studio para Mac
No Visual Studio 2017, abra um arquivo XAML de xamarin. Forms para edição. A caixa de ferramentas pode ser
mostrada, pressionando Ctrl + W, X no teclado, ou escolhendo o Exibir > caixa de ferramentas item de menu.
A caixa de ferramentas pode ser ocultada e encaixada como outros painéis no Visual Studio 2017, usando os
ícones no canto superior direito ou o menu de contexto. A caixa de ferramentas do xamarin. Forms XAML tem
opções de modo de exibição personalizado que podem ser alteradas clicando em cada seção. Ativar/desativar a
exibição de lista opção para alternar entre a lista e modos de exibição compactos:
Quando um arquivo XAML de xamarin. Forms é aberto para edição, arraste qualquer controle ou layout da caixa
de ferramentas para o arquivo e, em seguida, aproveitar o Intellisense para personalizar a interface do usuário.
Pré-visualizador XAML para xamarin. Forms
12/04/2019 • 5 minutes to read
Visão geral
O pré-visualizador XAML mostra qual será a aparência de sua página XAML de xamarin. Forms no iOS e
Android. Quando você faz alterações em seu XAML, você poderá vê-los imediatamente visualizado junto com seu
código. O pré-visualizador XAML está disponível no Visual Studio e Visual Studio para Mac.
Introdução
Visual Studio 2019
Você pode abrir o pré-visualizador XAML clicando nas setas no painel de exibição de divisão. Se você quiser
alterar o padrão dividir o comportamento do modo de exibição, use o Ferramentas > Opções > Xamarin >
formulários pré-visualizador caixa de diálogo. Nesta caixa de diálogo, você pode selecionar o modo de exibição
de documento padrão e a orientação de divisão.
Quando você abre um arquivo XAML, o editor será aberto em tamanho normal ou Avançar para o pré-
visualizador, com base nas configurações selecionadas na Ferramentas > Opções > Xamarin > formulários
pré-visualizador caixa de diálogo. No entanto, a divisão pode ser alterada para cada arquivo na janela do editor.
Controles de visualização do XAML
Escolha se você quiser ver seu código, o pré-visualizador de XAML, ou ambas selecionando esses botões na
divisão de exibir o painel. O botão do meio alterna o que são o pré-visualizador de lado e seu código em:
Você pode alterar se a tela é dividida verticalmente ou horizontalmente, ou recolher um painel completamente:
if (DesignMode.IsDesignModeEnabled)
{
// Previewer only code
}
if (!DesignMode.IsDesignModeEnabled)
{
// Don't run in the Previewer
}
Essa propriedade é útil se você inicializar uma biblioteca em seu construtor de página que não é possível executar
em tempo de design.
Solução de problemas
Verifique os problemas a seguir e o fóruns do Xamarin, se o pré-visualizador não está funcionando.
Pré -visualizador de XAML não estiver visível ou mostrará um erro
Pode levar algum tempo para que o pré-visualizador iniciar - consulte "Inicializando renderizar" até que ele
esteja pronto.
Tente fechar e reabrir o arquivo XAML.
Certifique-se de que seu App classe tem um construtor sem parâmetros.
Verifique a versão do xamarin. Forms - ele deve ser pelo menos 3.6 do xamarin. Forms. Você pode atualizar
para a versão mais recente do xamarin. Forms por meio do NuGet.
Verifique sua instalação do JDK - visualizando Android requer pelo menos JDK 8.
Tente encapsulamento qualquer inicializado classes na página de C# código por trás
if (!DesignMode.IsDesignModeEnabled) .
Alguns layouts são difíceis de visualizar sem dados. Use estas dicas para fazer o máximo proveito de visualização
de suas páginas com uso intenso de dados no Visualizador de XAML.
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Depois de adicionar os namespaces, você pode colocar d: na frente de qualquer atributo ou o controle para
mostrá-lo no Visualizador de XAML. Elementos com d: não são mostrados em tempo de execução.
Por exemplo, você pode adicionar texto a um rótulo que geralmente tem dados associados a ele.
Neste exemplo, sem d:Text , pré-visualizador XAML mostraria nada para o rótulo. Em vez disso, ele mostra
"Name" no qual o rótulo terá dados reais no tempo de execução.
Você pode usar d: com qualquer atributo para um controle xamarin. Forms, como cores, tamanhos de fonte e
espaçamento. Você pode até mesmo adicioná-lo ao próprio controle:
<StackLayout>
<ListView ItemsSource="{Binding Items}">
<d:ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Item One</x:String>
<x:String>Item Two</x:String>
<x:String>Item Three</x:String>
</x:Array>
</d:ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding ItemName}"
d:Text="{Binding .}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
Este exemplo mostrará um ListView de três TextCells no pré-visualizador XAML. Você pode alterar x:String para
um modelo de dados existente em seu projeto.
Consulte a aplicativo de Hanselman.Forms de James Montemagno para obter um exemplo mais complexo.
Solução de problemas
Requisitos
Dados de tempo de design requer uma versão mínima do xamarin. Forms 3.6.
O IntelliSense mostra linhas onduladas sob os meus dados de tempo de design
Isso é um problema conhecido e será corrigido em uma versão futura do Visual Studio. O projeto ainda será
compilado sem erros.
O pré -visualizador XAML parou de funcionar
Tente fechar e reabrir o arquivo XAML e a limpeza e recriar o projeto.
Renderizar controles personalizados no pré-
visualizador XAML
12/04/2019 • 3 minutes to read
Controles personalizados às vezes, não funcionam conforme o esperado no pré-visualizador XAML. Use as
diretrizes neste artigo para entender as limitações de visualização de seus controles personalizados.
namespace MyProject
{
[DesignTimeVisible(true)]
public class MyControl : BaseControl
{
// Your control's code here
}
Controles de SkiaSharp
Atualmente, os controles de SkiaSharp só têm suporte quando você está visualizando no iOS. Eles não serão
renderizadas na visualização do Android.
Solução de problemas
Verifique a versão do xamarin. Forms
Verifique se você tem pelo menos 3.6 do xamarin. Forms instalado. Você pode atualizar sua versão do xamarin.
Forms no NuGet.
Mesmo com [DesignTimeVisible(true)] , meu controle personalizado não estiver renderizando corretamente.
Controles personalizados que dependem muito do code-behind ou back-end de dados sempre não funcionam no
pré-visualizador XAML. Você pode tentar:
Movendo o controle para que ele não inicializar se o modo de design está habilitado
Configurando dados de tempo de design para mostrar dados fictícios de back-end
O pré -visualizador XAML mostra o erro "Controles personalizados não renderizar corretamente"
Tente limpar e recriar o projeto, ou fechar e reabrir o arquivo XAML.
Namespaces XAML no xamarin. Forms
12/04/2019 • 8 minutes to read
XAML usa o atributo xmlns XML para declarações de namespace. Este artigo apresenta a sintaxe do namespace
XAML e demonstra como declarar um namespace XAML para um tipo de acesso.
Visão geral
Há duas declarações de namespace XAML que sempre estão dentro do elemento raiz de um arquivo XAML. A
primeira define o namespace padrão, conforme mostrado no exemplo de código XAML a seguir:
xmlns="http://xamarin.com/schemas/2014/forms"
O namespace padrão especifica que elementos definidos no arquivo XAML sem prefixo se referem às classes do
xamarin. Forms, tal como ContentPage .
A segunda declaração de namespace usa o x prefixo, conforme mostrado no exemplo de código XAML a seguir:
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
XAML usa prefixos de declarar namespaces não-padrão, com o prefixo que está sendo usado ao fazer referência
a tipos no namespace. O x declaração de namespace Especifica que os elementos definidos dentro do XAML
com um prefixo de x são usados para elementos e atributos que são intrínsecos para XAML (especificamente, a
especificação de XAML de 2009).
A tabela a seguir descreve o x atributos de namespace com suporte de xamarin. Forms:
CONSTRUCTO DESCRIÇÃO
Para obter mais informações sobre o x:DataType atributo, consulte compilado associações. Para obter mais
informações sobre o x:FieldModifier atributo, consulte modificadores de campo. Para obter mais informações
sobre o x:Arguments , x:FactoryMethod , e x:TypeArguments atributos, consulte passando argumentos em XAML.
NOTE
Além dos atributos de namespace listados acima, o xamarin. Forms também inclui extensões de marcação que podem ser
consumidas por meio de x prefixo de namespace. Para obter mais informações, consulte extensões de marcação XAML
consumindo.
No XAML, as declarações de namespace herdam de elemento pai para o elemento filho. Portanto, ao definir um
namespace no elemento raiz de um arquivo XAML, todos os elementos dentro desse arquivo herdam a
declaração de namespace.
O local prefixo é uma convenção usada para indicar que os tipos no namespace são locais para o aplicativo.
Como alternativa, se os tipos estão em um assembly diferente, o nome do assembly deve também ser definido
na declaração de namespace, conforme demonstrado no exemplo de código XAML a seguir:
<ListView ...>
<ListView.Behaviors>
<behaviors:EventToCommandBehavior EventName="ItemSelected" ... />
</ListView.Behaviors>
</ListView>
Para obter informações sobre como definir um esquema personalizado de namespace, consulte esquemas
personalizados de Namespace XAML.
Resumo
Este artigo introduziu a sintaxe do namespace XAML e demonstrou como declarar um namespace XAML para
um tipo de acesso. XAML usa a xmlns atributo XML para tipos e declarações de namespace pode ser
referenciado em XAML, declarando um namespace XAML com um prefixo.
Links relacionados
Passando argumentos em XAML
Esquemas de personalizado de Namespace XAML
no xamarin. Forms
12/04/2019 • 6 minutes to read
Baixar o exemplo
Tipos em uma biblioteca podem ser referenciados em XAML, declarando um namespace XAML para a biblioteca,
com a declaração de namespace, especificando o nome do namespace de Common Language Runtime (CLR ) e
um nome de assembly:
<ContentPage ...
xmlns:controls="clr-namespace:MyCompany.Controls;assembly="MyCompany.Controls">
...
</ContentPage>
No entanto, especificando um nome de namespace e assembly do CLR em um xmlns definição pode ser
complicada e sujeito a erros. Além disso, várias declarações de namespace XAML podem ser necessárias se a
biblioteca contém tipos em vários namespaces.
Uma abordagem alternativa é definir um esquema personalizado de namespace, tal como
http://mycompany.com/schemas/controls , que é mapeado para um ou mais namespaces CLR. Isso permite que uma
única declaração de namespace XAML fazer referência a todos os tipos em um assembly, mesmo se eles estão em
namespaces diferentes. Ele também permite que uma única declaração de namespace XAML para tipos de
referência em vários assemblies.
Para obter mais informações sobre namespaces XAML, consulte Namespaces de XAML no xamarin. Forms.
using Xamarin.Forms;
namespace MyCompany.Controls
{
public class CircleButton : Button
{
...
}
}
Todos os controles na biblioteca residem no MyCompany.Controls namespace. Esses controles podem ser expostos
a um assembly de chamada por meio de um esquema personalizado de namespace.
Um esquema personalizado de namespace é definido com o XmlnsDefinitionAttribute classe, que especifica o
mapeamento entre um namespace XAML e um ou mais namespaces CLR. O XmlnsDefinitionAttribute leva dois
argumentos: o nome do namespace XAML e o nome do namespace CLR. O nome do namespace XAML é
armazenado na XmlnsDefinitionAttribute.XmlNamespace propriedade e o nome do namespace CLR é armazenada
no XmlnsDefinitionAttribute.ClrNamespace propriedade.
NOTE
O XmlnsDefinitionAttribute classe também tem uma propriedade chamada AssemblyName , que pode ser definido
opcionalmente para o nome do assembly. Isso só é necessário quando um namespace CLR referenciado de um
XmlnsDefinitionAttribute está em um assembly externo.
O XmlnsDefinitionAttribute deve ser definida no nível de assembly no projeto que contém os namespaces CLR
que serão mapeados no esquema do namespace personalizado. A exemplo a seguir mostra a AssemblyInfo.cs
arquivo do aplicativo de exemplo:
using Xamarin.Forms;
using MyCompany.Controls;
[assembly: Preserve]
[assembly: XmlnsDefinition("http://mycompany.com/schemas/controls", "MyCompany.Controls")]
IMPORTANT
O Preserve atributo deve ser aplicado a classes no assembly que são mapeadas por meio do esquema do namespace
personalizado ou aplicado ao assembly inteiro.
O esquema do namespace personalizado, em seguida, pode ser usado para resolução de tipo nos arquivos XAML.
namespace MyCompany.Controls
{
public static class Controls
{
public static void Init()
{
}
}
}
O Init método, em seguida, pode ser chamado do assembly que consome os tipos do esquema do namespace
personalizado:
using Xamarin.Forms;
using MyCompany.Controls;
namespace CustomNamespaceSchemaDemo
{
public partial class MainPage : ContentPage
{
public MainPage()
{
Controls.Init();
InitializeComponent();
}
}
}
WARNING
Falha ao incluir uma referência de código desse tipo resultará no compilador XAML sendo não é possível localizar o assembly
que contém os tipos de esquema do namespace personalizado.
Para consumir o CircleButton controle, um namespace XAML é declarado, com a declaração de namespace,
especificando a URL de esquema do namespace personalizado:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="http://mycompany.com/schemas/controls"
x:Class="CustomNamespaceSchemaDemo.MainPage">
<StackLayout Margin="20,35,20,20">
...
<controls:CircleButton Text="+"
BackgroundColor="Fuchsia"
BorderColor="Black"
CircleDiameter="100" />
<controls:CircleButton Text="-"
BackgroundColor="Teal"
BorderColor="Silver"
CircleDiameter="70" />
...
</StackLayout>
</ContentPage>
CircleButton instâncias, em seguida, podem ser adicionadas para o ContentPage declarando-os com o controls
prefixo de namespace.
Para localizar o namespace personalizado os tipos de esquema, o xamarin. Forms pesquisará os assemblies
referenciados para XmlnsDefinitionAttribute instâncias. Se o xmlns corresponde ao atributo de um elemento em
um arquivo XAML a XmlNamespace valor da propriedade em um XmlnsDefinitionAttribute , xamarin. Forms
tentará usar o XmlnsDefinitionAttribute.ClrNamespace para a resolução do tipo de valor da propriedade. Se a
resolução de tipo falhar, xamarin. Forms continuará a tentar a resolução de tipo com base em qualquer
correspondência adicionais XmlnsDefinitionAttribute instâncias.
O resultado é que dois CircleButton instâncias são exibidas:
Links relacionados
Esquemas personalizados de Namespace (amostra)
Recomendado prefixos de Namespace XAML
Namespaces XAML no xamarin. Forms
Namespace XAML recomendado prefixos no
xamarin. Forms
12/04/2019 • 2 minutes to read
O XmlnsPrefixAttribute classe pode ser usada por autores de controle para especificar um prefixo recomendado a
ser associado a um namespace XAML, para uso do XAML. O prefixo é útil quando o suporte à serialização de
árvore de objeto para XAML, ou ao interagir com um ambiente de design que tenha recursos de edição de XAML.
Por exemplo:
Editores de texto XAML pode usar o XmlnsPrefixAttribute como uma dica para um namespace XAML inicial
xmlns mapeamento.
Ambientes de design XAML pode usar o XmlnsPrefixAttribute para adição de mapeamentos para o XAML ao
arrastar objetos para fora de uma caixa de ferramentas e em uma superfície de design visual.
Recomendado prefixos de namespace devem ser definidos no nível de assembly com o XmlnsPrefixAttribute
construtor, que leva dois argumentos: uma cadeia de caracteres que especifica o identificador de um namespace
XAML e uma cadeia de caracteres que especifica um prefixo recomendado:
Prefixos devem usar cadeias de caracteres curtas, porque, normalmente, o prefixo é aplicado a todos os elementos
serializados que vêm do namespace XAML. Portanto, o comprimento da cadeia de caracteres de prefixo pode ter
um efeito notável no tamanho da saída XAML serializado.
NOTE
Mais de um XmlnsPrefixAttribute pode ser aplicado a um assembly. Por exemplo, se você tiver um assembly que define
os tipos para mais de um namespace XAML, você pode definir valores de prefixo diferente para cada namespace XAML.
Links relacionados
Esquemas Personalizados de Namespace de XAML
Namespaces XAML no xamarin. Forms
Extensões de marcação XAML
12/04/2019 • 2 minutes to read
baixar o exemplo
Extensões de marcação XAML ajudam a estender o poder e flexibilidade do XAML, permitindo que os atributos do
elemento a ser definido de fontes diferentes cadeias de caracteres de texto literal.
Por exemplo, normalmente você defina as Color propriedade de BoxView semelhante a esta:
Em ambos os casos, a cadeia de caracteres de texto é definida como o Color atributo será convertido em um
Color valor pela ColorTypeConverter classe.
Talvez você prefira em vez disso, defina as Color de um valor armazenado em um dicionário de recurso, ou o
valor de uma propriedade estática de uma classe que você criou ou uma propriedade de tipo de atributo Color de
outro elemento na página, ou construídos a partir de Separe os valores de matiz, saturação e luminosidade.
Todas essas opções são possíveis usando extensões de marcação XAML. Mas não deixe que a frase "extensões de
marcação" assustam você: extensões de marcação XAML são não extensões para XML. Mesmo com extensões de
marcação XAML, o XAML é sempre XML legal.
Uma extensão de marcação é realmente apenas uma maneira diferente para expressar um atributo de um
elemento. Extensões de marcação XAML são geralmente identificadas por uma configuração de atributo que é
colocada entre chaves:
Qualquer configuração de atributo entre chaves é sempre uma extensão de marcação XAML. No entanto, como
você verá, extensões de marcação XAML também podem ser referenciadas sem o uso de chaves.
Este artigo está dividido em duas partes:
Links relacionados
Extensões de marcação (amostra)
Capítulo de extensões de marcação XAML do xamarin. Forms book
Dicionários de recurso
Estilos dinâmicos
Associação de dados
Consumo de extensões de marcação XAML
12/04/2019 • 27 minutes to read
baixar o exemplo
Extensões de marcação XAML ajudar a aprimorar o poder e flexibilidade do XAML, permitindo que os atributos
do elemento a ser definido de uma variedade de fontes. Várias extensões de marcação XAML são parte da
especificação do XAML 2009. Eles aparecem nos arquivos XAML com o habitual x prefixo de namespace e são
normalmente chamados para com esse prefixo. Este artigo discute as extensões de marcação a seguir:
x:Static – fazer referência a propriedades estáticas, campos ou membros de enumeração.
x:Reference – chamada elementos na página de referência.
x:Type – definir um atributo para um System.Type objeto.
x:Array – construir uma matriz de objetos de um tipo específico.
x:Null – definir um atributo para um null valor.
OnPlatform – Personalizar a aparência da interface do usuário em uma base por plataforma.
OnIdiom – Personalizar a aparência da interface do usuário com base no idioma do dispositivo em que o
aplicativo está sendo executado.
Extensões de marcação XAML adicionais historicamente são suportadas pelas outras implementações de XAML e
também são suportadas pelo xamarin. Forms. Elas são descritas mais detalhadamente em outros artigos:
StaticResource – fazer referência a objetos de um dicionário de recursos, conforme descrito no artigo
dicionários de recursos.
DynamicResource – responder a alterações em objetos em um dicionário de recursos, conforme descrito no
artigo estilos dinâmicos.
Binding – estabelecer um vínculo entre as propriedades de dois objetos, conforme descrito no artigo
associação de dados.
TemplateBinding – executa a associação de dados de um modelo de controle, conforme discutido no artigo de
um modelo de controle de associação.
O RelativeLayout layout faz uso da extensão de marcação personalizada ConstraintExpression . Esta extensão de
marcação é descrita no artigo RelativeLayout.
O demonstração X:Static página demonstra várias maneiras de usar o x:Static extensão de marcação. A
abordagem mais detalhada cria uma instância de StaticExtension classe entre Label.FontSize marcas de
elemento de propriedade:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.StaticDemoPage"
Title="x:Static Demo">
<StackLayout Margin="10, 0">
<Label Text="Label No. 1">
<Label.FontSize>
<x:StaticExtension Member="local:AppConstants.NormalFontSize" />
</Label.FontSize>
</Label>
···
</StackLayout>
</ContentPage>
O analisador XAML também permite que o StaticExtension classe deverá ser abreviado como x:Static :
Isso pode ser simplificado ainda mais, mas a alteração apresenta algumas novas sintaxes: Ele consiste em colocar
o StaticExtension classe e o membro definição entre chaves. A expressão resultante é definida diretamente para
o FontSize atributo:
Observe que há nenhum aspas dentro das chaves. O Member propriedade de StaticExtension não é mais um
atributo XML. Em vez disso, ele é parte da expressão para a extensão de marcação.
Assim como você pode abreviar x:StaticExtension para x:Static quando você usá-lo como um elemento de
objeto, você também pode abreviá-lo na expressão entre chaves:
O StaticExtension classe tem um ContentProperty referenciar a propriedade de atributo Member , que marca essa
propriedade como propriedade de conteúdo de padrão da classe. Para extensões de marcação XAML expressadas
com chaves, você pode eliminar o Member= faz parte da expressão:
Isso permite que o Label tamanho da fonte a ser definido para o campo estático Math.PI . Que resulta em texto
em vez disso, pequeno, portanto, o Scale estiver definida como Math.E :
O exemplo final exibe o Device.RuntimePlatform valor. O Environment.NewLine propriedade estática é usada para
inserir um caractere de nova linha entre os dois Span objetos:
<Label HorizontalTextAlignment="Center"
FontSize="{x:Static local:AppConstants.NormalFontSize}">
<Label.FormattedText>
<FormattedString>
<Span Text="Runtime Platform: " />
<Span Text="{x:Static sys:Environment.NewLine}" />
<Span Text="{x:Static Device.RuntimePlatform}" />
</FormattedString>
</Label.FormattedText>
</Label>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.ReferenceDemoPage"
x:Name="page"
Title="x:Reference Demo">
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="Center" />
</StackLayout>
</ContentPage>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.MainPage"
Title="Markup Extensions"
Padding="10">
<TableView Intent="Menu">
<TableRoot>
<TableSection>
<TextCell Text="x:Static Demo"
Detail="Access constants or statics"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:StaticDemoPage}" />
···
</TableRoot>
</TableView>
</ContentPage>
BindingContext = this;
}
O NavigateCommand propriedade é um Command objeto que implementa um comando execute com um argumento
do tipo Type — o valor de CommandParameter . Usa o método Activator.CreateInstance para instanciar a página e,
em seguida, navega até ela. O construtor é concluído, definindo o BindingContext da página para si mesmo, que
permite que o Binding em Command funcione. Consulte a associação de dados artigo e principalmente o
Commanding artigo para obter mais detalhes sobre esse tipo de código.
O demonstração X:Type página usa uma técnica semelhante para instanciar os elementos de xamarin. Forms e
adicioná-los para um StackLayout . O arquivo XAML inicialmente consiste em três Button elementos com seus
Command as propriedades definidas para um Binding e o CommandParameter propriedades definidas como tipos de
três modos de exibição do xamarin. Forms:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.TypeDemoPage"
Title="x:Type Demo">
<StackLayout x:Name="stackLayout"
Padding="10, 0">
BindingContext = this;
}
O método que é executado quando um Button é pressionado cria uma nova instância do argumento, define sua
VerticalOptions propriedade e adiciona-o para o StackLayout . Os três Button elementos, em seguida,
compartilhem a página com modos de exibição criados dinamicamente:
Extensão de marcação x:Array
O x:Arrayextensão de marcação permite que você defina uma matriz na marcação. Ele dá suporte a
ArrayExtension classe, que define duas propriedades:
O x:Array extensão de marcação em si nunca aparece entre chaves. Em vez disso, x:Array marcas de início e
término delimitam a lista de itens. Defina as Type propriedade para um x:Type extensão de marcação.
O demonstração X:array página mostra como usar x:Array para adicionar itens a um ListView definindo o
ItemsSource propriedade para uma matriz:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MarkupExtensions.ArrayDemoPage"
Title="x:Array Demo Page">
<ListView Margin="10">
<ListView.ItemsSource>
<x:Array Type="{x:Type Color}">
<Color>Aqua</Color>
<Color>Black</Color>
<Color>Blue</Color>
<Color>Fuchsia</Color>
<Color>Gray</Color>
<Color>Green</Color>
<Color>Lime</Color>
<Color>Maroon</Color>
<Color>Navy</Color>
<Color>Olive</Color>
<Color>Pink</Color>
<Color>Purple</Color>
<Color>Red</Color>
<Color>Silver</Color>
<Color>Teal</Color>
<Color>White</Color>
<Color>Yellow</Color>
</x:Array>
</ListView.ItemsSource>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<BoxView Color="{Binding}"
Margin="3" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
Há várias maneiras para especificar o indivíduo Color itens nessa matriz. Você pode usar um x:Static extensão
de marcação:
<x:Static Member="Color.Blue" />
Ou, você pode usar StaticResource para recuperar uma cor de um dicionário de recursos:
No final deste artigo, você verá uma extensão de marcação XAML personalizada que também cria um novo valor
de cor:
Ao definir matrizes de tipos comuns, como cadeias de caracteres ou números, use as marcas listadas na passar
argumentos de construtor artigo para delimitar os valores.
<ContentPage.Content>
<StackLayout Padding="10, 0">
<Label Text="Text 1" />
<Label Text="Text 2" />
Em seguida, você descobre que, para uma da Label elementos, você deseja que todas as configurações de
propriedade na implícito Style , exceto para o FontFamily , que você deseja ser o valor padrão. Você pode definir
outra Style para essa finalidade, mas uma abordagem mais simples é simplesmente definir o FontFamily
propriedade de determinada Label ao x:Null , conforme demonstrado no Centro de Label .
Aqui está o programa em execução:
Observe que quatro dos Label elementos têm uma fonte com serifa, mas o centro Label tem a fonte sem serifa
padrão.
Extensão de marcação OnPlatform
O OnPlatform extensão de marcação permite que você personalize a aparência da interface do usuário em uma
base por plataforma. Ele fornece a mesma funcionalidade que o OnPlatform e On classes, mas com uma
representação mais concisa.
O OnPlatform extensão de marcação dá suporte a OnPlatformExtension classe, que define as propriedades a
seguir:
Default do tipo object , que você defina como um valor padrão a ser aplicado às propriedades que
representam as plataformas.
Android do tipo object , que é definido como um valor a ser aplicado no Android.
GTK do tipo object , que é definido como um valor a ser aplicado em plataformas GTK.
iOS do tipo object , que é definido como um valor a ser aplicado no iOS.
macOS do tipo object , que é definido como um valor a ser aplicado no macOS.
Tizen do tipo object , que é definido como um valor a ser aplicado na plataforma Tizen.
UWP do tipo object , que é definido como um valor a ser aplicado na plataforma Universal do Windows.
WPF do tipo object , que é definido como um valor a ser aplicado na plataforma Windows Presentation
Foundation.
Converter do tipo IValueConverter , que podem ser definidas um IValueConverter implementação.
ConverterParameter do tipo object , que é definido como um valor para passar para o IValueConverter
implementação.
NOTE
O analisador XAML permite que o OnPlatformExtension classe deverá ser abreviado como OnPlatform .
IMPORTANT
O analisador XAML espera que os valores do tipo correto serão fornecidos às propriedades consumindo o OnPlatform
extensão de marcação. Se a conversão de tipo for necessário, o OnPlatform extensão de marcação tentará executá-lo
usando os conversores de padrão fornecidos pelo xamarin. Forms. No entanto, há algumas conversões de tipo não podem
ser executadas pelos conversores padrão e nesses casos o Converter propriedade deve ser definida como um
IValueConverter implementação.
Neste exemplo, todos os três OnPlatform expressões usam a versão abreviada do OnPlatformExtension nome de
classe. Os três OnPlatform conjunto de extensões de marcação a Color , WidthRequest , e HeightRequest
propriedades do BoxView como valores diferentes em iOS, Android e UWP. As extensões de marcação também
fornecem valores padrão para essas propriedades nas plataformas que não forem especificadas, eliminando o
Default= faz parte da expressão. Observe que as propriedades de extensão de marcação que são definidas são
separadas por vírgulas.
Aqui está o programa em execução:
NOTE
O analisador XAML permite que o OnIdiomExtension classe deverá ser abreviado como OnIdiom .
Neste exemplo, todos os três OnIdiom expressões usam a versão abreviada do OnIdiomExtension nome de classe.
Os três OnIdiom conjunto de extensões de marcação a Color , WidthRequest , e HeightRequest propriedades do
BoxView como valores diferentes em telefone, tablet e expressões da área de trabalho. As extensões de marcação
também fornecem valores padrão para essas propriedades em que as linguagens que não forem especificadas,
eliminando o Default= faz parte da expressão. Observe que as propriedades de extensão de marcação que são
definidas são separadas por vírgulas.
Aqui está o programa em execução:
Links relacionados
Extensões de marcação (amostra)
Capítulo de extensões de marcação XAML do xamarin. Forms book
Dicionários de recurso
Estilos dinâmicos
Associação de dados
Criando extensões de marcação XAML
12/04/2019 • 10 minutes to read
baixar o exemplo
No nível de programação, uma extensão de marcação XAML é uma classe que implementa o IMarkupExtension
ou IMarkupExtension<T> interface. Você pode explorar o código-fonte das extensões de marcação padrão descrito
abaixo na MarkupExtensions diretório do repositório GitHub do xamarin. Forms.
Também é possível definir suas próprias extensões de marcação XAML personalizados derivando
IMarkupExtension ou IMarkupExtension<T> . Use o formulário genérico se a extensão de marcação obtém um valor
de um tipo específico. Esse é o caso com várias das extensões de marcação do xamarin. Forms:
TypeExtension deriva de IMarkupExtension<Type>
ArrayExtension deriva de IMarkupExtension<Array>
DynamicResourceExtension deriva de IMarkupExtension<DynamicResource>
BindingExtension deriva de IMarkupExtension<BindingBase>
ConstraintExpression deriva de IMarkupExtension<Constraint>
Os dois IMarkupExtension interfaces definir apenas um método de cada um, chamado ProvideValue :
Uma vez que IMarkupExtension<T> deriva IMarkupExtension e inclui o new palavra-chave na ProvideValue ,
contém os ProvideValue métodos.
Com muita frequência, extensões de marcação XAML definem propriedades que contribuem para o valor de
retorno. (É a óbvia exceção NullExtension , no qual ProvideValue simplesmente retorna null .) O ProvideValue
método tem um único argumento do tipo IServiceProvider que será discutido neste artigo.
Porque IMarkupExtension<T> deriva IMarkupExtension , a classe deve conter dois ProvideValue métodos, que
retorna Color e outro que retorna object , mas o segundo método pode simplesmente chamar o primeiro
método.
O demonstração de cor HSL página mostra uma variedade de formas HslColorExtension pode aparecer em um
arquivo XAML para especificar a cor de um BoxView :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.HslColorDemoPage"
Title="HSL Color Demo">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="BoxView">
<Setter Property="WidthRequest" Value="80" />
<Setter Property="HeightRequest" Value="80" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<BoxView>
<BoxView.Color>
<local:HslColorExtension H="0" S="1" L="0.5" A="1" />
</BoxView.Color>
</BoxView>
<BoxView>
<BoxView.Color>
<local:HslColor H="0.33" S="1" L="0.5" />
</BoxView.Color>
</BoxView>
Observe que, quando HslColorExtension é uma marca XML, as quatro propriedades são definidas como atributos,
mas quando ela aparecer entre chaves, as quatro propriedades são separadas por vírgulas sem aspas. Os valores
padrão para H , S , e L são 0 e o valor padrão de A é 1, portanto, essas propriedades podem ser omitidas se
você deseja que eles são definidos como valores padrão. O último exemplo mostra um exemplo onde a
luminosidade é 0, que normalmente resulta em preto, mas o canal alfa é 0,5, para que ele é parcialmente
transparente e aparece cinza o plano de fundo branca da página:
Uma extensão de marcação para acessar os Bitmaps
O argumento ProvideValue é um objeto que implementa o IServiceProvider interface, que é definida no .NET
System namespace. Essa interface tem um membro, um método chamado GetService com um Type argumento.
O ImageResourceExtension classe mostrado a seguir mostra um uso possível dos IServiceProvider e GetService
para obter um IXmlLineInfoProvider objeto que pode fornecer informações de linha e o caractere que indica onde
um determinado erro foi detectado. Nesse caso, uma exceção é gerada quando o Source propriedade não foi
definida:
[ContentProperty("Source")]
class ImageResourceExtension : IMarkupExtension<ImageSource>
{
public string Source { set; get; }
ImageResourceExtension é útil quando um arquivo XAML precisa acessar um arquivo de imagem armazenado
como um recurso incorporado no projeto da biblioteca .NET Standard. Ele usa o Source propriedade para chamar
estático ImageSource.FromResource método. Esse método requer um nome de recurso totalmente qualificado, que
consiste o nome do assembly, o nome da pasta e o nome do arquivo separados por pontos. O segundo
argumento para o ImageSource.FromResource método fornece o nome do assembly e só é necessária para
compilações de versão na UWP. Independentemente disso, ImageSource.FromResource deve ser chamado a partir
do assembly que contém o bitmap, o que significa que essa extensão de recurso XAML não pode ser parte de
uma biblioteca externa, a menos que as imagens também são nessa biblioteca. (Consulte a imagens inseridas
artigo para obter mais informações sobre como acessar os bitmaps armazenados como recursos incorporados.)
Embora ImageResourceExtension exige as Source propriedade seja definida, o Source propriedade é indicada em
um atributo, como a propriedade de conteúdo da classe. Isso significa que o Source= parte da expressão entre
chaves pode ser omitido. No demonstração do recurso de imagem página, o Image elementos buscar duas
imagens usando o nome de pasta e o nome do arquivo separados por pontos:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MarkupExtensions"
x:Class="MarkupExtensions.ImageResourceDemoPage"
Title="Image Resource Demo">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
</Grid>
</ContentPage>
Provedores de serviço
Usando o IServiceProvider argumento para ProvideValue , extensões de marcação XAML podem obter acesso a
informações úteis sobre o arquivo XAML no qual eles estão sendo usados. Mas, para usar o IServiceProvider
argumento com êxito, você precisa saber que tipo de serviços estão disponíveis em contextos específicos. A
melhor maneira de entender esse recurso está estudando o código-fonte das extensões de marcação XAML
existentes na MarkupExtensions pasta no repositório do xamarin. Forms no GitHub. Lembre-se de que alguns
tipos de serviços são internos ao xamarin. Forms.
Em algumas extensões de marcação XAML, esse serviço pode ser útil:
Conclusão
Extensões de marcação XAML desempenham um papel vital em XAML ao estender a capacidade de definir os
atributos de uma variedade de fontes. Além disso, se as extensões de marcação XAML existentes não fornecerem
exatamente o que você precisa, você também pode escrever seus próprios.
Links relacionados
Extensões de marcação (amostra)
Capítulo de extensões de marcação XAML do xamarin. Forms book
Modificadores de campo XAML no xamarin. Forms
12/04/2019 • 2 minutes to read
O x:FieldModifier atributo namespace Especifica o nível de acesso para campos gerados para elementos XAML
nomeados.
Visão geral
Os valores válidos do atributo são:
Public – Especifica que o campo gerado para o elemento XAML public .
NotPublic – Especifica que o campo gerado para o elemento XAML internal ao assembly.
Se o valor do atributo não está definido, o campo gerado para o elemento será private .
As seguintes condições devem ser atendidas para uma x:FieldModifier atributo a ser processado:
O elemento de nível superior XAML deve ser um válido x:Class .
O elemento atual XAML tem um x:Name especificado.
O XAML a seguir mostra exemplos de configuração do atributo:
NOTE
O x:FieldModifier atributo não pode ser usado para especificar o nível de acesso de uma classe XAML.
Passando argumentos em XAML
12/04/2019 • 6 minutes to read
baixar o exemplo
Este artigo demonstra como usar os atributos XAML que podem ser usados para passar argumentos para o
construtor não padrão, para chamar métodos de fábrica e para especificar o tipo de um argumento genérico.
Visão geral
Ele geralmente é necessário instanciar objetos com construtores que requerem argumentos, ou chamando um
método de criação estáticos. Isso pode ser obtido em XAML usando o x:Arguments e x:FactoryMethod atributos:
O x:Arguments atributo é usado para especificar argumentos de construtor para um construtor não padrão ou
para uma declaração de objeto do método de fábrica. Para obter mais informações, consulte passar
argumentos de construtor.
O x:FactoryMethod atributo é usado para especificar um método de fábrica que pode ser usado para inicializar
um objeto. Para obter mais informações, consulte chamando métodos de fábrica.
Além disso, o x:TypeArguments atributo pode ser usado para especificar os argumentos de tipo genérico para o
construtor de um tipo genérico. Para obter mais informações, consulte especificando um argumento de tipo
genérico.
O exemplo de código a seguir demonstra como usar o x:Arguments atributo com três Color construtores:
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>0.9</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>0.25</x:Double>
<x:Double>0.5</x:Double>
<x:Double>0.75</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color>
<x:Arguments>
<x:Double>0.8</x:Double>
<x:Double>0.5</x:Double>
<x:Double>0.2</x:Double>
<x:Double>0.5</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
O número de elementos dentro de x:Arguments marca e os tipos desses elementos devem corresponder a um
dos Color construtores. O Color construtor com um único parâmetro requer um valor de escala de cinza de 0
(preto) a 1 (branco). O Color construtor com três parâmetros requer um valor de vermelho, verde e azul,
variando de 0 a 1. O Color construtor com quatro parâmetros adiciona um canal alfa, como o quarto parâmetro.
As capturas de tela a seguir mostram o resultado da chamada a cada Color construtor com os valores de
argumento especificado:
Chamar métodos de fábrica
Métodos de fábrica podem ser chamados em XAML, especificando o método nome usando o x:FactoryMethod
atributo e seus argumentos usando o x:Arguments atributo. Um método de fábrica é um public static método
que retorna os valores do mesmo tipo que a classe ou estrutura que define os métodos ou objetos.
O Color estrutura define vários métodos de fábrica e o exemplo de código a seguir demonstra a chamada três
argumentos:
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color x:FactoryMethod="FromRgba">
<x:Arguments>
<x:Int32>192</x:Int32>
<x:Int32>75</x:Int32>
<x:Int32>150</x:Int32>
<x:Int32>128</x:Int32>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color x:FactoryMethod="FromHsla">
<x:Arguments>
<x:Double>0.23</x:Double>
<x:Double>0.42</x:Double>
<x:Double>0.69</x:Double>
<x:Double>0.7</x:Double>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
<BoxView HeightRequest="150" WidthRequest="150" HorizontalOptions="Center">
<BoxView.Color>
<Color x:FactoryMethod="FromHex">
<x:Arguments>
<x:String>#FF048B9A</x:String>
</x:Arguments>
</Color>
</BoxView.Color>
</BoxView>
O número de elementos dentro de x:Arguments marca e os tipos desses elementos devem coincidir com os
argumentos de método de fábrica que está sendo chamado. O FromRgba método de fábrica exige quatro Int32
parâmetros, que representam os valores de vermelhos, verdes, azuis e alfabéticos, variando de 0 a 255,
respectivamente. O FromHsla método de fábrica exige quatro Double parâmetros, que representam o matiz,
saturação, luminosidade e valores alfa, variando de 0 a 1, respectivamente. O FromHex método de fábrica exige
uma String que representa o hexadecimal (A) de cor RGB.
As capturas de tela a seguir mostram o resultado da chamada a cada Color método de fábrica com os valores de
argumento especificado:
Especificando um argumento de tipo genérico
Argumentos de tipo genérico para o construtor de um tipo genérico podem ser especificados usando o
x:TypeArguments de atributo, conforme demonstrado no exemplo de código a seguir:
<ContentPage ...>
<StackLayout>
<StackLayout.Margin>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,20,0,0" />
<On Platform="Android" Value="5, 10" />
<On Platform="UWP" Value="10" />
</OnPlatform>
</StackLayout.Margin>
</StackLayout>
</ContentPage>
O OnPlatform classe é uma classe genérica e deve ser instanciado com um x:TypeArguments atributo que
corresponde ao tipo de destino. No On classe, o Platform atributo pode aceitar um único string valor ou
vários delimitada por vírgula string valores. Neste exemplo, o StackLayout.Margin estiver definida como uma
plataforma específica Thickness .
Resumo
Este artigo demonstrou usando os atributos XAML que podem ser usados para passar argumentos para o
construtor não padrão, para chamar métodos de fábrica e para especificar o tipo de um argumento genérico.
Links relacionados
Namespaces XAML
Passando argumentos de construtor (amostra)
Chamar métodos de fábrica (amostra)
Propriedades vinculáveis
12/04/2019 • 16 minutes to read
baixar o exemplo
No xamarin. Forms, a funcionalidade de propriedades comuns de runtime (CLR ) de linguagem é estendida por
propriedades associáveis. Uma propriedade associável é um tipo especial de propriedade, em que o valor da
propriedade é controlado pelo sistema de propriedades de xamarin. Forms. Este artigo fornece uma introdução a
propriedades associáveis e demonstra como criar e consumi-los.
Visão geral
Propriedades vinculáveis estendem a funcionalidade de propriedade CLR, fazendo uma propriedade com um
BindableProperty tipo, em vez de uma propriedade com um campo de suporte. A finalidade de propriedades
vinculáveis é fornecer um sistema de propriedade que dá suporte à vinculação de dados, estilos, modelos e
valores definidos por meio de relações pai-filho. Além disso, propriedades vinculáveis podem fornecer valores
padrão, validação de valores de propriedade e retornos de chamada que monitoram as alterações de propriedade.
As propriedades devem ser implementadas como propriedades vinculáveis para dar suporte a um ou mais dos
seguintes recursos:
Atuando como uma opção válida destino propriedade para associação de dados.
Definindo a propriedade por meio de um estilo.
Fornecendo um valor de propriedade padrão que é diferente do padrão para o tipo da propriedade.
Validando o valor da propriedade.
Monitoramento de alterações de propriedade.
Exemplos de propriedades vinculáveis do xamarin. Forms Label.Text , Button.BorderRadius , e
StackLayout.Orientation . Cada propriedade associável tem um correspondente public static readonly
propriedade do tipo BindableProperty que é exposto na mesma classe e que é o identificador da propriedade
associável. Por exemplo, o identificador a propriedade associável correspondente para o Label.Text é de
propriedade Label.TextProperty .
Isso cria uma BindableProperty instância denominada EventName , do tipo string . A propriedade pertencente a
EventToCommandBehavior de classe e tem um valor padrão de null . A convenção de nomenclatura para
propriedades vinculáveis é que o identificador de propriedade associável deve corresponder ao nome de
propriedade especificado no Create método, com "Propriedade" acrescentada a ela. Portanto, no exemplo acima,
o identificador de propriedade associável é EventNameProperty .
Opcionalmente, durante a criação de um BindableProperty da instância, as seguintes parâmetros podem ser
especificados:
O modo de associação. Isso é usado para especificar a direção na qual as alterações de valor de propriedade
serão propagadas. No modo de associação padrão, as alterações sejam propagadas do fonte para o destino.
Um delegado de validação que será chamado quando o valor da propriedade é definido. Para obter mais
informações, consulte retornos de chamada de validação.
Um delegado de alteração de propriedade que será chamado quando o valor da propriedade foi alterada. Para
obter mais informações, consulte detectando alterações de propriedade.
Uma propriedade alterando o delegado que será chamado quando o valor da propriedade será alterada. Esse
delegado tem a mesma assinatura que o delegado de propriedade alterada.
Um delegado de valor de retornos que será chamado quando o valor da propriedade foi alterada. Para obter
mais informações, consulte forçar retornos de chamada de valor.
Um Func que é usado para inicializar um valor de propriedade padrão. Para obter mais informações, consulte
criação de um valor padrão com um Func.
Criação de acessadores
Acessadores de propriedade são necessários para usar a sintaxe de propriedade para acessar uma propriedade
associável. O Get acessador deve retornar o valor contido na propriedade associável correspondente. Isso pode
ser obtido chamando o GetValue método, passando o identificador de propriedade associável no qual obter o
valor e, em seguida, convertendo os resultados para o tipo solicitado. O Set acessador deve definir o valor da
propriedade associável correspondente. Isso pode ser obtido chamando o SetValue método, passando o
identificador de propriedade associável no qual definir o valor e o valor a ser definido.
O exemplo de código a seguir mostra os acessadores para o EventName propriedade associável:
public string EventName {
get { return (string)GetValue (EventNameProperty); }
set { SetValue (EventNameProperty, value); }
}
<ListView ...>
<ListView.Behaviors>
<local:EventToCommandBehavior EventName="ItemSelected" ... />
</ListView.Behaviors>
</ListView>
Cenários avançados
Ao criar uma BindableProperty da instância, há um número de parâmetros opcionais que podem ser definidas
para habilitar cenários avançados de propriedade associável. Essa seção explora esses cenários.
Detectando alterações de propriedade
Um static método de retorno de chamada de propriedade alterada pode ser registrado com uma propriedade
vinculável, especificando as propertyChanged parâmetro para o BindableProperty.Create método. O método de
retorno de chamada especificado será invocado quando o valor da propriedade associável é alterada.
O seguinte exemplo de código mostra como o EventName registra a propriedade associável a OnEventNameChanged
método como um método de retorno de chamada de propriedade alterada:
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create (
"EventName", typeof(string), typeof(EventToCommandBehavior), null, propertyChanged: OnEventNameChanged);
...
No método de retorno de chamada de propriedade alterada, o BindableObject parâmetro é usado para indicar
qual instância da classe proprietária reportou uma alteração e os valores dos dois object parâmetros
representam os valores novos e antigos de a propriedade associável.
Retornos de chamadas de validação
Um static método de retorno de chamada de validação pode ser registrado com uma propriedade vinculável,
especificando as validateValue parâmetro para o BindableProperty.Create método. O método de retorno de
chamada especificado será chamado quando o valor da propriedade associável é definido.
O seguinte exemplo de código mostra como o Angle registra a propriedade associável a IsValidValue método
como um método de retorno de chamada de validação:
Retornos de chamada de validação são fornecidos com um valor e deve retornar true se o valor é válido para a
propriedade, caso contrário, false . Uma exceção será gerada se um retorno de chamada de validação retornar
false , que deve ser tratado pelo desenvolvedor. Um uso típico de um método de retorno de chamada de
validação é restringir os valores de números inteiros ou duplos quando a propriedade associável é definida. Por
exemplo, o IsValidValue método verifica que o valor da propriedade é um double dentro do intervalo de 0 a
360.
Forçar retornos de chamada de valor
Um static forçar o valor do método de retorno de chamada pode ser registrado com uma propriedade
vinculável, especificando as coerceValue parâmetro para o BindableProperty.Create método. O método de
retorno de chamada especificado será invocado quando o valor da propriedade associável é alterada.
Forçar retornos de chamada são usados para forçar uma reavaliação de uma propriedade associável quando o
valor da propriedade muda de valor. Por exemplo, um retorno de chamada de valor de retornos pode ser usado
para garantir que o valor de uma propriedade associável não é maior que o valor de outra propriedade associável.
O seguinte exemplo de código mostra como o Angle registra a propriedade associável a CoerceAngle método
como um método de retorno de chamada de valor retornos:
public static readonly BindableProperty AngleProperty = BindableProperty.Create (
"Angle", typeof(double), typeof(HomePage), 0.0, coerceValue: CoerceAngle);
public static readonly BindableProperty MaximumAngleProperty = BindableProperty.Create (
"MaximumAngle", typeof(double), typeof(HomePage), 360.0);
...
return input;
}
O defaultValueCreator parâmetro é definido como um Func que invoca a Device.GetNamedSize método para
retornar uma double que representa o tamanho nomeado para a fonte que é usada em um Label na plataforma
nativa.
Resumo
Este artigo fornece uma introdução para propriedades vinculáveis e demonstrou como criar e consumi-los. Uma
propriedade associável é um tipo especial de propriedade, em que o valor da propriedade é controlado pelo
sistema de propriedades de xamarin. Forms.
Links relacionados
Namespaces XAML
Eventos para comportamento de comando (amostra)
Retorno de chamada de validação (amostra)
Impor o valor de retorno de chamada (exemplo)
BindableProperty
BindableObject
Propriedades anexadas
12/04/2019 • 9 minutes to read
baixar o exemplo
Uma propriedade anexada é um tipo especial de propriedade associável, definido em uma classe, mas anexado
a outros objetos e reconhecível no XAML como um atributo que contém uma classe e um nome de propriedade
separados por um período. Este artigo fornece uma introdução para propriedades anexadas e demonstra como
criar e consumi-los.
Visão geral
Anexado a habilitação de propriedades para atribuir um valor para uma propriedade de sua própria classe não
define um objeto. Por exemplo, filho, elementos podem usar propriedades para informar o usuário de seu
elemento pai como devem ser apresentados na interface do usuário anexadas. O Grid controle permite que a
linha e coluna de um filho seja especificado definindo a Grid.Row e Grid.Column propriedades anexadas.
Grid.Row e Grid.Column são propriedades anexadas, porque eles são definidos em elementos que são filhos de
um Grid , em vez de no Grid em si.
Propriedades vinculáveis devem ser implementadas como propriedades anexadas nos seguintes cenários:
Quando é necessário ter um mecanismo de configuração de propriedade disponível para classes diferentes
da definição de classe.
Quando a classe representa um serviço que precisa ser facilmente integrados com outras classes.
Para obter mais informações sobre propriedades vinculáveis, consulte propriedades vinculáveis.
Uma propriedade anexada pode ser criada, declarando uma public static readonly propriedade do tipo
BindableProperty . A propriedade associável deve ser definida para o valor retornado de um dos
BindableProperty.CreateAttached sobrecargas de método. A declaração deve ser dentro do corpo da classe
proprietária, mas fora das definições de membro.
O código a seguir mostra um exemplo de uma propriedade anexada:
Isso cria uma propriedade anexada nomeada HasShadow , do tipo bool . A propriedade pertencente a
ShadowEffect de classe e tem um valor padrão de false . A convenção de nomenclatura para propriedades
anexadas é que o identificador da propriedade anexada deve corresponder ao nome de propriedade especificado
no CreateAttached método, com "Propriedade" acrescentada a ela. Portanto, no exemplo acima, o identificador
da propriedade anexada é HasShadowProperty .
Para obter mais informações sobre como criar propriedades vinculáveis, incluindo os parâmetros que podem ser
especificados durante a criação, consulte criando e consumindo uma propriedade vinculável.
Criação de acessadores
Estática Get PropertyName e Set PropertyName métodos são necessários como acessadores para a
propriedade anexada, caso contrário, o sistema de propriedades não poderá usar o propriedade anexada. O Get
PropertyName acessador deve estar de acordo com a seguinte assinatura:
O Get PropertyName acessador deve retornar o valor contido no correspondente BindableProperty campo
para a propriedade anexada. Isso pode ser obtido chamando o GetValue método, passando o identificador de
propriedade associável no qual obter o valor e, em seguida, converter o valor resultante para o tipo solicitado.
O Set PropertyName acessador deve estar de acordo com a seguinte assinatura:
O Set PropertyName acessador deve definir o valor correspondente BindableProperty campo para a
propriedade anexada. Isso pode ser obtido chamando o SetValue método, passando o identificador de
propriedade associável no qual definir o valor e o valor a ser definido.
Para ambos os acessadores, o alvo objeto deve ser de, ou derivar dele BindableObject .
O exemplo de código a seguir mostra os acessadores para o HasShadow propriedade anexada:
O Style pode ser aplicado a um Label definindo seu Style propriedade para o Style instância usando o
StaticResource extensão de marcação, conforme demonstrado no exemplo de código a seguir:
Cenários avançados
Ao criar uma propriedade anexada, há um número de parâmetros opcionais que podem ser definidas para
habilitar cenários avançados de propriedade anexada. Isso inclui a detecção de alterações de propriedade,
validando valores de propriedade e coerção de valores de propriedade. Para obter mais informações, consulte
cenários avançados de.
Resumo
Este artigo fornece uma introdução para propriedades anexadas e demonstrou como criar e consumi-los. Uma
propriedade anexada é um tipo especial de propriedade associável, definido em uma classe, mas anexado a
outros objetos e reconhecível no XAML como atributos que contêm uma classe e um nome de propriedade
separados por um período.
Links relacionados
Propriedades vinculáveis
Namespaces XAML
Efeito de sombra (amostra)
BindableProperty
BindableObject
Dicionários de recursos
12/04/2019 • 16 minutes to read
baixar o exemplo
Recursos XAML são definições de objetos que podem ser compartilhados e reutilizados em todo um aplicativo
xamarin. Forms.
Esses objetos de recurso são armazenados em um dicionário de recursos. Este artigo descreve como criar e
consumir um dicionário de recursos e como mesclar os dicionários de recursos.
Visão geral
Um ResourceDictionary é um repositório para os recursos que são usados por um aplicativo xamarin. Forms.
Recursos comuns que são armazenados em uma ResourceDictionary incluem estilos, modelos de controle,
modelos de dados, cores e conversores.
No XAML, recursos que são armazenados em uma ResourceDictionary podem ser recuperadas e aplicadas aos
elementos usando o StaticResource extensão de marcação. No c#, os recursos também podem ser definidos em
um ResourceDictionary e, em seguida, recuperados e aplicados aos elementos usando um indexador de cadeia
de caracteres. No entanto, há pouca vantagem em usar um ResourceDictionary no c#, como objetos
compartilhados podem simplesmente ser armazenados como campos ou propriedades e acessados diretamente
sem ter que primeiro recuperá-los de um dicionário.
Um programa do xamarin. Forms contém apenas uma classe que deriva de Application , mas geralmente faz
uso de muitas classes que derivam de VisualElement , incluindo páginas, layouts e controles. Qualquer um
desses objetos podem ter seus Resources propriedade definida como um ResourceDictionary . Escolher onde
colocar um determinado ResourceDictionary impactos onde os recursos podem ser usados:
Recursos em um ResourceDictionary que está anexado a um modo de exibição, como Button ou Label só
pode ser aplicado a esse objeto específico, portanto, isso não é muito útil.
Recursos em um ResourceDictionary anexados a um layout, como StackLayout ou Grid podem ser
aplicadas a todos os filhos do que o layout e de layout.
Recursos em um ResourceDictionary definidos na página do nível pode ser aplicado à página e para todos os
seus filhos.
Recursos em um ResourceDictionary definidos no aplicativo de nível pode ser aplicado em todo o aplicativo.
O XAML a seguir mostra os recursos definidos no nível do aplicativo ResourceDictionary no App. XAML
arquivo criado como parte do programa do xamarin. Forms padrão:
<Application ...>
<Application.Resources>
<ResourceDictionary>
<Color x:Key="PageBackgroundColor">Yellow</Color>
<Color x:Key="HeadingTextColor">Black</Color>
<Color x:Key="NormalTextColor">Blue</Color>
<Style x:Key="LabelPageHeadingStyle" TargetType="Label">
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Isso ResourceDictionary define três Color recursos e uma Style recursos. Para obter mais informações sobre
o App classe, consulte classe App.
A partir do xamarin. Forms 3.0, explícito ResourceDictionary marcas não são necessárias. O ResourceDictionary
objeto é criado automaticamente e você pode inserir os recursos diretamente entre o Resources marcas de
elemento de propriedade:
<Application ...>
<Application.Resources>
<Color x:Key="PageBackgroundColor">Yellow</Color>
<Color x:Key="HeadingTextColor">Black</Color>
<Color x:Key="NormalTextColor">Blue</Color>
<Style x:Key="LabelPageHeadingStyle" TargetType="Label">
<Setter Property="FontAttributes" Value="Bold" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="TextColor" Value="{StaticResource HeadingTextColor}" />
</Style>
</Application.Resources>
</Application>
Cada recurso tem uma chave que é especificada usando o x:Key atributo, que se torna a chave de dicionário no
ResourceDictionary . A chave é usada para recuperar um recurso do ResourceDictionary pelo StaticResource
extensão de marcação, conforme demonstrado no seguinte exemplo de código XAML que mostra os recursos
adicionais definidos dentro de StackLayout :
<StackLayout Margin="0,20,0,0">
<StackLayout.Resources>
<ResourceDictionary>
<Style x:Key="LabelNormalStyle" TargetType="Label">
<Setter Property="TextColor" Value="{StaticResource NormalTextColor}" />
</Style>
<Style x:Key="MediumBoldText" TargetType="Button">
<Setter Property="FontSize" Value="Medium" />
<Setter Property="FontAttributes" Value="Bold" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<Label Text="ResourceDictionary Demo" Style="{StaticResource LabelPageHeadingStyle}" />
<Label Text="This app demonstrates consuming resources that have been defined in resource dictionaries."
Margin="10,20,10,0"
Style="{StaticResource LabelNormalStyle}" />
<Button Text="Navigate"
Clicked="OnNavigateButtonClicked"
TextColor="{StaticResource NormalTextColor}"
Margin="0,20,0,0"
HorizontalOptions="Center"
Style="{StaticResource MediumBoldText}" />
</StackLayout>
Substituição de recursos
Quando ResourceDictionary compartilham recursos x:Key valores de atributo definidos inferior na hierarquia
de exibição de recursos terá precedência sobre aquelas definidas superior para cima. Por exemplo, definindo a
PageBackgroundColor recursos para Blue no aplicativo de nível será substituído por um nível de página
PageBackgroundColor conjunto de recursos Yellow . Da mesma forma, um nível de página PageBackgroundColor
recurso será substituído por um nível de controle PageBackgroundColor recursos. Essa precedência é
demonstrada pelo exemplo de código XAML a seguir:
<ContentPage ...>
<ContentPage.Resources>
<local:MyResourceDictionary />
</ContentPage.Resources>
...
</ContentPage>
IMPORTANT
ResourceDictionary também define uma MergedWith propriedade. Não use essa propriedade; ele foi preterido a partir
do xamarin. Forms 3.0.
Uma instância do MyResourceDictionary podem ser mesclados em qualquer aplicativo, a página ou o nível de
controle ResourceDictionary . O exemplo de código XAML a seguir mostra que ele está sendo mesclados em um
nível de página ResourceDictionary usando o MergedDictionaries propriedade:
<ContentPage ...>
<ContentPage.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MyResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
A marcação mostra apenas uma instância do MyResourceDictionary que está sendo adicionado para o
ResourceDictionary , mas você também pode referenciar outro ResourceDictionary instâncias no
MergedDictionary marcas de elemento de propriedade e outros recursos fora essas marcas:
<ContentPage ...>
<ContentPage.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<local:MyResourceDictionary />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Pode haver apenas um MergedDictionaries seção em um ResourceDictionary , mas você pode colocar quantas
ResourceDictionary instâncias aqui como você deseja.
Quando mescladas ResourceDictionary recursos compartilham idênticos x:Key valores de atributo, xamarin.
Forms usa a precedência de recursos a seguir:
1. Os recursos locais para o dicionário de recursos.
2. Os recursos contidos no dicionário de recursos que foi mesclado via preteridas MergedWith propriedade.
3. Os recursos contidos nos dicionários de recursos que foram mesclados por meio de MergedDictionaries
coleção, na ordem inversa, eles são listados no MergedDictionaries propriedade.
NOTE
Dicionários de recursos de pesquisa pode ser uma tarefa de computação intensa, se um aplicativo contém vários
dicionários de recursos grandes. Portanto, para evitar pesquisas desnecessárias, você deve garantir que cada página em um
aplicativo só usa dicionários de recursos que são apropriados para a página.
<ContentPage ...>
<ContentPage.Resources>
<ResourceDictionary>
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Porque o xamarin. Forms 3.0 automaticamente cria uma instância de ResourceDictionary , esses dois externos
ResourceDictionary marcas não são mais necessárias:
<ContentPage ...>
<ContentPage.Resources>
</ContentPage.Resources>
...
</ContentPage>
Essa nova sintaxe faz não instanciar o MyResourceDictionary classe. Em vez disso, ele faz referência ao arquivo
XAML. Por esse motivo que o arquivo code-behind (MyResourceDictionary.xaml.cs) não é mais necessário.
Você também pode remover o x:Class atributo na marca raiz do MyResourceDictionary.xaml arquivo.
Resumo
Este artigo explicou como criar e consumir um ResourceDictionary e como mesclar os dicionários de recursos.
Um ResourceDictionary permite que os recursos sejam definidos em um único local e reutilizadas em todo um
aplicativo xamarin. Forms.
Links relacionados
Dicionários de recursos (amostra)
Estilos
Dicionário de recurso
XAML Standard (visualização)
12/04/2019 • 2 minutes to read
Siga estas etapas para fazer experiências com o padrão de XAML no xamarin. Forms:
Visual Studio
Visual Studio para Mac
1. Baixe o visualizar o pacote do NuGet aqui.
2. Adicione a Xamarin.Forms.Alias pacote do NuGet para seus projetos xamarin. Forms .NET Standard e
plataforma.
3. Inicializar o pacote com Alias.Init()
4. Adicionar um xmlns:a referência xmlns:a="clr-namespace:Xamarin.Forms.Alias;assembly=Xamarin.Forms.Alias"
5. Use os tipos no XAML - consulte o referência controles para obter mais informações.
O XAML a seguir demonstra alguns controles XAML padrão que está sendo usados em um xamarin. Forms
ContentPage :
Links relacionados
NuGet de visualização
Referência de controles
Controles do XAML Standard (visualização)
12/04/2019 • 2 minutes to read
Esta página lista os controles XAML padrão disponíveis na visualização, juntamente com seu controle equivalente
do xamarin. Forms.
Também é uma lista de controles que têm novos nomes de propriedade e de enumeração no XAML padrão.
Controles
XAMARIN.FORMS XAML STANDARD
Quadro Borda
Seletor ComboBox
ActivityIndicator ProgressRing
StackLayout StackPanel
Rotular TextBlock
Entrada TextBox
Alternar ToggleSwitch
ContentView UserControl
Propriedades e enumerações
CONTROLES DO XAMARIN. FORMS COM AS PROPRIEDADE DO XAMARIN. FORMS OU
PROPRIEDADES ATUALIZADAS ENUMERAÇÃO EQUIVALENTE XAML PADRÃO
IMPORTANT
Itens marcados com * estão incompletos na visualização atual
Links relacionados
NuGet de visualização
Carregando XAML em tempo de execução no
xamarin. Forms
12/04/2019 • 4 minutes to read
Baixar o exemplo
O Xamarin.Forms.Xaml namespace inclui dois LoadFromXaml métodos de extensão que podem ser usados para
carregar e analisar o XAML em tempo de execução.
Informações preliminares
Quando uma classe de XAML de xamarin. Forms é construída, o LoadFromXaml método é chamado indiretamente.
Isso ocorre porque o arquivo code-behind para um XAML classe chama o InitializeComponent método de seu
construtor:
Quando o Visual Studio compila um projeto que contém um arquivo XAML, ele analisa o arquivo XAML para
gerar um C# arquivo de código (por exemplo, MainPage.xaml.g.cs) que contém a definição do
InitializeComponent método:
O InitializeComponent chamadas de método de LoadFromXaml método para extrair o arquivo XAML (ou seu
binário compilado) da biblioteca do .NET Standard. Após a extração, ele inicializa todos os objetos definidos no
arquivo XAML, conecta-se-los todos juntos em relações pai-filho, anexa os manipuladores de eventos definidos no
código aos eventos definido no arquivo XAML e define a árvore resultante de objetos que o conteúdo das página.
WARNING
Carregar XAML em tempo de execução tem um custo de desempenho significativo e geralmente deve ser evitado.
Neste exemplo, uma Button instância é criada, com seus Text definido pelo valor da propriedade sendo definida
do XAML no string . O Button é adicionado a um StackLayout que foi definido no XAML para a página.
NOTE
O LoadFromXaml métodos de extensão permitem que um argumento de tipo genérico a ser especificado. No entanto,
raramente é necessário especificar o argumento de tipo, pois ela será inferido do tipo da instância de seu operando.
O LoadFromXaml método pode ser usado para Inflar qualquer XAML, com o exemplo a seguir inflacionando uma
ContentPage e, em seguida, navegando até ele:
using Xamarin.Forms.Xaml;
...
Acessando elementos
Carregando XAML em tempo de execução com o LoadFromXaml método não permite acesso fortemente tipado
aos elementos XAML que especificou os nomes de objeto de tempo de execução (usando x:Name ). No entanto,
esses elementos XAML podem ser recuperados usando o FindByName método e, em seguida, acessados conforme
necessário:
Neste exemplo, o XAML para um ContentPage está inflado. Esse XAML inclui um Label denominada monkeyName ,
que é recuperado usando o FindByName método, antes que ele tenha Text propriedade está definida.
Links relacionados
LoadRuntimeXAML (amostra)
Conceitos básicos de aplicativo Xamarin.Forms
12/04/2019 • 5 minutes to read • Edit Online
Acessibilidade
Dicas para incorporar recursos acessíveis (como dar suporte às ferramentas de leitura de tela) com o
Xamarin.Forms.
Classe de aplicativo
A classe Application é o ponto de partida para o Xamarin.Forms – todo aplicativo precisa implementar uma
subclasse App para definir a página inicial. Ela também fornece a coleta Properties para armazenamento de
dados simples. Ela pode ser definida em C# ou em XAML.
Comportamentos
Controles de interface do usuário podem ser estendidos facilmente sem a criação de subclasses pelo uso de
comportamentos para adicionar funcionalidade.
Renderizadores personalizados
Renderizadores personalizados permitem que os desenvolvedores 'substituam' a renderização padrão de controles
do Xamarin.Forms para personalizar sua aparência e comportamento em cada plataforma (usando SDKs nativos,
se desejado).
Associação de dados
A associação de dados associa as propriedades de dois objetos, permitindo que as alterações em uma propriedade
sejam automaticamente refletidas na outra. A associação de dados é parte integrante da arquitetura do aplicativo
MVVM (Model-View -ViewModel).
Serviço de dependência
O DependencyService fornece um localizador simples para que você possa codificar para interfaces em seu código
compartilhado e fornecer implementações específicas a uma plataforma que são resolvidas automaticamente,
tornando mais fácil fazer referência a funcionalidades específicas a uma plataforma no Xamarin.Forms.
Efeitos
Efeitos permitem que os controles nativos em cada plataforma sejam personalizados e são geralmente usados para
pequenas alterações de estilo.
Arquivos
O tratamento de arquivos com o Xamarin.Forms pode ser alcançado usando código em uma biblioteca .NET
Standard ou usando recursos inseridos.
Gestos
A classe GestureRecognizer do Xamarin.Forms dá suporte a gestos de toque, pinçagem e panorâmica em controles
da interface do usuário.
Localização
A estrutura de localização interna do .NET pode ser usada para criar aplicativos multilíngues multiplataforma com
o Xamarin.Forms.
Centro de mensagens
O MessagingCenter do Xamarin.Forms habilita a exibição de modelos e outros componentes com os quais se
comunicar sem que eles precisem saber nada uns sobre os outros, além de um contrato de mensagem simples.
Navegação
o Xamarin.Forms oferece uma série de experiências de navegação de página diferentes, dependendo do tipo do
Page sendo usado.
Shell
O Shell do Xamarin.Forms é um contêiner para aplicativos, que fornece os recursos fundamentais da interface do
usuário que a maioria dos aplicativos exige, permitindo que você se concentre na carga de trabalho principal do
aplicativo.
Modelos
Modelos de controle fornecem a capacidade de definir e redefinir temas de páginas de aplicativo em tempo de
execução com facilidade, enquanto modelos de dados fornecem a capacidade de definir a apresentação de dados
em controles compatíveis.
Gatilhos
Atualize os controles respondendo a alterações de propriedade e eventos no XAML.
Acessibilidade do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Criar um aplicativo acessível garante que o aplicativo seja utilizável por pessoas que abordem a interface do
usuário com uma variedade de necessidades e experiências.
Tornar um aplicativo Xamarin.Forms disponível significa pensar sobre o layout e o design de muitos elementos da
interface do usuário. Para obter diretrizes sobre problemas a serem considerados, consulte a lista de verificação de
acessibilidade. Muitas preocupações de acessibilidade, tais como fontes grandes e configurações de cor e contraste
adequadas, já podem ser tratadas por APIs do Xamarin.Forms.
Os guias Acessibilidade do Android e Acessibilidade iOS contêm detalhes das APIs nativas expostas pelo Xamarin,
enquanto o guia de acessibilidade da Plataforma Universal do Windows no MSDN explica a abordagem nativa
nessa plataforma. Essas APIs são usadas para implementar totalmente aplicativos acessíveis em cada plataforma.
O Xamarin.Forms não tem suporte interno para todas as APIs de acessibilidade disponíveis em cada uma das
plataformas subjacentes. No entanto, ele dá suporte a propriedades de automação de configuração em elementos
de interface do usuário para dar suporte a ferramentas de assistência de navegação e de leitor de tela, uma das
partes mais importantes da criação de aplicativos acessíveis. Para obter mais informações, veja Propriedades de
automação.
Aplicativos Xamarin.Forms também podem ter a ordem de tabulação de controles especificada. Para obter mais
informações, veja Navegação pelo teclado.
Outras APIs de acessibilidade (assim como PostNotification no iOS ) podem ser mais adequadas para uma
implementação de DependencyService ou de renderizador personalizado. Elas não são abordadas neste guia.
Testando a acessibilidade
Aplicativos Xamarin.Forms normalmente são direcionados a várias plataformas, o que significa testar os recursos
de acessibilidade de acordo com a plataforma. Siga estes links para saber como testar a acessibilidade em cada
plataforma:
Testes de iOS
Testes de Android
Windows AccScope (MSDN )
Links relacionados
Acessibilidade multiplataforma
Propriedades de automação
Acessibilidade do teclado
Propriedades de automação no Xamarin.Forms
12/04/2019 • 11 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms permite que valores de acessibilidade sejam definidos em elementos da interface do usuário
usando propriedades anexadas da classe AutomationProperties, que, por sua vez, definem valores de
acessibilidade nativos. Este artigo explica como usar a classe AutomationProperties para que um leitor de tela
possa falar sobre os elementos na página.
O Xamarin.Forms permite que propriedades de automação sejam definidas em elementos da interface do usuário
por meio das propriedades anexadas a seguir:
AutomationProperties.IsInAccessibleTree – indica se o elemento está disponível para um aplicativo acessível.
Para obter mais informações, confira AutomationProperties.IsInAccessibleTree.
AutomationProperties.Name – uma breve descrição do elemento que serve como um identificador falado para o
elemento. Para obter mais informações, confira AutomationProperties.Name.
AutomationProperties.HelpText – uma descrição mais detalhada do elemento, que pode ser considerada como
o texto de dica de ferramenta associado ao elemento. Para obter mais informações, confira
AutomationProperties.HelpText.
AutomationProperties.LabeledBy – permite que outro elemento defina informações de acessibilidade sobre o
elemento atual. Para obter mais informações, confira AutomationProperties.LabeledBy.
Essas propriedades anexadas definem valores de acessibilidade nativos, de modo que um leitor de tela pode falar
sobre o elemento. Para obter mais informações sobre as propriedades anexadas, confira Propriedades anexadas.
IMPORTANT
Usar as propriedades anexadas AutomationProperties pode afetar a execução de testes de interface do usuário no
Android. As propriedades AutomationId , AutomationProperties.Name e AutomationProperties.HelpText definirão a
propriedade ContentDescription nativa, com os valores das propriedades AutomationProperties.Name e
AutomationProperties.HelpText tendo precedência sobre o valor AutomationId (se AutomationProperties.Name e
AutomationProperties.HelpText forem definidos, os valores serão concatenados). Isso significa que testes que
procurarem AutomationId falharão se AutomationProperties.Name ou AutomationProperties.HelpText também
estiverem definidos no elemento. Nesse cenário, testes da interface do usuário deverão ser alterados para procurar pelo
valor de AutomationProperties.Name ou AutomationProperties.HelpText , ou por uma concatenação dos dois.
Cada plataforma tem um leitor de tela diferente para narrar os valores de acessibilidade:
O iOS tem o VoiceOver. Para obter mais informações, confira Test Accessibility on Your Device with VoiceOver
(Testando a acessibilidade em seu dispositivo com o VoiceOver) em developer.apple.com.
O Android tem o TalkBack. Para obter mais informações, confira Testing Your App's Accessibility (Testando a
acessibilidade de seu aplicativo) em developer.android.com.
O Windows tem o Narrador. Para obter mais informações, confira Verificar cenários do aplicativo principal
usando o Narrador.
No entanto, o comportamento exato do leitor de tela depende do software e da configuração que o usuário faz
nele. Por exemplo, a maioria dos leitores de tela lê o texto associado a um controle quando ele entra em foco,
permitindo que os usuários se orientem enquanto percorrem os controles na página. Alguns leitores de tela
também leem toda a interface do usuário do aplicativo quando a página é exibida, o que permite que o usuário
receba todo o conteúdo informativo disponível na página antes de tentar navegar por ela.
Leitores de tela também leem diferentes valores de acessibilidade. No aplicativo de exemplo:
O VoiceOver lê o valor de Placeholder de Entry , seguido por instruções de como usar o controle.
O TalkBack lê o valor de Placeholder de Entry , seguido pelo valor de AutomationProperties.HelpText e por
instruções de como usar o controle.
O Narrador lê o valor de AutomationProperties.LabeledBy de Entry , seguido por instruções de como usar o
controle.
Além disso, o Narrador prioriza AutomationProperties.Name , AutomationProperties.LabeledBy e, em seguida,
AutomationProperties.HelpText . No Android, o TalkBack pode combinar os valores de AutomationProperties.Name
e AutomationProperties.HelpText . Portanto, é recomendável que testes de acessibilidade minuciosos sejam
executados em cada plataforma para garantir a experiência ideal.
AutomationProperties.IsInAccessibleTree
A propriedade anexada AutomationProperties.IsInAccessibleTree é um boolean que determina se o elemento é
acessível e, portanto, visível para leitores de tela. Ela deve ser definida como true para usar outras propriedades
anexadas de acessibilidade. Isso pode ser feito no XAML da seguinte maneira:
NOTE
Observe que o método SetValuetambém pode ser usado para definir a propriedade anexada
AutomationProperties.IsInAccessibleTree –
entry.SetValue(AutomationProperties.IsInAccessibleTreeProperty, true);
AutomationProperties.Name
O valor da propriedade anexada AutomationProperties.Name deve ser uma cadeia de caracteres de texto curta e
descritiva que usa de um leitor de tela para anunciar um elemento. Essa propriedade deve ser definida para
elementos cujo significado é importante para entender o conteúdo ou para interagir com a interface do usuário.
Isso pode ser feito no XAML da seguinte maneira:
<ActivityIndicator AutomationProperties.IsInAccessibleTree="true"
AutomationProperties.Name="Progress indicator" />
AutomationProperties.HelpText
A propriedade anexada AutomationProperties.HelpText deve ser definida como o texto que descreve o elemento
da interface do usuário e pode ser considerada como um texto de dica de ferramenta associado ao elemento. Isso
pode ser feito no XAML da seguinte maneira:
NOTE
Observe que o método SetValue também pode ser usado para definir a propriedade anexada
AutomationProperties.HelpText –
button.SetValue(AutomationProperties.HelpTextProperty, "Tap to toggle the activity indicator");
Em algumas plataformas, para controles de edição como um Entry , a propriedade HelpText às vezes pode ser
omitida e substituída por um texto de espaço reservado. Por exemplo, "Digite seu nome aqui" é um bom
candidato para a propriedade Entry.Placeholder , que coloca o texto no controle antes da entrada feita pelo
usuário.
AutomationProperties.LabeledBy
A propriedade anexada AutomationProperties.LabeledBy permite que outro elemento defina informações de
acessibilidade sobre o elemento atual. Por exemplo, um Label próximo a um Entry pode ser usado para
descrever o que o Entry representa. Isso pode ser feito no XAML da seguinte maneira:
Complexidades de acessibilidade
As seções a seguir descrevem as complexidades da configuração dos valores de acessibilidade em certos
controles.
NavigationPage
No Android, para definir o texto que os leitores de tela lerão para a seta voltar na barra de ação em um
NavigationPage , defina as propriedades AutomationProperties.Name e AutomationProperties.HelpText em um
Page . No entanto, observe que isso não terá um efeito em botões voltar de sistema operacional.
MasterDetailPage
No iOS e UWP (Plataforma Universal do Windows), para definir o texto que os leitores de tela lerão para o botão
de alternância em um MasterDetailPage , defina as propriedades AutomationProperties.Name e
AutomationProperties.HelpText em MasterDetailPage ou na propriedade Icon da página Master .
No Android, para definir o texto que os leitores da tela lerão para o botão de alternância em um MasterDetailPage
, adicione recursos de cadeia de caracteres ao projeto Android:
<resources>
<string name="app_name">Xamarin Forms Control Gallery</string>
<string name="btnMDPAutomationID_open">Open Side Menu message</string>
<string name="btnMDPAutomationID_close">Close Side Menu message</string>
</resources>
Em seguida, defina a propriedade AutomationId da propriedade Icon da página Master na cadeia de caracteres
apropriada:
ToolbarItem
No iOS, Android e UWP, os leitores de tela lerão o valor da propriedade Text das instâncias ToolbarItem ,
contanto que os valores AutomationProperties.Name ou AutomationProperties.HelpText não estejam definidos.
No iOS e UWP, o valor da propriedade AutomationProperties.Name substituirá o valor da propriedade Text que é
lido pelo leitor de tela.
No Android, os valores de propriedade AutomationProperties.Name e/ou AutomationProperties.HelpText
substituirão completamente o valor da propriedade Text que está visível e é lida pelo leitor de tela. Observe que
essa é uma limitação de APIs menores que 26.
Links relacionados
Propriedades anexadas
Acessibilidade (amostra)
Navegação por teclado no Xamarin.Forms
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Alguns usuários podem ter dificuldade para usar aplicativos que não fornecem acesso apropriado por teclado.
Especificar uma ordem de tabulação para os controles habilita a navegação por teclado e prepara as páginas do
aplicativo para receber as entradas em uma ordem específica.
Por padrão, a ordem de tabulação dos controles é a mesma ordem em que eles são listados no XAML ou são
adicionados de maneira programática a uma coleção filho. Essa é a ordem em que os controles serão navegados
usando um teclado e geralmente a ordem padrão é a melhor ordem. No entanto, a ordem padrão nem sempre é o
mesmo que a ordem esperada, conforme mostrado no exemplo de código XAML a seguir:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Text="You"
HorizontalOptions="Center" />
<Label Grid.Column="1"
Text="Manager"
HorizontalOptions="Center" />
<Entry Grid.Row="1"
Placeholder="Enter forename" />
<Entry Grid.Column="1"
Grid.Row="1"
Placeholder="Enter forename" />
<Entry Grid.Row="2"
Placeholder="Enter surname" />
<Entry Grid.Column="1"
Grid.Row="2"
Placeholder="Enter surname" />
</Grid>
A captura de tela a seguir mostra a ordem de tabulação padrão para este exemplo de código:
A ordem de tabulação aqui é baseada nas linhas e é a ordem em que os controles são listados no XAML. Portanto,
pressionar a tecla Tab navega pelas instâncias de Entry do primeiro nome, seguidas pelas instâncias de Entry do
sobrenome. No entanto, uma experiência mais intuitiva seria usar a navegação com tabulação por colunas, de
modo que pressionar a tecla Tab navegaria pelos pares de primeiro nome e sobrenome. Isso pode ser feito
especificando a ordem de tabulação dos controles de entrada.
NOTE
Na Plataforma Universal do Windows, é possível definir atalhos de teclado que fornecem uma maneira intuitiva para os
usuários navegarem e interagirem rapidamente com a interface do usuário visível do aplicativo usando um teclado em vez
do mouse ou de uma tela de toque. Para obter mais informações, confira Configurando chaves de acesso de VisualElement.
A captura de tela a seguir mostra a ordem de tabulação para este exemplo de código:
A ordem de tabulação aqui é baseada em colunas. Portanto, pressionar a tecla Tab navega pelos pares de Entry
de primeiro nome e sobrenome.
NOTE
Esses controles não são focalizáveis pela tabulação em todas as plataformas.
Links relacionados
Acessibilidade (amostra)
Classe App do Xamarin.Forms
12/04/2019 • 8 minutes to read • Edit Online
A classe base Application oferece os seguintes recursos, que são expostos na subclasse App padrão de seus
projetos:
Uma propriedade MainPage , que é onde a página inicial do aplicativo deve ser definida.
Um dicionário de Properties persistente para armazenar valores simples durante alterações de estado do
ciclo de vida.
Uma propriedade Current estática que contém uma referência ao objeto do aplicativo atual.
Ela também expõe Métodos de ciclo de vida como OnStart , OnSleep e OnResume , bem como eventos de
navegação modal.
Dependendo do modelo escolhido, a classe App poderá ser definida de uma das duas maneiras:
C# ou
XAML e C#
Para criar uma classe App usando XAML, a classe App padrão deve ser substituída por uma classe App XAML e
pelo code-behind associado, conforme mostrado no exemplo de código a seguir:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Photos.App">
</Application>
Propriedade MainPage
A propriedade MainPage na classe Application define a página raiz do aplicativo.
Por exemplo, você pode criar a lógica em sua classe App para exibir uma página diferente se o usuário estiver
conectado ou não.
A propriedade MainPage deve ser definida no construtor App ,
public class App : Xamarin.Forms.Application
{
public App ()
{
MainPage = new ContentPage { Title = "App Lifecycle Sample" }; // your page here
}
}
Dicionário de propriedades
A subclasse Application tem um dicionário Properties estático que pode ser usado para armazenar dados, em
particular para uso nos métodos OnStart , OnSleep e OnResume . Ele pode ser acessado de qualquer lugar de seu
código do Xamarin.Forms usando Application.Current.Properties .
O dicionário Properties usa uma chave string e armazena um valor de object .
Por exemplo, você poderia definir uma propriedade "id" persistente em qualquer lugar de seu código (quando
um item é selecionado, no método OnDisappearing de uma página ou no método OnSleep ), da seguinte forma:
Nos métodos OnStart ou OnResume , você pode usar esse valor para recriar a experiência do usuário de alguma
forma. O dicionário Properties armazena object s, de modo que você precisa converter seu valor antes de usá-
lo.
if (Application.Current.Properties.ContainsKey("id"))
{
var id = Application.Current.Properties ["id"] as int;
// do something with id
}
Sempre verifique a presença da chave antes de acessá-la para evitar erros inesperados.
NOTE
O dicionário Properties pode serializar apenas tipos primitivos para armazenamento. Tentar armazenar outros tipos
(como List<string> ) pode falhar de modo silencioso.
Persistência
O dicionário Properties é salvo automaticamente no dispositivo. Dados adicionados ao dicionário estarão
disponíveis quando o aplicativo voltar do segundo plano ou até mesmo após ser reiniciado.
O Xamarin.Forms 1.4 introduziu um método adicional na classe Application – SavePropertiesAsync() – que
pode ser chamado para persistir proativamente o dicionário Properties . A finalidade disso é permitir que você
salve propriedades após atualizações importantes, em vez de correr o risco de que elas não sejam serializadas
devido a uma falha ou a uma interrupção do sistema operacional.
Você pode encontrar referências ao uso do dicionário Properties no livro Creating Mobile Apps with
Xamarin.Forms (Criando aplicativos móveis com o Xamarin.Forms), nos capítulos 6, 15 e 20 e nos exemplos
associados.
A classe do aplicativo
Uma implementação completa da classe Application é mostrada abaixo para referência:
Em seguida, essa classe é instanciada em cada projeto específico da plataforma e passada para o método
LoadApplication , em que o MainPage é carregado e exibido para o usuário. O código para cada plataforma é
mostrado nas seções a seguir. Os modelos de solução do Xamarin.Forms mais recentes já contêm todo esse
código pré-configurado para seu aplicativo.
Projeto do iOS
A classe AppDelegate do iOS herda de FormsApplicationDelegate . Ele deve:
Chamar LoadApplication com uma instância da classe App .
Sempre retorna base.FinishedLaunching (app, options); .
[Register ("AppDelegate")]
public partial class AppDelegate :
global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate // superclass new in 1.3
{
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
global::Xamarin.Forms.Forms.Init ();
Projeto do Android
O MainActivity do Android herda de FormsAppCompatActivity . Na substituição OnCreate , o método
LoadApplication é chamado com uma instância da classe App .
[Activity (Label = "App Lifecycle Sample", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher
= true,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
<forms:WindowsPage
...
xmlns:forms="using:Xamarin.Forms.Platform.UWP"
...>
</forms:WindowsPage>
A construção com code-behind de C# deve chamar LoadApplication para criar uma instância de seu App do
Xamarin.Forms. Observe que é uma boa prática usar explicitamente o namespace do aplicativo para qualificar o
App , pois aplicativos da UWP também têm sua própria classe App , não relacionada ao Xamarin.Forms.
LoadApplication(new YOUR_NAMESPACE.App());
}
}
Observe que Forms.Init() precisa ser chamado por App.xaml.cs no projeto UWP.
Para obter mais informações, confira Configurar projetos do Windows, que inclui as etapas para adicionar um
projeto UWP a uma solução do Xamarin.Forms existente que não seja direcionada à UWP.
Ciclo de vida do aplicativo no Xamarin.Forms
12/04/2019 • 4 minutes to read • Edit Online
Ao atualizar aplicativos mais antigos do Xamarin.Forms (por exemplo, criado com o Xamarin.Forms 1.3 ou mais
antigo), verifique se a atividade principal do Android inclui
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation no atributo [Activity()] . Se ele
não estiver presente, você observará que o método OnStart é chamado em rotação e quando o aplicativo é
iniciado pela primeira vez. Esse atributo é incluído automaticamente nos modelos de aplicativo atuais do
Xamarin.Forms.
NOTE
Os eventos PageAppearing e PageDisappearing são gerados da classe base Page imediatamente após os eventos
Page.Appearing e Page.Disappearing , respectivamente.
NOTE
Para implementar os métodos de ciclo de vida do aplicativo e eventos de navegação modal, todos os métodos pré
Application para criar um aplicativo do Xamarin.Forms (ou seja, aplicativos escritos na versão 1.2 ou mais antiga que
usam um método GetMainPage estático) foram atualizados para criar um Application padrão que é definido como pai
do MainPage .
Aplicativos do Xamarin.Forms que usam esse comportamento herdado devem ser atualizados para uma subclasse de
Application , conforme descrito na página Classe do aplicativo.
Indexação de aplicativo e vinculação profunda
12/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
A indexação de aplicativo permite que os aplicativos que seriam esquecidos após alguns usos permaneçam
relevantes fazendo com que eles apareçam nos resultados da pesquisa. A vinculação profunda permite que os
aplicativos respondam a um resultado de pesquisa que contém dados de aplicativo, normalmente navegando até
uma página referenciada de um link profundo. Este artigo explica como usar a indexação de aplicativo e a
vinculação profunda para fazer com que o Xamarin.Forms tenha conteúdo pesquisável em dispositivos iOS e
Android.
Cada instância TodoItem criada pelo usuário é indexada. Então, a pesquisa específica da plataforma pode ser usada
para localizar dados indexados do aplicativo. Quando o usuário toca em um item de resultado de pesquisa para o
aplicativo, o aplicativo é iniciado, o TodoItemPage é navegada e o TodoItem referenciado do link profundo é
exibido.
Para obter mais informações sobre como usar um banco de dados do SQLite, consulte Bancos de Dados Locais do
Xamarin.Forms.
NOTE
A funcionalidade de indexação de aplicativo e vinculação profunda do Xamarin.Forms somente está disponível nas
plataformas Android e iOS e requer um mínimo de iOS 9 e API 23, respectivamente.
Configuração
As seções a seguir fornecem instruções de configuração adicionais para usar esse recurso nas plataformas Android
e iOS.
iOS
Na plataforma iOS, certifique-se de que seu projeto da plataforma iOS defina o arquivo Entitlements.plist como
o arquivo de direitos personalizados para assinar o pacote.
Para usar Links Universais do iOS:
1. Adicione um direito de Domínios Associados ao seu aplicativo, com a chave applinks , incluindo todos os
domínios que seu aplicativo dará suporte.
2. Adicione um arquivo de Associação de Site do Aplicativo da Apple ao seu site.
3. Adicione a chave applinks ao arquivo de Associação de Site do Aplicativo da Apple.
Para obter mais informações, consulte Permitir que aplicativos e sites se vinculem ao seu conteúdo em
developer.apple.com.
Android
Na plataforma Android, há uma série de pré-requisitos que devem ser atendidos para usar a funcionalidade de
indexação de aplicativo e vinculação profunda:
1. Uma versão do seu aplicativo deve estar em tempo real no Google Play.
2. Um site complementar deve ser registrado com o aplicativo no Console do Desenvolvedor do Google. Depois
que o aplicativo é associado a um site, as URLs podem ser indexadas e funcionam para o site e o aplicativo, que
pode ser atendido nos resultados da pesquisa. Para obter mais informações, consulte Indexação de apps na
Pesquisa Google no site do Google.
3. Seu aplicativo deve dar suporte a intenções de URL HTTP na classe MainActivity , que informa à indexação de
aplicativo quais tipos de esquemas de dados de URL o aplicativo pode responder. Para obter mais informações,
consulte Configurar o Filtro de Intenção.
Depois que esses pré-requisitos forem atendidos, a seguinte configuração adicional será necessária para usar a
indexação de aplicativo e a vinculação profunda do Xamarin.Forms na plataforma Android:
1. Instale o pacote do NuGet do Xamarin.Forms.AppLinks no projeto de aplicativo do Android.
2. No arquivo MainActivity.cs, adicione uma declaração para usar o namespace
Xamarin.Forms.Platform.Android.AppLinks .
3. No arquivo MainActivity.cs, adicione uma declaração para usar o namespace Firebase .
4. Em um navegador da Web, crie um projeto por meio do Console do Firebase.
5. No Console do Firebase, adicione o Firebase ao seu aplicativo Android e insira os dados necessários.
6. Baixe o arquivo google-services.json resultante.
7. Adicione o arquivo google-services.json ao diretório raiz do projeto do Android e defina sua Ação de Build
como GoogleServicesJson.
8. Na substituição de MainActivity.OnCreate , adicione a seguinte linha de código abaixo de
Forms.Init(this, bundle) :
FirebaseApp.InitializeApp(this);
AndroidAppLinks.Init(this);
pageLink.KeyValues.Add("contentType", "TodoItemPage");
pageLink.KeyValues.Add("appName", App.AppName);
pageLink.KeyValues.Add("companyName", "Xamarin");
return pageLink;
}
A instância AppLinkEntry contém uma série de propriedades cujos valores são necessários para indexar a página e
criar um link profundo. As propriedades Title , Description e Thumbnail são usadas para identificar o conteúdo
indexado quando ele for exibido nos resultados da pesquisa. A propriedade IsLinkActive é definida como true
para indicar que o conteúdo indexado está sendo exibido atualmente. A propriedade AppLinkUri é uma Uri que
contém as informações necessárias para retornar à página atual e exibir o TodoItem atual. O exemplo a seguir
mostra um Uri de exemplo para o aplicativo de exemplo:
http://deeplinking/DeepLinking.TodoItemPage?id=2
Application.Current.AppLinks.RegisterLink (appLink);
NOTE
O método RegisterLink também pode ser usado para atualizar o conteúdo que foi indexado para uma página.
Assim que uma instância AppLinkEntry tiver sido registrada para indexação, ela poderá aparecer nos resultados da
pesquisa. A captura de tela a seguir mostra o conteúdo indexado que aparece nos resultados da pesquisa na
plataforma iOS:
Application.Current.AppLinks.DeregisterLink (appLink);
O método OnAppLinkRequestReceived verifica se o Uri recebido destina-se ao aplicativo antes da análise de Uri
em uma página que será navegada e do parâmetro que será passado para a página. Uma instância da página que
será navegada é criada e o TodoItem representado pelo parâmetro da página é recuperado. O BindingContext da
página que será navegada é definido como TodoItem . Isso garante que, quando o TodoItemPage for exibido pelo
método PushAsync , ele estará mostrando o TodoItem cujo ID está contido no link profundo.
Da mesma forma, quando a página representada por um link profundo for retirada da navegação, a propriedade
AppLinkEntry.IsLinkActive poderá ser definida como false . No iOS e no Android, isso interrompe a instância
AppLinkEntry que está sendo anunciada para indexação de pesquisa. No iOS, isso também interrompe o anúncio
da instância AppLinkEntry para entrega. Isso pode ser feito na substituição de Page.OnDisappearing , conforme
demonstrado no exemplo de código a seguir:
Os valores armazenados na coleção KeyValues serão armazenados nos metadados para a página indexada e serão
restaurados quando o usuário tocar em um resultado de pesquisa que contém um link profundo (ou quando a
entrega for usada para exibir o conteúdo em outro dispositivo conectado).
Além disso, os valores para as seguintes chaves podem ser especificados:
contentType – um string que especifica o identificador de tipo uniforme do conteúdo indexado. A convenção
recomendada para uso para esse valor é o nome do tipo da página com o conteúdo indexado.
associatedWebPage – um string que representa a página da Web a ser visitada se o conteúdo indexado
também puder ser exibido na Web ou se o aplicativo der suporte a links profundos do Safari.
shouldAddToPublicIndex – um string de true ou false que controla a necessidade de adição de conteúdo
indexado ao índice de nuvem pública da Apple, que, em seguida, pode ser apresentado aos usuários que ainda
não instalaram o aplicativo em seu dispositivo iOS. No entanto, o conteúdo ter sido definido para indexação
pública não significa que ele será automaticamente adicionado ao índice de nuvem pública da Apple. Para obter
mais informações, consulte Indexação de pesquisa pública. Observe que essa chave deve ser definida como
false ao adicionar dados pessoais à coleção KeyValues .
NOTE
A coleção KeyValues não é usada na plataforma Android.
Resumo
Este artigo explicou como usar a indexação de aplicativo e a vinculação profunda para tornar o conteúdo do
aplicativo Xamarin.Forms pesquisável em dispositivos iOS e Android. A indexação de aplicativo permite que os
aplicativos que seriam esquecidos após alguns usos permaneçam relevantes fazendo com que eles apareçam nos
resultados da pesquisa.
Links relacionados
Vinculação profunda (amostra)
APIs de pesquisa do iOS
Vinculação de aplicativo no Android 6.0
AppLinkEntry
IAppLinkEntry
IAppLinks
Comportamentos do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Comportamentos permitem adicionar funcionalidade a controles de interface do usuário sem precisar dividi-los
em subclasses. Comportamentos são escritos em código e adicionados aos controles em XAML ou em código.
Comportamentos anexados
Comportamentos anexados são classes static com uma ou mais propriedades anexadas. Este artigo demonstra
como criar e consumir comportamentos anexados.
Comportamentos do Xamarin.Forms
Comportamentos do Xamarin.Forms são criados derivando da classe Behavior ou Behavior<T> . Este artigo
demonstra como criar e consumir comportamentos do Xamarin.Forms.
Comportamentos reutilizáveis
Comportamentos são reutilizáveis em mais de um aplicativo. Estes artigos explicam como criar comportamentos
úteis para executar a funcionalidade comumente usada.
Introdução aos comportamentos
12/04/2019 • 2 minutes to read • Edit Online
Comportamentos permitem adicionar funcionalidade a controles de interface do usuário sem precisar dividi-los
em subclasses. Em vez disso, a funcionalidade é implementada em uma classe de comportamento e anexada ao
controle como se fizesse parte do próprio controle. Este artigo fornece uma introdução a comportamentos.
Os comportamentos permitem que você implemente código que normalmente precisaria escrever como code-
behind, porque interagem diretamente com a API do controle, de forma que podem ser anexados de forma
concisa ao controle e empacotados para reutilização em mais de um aplicativo. Eles podem ser usados para
fornecer uma ampla gama de funcionalidade para controles, como:
Adicionar um validador de email a um Entry .
Criar um controle de classificação usando um reconhecedor de gesto de toque.
Controlar uma animação.
Adicionar um efeito a um controle.
Os comportamentos também permitem cenários mais avançados. No contexto dos comandos, os
comportamentos são uma abordagem útil para conectar um controle a um comando. Além disso, eles podem ser
usados para associar comandos a controles que não foram projetados para interagir com comandos. Por exemplo,
podem ser usados para invocar um comando em resposta ao acionamento de um evento.
O Xamarin.Forms dá suporte a dois estilos diferentes de comportamentos:
Comportamentos do Xamarin.Forms – as classes que derivam da classe Behavior ou Behavior<T> , em que
T é o tipo do controle ao qual o comportamento deve ser aplicado. Para obter mais informações sobre
comportamentos no Xamarin.Forms, confira Comportamentos do Xamarin.Forms e Comportamentos
reutilizáveis.
Comportamentos anexados – classes static com uma ou mais propriedades anexadas. Para obter mais
informações sobre comportamentos anexados, confira Comportamentos anexados.
Este guia se concentra em comportamentos do Xamarin.Forms porque eles são a abordagem preferida para
construção de comportamentos.
Links relacionados
Comportamento
Comportamento<T>
Comportamentos anexados
12/04/2019 • 7 minutes to read • Edit Online
Baixar o exemplo
Comportamentos anexados são classes estáticas com uma ou mais propriedades anexadas. Este artigo demonstra
como criar e consumir comportamentos anexados.
Visão geral
Uma propriedade anexada é um tipo especial de propriedade associável. Elas são definidas em uma classe, mas
são anexadas a outros objetos e reconhecíveis no XAML como atributos que contêm uma classe e um nome de
propriedade separados por um ponto.
Uma propriedade anexada pode definir um delegado propertyChanged que será executado quando o valor da
propriedade for alterado, por exemplo, quando a propriedade for definida em um controle. Quando o delegado
propertyChanged é executado, é passada a ele uma referência ao controle a que ele está sendo anexado, bem como
parâmetros que contêm os valores antigo e novo da propriedade. Esse delegado pode ser usado para adicionar
uma nova funcionalidade ao controle a que a propriedade está anexada manipulando a referência que é passada,
da seguinte maneira:
1. O delegado propertyChanged converte a referência do controle, que é recebida como um BindableObject , para
o tipo de comportamento que o controle deve melhorar.
2. O delegado propertyChanged modifica as propriedades do controle, chama os métodos do controle ou registra
manipuladores de eventos para eventos expostos pelo controle, a fim de implementar a funcionalidade do
comportamento de núcleo.
Um problema com comportamentos anexados é que eles são definidos em uma classe static , com propriedades
static e métodos. Isso dificulta a criação de comportamentos anexados com estado. Além disso, os
comportamentos do Xamarin.Forms substituíram os comportamentos anexados como a abordagem preferencial
para a construção de comportamentos. Para obter mais informações sobre comportamentos no Xamarin.Forms,
confira Comportamentos do Xamarin.Forms e Comportamentos reutilizáveis.
A classe NumericValidationBehavior contém uma propriedade anexada chamada AttachBehavior , com um getter e
setter static , que controla a adição ou remoção do comportamento do controle a que ele será anexado. Essa
propriedade anexada registra o método OnAttachBehaviorChanged que será executado quando o valor da
propriedade for alterado. Esse método registra ou cancela o registra de um manipulador de eventos para o evento
TextChanged , com base no valor da propriedade anexada AttachBehavior . A funcionalidade núcleo do
comportamento é fornecida pelo método OnEntryTextChanged , que analisa o valor inserido no Entry pelo usuário
e define a propriedade TextColor como vermelha caso o valor não seja um double .
NOTE
Comportamentos anexados são escritos para um tipo de controle específico (ou uma superclasse que pode ser aplicada a
muitos controles) e só devem ser adicionados a um controle compatível. Tentar anexar um comportamento a um controle
incompatível resultará em um comportamento desconhecido e depende da implementação do comportamento.
Resumo
Este artigo demonstrou como criar e consumir comportamentos anexados. Comportamentos anexados são
classes static com uma ou mais propriedades anexadas.
Links relacionados
Comportamentos anexados (amostra)
Criar comportamentos do Xamarin.Forms
12/04/2019 • 10 minutes to read • Edit Online
Baixar o exemplo
Os comportamentos do Xamarin.Forms são criados pela derivação da classe Behavior ou Behavior<T>. Este
artigo demonstra como criar e consumir comportamentos do Xamarin.Forms.
Visão geral
O processo para criar um comportamento do Xamarin.Forms é o seguinte:
1. Criar uma classe que herda da classe Behavior ou Behavior<T> , em que T é o tipo do controle ao qual o
comportamento deve ser aplicado.
2. Substituir o método OnAttachedTo para executar qualquer configuração necessária.
3. Substituir o método OnDetachingFrom para executar qualquer limpeza necessária.
4. Implementar a funcionalidade principal do comportamento.
Isso resulta na estrutura mostrada no exemplo de código a seguir:
// Behavior implementation
}
O método OnAttachedTo será acionado imediatamente após o comportamento ser anexado a um controle. Esse
método recebe uma referência ao controle ao qual ele está anexado e pode ser usado para registrar
manipuladores de eventos ou para realizar outra configuração necessária para dar suporte à funcionalidade do
comportamento. Por exemplo, você pode assinar um evento em um controle. A funcionalidade do
comportamento, então, seria implementada no manipulador do evento.
O método OnDetachingFrom é acionado quando o comportamento é removido do controle. Esse método recebe
uma referência ao controle ao qual ele está anexado e é usado para executar qualquer limpeza necessária. Por
exemplo, você poderia cancelar a assinatura de um evento em um controle para evitar perdas de memória.
O comportamento, em seguida, poderá ser consumido sendo anexado à coleção Behaviors do controle
apropriado.
NOTE
O Xamarin.Forms não define o BindingContext de um comportamento, porque os comportamentos podem ser
compartilhados e aplicados a vários controles por meio dos estilos.
O exemplo de código a seguir mostra uma propriedade anexada que controla a adição e a remoção de
NumericValidationBehavior :
public class NumericValidationBehavior : Behavior<Entry>
{
public static readonly BindableProperty AttachBehaviorProperty =
BindableProperty.CreateAttached ("AttachBehavior", typeof(bool), typeof(NumericValidationBehavior),
false, propertyChanged: OnAttachBehaviorChanged);
A classe NumericValidationBehavior contém uma propriedade anexada chamada AttachBehavior , com um getter
e setter static , que controla a adição ou remoção do comportamento do controle a que ele será anexado. Essa
propriedade anexada registra o método OnAttachBehaviorChanged que será executado quando o valor da
propriedade for alterado. Esse método adiciona ou remove o comportamento do controle com base no valor da
propriedade anexada AttachBehavior .
O seguinte exemplo de código mostra um estilo explícito para o NumericValidationBehavior que usa a
propriedade anexada AttachBehavior e que pode ser aplicado a controles Entry :
O Style pode ser aplicado a um controle Entry definindo sua propriedade Style para a instância de Style
usando a extensão de marcação StaticResource , conforme demonstrado no exemplo de código a seguir:
Como alternativa, a coleção Behaviors do controle pode ser limpa, conforme demonstrado no exemplo de código
a seguir:
entry.Behaviors.Clear();
Além disso, observe que os comportamentos não serão removidos implicitamente dos controles quando páginas
forem removidas da pilha de navegação. Em vez disso, eles devem ser removidos explicitamente antes que
páginas saiam do escopo.
Resumo
Este artigo demonstrou como criar e consumir comportamentos do Xamarin.Forms. Comportamentos do
Xamarin.Forms são criados derivando da classe Behavior ou Behavior<T> .
Links relacionados
Comportamento do Xamarin.Forms (amostra)
Comportamento de Xamarin.Forms aplicado com um estilo (amostra)
Comportamento
Comportamento
Comportamentos reutilizáveis
12/04/2019 • 2 minutes to read • Edit Online
Comportamentos são reutilizáveis em mais de um aplicativo. Estes artigos explicam como criar comportamentos
úteis para executar a funcionalidade comumente usada.
EffectBehavior reutilizável
Os comportamentos são uma abordagem útil para adicionar um efeito a um controle, removendo o código de
texto clichê de tratamento de efeito dos arquivos code-behind. Este artigo demonstra como criar e consumir um
comportamento de Xamarin.Forms para adicionar um efeito a um controle.
EventToCommandBehavior reutilizável
Comportamentos podem ser usados para associar comandos a controles que não foram projetados para interagir
com comandos. Este artigo demonstra como criar e consumir um comportamento de Xamarin.Forms para
invocar um comando quando um evento é disparado.
EffectBehavior reutilizável
12/04/2019 • 7 minutes to read • Edit Online
Visão geral
A classe EffectBehavior é um comportamento personalizado do Xamarin.Forms reutilizável que adiciona uma
instância Effect a um controle quando o comportamento é anexado ao controle e remove a instância Effect
quando o comportamento é desanexado do controle.
As seguintes propriedades de comportamento precisam ser definidas para que o comportamento seja usado:
Grupo – o valor do atributo ResolutionGroupName para a classe de efeito.
Name – o valor do atributo ExportEffect para a classe de efeito.
Para obter mais informações sobre efeitos, confira Efeitos.
NOTE
O EffectBehavior é uma classe personalizada que pode estar localizada no exemplo de Comportamento de efeito, e não
faz parte do Xamarin.Forms.
Criação do comportamento
A classe EffectBehaviorderiva da classe Behavior<T> , em que T é um View . Isso significa que a classe
EffectBehavior pode ser anexada a qualquer controle do Xamarin.Forms.
Implementação de propriedades associáveis
A classe EffectBehavior define duas instâncias BindableProperty , usadas para adicionar um Effect a um
controle quando o comportamento é anexado ao controle. Essas propriedades são mostradas no seguinte
exemplo de código:
public class EffectBehavior : Behavior<View>
{
public static readonly BindableProperty GroupProperty =
BindableProperty.Create ("Group", typeof(string), typeof(EffectBehavior), null);
public static readonly BindableProperty NameProperty =
BindableProperty.Create ("Name", typeof(string), typeof(EffectBehavior), null);
Quando o EffectBehavior é consumido, a propriedade Group deve ser definida como o valor do atributo
ResolutionGroupName para o efeito. Além disso, a propriedade Name deve ser definida como o valor do atributo
ExportEffect para o efeito.
Implementação de substituições
A classe EffectBehavior substitui os métodos OnAttachedTo e OnDetachingFrom da classe Behavior<T> , conforme
mostrado no seguinte exemplo de código:
O método OnAttachedTo realiza a instalação chamando o método AddEffect , passando o controle anexado como
parâmetro. O método OnDetachingFrom realiza a limpeza chamando o método RemoveEffect , passando o controle
anexado como um parâmetro.
Implementação da funcionalidade de comportamento
A finalidade do comportamento é adicionar o Effect definido nas propriedades Group e Name a um controle
quando o comportamento é anexado ao controle e remover o Effect quando o comportamento é desanexado do
controle. A principal funcionalidade de comportamento é mostrada no seguinte exemplo de código:
public class EffectBehavior : Behavior<View>
{
...
void AddEffect (View view)
{
var effect = GetEffect ();
if (effect != null) {
view.Effects.Add (GetEffect ());
}
}
Effect GetEffect ()
{
if (!string.IsNullOrWhiteSpace (Group) && !string.IsNullOrWhiteSpace (Name)) {
return Effect.Resolve (string.Format ("{0}.{1}", Group, Name));
}
return null;
}
}
O método AddEffect é executado em resposta ao EffectBehavior ser anexado a um controle e ele recebe o
controle anexado como um parâmetro. O método, então, adiciona o efeito recuperado à coleção Effects do
controle. O método RemoveEffect é executado em resposta ao EffectBehavior ser desanexado de um controle e
ele recebe o controle anexado como um parâmetro. O método, então, remove o efeito da coleção Effects do
controle.
O método GetEffect usa o método Effect.Resolve para recuperar o Effect . O efeito é localizado por meio de
uma concatenação dos valores de propriedade Group e Name . Se uma plataforma não fornecer o efeito, o método
Effect.Resolve retornará um valor não null .
Consumo do comportamento
A classe EffectBehavior pode ser anexada à coleção Behaviors de um controle, conforme demonstrado no
seguinte exemplo de código XAML:
A vantagem de usar esse comportamento para adicionar e remover efeitos de controles é que o código de
manipulação de efeito clichê pode ser removido de arquivos code-behind.
Resumo
Este artigo demonstrou o uso de um comportamento para adicionar um efeito a um controle. A classe
EffectBehavior é um comportamento personalizado do Xamarin.Forms reutilizável que adiciona uma instância
Effect a um controle quando o comportamento é anexado ao controle e remove a instância Effect quando o
comportamento é desanexado do controle.
Links relacionados
Efeitos
Comportamento de efeito (exemplo)
Comportamento
Comportamento<T>
EventToCommandBehavior reutilizável
12/04/2019 • 11 minutes to read • Edit Online
Baixar o exemplo
Comportamentos podem ser usados para associar comandos a controles que não foram projetados para interagir
com comandos. Este artigo demonstra como criar e consumir um comportamento do Xamarin.Forms para
invocar um comando quando um evento é disparado.
Visão geral
A classe EventToCommandBehavior é um comportamento personalizado reutilizável do Xamarin.Forms que executa
um comando em resposta a qualquer acionamento de evento. Por padrão, os argumentos de evento para o evento
serão passados para o comando e podem ser opcionalmente convertidos por uma implementação de
IValueConverter .
As seguintes propriedades de comportamento precisam ser definidas para que o comportamento seja usado:
EventName – o nome do evento que o comportamento escuta.
Command – o ICommand a ser executado. O comportamento espera encontrar a instância ICommand do
BindingContext do controle anexado, que pode ser herdada de um elemento pai.
NOTE
O EventToCommandBehavior é uma classe personalizada que pode estar localizada na amostra de Comportamento de
EventToCommand, não fazendo parte do Xamarin.Forms.
Criação do comportamento
A classe EventToCommandBehavior deriva da classe BehaviorBase<T> , que, por sua vez, deriva da classe Behavior<T> .
A finalidade da classe BehaviorBase<T> é fornecer uma classe base para todos os comportamentos do
Xamarin.Forms que exigem que o BindingContext do comportamento seja definido como o controle anexado. Isso
garante que o comportamento possa ser associado ao ICommand especificado pela propriedade Command e possa
executá-lo quando o comportamento for consumido.
A classe BehaviorBase<T> fornece um método OnAttachedTo substituível que define o BindingContext do
comportamento e um método OnDetachingFrom substituível que limpa o BindingContext . Além disso, a classe
armazena uma referência ao controle anexado na propriedade AssociatedObject .
Implementação de propriedades associáveis
A classe EventToCommandBehavior define quatro instâncias de BindableProperty , que executam um comando
definido pelo usuário quando um evento é disparado. Essas propriedades são mostradas no seguinte exemplo de
código:
public class EventToCommandBehavior : BehaviorBase<View>
{
public static readonly BindableProperty EventNameProperty =
BindableProperty.Create ("EventName", typeof(string), typeof(EventToCommandBehavior), null,
propertyChanged: OnEventNameChanged);
public static readonly BindableProperty CommandProperty =
BindableProperty.Create ("Command", typeof(ICommand), typeof(EventToCommandBehavior), null);
public static readonly BindableProperty CommandParameterProperty =
BindableProperty.Create ("CommandParameter", typeof(object), typeof(EventToCommandBehavior), null);
public static readonly BindableProperty InputConverterProperty =
BindableProperty.Create ("Converter", typeof(IValueConverter), typeof(EventToCommandBehavior), null);
Quando a classe EventToCommandBehavior é consumida, a propriedade Command deve ser associada a um ICommand ,
a ser executado em resposta ao acionamento do evento definido na propriedade EventName . O comportamento
esperará encontrar o ICommand no BindingContext do controle anexado.
Por padrão, os argumentos do evento para o evento serão passados para o comando. Esses dados podem ser
opcionalmente convertidos conforme são passados entre a origem e o destino pelo mecanismo de associação,
especificando uma implementação de IValueConverter como o valor da propriedade Converter . Como
alternativa, um parâmetro pode ser passado para o comando especificando o valor da propriedade
CommandParameter .
Implementação de substituições
A classe EventToCommandBehavior substitui os métodos OnAttachedTo e OnDetachingFrom da classe
BehaviorBase<T> , conforme mostrado no seguinte exemplo de código:
O método OnAttachedTo executa a instalação por meio da chamada ao método RegisterEvent , passando o valor
da propriedade EventName como um parâmetro. O método OnDetachingFrom executa a limpeza por meio da
chamada ao método DeregisterEvent , passando o valor da propriedade EventName como um parâmetro.
Implementação da funcionalidade de comportamento
A finalidade do comportamento é executar o comando definido pela propriedade Command em resposta ao
acionamento do evento definido pela propriedade EventName . A principal funcionalidade de comportamento é
mostrada no seguinte exemplo de código:
public class EventToCommandBehavior : BehaviorBase<View>
{
...
void RegisterEvent (string name)
{
if (string.IsNullOrWhiteSpace (name)) {
return;
}
object resolvedParameter;
if (CommandParameter != null) {
resolvedParameter = CommandParameter;
} else if (Converter != null) {
resolvedParameter = Converter.Convert (eventArgs, typeof(object), null, null);
} else {
resolvedParameter = eventArgs;
}
if (Command.CanExecute (resolvedParameter)) {
Command.Execute (resolvedParameter);
}
}
...
}
Consumo do comportamento
A classe EventToCommandBehavior pode ser anexada à coleção Behaviors de um controle, conforme demonstrado
no seguinte exemplo de código XAML:
Em tempo de execução, o comportamento responderá à interação com o controle. Quando um item for
selecionado na ListView , o evento ItemSelected será disparado, o que executará o OutputAgeCommand no
ViewModel. Isso, por sua vez, atualiza a propriedade SelectedItemText do ViewModel à qual o Label está
associado, conforme mostrado nas seguintes capturas de tela:
A vantagem de usar esse comportamento para executar um comando quando um evento é disparado é que os
comandos podem ser associados a controles que não foram projetados para interagir com comandos. Além disso,
isso remove o código de manipulação de eventos de texto clichê dos arquivos code-behind.
Resumo
Este artigo demonstrou como usar um comportamento do Xamarin.Forms para invocar um comando quando um
evento é disparado. Comportamentos podem ser usados para associar comandos a controles que não foram
projetados para interagir com comandos.
Links relacionados
Comportamento de EventToCommand (amostra)
Comportamento
Comportamento<T>
Renderizadores personalizados do Xamarin.Forms
12/04/2019 • 5 minutes to read • Edit Online
Personalizar um ContentPage
Um ContentPage é um elemento visual que mostra uma única exibição e ocupa a maior parte da tela. Este
artigo demonstra como criar um renderizador personalizado para a página ContentPage , permitindo que os
desenvolvedores substituam a renderização nativa padrão com sua própria personalização específica a uma
plataforma.
Implementar um HybridWebView
Este artigo demonstra como criar um renderizador personalizado para um controle personalizado
HybridWebView , que demonstra como aprimorar os controles da Web específicos a uma plataforma para
permitir que código C# seja invocado do JavaScript.
Links relacionados
Efeitos
Renderizadores personalizados (vídeo do Xamarin University)
Introdução a renderizadores personalizados
12/04/2019 • 9 minutes to read • Edit Online
O controle MyEntry é um controle Entry em que o BackgroundColor é definido como cinza, que pode ser
referenciado no XAML declarando um namespace para sua localização e usando o prefixo do namespace no
elemento de controle. O seguinte exemplo de código mostra como o controle personalizado MyEntry pode ser
consumido por um ContentPage :
<ContentPage
...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<local:MyEntry Text="In Shared Code" />
...
</ContentPage>
O prefixo do namespace local pode ser qualquer coisa. No entanto, os valores de namespace e assembly devem
corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado para
referenciar o controle personalizado.
NOTE
Definir o xmlns é muito mais simples em projetos de biblioteca do .NET Standard do que em projetos compartilhados. Uma
biblioteca do .NET Standard é compilada em um assembly e, portanto, é fácil determinar qual deveria ser o valor de
assembly=CustomRenderer . Ao usar Projetos compartilhados, todos os ativos compartilhados (incluindo o XAML) são
compilados em cada um dos projetos de referência, o que significa que, se os projetos do iOS, do Android e da UWP tiverem
seus próprios nomes de assembly, será impossível escrever a declaração xmlns porque o valor deverá ser diferente para
cada aplicativo. Controles personalizados em XAML para Projetos compartilhados exigirão que cada projeto de aplicativo seja
configurado com o mesmo nome de assembly.
O controle personalizado MyEntry é renderizado em cada plataforma, com uma tela de fundo cinza, conforme
mostrado nas capturas de tela seguir:
A alteração da cor da tela de fundo do controle em cada plataforma foi feira usando apenas subclasses do controle.
No entanto, há limites para o que é possível realizar com essa técnica, pois não é possível tirar proveito dos
aprimoramentos e personalizações específicos da plataforma. Quando são necessários, renderizadores
personalizados devem ser implementados.
Os tópicos desta série fornecem demonstrações e explicações sobre esse processo para diferentes elementos do
Xamarin.Forms.
Solução de problemas
Se um controle personalizado estiver em um projeto de biblioteca do .NET Standard que foi adicionado à solução
(ou seja, não na biblioteca do .NET Standard criada pelo modelo de projeto de aplicativo do Xamarin.Forms para
Visual Studio para Mac/Visual Studio), poderá ocorrer uma exceção no iOS ao tentar acessar o controle
personalizado. Se esse problema ocorrer, ele poderá ser resolvido criando uma referência ao controle
personalizado usando a classe AppDelegate :
var temp = new ClassInPCL(); // in AppDelegate, but temp not used anywhere
Isso força o compilador a reconhecer o tipo ClassInPCL resolvendo-o. Como alternativa, o atributo Preserve pode
ser adicionado à classe AppDelegate para alcançar o mesmo resultado:
Isso cria uma referência ao tipo ClassInPCL , indicando que ele é necessário no tempo de execução. Para obter
mais informações, confira Preservando o código.
Resumo
Este artigo forneceu uma introdução aos renderizadores personalizados e descreveu o processo de criação de um
renderizador personalizado. Renderizadores personalizados fornecem uma abordagem eficiente para personalizar
a aparência e o comportamento de controles do Xamarin.Forms. Eles podem ser usados para pequenas alterações
de estilo ou personalização sofisticada de comportamento e de layout específico da plataforma.
Links relacionados
Efeitos
Classes base de renderizador e controles nativos
12/04/2019 • 5 minutes to read • Edit Online
Cada controle do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria uma
instância de um controle nativo. Este artigo lista as classes de renderizador e controle nativo que implementam
cada página, layout, exibição e célula do Xamarin.Forms.
Com exceção da classe MapRenderer , os renderizadores específicos da plataforma podem ser encontrados nos
seguintes namespaces:
iOS – Xamarin.Forms.Platform.iOS
Android – Xamarin.Forms.Platform.Android
Android (AppCompat) – Xamarin.Forms.Platform.Android.AppCompat
UWP (Plataforma Universal do Windows) – Xamarin.Forms.Platform.UWP
A classe MapRenderer pode ser encontrada nos seguintes namespaces:
iOS – Xamarin.Forms.Maps.iOS
Android – Xamarin.Forms.Maps.Android
UWP (Plataforma Universal do Windows) – Xamarin.Forms.Maps.UWP
Pages (Páginas)
A seguinte tabela lista as classes de renderizador e controle nativo que implementam cada tipo Page do
Xamarin.Forms:
ANDROID
PÁGINA RENDERIZADOR IOS ANDROID (APPCOMPAT) UWP
Layouts
A seguinte tabela lista as classes de renderizador e controle nativo que implementam cada tipo Layout do
Xamarin.Forms:
Exibições
A seguinte tabela lista as classes de renderizador e controle nativo que implementam cada tipo View do
Xamarin.Forms:
ANDROID
EXIBIÇÕES RENDERIZADOR IOS ANDROID (APPCOMPAT) UWP
Células
A seguinte tabela lista as classes de renderizador e controle nativo que implementam cada tipo Cell do
Xamarin.Forms:
Resumo
Este artigo listou as classes de renderizador e controle nativo que implementam cada página, layout, exibição e
célula do Xamarin.Forms. Cada controle do Xamarin.Forms tem um renderizador que o acompanha para cada
plataforma que cria uma instância de um controle nativo.
Links relacionados
Renderizadores personalizados (vídeo do Xamarin University)
Personalizando uma entrada
12/04/2019 • 12 minutes to read • Edit Online
Baixar o exemplo
O controle Entry do Xamarin.Forms permite a edição de uma única linha de texto. Este artigo demonstra como
criar um renderizador personalizado para o controle Entry, permitindo que os desenvolvedores substituam a
renderização nativa padrão por sua própria personalização específica da plataforma.
Cada controle do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria uma
instância de um controle nativo. Quando um controle Entry é renderizado por um aplicativo Xamarin.Forms, no
iOS, é criada uma instância da classe EntryRenderer , que, por sua vez, cria uma instância de um controle
UITextField nativo. Na plataforma Android, a classe EntryRenderer cria uma instância de um controle EditText .
No UWP (Plataforma Universal do Windows), a classe EntryRenderer cria uma instância de um controle TextBox .
Para obter mais informações sobre as classes de renderizador e de controle nativo para as quais os controles do
Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles nativos.
O diagrama a seguir ilustra a relação entre o controle Entry e os controles nativos correspondentes que o
implementam:
O controle MyEntry é criado no projeto da biblioteca do .NET Standard e é apenas um controle Entry . A
personalização do controle será realizada no renderizador personalizado. Portanto, nenhuma implementação
adicional é necessária no controle MyEntry .
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<local:MyEntry Text="In Shared Code" />
...
</ContentPage>
O prefixo do namespace local pode ter qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar o controle personalizado.
O seguinte exemplo de código mostra como o controle MyEntry pode ser consumido por uma página em C#:
public class MainPage : ContentPage
{
public MainPage ()
{
Content = new StackLayout {
Children = {
new Label {
Text = "Hello, Custom Renderer !",
},
new MyEntry {
Text = "In Shared Code",
}
},
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
}
}
Esse código cria uma instância de um novo objeto ContentPage que exibirá um Label e um controle MyEntry ,
centralizado vertical e horizontalmente na página.
Agora, um renderizador personalizado pode ser adicionado a cada projeto de aplicativo para personalizar a
aparência do controle em cada plataforma.
NOTE
O fornecimento de um renderizador personalizado em cada projeto da plataforma é opcional. Se um renderizador
personalizado não estiver registrado, será usado o renderizador padrão da classe base do controle.
O seguinte diagrama ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações
entre elas:
O controle MyEntry é renderizado por classes MyEntryRenderer específicas da plataforma, que derivam da classe
EntryRenderer para cada plataforma. Isso faz com que cada controle MyEntry seja renderizado com a cor da tela
de fundo específica da plataforma, conforme mostrado nas seguintes capturas de tela:
A classe EntryRenderer expõe o método OnElementChanged , que é chamado quando um controle do
Xamarin.Forms é criado para renderizar o controle nativo correspondente. Esse método usa um parâmetro
ElementChangedEventArgs , que contém as propriedades OldElement e NewElement . Essas propriedades
representam o elemento do Xamarin.Forms ao qual o renderizador estava anexado e o elemento do
Xamarin.Forms ao qual o renderizador está anexado, respectivamente. No aplicativo de exemplo, a propriedade
OldElement será null e a propriedade NewElement conterá uma referência ao controle MyEntry .
Uma versão de substituição do método OnElementChanged na classe MyEntryRenderer é o lugar para realizar a
personalização do controle nativo. Uma referência tipada ao controle nativo que está sendo usado na plataforma
pode ser acessada por meio da propriedade Control . Além disso, é possível obter uma referência ao controle do
Xamarin.Forms que está sendo renderizado por meio da propriedade Element , embora ela não seja usada no
aplicativo de exemplo.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo usa dois parâmetros – o nome do tipo do controle do Xamarin.Forms
que está sendo renderizado e o nome do tipo do renderizador personalizado. O prefixo assembly do atributo
especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a implementação de cada classe de renderizador personalizado MyEntryRenderer
específica da plataforma.
Criando o renderizador personalizado no iOS
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma iOS:
using Xamarin.Forms.Platform.iOS;
if (Control != null) {
// do whatever you want to the UITextField here!
Control.BackgroundColor = UIColor.FromRGB (204, 153, 255);
Control.BorderStyle = UITextBorderStyle.Line;
}
}
}
}
A chamada ao método OnElementChanged da classe base cria uma instância de um controle UITextField do iOS,
com uma referência ao controle que está sendo atribuído à propriedade Control do renderizador. A cor da tela de
fundo é definida como roxo-claro com o método UIColor.FromRGB .
Criando o renderizador personalizado no Android
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma Android:
using Xamarin.Forms.Platform.Android;
if (Control != null)
{
Control.SetBackgroundColor(global::Android.Graphics.Color.LightGreen);
}
}
}
}
A chamada ao método OnElementChanged da classe base cria uma instância de um controle EditText do Android,
com uma referência ao controle que está sendo atribuído à propriedade Control do renderizador. A cor da tela de
fundo é definida como verde-claro com o método Control.SetBackgroundColor .
Criando o renderizador personalizado na UWP
O seguinte exemplo de código mostra o renderizador personalizado para o UWP:
if (Control != null)
{
Control.Background = new SolidColorBrush(Colors.Cyan);
}
}
}
}
A chamada ao método OnElementChanged da classe base cria uma instância de um controle TextBox , com uma
referência ao controle que está sendo atribuído à propriedade Control do renderizador. A cor da tela de fundo é
então definida como ciano pela criação de uma instância SolidColorBrush .
Resumo
Este artigo demonstrou como criar um renderizador de controle personalizado para o controle Entry do
Xamarin.Forms, permitindo que os desenvolvedores substituam a renderização nativa padrão por sua própria
personalização específica da plataforma. Os renderizadores personalizados fornecem uma abordagem eficiente
para personalizar a aparência de controles do Xamarin.Forms. Eles podem ser usados para pequenas alterações de
estilo ou personalização sofisticada de comportamento e de layout específico da plataforma.
Links relacionados
CustomRendererEntry (amostra)
Personalizando uma ContentPage
12/04/2019 • 13 minutes to read • Edit Online
Baixar o exemplo
Uma ContentPage é um elemento visual que mostra uma única exibição e ocupa a maior parte da tela. Este
artigo mostra como criar um renderizador personalizado para a página ContentPage, permitindo que os
desenvolvedores substituam a renderização nativa padrão por sua própria personalização específica a uma
plataforma.
Cada um dos controles do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria
uma instância de um controle nativo. Quando um ContentPage é renderizado por um aplicativo Xamarin.Forms,
no iOS é criada uma instância da classe PageRenderer , o que por sua vez cria uma instância de um controle
UIViewController nativo. Na plataforma Android, a classe PageRenderer cria uma instância de um controle
ViewGroup . Na UWP ( Plataforma Universal do Windows), a classe PageRenderer cria uma instância de um
controle FrameworkElement . Para obter mais informações sobre as classes de renderizador e de controle nativo
para as quais os controles do Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles
nativos.
O diagrama a seguir ilustra a relação entre o ContentPage e os controles nativos correspondentes que o
implementam:
De forma semelhante, o arquivo code-behind do ContentPage também deve permanecer inalterado, conforme
mostrado no exemplo de código a seguir:
O exemplo de código a seguir mostra como a página pode ser criada em C#:
Uma instância do CameraPage será usada para exibir o feed de câmera em tempo real em cada plataforma. A
personalização do controle será realizada no renderizador personalizado, portanto, nenhuma implementação
adicional é necessária na classe CameraPage .
Esse código simplesmente navega para o CameraPage , em que os renderizadores personalizados personalizarão a
aparência da página em cada plataforma.
NOTE
O fornecimento de um renderizador de página em cada projeto de plataforma é opcional. Se um renderizador de página não
estiver registrado, será usado o renderizador de página padrão.
O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como a relação
entre elas:
A classe PageRenderer expõe o método OnElementChanged , que é chamado quando a página do Xamarin.Forms é
criada para renderizar o controle nativo correspondente. Esse método usa um parâmetro ElementChangedEventArgs
, que contém as propriedades OldElement e NewElement . Essas propriedades representam o elemento do
Xamarin.Forms ao qual o renderizador estava anexado e o elemento do Xamarin.Forms ao qual o renderizador
está anexado, respectivamente. No aplicativo de exemplo, a propriedade OldElement será null e a propriedade
NewElement conterá uma referência à instância de CameraPage .
Uma versão de substituição do método OnElementChanged na classe CameraPageRenderer é o lugar para realização
da personalização da página nativa. É possível obter uma referência para a instância da página do Xamarin.Forms
que está sendo renderizada por meio da propriedade Element .
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo de página do Xamarin.Forms
que está sendo renderizada e o nome do tipo de renderizador personalizado. O prefixo assembly do atributo
especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a implementação do renderizador personalizado CameraPageRenderer para cada
plataforma.
Criando o renderizador de página no iOS
O exemplo de código a seguir mostra o renderizador de página para a plataforma iOS:
try {
SetupUserInterface ();
SetupEventHandlers ();
SetupLiveCameraStream ();
AuthorizeCameraUse ();
} catch (Exception ex) {
System.Diagnostics.Debug.WriteLine (@" ERROR: ", ex.Message);
}
}
...
}
}
A chamada para o método OnElementChanged da classe base cria uma instância do controle UIViewController do
iOS. O fluxo da câmera em tempo real será renderizado somente se o renderizador ainda não estiver anexado a
um elemento existente do Xamarin.Forms e se houver uma instância da página sendo renderizada pelo
renderizador personalizado.
A página, então, é personalizada por uma série de métodos que usam as APIs AVCapture para fornecer o -fluxo
em tempo real da câmera e a capacidade de tirar uma foto.
Criando o renderizador de página no Android
O exemplo de código a seguir mostra o renderizador de página para a plataforma Android:
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.Droid
{
public class CameraPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
{
...
public CameraPageRenderer(Context context) : base(context)
{
}
try
{
SetupUserInterface();
SetupEventHandlers();
AddView(view);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message);
}
}
...
}
}
A chamada para o método OnElementChanged da classe base cria uma instância de um controle ViewGroup do
Android, que é um grupo de exibições. O fluxo da câmera em tempo real será renderizado somente se o
renderizador ainda não estiver anexado a um elemento existente do Xamarin.Forms e se houver uma instância da
página sendo renderizada pelo renderizador personalizado.
A página, então, é personalizada invocando uma série de métodos que usam a API Camera para fornecer o fluxo
em tempo real da câmera e a capacidade de tirar uma foto, antes que o método AddView seja invocado para
adicionar a interface do usuário de fluxo em tempo real da câmera ao ViewGroup . Observe que, no Android,
também é necessário substituir o método OnLayout para executar operações de medida e layout na exibição. Para
obter mais informações, confira o Exemplo de renderizador de ContentPage.
Criando o renderizador de página na UWP
O exemplo de código a seguir mostra o renderizador de página para a UWP:
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace CustomRenderer.UWP
{
public class CameraPageRenderer : PageRenderer
{
...
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.Page> e)
{
base.OnElementChanged(e);
try
{
...
SetupUserInterface();
SetupBasedOnStateAsync();
this.Children.Add(page);
}
...
}
A chamada para o método OnElementChanged da classe base instancia um controle FrameworkElement , em que a
página é renderizada. O fluxo da câmera em tempo real será renderizado somente se o renderizador ainda não
estiver anexado a um elemento existente do Xamarin.Forms e se houver uma instância da página sendo
renderizada pelo renderizador personalizado. A página, então, é personalizada invocando uma série de métodos
que usam a API MediaCapture para fornecer o fluxo em tempo real da câmera e a capacidade de tirar uma foto,
antes que a página personalizada seja adicionada à coleção Children para exibição.
Ao implementar um renderizador personalizado que deriva de PageRenderer na UWP, o método ArrangeOverride
também deve ser implementado para organizar os controles da página, porque o renderizador de base não sabe o
que fazer com eles. Caso contrário, será gerada uma página em branco. Portanto, neste exemplo, o método
ArrangeOverride chamada o método Arrange na instância de Page .
NOTE
É importante parar e descartar os objetos que fornecem acesso à câmera em um aplicativo da UWP. Deixar de fazer isso
pode interferir em outros aplicativos que tentam acessar a câmera do dispositivo. Para obter mais informações, confira Exibir
a visualização da câmera.
Resumo
Este artigo demonstrou como criar um renderizador personalizado para a página ContentPage , permitindo que os
desenvolvedores substituam a renderização nativa padrão com sua própria personalização específica a uma
plataforma. Um ContentPage é um elemento visual que mostra uma única exibição e ocupa a maior parte da tela.
Links relacionados
CustomRendererContentPage (amostra)
Personalizar um mapa do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
O Xamarin.Forms.Maps fornece uma abstração multiplataforma para a exibição de mapas que usam as APIs de
mapa nativo em cada plataforma, a fim de fornecer uma experiência de mapa rápida e familiar para os usuários.
E possível usar o processo de renderização para implementar personalizações específicas da plataforma criando
um renderizador personalizado para um Map em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar um mapa personalizado do Xamarin.Forms.
2. Consumir o mapa personalizado do Xamarin.Forms.
3. Criar o renderizador personalizado para o mapa em cada plataforma.
Cada item agora será abordado por vez, para implementar um renderizador CustomMap que exibe um mapa
nativo com um marcador personalizado e uma exibição personalizada dos dados do marcador em cada
plataforma.
NOTE
Xamarin.Forms.Maps precisa ser inicializado e configurado antes do uso. Para obter mais informações, consulte
Maps Control .
O controle CustomMap é criado no projeto da biblioteca do .NET Standard e define a API para o mapa
personalizado. O mapa personalizado expõe a propriedade CustomPins que representa a coleção de objetos
CustomPin que serão renderizados pelo Controle de Mapeamento nativo em cada plataforma. A classe
CustomPin é mostrada no seguinte exemplo de código:
Essa classe define um CustomPin como herdando as propriedades da classe Pin e adicionando uma propriedade
Url .
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer">
<ContentPage.Content>
<local:CustomMap x:Name="myMap" MapType="Street"
WidthRequest="{x:Static local:App.ScreenWidth}"
HeightRequest="{x:Static local:App.ScreenHeight}" />
</ContentPage.Content>
</ContentPage>
O prefixo do namespace local pode ter qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do mapa personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar o mapa personalizado.
O seguinte exemplo de código mostra como o controle CustomMap pode ser consumido por uma página em C#:
Content = customMap;
}
}
A instância CustomMap será usada para exibir o mapa nativo em cada plataforma. Sua propriedade MapType
define o estilo de exibição do Map , com os valores possíveis sendo definidos na enumeração MapType . Para o iOS
e o Android, a largura e a altura do mapa são definidas por meio das propriedades da classe App são
inicializadas nos projetos específicos da plataforma.
A localização do mapa e os marcadores que ele contém são inicializados conforme mostrado no seguinte
exemplo de código:
public MapPage ()
{
...
var pin = new CustomPin {
Type = PinType.Place,
Position = new Position (37.79752, -122.40183),
Label = "Xamarin San Francisco Office",
Address = "394 Pacific Ave, San Francisco CA",
Id = "Xamarin",
Url = "http://xamarin.com/about/"
};
Essa inicialização adiciona um marcador personalizado e posiciona a exibição do mapa com o método
MoveToRegion , que altera a posição e o nível de aplicação de zoom do mapa com a criação de um MapSpan com
base em uma Position e uma Distance .
Agora, um renderizador personalizado pode ser adicionado a cada projeto de aplicativo para personalizar os
controles de mapa nativos.
NOTE
O fornecimento de um renderizador personalizado em cada projeto da plataforma é opcional. Se um renderizador
personalizado não estiver registrado, será usado o renderizador padrão da classe base do controle.
O seguinte diagrama ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as
relações entre elas:
O controle CustomMap é renderizado por classes de renderizador específicas da plataforma, que derivam da classe
MapRenderer para cada plataforma. Isso faz com que cada controle CustomMap seja renderizado com controles
específicos da plataforma, conforme mostrado nas seguintes capturas de tela:
A classe MapRenderer expõe o método OnElementChanged , que é chamado quando o mapa personalizado do
Xamarin.Forms é criado para renderizar o controle nativo correspondente. Esse método usa um parâmetro
ElementChangedEventArgs , que contém as propriedades OldElement e NewElement . Essas propriedades
representam o elemento do Xamarin.Forms ao qual o renderizador estava anexado e o elemento do
Xamarin.Forms ao qual o renderizador está anexado, respectivamente. No aplicativo de exemplo, a propriedade
OldElement será null e a propriedade NewElement conterá uma referência à instância de CustomMap .
if (e.OldElement != null) {
// Unsubscribe from event handlers
}
if (e.NewElement != null) {
// Configure the native control and subscribe to event handlers
}
}
O controle nativo deverá ser configurado e os manipuladores de eventos deverão ser assinados apenas quando o
renderizador personalizado for anexado a um novo elemento do Xamarin.Forms. De forma semelhante, a
assinatura dos manipuladores de eventos assinados só deverá ser cancelada quando o elemento ao qual o
renderizador está anexado for alterado. A adoção dessa abordagem ajudará a criar um renderizador
personalizado que não sofre perdas de memória.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo de controle personalizado
do Xamarin.Forms que está sendo renderizado e o nome do tipo de renderizador personalizado. O prefixo
assembly do atributo especifica que o atributo se aplica a todo o assembly.
No iOS, o marcador é chamado de anotação e pode ser uma imagem personalizada ou um marcador definido
pelo sistema de várias cores. As anotações podem opcionalmente mostrar um texto explicativo, que é exibido em
resposta à seleção da anotação pelo usuário. O texto explicativo exibe o Label e as propriedades Address da
instância Pin , com as exibições acessório direita e esquerda opcionais. Na captura de tela acima, a exibição
acessório esquerda é a imagem de um macaco, com a exibição acessório direita sendo o botão Informações.
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma iOS:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.iOS
{
public class CustomMapRenderer : MapRenderer
{
UIView customPinView;
List<CustomPin> customPins;
if (e.OldElement != null) {
var nativeMap = Control as MKMapView;
if (nativeMap != null) {
nativeMap.RemoveAnnotations(nativeMap.Annotations);
nativeMap.GetViewForAnnotation = null;
nativeMap.CalloutAccessoryControlTapped -= OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView -= OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView -= OnDidDeselectAnnotationView;
}
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
customPins = formsMap.CustomPins;
nativeMap.GetViewForAnnotation = GetViewForAnnotation;
nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView += OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView += OnDidDeselectAnnotationView;
}
}
...
}
}
O método OnElementChanged executa a seguinte configuração da instância MKMapView , desde que o renderizador
personalizado esteja anexado a um novo elemento do Xamarin.Forms:
A propriedade GetViewForAnnotation é definida como o método GetViewForAnnotation . Esse método é
chamado quando a localização da anotação se torna visível no mapa e é usado para personalizar a anotação
antes da exibição.
Os manipuladores de eventos para os eventos CalloutAccessoryControlTapped , DidSelectAnnotationView e
DidDeselectAnnotationView são registrados. Esses eventos são disparados quando o usuário toca o acessório
direito no texto explicativo e quando o usuário marca e desmarca a anotação, respectivamente. A assinatura
dos eventos é cancelada somente quando o elemento ao qual o renderizador está anexado é alterado.
Exibindo a anotação
O método GetViewForAnnotation é chamado quando a localização da anotação se torna visível no mapa e é usado
para personalizar a anotação antes da exibição. Uma anotação tem duas partes:
MkAnnotation – inclui o título, o subtítulo e a localização da anotação.
MkAnnotationView – contém a imagem para representar a anotação e, opcionalmente, um texto explicativo que
é mostrado quando o usuário toca a anotação.
O método GetViewForAnnotation aceita uma IMKAnnotation que contém os dados da anotação e retorna uma
MKAnnotationView para exibição no mapa e é mostrado no seguinte exemplo de código:
protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
annotationView = mapView.DequeueReusableAnnotation(customPin.Id.ToString());
if (annotationView == null) {
annotationView = new CustomMKAnnotationView(annotation, customPin.Id.ToString());
annotationView.Image = UIImage.FromFile("pin.png");
annotationView.CalloutOffset = new CGPoint(0, 0);
annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
((CustomMKAnnotationView)annotationView).Id = customPin.Id.ToString();
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
}
annotationView.CanShowCallout = true;
return annotationView;
}
Esse método garante que a anotação seja exibida como uma imagem personalizada, em vez de como um
marcador definido pelo sistema, e que quando a anotação for tocada, um texto explicativo seja exibido que inclua
conteúdo adicional à esquerda e à direita do título da anotação e do endereço. Isso é feito da seguinte maneira:
1. O método GetCustomPin é chamado para retornar os dados de marcador personalizados da anotação.
2. Para conservar a memória, a exibição da anotação é colocada em pool para reutilização com a chamada a
DequeueReusableAnnotation .
3. A classe CustomMKAnnotationView estende a classe MKAnnotationView com as propriedades Id e Url que
correspondem às propriedades idênticas na instância CustomPin . Uma nova instância da
CustomMKAnnotationView é criada, desde que a anotação seja null :
A propriedade CustomMKAnnotationView.Image está definida como a imagem que representará a
anotação no mapa.
A propriedade CustomMKAnnotationView.CalloutOffset é definida como um CGPoint que especifica que
o texto explicativo será centralizado acima da anotação.
A propriedade CustomMKAnnotationView.LeftCalloutAccessoryView é definida como uma imagem de um
macaco que será exibido à esquerda do título da anotação e do endereço.
A propriedade CustomMKAnnotationView.RightCalloutAccessoryView é definida como um botão
Informações que será exibido à direita do título da anotação e do endereço.
A propriedade CustomMKAnnotationView.Id é definida como a propriedade CustomPin.Id retornada pelo
método GetCustomPin . Isso permite que a anotação seja identificada para que seu texto explicativo
possa ser personalizado ainda mais, se desejado.
A propriedade CustomMKAnnotationView.Url é definida como a propriedade CustomPin.Url retornada
pelo método GetCustomPin . A URL será direcionada quando o usuário tocar o botão exibido na exibição
acessório direita do texto explicativo.
4. A propriedade MKAnnotationView.CanShowCallout é definida como true para que o texto explicativo seja
exibido quando a anotação é tocada.
5. A anotação é retornada para a exibição no mapa.
Selecionando a anotação
Quando o usuário toca a anotação, o evento DidSelectAnnotationView é disparado, que, por sua vez, executa o
método OnDidSelectAnnotationView :
if (customView.Id == "Xamarin") {
customPinView.Frame = new CGRect (0, 0, 200, 84);
var image = new UIImageView (new CGRect (0, 0, 200, 84));
image.Image = UIImage.FromFile ("xamarin.png");
customPinView.AddSubview (image);
customPinView.Center = new CGPoint (0, -(e.View.Frame.Height + 75));
e.View.AddSubview (customPinView);
}
}
Esse método estende o texto explicativo existente (que contém as exibições acessório esquerda e direita),
adicionando uma instância UIView a ele que contém uma imagem do logotipo do Xamarin, desde que a anotação
selecionada tenha sua propriedade Id definida como Xamarin . Isso permite cenários em que diferentes textos
explicativos podem ser exibidos para diferentes anotações. A instância UIView será exibida centralizada acima do
texto explicativo existente.
Tocando a exibição acessório direita do texto explicativo
Quando o usuário toca o botão Informações na exibição acessório direita do texto explicativo, o evento
CalloutAccessoryControlTapped é disparado, que, por sua vez, executa o método OnCalloutAccessoryControlTapped :
Esse método abre um navegador da Web e navega para o endereço armazenado na propriedade
CustomMKAnnotationView.Url . Observe que o endereço foi definido durante a criação da coleção CustomPin no
projeto da biblioteca do .NET Standard.
Cancelando a seleção da anotação
Quando a anotação é exibida e o usuário toca o mapa, o evento DidDeselectAnnotationView é disparado, que, por
sua vez, executa o método OnDidDeselectAnnotationView :
Esse método garante que, quando o texto explicativo existente não estiver selecionado, a parte estendida do texto
explicativo (a imagem do logotipo do Xamarin) também não será mais exibida e seus recursos serão liberados.
Para obter mais informações sobre como personalizar uma instância MKMapView , confira Mapas do iOS.
Criando o renderizador personalizado no Android
As seguintes capturas de tela mostram o mapa, antes e após a personalização:
No Android, o marcador é chamado de marcador e pode ser uma imagem personalizada ou um marcador
definido pelo sistema de várias cores. Os marcadores podem mostrar uma janela de informações, que é exibida
na resposta ao toque do usuário no marcador. A janela de informações exibe as propriedades Label e Address
da instância Pin e pode ser personalizada para incluir outros tipos de conteúdo. No entanto, apenas uma janela
de informações pode ser mostrada por vez.
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma Android:
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
Control.GetMapAsync(this);
}
}
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
}
...
}
}
Desde que o renderizador personalizado esteja anexado a um novo elemento do Xamarin.Forms, o método
OnElementChanged chamará o método MapView.GetMapAsync , que obterá o GoogleMap subjacente que está
vinculado à exibição. Depois que a instância GoogleMap estiver disponível, a substituição OnMapReady será
invocada. Esse método registra um manipulador de eventos para o evento InfoWindowClick , que é disparado
quando a janela de informações recebe um clique e tem a assinatura cancelada somente quando o elemento ao
qual o renderizador está anexado é alterado. A substituição OnMapReady também chama o método
SetInfoWindowAdapter para especificar que a instância da classe CustomMapRenderer fornecerá os métodos para
personalizar a janela de informações.
A classe CustomMapRenderer implementa a interface GoogleMap.IInfoWindowAdapter para personalizar a janela de
informações. Essa interface especifica que os seguintes métodos precisam ser implementados:
public Android.Views.View GetInfoWindow(Marker marker) – Esse método é chamado para retornar uma janela
de informações personalizada para um marcador. Se ele retornar null , a renderização de janela padrão será
usada. Se ele retornar uma View , essa View será colocada dentro do quadro da janela de informações.
public Android.Views.View GetInfoContents(Marker marker) – Esse método é chamado para retornar uma View
que traz o conteúdo da janela de informações e só é chamado se o método GetInfoWindow retorna null . Se
ele retornar null , a renderização padrão do conteúdo da janela de informações será usada.
Personalizando o marcador
O ícone usado para representar um marcador pode ser personalizado por meio da chamada ao método
MarkerOptions.SetIcon . Isso pode ser feito pela substituição do método CreateMarker , que é invocado para cada
Pin adicionado ao mapa:
Esse método cria uma instância MarkerOption para cada instância Pin . Depois de definir a posição, o rótulo e o
endereço do marcador, seu ícone será definido com o método SetIcon . Esse método usa um objeto
BitmapDescriptor que contém os dados necessários para renderizar o ícone, com a classe
BitmapDescriptorFactory fornecendo métodos auxiliares para simplificar a criação do BitmapDescriptor . Para
obter mais informações sobre como usar a classe BitmapDescriptorFactory para personalizar um marcador,
confira Personalizando um marcador.
NOTE
Se necessário, o método GetMarkerForPin pode ser invocado no renderizador de mapa para recuperar um Marker de
um Pin .
if (customPin.Id.ToString() == "Xamarin") {
view = inflater.Inflate (Resource.Layout.XamarinMapInfoWindow, null);
} else {
view = inflater.Inflate (Resource.Layout.MapInfoWindow, null);
}
if (infoTitle != null) {
infoTitle.Text = marker.Title;
}
if (infoSubtitle != null) {
infoSubtitle.Text = marker.Snippet;
}
return view;
}
return null;
}
Esse método retorna uma View que traz o conteúdo da janela de informações. Isso é feito da seguinte maneira:
Uma instância LayoutInflater é recuperada. Isso é usado para criar uma instância de um arquivo XML de
layout em sua View correspondente.
O método GetCustomPin é chamado para retornar os dados de marcador personalizados para a janela de
informações.
O layout XamarinMapInfoWindow é inflado se a propriedade CustomPin.Id é igual a Xamarin . Caso contrário, o
layout MapInfoWindow é inflado. Isso permite cenários em que diferentes layouts da janela de informações
podem ser exibidos para diferentes marcadores.
Os recursos InfoWindowTitle e InfoWindowSubtitle são recuperados do layout inflado e suas propriedades
Text são definidas com os dados correspondentes por meio da instância Marker , desde que os recursos não
sejam null .
A instância View é retornada para exibição no mapa.
NOTE
Uma janela de informações não é uma View dinâmica. Em vez disso, o Android converterá a View em um bitmap
estático e os exibirá como uma imagem. Isso significa que, embora uma janela de informações possa responder a um
evento de clique, ela não pode responder a eventos de toque ou gestos e os controles individuais na janela de informações
não podem responder a seus próprios eventos de clique.
if (!string.IsNullOrWhiteSpace (customPin.Url)) {
var url = Android.Net.Uri.Parse (customPin.Url);
var intent = new Intent (Intent.ActionView, url);
intent.AddFlags (ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity (intent);
}
}
Esse método abre um navegador da Web e navega para o endereço armazenado na propriedade Url da
instância CustomPin recuperada para o Marker . Observe que o endereço foi definido durante a criação da
coleção CustomPin no projeto da biblioteca do .NET Standard.
Para obter mais informações sobre como personalizar uma instância MapView , confira API de Mapas.
Criando o renderizador personalizado na Plataforma Universal do Windows
As seguintes capturas de tela mostram o mapa, antes e após a personalização:
No UWP, o marcador é chamado de ícone de mapa e pode ser uma imagem personalizada ou a imagem padrão
definida pelo sistema. Um ícone de mapa pode mostrar um UserControl , que é exibido em resposta ao toque do
usuário no ícone de mapa. O UserControl pode exibir qualquer conteúdo, incluindo as propriedades Label e
Address da instância Pin .
if (e.OldElement != null)
{
nativeMap.MapElementClick -= OnMapElementClick;
nativeMap.Children.Clear();
mapOverlay = null;
nativeMap = null;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
nativeMap = Control as MapControl;
customPins = formsMap.CustomPins;
nativeMap.Children.Clear();
nativeMap.MapElementClick += OnMapElementClick;
nativeMap.MapElements.Add(mapIcon);
}
}
}
...
}
}
O método OnElementChanged executa as seguintes operações, desde que o renderizador personalizado esteja
anexado a um novo elemento do Xamarin.Forms:
Ele limpa a coleção MapControl.Children para remover os elementos de interface do usuário existentes do
mapa, antes de registrar um manipulador de eventos para o evento MapElementClick . Esse evento é disparado
quando o usuário toca um MapElement ou clica nele no MapControl e tem a assinatura cancelada somente
quando o elemento ao qual o renderizador está anexado é alterado.
Cada marcador da coleção customPins é exibido na localização geográfica correta no mapa da seguinte
maneira:
A localização para o marcador é criado como uma instância Geopoint .
Uma instância MapIcon é criada para representar o marcador.
A imagem usada para representar o MapIcon é especificada definindo a propriedade MapIcon.Image .
No entanto, não há a garantia de que a imagem do ícone de mapa seja sempre mostrada, pois ela pode
ser obscurecida por outros elementos no mapa. Portanto, a propriedade CollisionBehaviorDesired do
ícone de mapa é definida como MapElementCollisionBehavior.RemainVisible , para garantir que ela
permaneça visível.
A localização do MapIcon é especificado definindo a propriedade MapIcon.Location .
A propriedade MapIcon.NormalizedAnchorPoint é definida como a localização aproximada do ponteiro na
imagem. Se essa propriedade retiver seu valor padrão de (0,0), que representa o canto superior
esquerdo da imagem, as alterações no nível de aplicação de zoom do mapa poderão fazer com que a
imagem aponte para uma localização diferente.
A instância MapIcon é adicionada à coleção MapControl.MapElements . Isso resulta na exibição do ícone
de mapa no MapControl .
NOTE
Ao usar a mesma imagem para vários ícones de mapa, a instância RandomAccessStreamReference deve ser declarada no
nível de página ou de aplicativo para melhor desempenho.
Exibindo o UserControl
Quando um usuário toca o ícone de mapa, o método OnMapElementClick é executado. O seguinte exemplo de
código mostra esse método:
if (customPin.Id.ToString() == "Xamarin")
{
if (mapOverlay == null)
{
mapOverlay = new XamarinMapOverlay(customPin);
}
nativeMap.Children.Add(mapOverlay);
MapControl.SetLocation(mapOverlay, snPoint);
MapControl.SetNormalizedAnchorPoint(mapOverlay, new Windows.Foundation.Point(0.5, 1.0));
xamarinOverlayShown = true;
}
}
else
{
nativeMap.Children.Remove(mapOverlay);
xamarinOverlayShown = false;
}
}
}
Esse método cria uma instância UserControl que exibe informações sobre o marcador. Isso é feito da seguinte
maneira:
A instância MapIcon é recuperada.
O método GetCustomPin é chamado para retornar os dados de marcador personalizados que serão exibidos.
Uma instância XamarinMapOverlay é criada para exibir os dados de fixação personalizados. Essa classe é um
controle de usuário.
A localização geográfica na qual exibir a instância XamarinMapOverlay no MapControl é criada como uma
instância Geopoint .
A instância XamarinMapOverlay é adicionada à coleção MapControl.Children . Essa coleção contém elementos
de interface do usuário XAML que serão exibidos no mapa.
A localização geográfica da instância XamarinMapOverlay no mapa é definida chamando o método
SetLocation .
A localização relativa na instância XamarinMapOverlay , que corresponde à localização especificada, é definida
chamando o método SetNormalizedAnchorPoint . Isso garante que as alterações no nível de aplicação de zoom
do mapa resultem na exibição constante da instância XamarinMapOverlay na localização correta.
Como alternativa, se as informações sobre o marcador já estiverem sendo exibidas no mapa, o toque no mapa
removerá a instância XamarinMapOverlay da coleção MapControl.Children .
Tocando no botão de informações
Quando o usuário toca o botão Informações no controle de usuário XamarinMapOverlay , o evento Tapped é
disparado, que, por sua vez, executa o método OnInfoButtonTapped :
Esse método abre um navegador da Web e navega para o endereço armazenado na propriedade Url da
instância CustomPin . Observe que o endereço foi definido durante a criação da coleção CustomPin no projeto da
biblioteca do .NET Standard.
Para obter mais informações sobre como personalizar uma instância MapControl , confira Visão geral de mapas e
localização no MSDN.
Resumo
Este artigo demonstrou como criar um renderizador personalizado para o controle Map , permitindo que os
desenvolvedores substituam a renderização nativa padrão por sua própria personalização específica da
plataforma. O Xamarin.Forms.Maps fornece uma abstração multiplataforma para a exibição de mapas que usam
as APIs de mapa nativo em cada plataforma, a fim de fornecer uma experiência de mapa rápida e familiar para os
usuários.
Links relacionados
Controle de mapas
Mapas do iOS
API de mapas
Marcador personalizado (exemplo)
Realçando uma área circular em um mapa
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
Este artigo explica como adicionar uma sobreposição circular a um mapa a fim de realçar uma área circular nele.
Visão geral
Uma sobreposição é um gráfico em camadas em um mapa. As sobreposições são suporte para elaborar conteúdos
gráficos que são dimensionados com o mapa conforme ele é ampliado e reduzido. As capturas de tela a seguir
mostram o resultado do acréscimo de uma sobreposição circular a um mapa:
Quando um controle Map é renderizado por um aplicativo Xamarin.Forms, no iOS é criada uma instância da
classe MapRenderer , o que por sua vez cria uma instância de um controle MKMapView nativo. Na plataforma
Android, a classe MapRenderer cria uma instância de um controle MapView nativo. Na UWP (Plataforma Universal
do Windows), a classe MapRenderer cria uma instância de um MapControl nativo. E possível aproveitar o processo
de renderização para implementar personalizações de mapa específicas da plataforma criando um renderizador
personalizado para um Map em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar um mapa personalizado do Xamarin.Forms.
2. Consumir o mapa personalizado do Xamarin.Forms.
3. Personalizar o mapa criando um renderizador personalizado para o mapa em cada plataforma.
NOTE
Xamarin.Forms.Maps precisa ser inicializado e configurado antes do uso. Para obter mais informações, confira
Maps Control
Para obter informações sobre como personalizar um mapa usando um renderizador personalizado, confira
Personalizando um marcador de mapa.
Criando o mapa personalizado
Crie uma classe CustomCircle com as propriedades Position e Radius :
public class CustomCircle
{
public Position Position { get; set; }
public double Radius { get; set; }
}
Em seguida, crie uma subclasse da classe Map , que adiciona uma propriedade do tipo CustomCircle :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MapOverlay;assembly=MapOverlay"
x:Class="MapOverlay.MapPage">
<ContentPage.Content>
<local:CustomMap x:Name="customMap" MapType="Street" WidthRequest="{x:Static local:App.ScreenWidth}"
HeightRequest="{x:Static local:App.ScreenHeight}" />
</ContentPage.Content>
</ContentPage>
Como alternativa, consuma o controle CustomMap declarando uma instância dele na instância da página em C#:
customMap.Pins.Add (pin);
customMap.MoveToRegion (MapSpan.FromCenterAndRadius (position, Distance.FromMiles (1.0)));
}
}
Essa inicialização adiciona instâncias de Pin e CustomCircle ao mapa personalizado e posiciona a exibição do
mapa com o método MoveToRegion , que altera a posição e o nível de aplicação de zoom do mapa com a criação de
um MapSpan com base em uma Position e uma Distance .
Personalizando o mapa
Agora, é necessário adicionar um renderizador personalizado a cada projeto de aplicativo para adicionar a
sobreposição circular ao mapa.
Criando o renderizador personalizado no iOS
Crie uma subclasse da classe MapRenderer e substitua seu método OnElementChanged para adicionar a
sobreposição circular:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.iOS
{
public class CustomMapRenderer : MapRenderer
{
MKCircleRenderer circleRenderer;
if (e.OldElement != null) {
var nativeMap = Control as MKMapView;
if (nativeMap != null) {
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
circleRenderer = null;
}
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
var circle = formsMap.Circle;
nativeMap.OverlayRenderer = GetOverlayRenderer;
Esse método executa a seguinte configuração, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A propriedade MKMapView.OverlayRenderer é definida como um delegado correspondente.
O círculo é criado definindo um objeto MKCircle estático que especifica o centro do círculo e seu raio em
metros.
O círculo é adicionado ao mapa chamando o método MKMapView.AddOverlay .
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
circle = formsMap.Circle;
Control.GetMapAsync(this);
}
}
NativeMap.AddCircle(circleOptions);
}
}
}
O método OnElementChanged chamará o método MapView.GetMapAsync , que obterá o GoogleMap subjacente que
está vinculado à exibição, desde que o renderizador personalizado esteja anexado a um novo elemento do
Xamarin.Forms. Quando a instância de GoogleMap estiver disponível, o método OnMapReady será invocado e o
círculo será criado instanciando um objeto CircleOptions que especifica o centro do círculo e seu raio em metros.
Em seguida, o círculo é adicionado ao mapa chamando o método NativeMap.AddCircle .
Criando o renderizador personalizado na Plataforma Universal do Windows
Crie uma subclasse da classe MapRenderer e substitua seu método OnElementChanged para adicionar a
sobreposição circular:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace MapOverlay.UWP
{
public class CustomMapRenderer : MapRenderer
{
const int EarthRadiusInMeteres = 6371000;
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MapControl;
var circle = formsMap.Circle;
Esse método executa as seguintes operações, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A posição e o raio do círculo são recuperados da propriedade CustomMap.Circle e passados para o método
GenerateCircleCoordinates , que gera coordenadas de latitude e longitude para o perímetro do círculo. O código
desse método auxiliar é mostrado abaixo.
As coordenadas de perímetro do círculo são convertidas em um List de coordenadas BasicGeoposition .
O círculo é criado instanciando um objeto MapPolygon . A classe MapPolygon é usada para exibir uma forma de
vários pontos no mapa, definindo sua propriedade Path como um objeto Geopath que contém as
coordenadas da forma.
O polígono é renderizado no mapa adicionando-o à coleção MapControl.MapElements .
List<Position> GenerateCircleCoordinates(Position position, double radius)
{
double latitude = position.Latitude.ToRadians();
double longitude = position.Longitude.ToRadians();
double distance = radius / EarthRadiusInMeteres;
var positions = new List<Position>();
return positions;
}
Resumo
Este artigo explicou como adicionar uma sobreposição circular a um mapa a fim de realçar uma área circular nele.
Links relacionados
Sobreposição de mapa circular (amostra)
Personalizar um Pin de mapa
Xamarin.Forms.Maps
Realçando uma região em um mapa
12/04/2019 • 10 minutes to read • Edit Online
Baixar o exemplo
Este artigo explicou como adicionar uma sobreposição poligonal a um mapa a fim de realçar uma determinada
região. Polígonos são uma forma fechada e têm seus interiores preenchidos.
Visão geral
Uma sobreposição é um gráfico em camadas em um mapa. As sobreposições são suporte para elaborar conteúdos
gráficos que são dimensionados com o mapa conforme ele é ampliado e reduzido. As capturas de tela a seguir
mostram o resultado do acréscimo de uma sobreposição de polígono a um mapa:
Quando um controle Map é renderizado por um aplicativo Xamarin.Forms, no iOS é criada uma instância da
classe MapRenderer , o que por sua vez cria uma instância de um controle MKMapView nativo. Na plataforma
Android, a classe MapRenderer cria uma instância de um controle MapView nativo. Na UWP (Plataforma Universal
do Windows), a classe MapRenderer cria uma instância de um MapControl nativo. E possível aproveitar o processo
de renderização para implementar personalizações de mapa específicas da plataforma criando um renderizador
personalizado para um Map em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar um mapa personalizado do Xamarin.Forms.
2. Consumir o mapa personalizado do Xamarin.Forms.
3. Personalizar o mapa criando um renderizador personalizado para o mapa em cada plataforma.
NOTE
Xamarin.Forms.Maps precisa ser inicializado e configurado antes do uso. Para obter mais informações, consulte
Maps Control .
Para obter informações sobre como personalizar um mapa usando um renderizador personalizado, confira
Personalizando um marcador de mapa.
Criando o mapa personalizado
Crie uma subclasse da classe Map , que adiciona uma propriedade ShapeCoordinates :
public CustomMap ()
{
ShapeCoordinates = new List<Position> ();
}
}
A propriedade ShapeCoordinates armazenará uma coleção de coordenadas que definem a região a ser realçada.
Consumindo o mapa personalizado
Consuma o controle CustomMap declarando uma instância dele na instância da página XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MapOverlay;assembly=MapOverlay"
x:Class="MapOverlay.MapPage">
<ContentPage.Content>
<local:CustomMap x:Name="customMap" MapType="Street" WidthRequest="{x:Static local:App.ScreenWidth}"
HeightRequest="{x:Static local:App.ScreenHeight}" />
</ContentPage.Content>
</ContentPage>
Como alternativa, consuma o controle CustomMap declarando uma instância dele na instância da página em C#:
if (e.OldElement != null) {
var nativeMap = Control as MKMapView;
if (nativeMap != null) {
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
polygonRenderer = null;
}
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = GetOverlayRenderer;
int index = 0;
foreach (var position in formsMap.ShapeCoordinates)
{
coords[index] = new CLLocationCoordinate2D(position.Latitude, position.Longitude);
index++;
}
Esse método executa a seguinte configuração, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A propriedade MKMapView.OverlayRenderer é definida como um delegado correspondente.
A coleção de coordenadas de latitude e longitude é recuperada da propriedade CustomMap.ShapeCoordinates e
armazenada como uma matriz de instâncias de CLLocationCoordinate2D .
O polígono é criado chamando o método MKPolygon.FromCoordinates estático, que especifica a latitude e a
longitude de cada ponto.
O polígono é adicionado ao mapa chamando o método MKMapView.AddOverlay . Esse método fecha
automaticamente o polígono desenhando uma linha que conecta o primeiro e último pontos.
Em seguida, implemente o método GetOverlayRenderer para personalizar a renderização da sobreposição:
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
shapeCoordinates = formsMap.ShapeCoordinates;
Control.GetMapAsync(this);
}
}
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MapControl;
Esse método executa as seguintes operações, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A coleção de coordenadas de latitude e longitude é recuperada da propriedade CustomMap.ShapeCoordinates e
convertida em uma List de coordenadas BasicGeoposition .
O polígono é criado instanciando um objeto MapPolygon . A classe MapPolygon é usada para exibir uma forma
de vários pontos no mapa, definindo sua propriedade Path como um objeto Geopath que contém as
coordenadas da forma.
O polígono é renderizado no mapa adicionando-o à coleção MapControl.MapElements . Observe que o polígono
será fechado automaticamente desenhando uma linha que conecta o primeiro e último pontos.
Resumo
Este artigo explicou como adicionar uma sobreposição poligonal a um mapa a fim de realçar uma determinada
região. Polígonos são uma forma fechada e têm seus interiores preenchidos.
Links relacionados
Sobreposição de mapa com polígono (amostra)
Personalizar um Pin de mapa
Xamarin.Forms.Maps
Realçando uma rota em um mapa
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
Este artigo explica como adicionar uma sobreposição de polilinha a um mapa. Uma sobreposição de polilinha é
uma série de segmentos de linha conectados que normalmente são usados para mostrar uma rota em um mapa
ou para formar qualquer forma que seja necessária.
Visão geral
Uma sobreposição é um gráfico em camadas em um mapa. As sobreposições são suporte para elaborar conteúdos
gráficos que são dimensionados com o mapa conforme ele é ampliado e reduzido. As capturas de tela a seguir
mostram o resultado do acréscimo de uma sobreposição de polilinha a um mapa:
Quando um controle Map é renderizado por um aplicativo Xamarin.Forms, no iOS é criada uma instância da
classe MapRenderer , o que por sua vez cria uma instância de um controle MKMapView nativo. Na plataforma
Android, a classe MapRenderer cria uma instância de um controle MapView nativo. Na UWP (Plataforma Universal
do Windows), a classe MapRenderer cria uma instância de um MapControl nativo. E possível aproveitar o processo
de renderização para implementar personalizações de mapa específicas da plataforma criando um renderizador
personalizado para um Map em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar um mapa personalizado do Xamarin.Forms.
2. Consumir o mapa personalizado do Xamarin.Forms.
3. Personalizar o mapa criando um renderizador personalizado para o mapa em cada plataforma.
NOTE
Xamarin.Forms.Maps precisa ser inicializado e configurado antes do uso. Para obter mais informações, consulte
Maps Control .
Para obter informações sobre como personalizar um mapa usando um renderizador personalizado, confira
Personalizando um marcador de mapa.
Criando o mapa personalizado
Crie uma subclasse da classe Map , que adiciona uma propriedade RouteCoordinates :
public CustomMap ()
{
RouteCoordinates = new List<Position> ();
}
}
A propriedade RouteCoordinates armazenará uma coleção de coordenadas que definem a rota a ser realçada.
Consumindo o mapa personalizado
Consuma o controle CustomMap declarando uma instância dele na instância da página XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MapOverlay;assembly=MapOverlay"
x:Class="MapOverlay.MapPage">
<ContentPage.Content>
<local:CustomMap x:Name="customMap" MapType="Street" WidthRequest="{x:Static local:App.ScreenWidth}"
HeightRequest="{x:Static local:App.ScreenHeight}" />
</ContentPage.Content>
</ContentPage>
Como alternativa, consuma o controle CustomMap declarando uma instância dele na instância da página em C#:
if (e.OldElement != null) {
var nativeMap = Control as MKMapView;
if (nativeMap != null) {
nativeMap.RemoveOverlays(nativeMap.Overlays);
nativeMap.OverlayRenderer = null;
polylineRenderer = null;
}
}
if (e.NewElement != null) {
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
nativeMap.OverlayRenderer = GetOverlayRenderer;
Esse método executa a seguinte configuração, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A propriedade MKMapView.OverlayRenderer é definida como um delegado correspondente.
A coleção de coordenadas de latitude e longitude é recuperada da propriedade CustomMap.RouteCoordinates e
armazenada como uma matriz de instâncias de CLLocationCoordinate2D .
A polilinha é criada chamando o método MKPolyline.FromCoordinates estático, que especifica a latitude e a
longitude de cada ponto.
A polilinha é adicionada ao mapa chamando o método MKMapView.AddOverlay .
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
routeCoordinates = formsMap.RouteCoordinates;
Control.GetMapAsync(this);
}
}
NativeMap.AddPolyline(polylineOptions);
}
}
}
if (e.OldElement != null)
{
// Unsubscribe
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MapControl;
Esse método executa as seguintes operações, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms:
A coleção de coordenadas de latitude e longitude é recuperada da propriedade CustomMap.RouteCoordinates e
convertida em uma List de coordenadas BasicGeoposition .
A polilinha é criada instanciando um objeto MapPolyline . A classe MapPolygon é usada para exibir uma linha no
mapa, definindo sua propriedade Path como um objeto Geopath que contém as coordenadas da linha.
A polilinha é renderizada no mapa adicionando-a à coleção MapControl.MapElements .
Resumo
Este artigo explicou como adicionar uma sobreposição de polilinha a um mapa, a fim de mostrar uma rota em um
mapa ou de criar qualquer forma necessária.
Links relacionados
Sobreposição de mapa de polilinha (amostra)
Personalizar um Pin de mapa
Xamarin.Forms.Maps
Personalizando uma ListView
12/04/2019 • 28 minutes to read • Edit Online
Baixar o exemplo
Uma ListView do Xamarin.Forms é uma exibição que mostra uma coleção de dados como uma lista vertical. Este
artigo demonstra como criar um renderizador personalizado que encapsula os controles de lista e layouts de
célula nativa específicos a uma plataforma, permitindo mais controle sobre o desempenho do controle de lista
nativo.
Cada exibição do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria uma
instância de um controle nativo. Quando um ListView é renderizado por um aplicativo Xamarin.Forms, no iOS é
criada uma instância da classe ListViewRenderer , o que por sua vez cria uma instância de um controle
UITableView nativo. Na plataforma Android, a classe ListViewRenderer cria uma instância de um controle
ListView nativo. Na UWP ( Plataforma Universal do Windows), a classe ListViewRenderer cria uma instância de
um controle ListView nativo. Para obter mais informações sobre as classes de renderizador e de controle nativo
para as quais os controles do Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles
nativos.
O diagrama a seguir ilustra a relação entre o controle ListView e os controles nativos correspondentes que o
implementam:
A NativeListView é criada no projeto da biblioteca .NET Standard e define a API para o controle personalizado.
Esse controle expõe uma propriedade Items que é usada para popular o ListView com os dados e que pode ser
associada a dados para fins de exibição. Ele também expõe um evento ItemSelected que será disparado sempre
que um item for selecionado em um controle de lista nativo específico da plataforma. Para obter mais informações
sobre vinculação de dados, veja Noções básicas de vinculação de dados.
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<ContentPage.Content>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="{x:Static local:App.Description}" HorizontalTextAlignment="Center" />
<local:NativeListView Grid.Row="1" x:Name="nativeListView" ItemSelected="OnItemSelected"
VerticalOptions="FillAndExpand" />
</Grid>
</ContentPage.Content>
</ContentPage>
O prefixo do namespace local pode ser qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar o controle personalizado.
O seguinte exemplo de código mostra como o controle personalizado NativeListView pode ser consumido por
um página em C#:
public class MainPageCS : ContentPage
{
NativeListView nativeListView;
public MainPageCS()
{
nativeListView = new NativeListView
{
Items = DataSource.GetList(),
VerticalOptions = LayoutOptions.FillAndExpand
};
switch (Device.RuntimePlatform)
{
case Device.iOS:
Padding = new Thickness(0, 20, 0, 0);
break;
case Device.Android:
case Device.UWP:
Padding = new Thickness(0);
break;
}
O controle personalizado NativeListView usa renderizadores personalizados específicos da plataforma para exibir
uma lista de dados, que são populados por meio da propriedade Items . Cada linha na lista contém três itens de
dados – um nome, uma categoria e um nome de arquivo de imagem. O layout de cada linha na lista é definido
pelo renderizador personalizado específico da plataforma.
NOTE
Como o controle personalizado NativeListView será renderizado usando controles de lista específicos da plataforma que
incluem a capacidade de rolagem, ele não deve ser colocado em controles de layout roláveis, como ScrollView .
Agora, é possível adicionar um renderizador personalizado a cada projeto de aplicativo para criar layouts de célula
nativa e controles de lista específicos da plataforma.
NOTE
O fornecimento de um renderizador personalizado em cada projeto de plataforma é opcional. Se um renderizador
personalizado não estiver registrado, será usado o renderizador padrão da classe base da célula.
O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações
entre elas:
A classe ListViewRenderer expõe o método OnElementChanged , que é chamado quando um controle personalizado
do Xamarin.Forms é criado para renderizar o controle nativo correspondente. Esse método usa um parâmetro
ElementChangedEventArgs , que contém as propriedades OldElement e NewElement . Essas propriedades
representam o elemento do Xamarin.Forms a que o renderizador estava anexado e o elemento a que o
renderizador está anexado, respectivamente. No aplicativo de exemplo, a propriedade OldElement será null e a
propriedade NewElement conterá uma referência à instância de NativeListView .
Uma versão de substituição do método OnElementChanged , em cada classe de renderizador específica da
plataforma, é o lugar para realização da personalização do controle nativo. Uma referência tipada ao controle
nativo que está sendo usado na plataforma pode ser acessada por meio da propriedade Control . Além disso, é
possível obter uma referência ao controle do Xamarin.Forms que está sendo renderizado por meio da
propriedade Element .
É necessário ter cuidado ao assinar manipuladores de eventos no método OnElementChanged , conforme
demonstrado no exemplo de código a seguir:
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the native control and subscribe to event handlers
}
}
O controle nativo deve ser configurado e os manipuladores de eventos devem ser inscritos apenas quando o
renderizador personalizado for anexado a um novo elemento Xamarin.Forms. De forma semelhante, a inscrição
de quaisquer manipuladores de evento inscritos só deve ser cancelada quando o elemento ao qual o renderizador
está anexado for alterado. Adotar essa abordagem ajudará a criar um renderizador personalizado que não sofre
perdas de memória.
Uma versão de substituição do método OnElementPropertyChanged , em cada classe de renderizador específica da
plataforma, é o lugar para responder a alterações de propriedade vinculáveis sobre o controle personalizado do
Xamarin.Forms. Uma verificação da propriedade alterada sempre deve ser feita, pois essa substituição pode ser
chamada várias vezes.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo de controle personalizado do
Xamarin.Forms que está sendo renderizado e o nome do tipo de renderizador personalizado. O prefixo assembly
do atributo especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a implementação de cada classe de renderizador personalizado específica da
plataforma.
Criando o renderizador personalizado no iOS
O exemplo de código a seguir mostra o renderizador personalizado para a plataforma iOS:
[assembly: ExportRenderer (typeof(NativeListView), typeof(NativeiOSListViewRenderer))]
namespace CustomRenderer.iOS
{
public class NativeiOSListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged (ElementChangedEventArgs<Xamarin.Forms.ListView> e)
{
base.OnElementChanged (e);
if (e.OldElement != null) {
// Unsubscribe
}
if (e.NewElement != null) {
Control.Source = new NativeiOSListViewSource (e.NewElement as NativeListView);
}
}
}
}
O controle UITableView é configurado criando uma instância da classe NativeiOSListViewSource , desde que o
renderizador personalizado esteja anexado a um novo elemento do Xamarin.Forms. Essa classe fornece dados ao
controle UITableView substituindo os métodos RowsInSection e GetCell da classe UITableViewSource e expondo
uma propriedade Items que contém a lista de dados a serem exibidos. A classe também fornece uma substituição
do método RowSelected que invoca o evento ItemSelected fornecido pelo controle personalizado
NativeListView . Para obter mais informações sobre as substituições de método, confira Subclassificação de
UITableViewSource. O método GetCell retorna um UITableCellView que é preenchido com os dados para cada
linha na lista e é mostrado no exemplo de código a seguir:
return cell;
}
Esse método cria uma instância de NativeiOSListViewCell para cada linha de dados que será exibida na tela. A
instância de NativeiOSCell define o layout de cada célula e os dados da célula. Quando uma célula desaparecer
da tela devido à rolagem, ela será disponibilizada para reutilização. Isso evita o desperdício de memória
garantindo que haja apenas instâncias de NativeiOSCell para os dados que estão sendo exibidos na tela, em vez
de todos os dados da lista. Para obter mais informações sobre a reutilização de células, confira Reutilização de
células. O método GetCell também lê a propriedade ImageFilename de cada linha de dados, desde que elas
existam, e lê a imagem e a armazena como uma instância de UIImage antes de atualizar a instância de
NativeiOSListViewCell com os dados (nome, categoria e imagem) da linha.
A classe NativeiOSListViewCell define o layout para cada célula e é mostrada no exemplo de código a seguir:
ContentView.Add (headingLabel);
ContentView.Add (subheadingLabel);
ContentView.Add (imageView);
}
Essa classe define os controles usados para renderizar o conteúdo da célula e seu layout. O construtor
NativeiOSListViewCell cria instâncias dos controles UILabel e UIImageView e inicializa sua aparência. Esses
controles são usados para exibir dados de cada linha, com o método UpdateCell sendo usado para definir esses
dados na instâncias de UILabel e UIImageView . A localização dessas instâncias é definida pelo método
LayoutSubviews substituído especificando suas coordenadas dentro da célula.
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Source = new NativeiOSListViewSource (Element as NativeListView);
}
}
O método cria uma nova instância da classe NativeiOSListViewSource que fornece dados para o controle
UITableView , desde que a propriedade NativeListView.Items vinculável tenha sido alterada.
if (e.OldElement != null)
{
// unsubscribe
Control.ItemClick -= OnItemClick;
}
if (e.NewElement != null)
{
// subscribe
Control.Adapter = new NativeAndroidListViewAdapter(_context as Android.App.Activity,
e.NewElement as NativeListView);
Control.ItemClick += OnItemClick;
}
}
...
O controle ListView nativo é configurado, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms. Essa configuração envolve a criação de uma instância da classe
NativeAndroidListViewAdapter que fornece dados para o controle ListView nativo e o registro de um
manipulador de eventos para processar o evento ItemClick . Por sua vez, esse manipulador invocará o evento
ItemSelected fornecido pelo controle personalizado NativeListView . O evento ItemClick terá a assinatura
cancelada se o elemento Xamarin.Forms a que o renderizador está anexado for alterado.
O NativeAndroidListViewAdapter deriva da classe BaseAdapter e expõe uma propriedade Items que contém a
lista de dados a serem exibidos, além de substituir os métodos Count , GetView , GetItemId e this[int] . Para
obter mais informações sobre essas substituições de método, confira Implementando um ListAdapter. O método
GetView retorna uma exibição para cada linha, preenchida com os dados, e é mostrado no exemplo de código a
seguir:
public override View GetView (int position, View convertView, ViewGroup parent)
{
var item = tableItems [position];
return view;
}
O método GetView é chamado para retornar a célula a ser renderizada, como um View , para cada linha de dados
na lista. Ele cria uma instância de View para cada linha de dados que será exibida na tela, com a aparência da
instância de View definida em um arquivo de layout. Quando uma célula desaparecer da tela devido à rolagem,
ela será disponibilizada para reutilização. Isso evita o desperdício de memória garantindo que haja apenas
instâncias de View para os dados que estão sendo exibidos na tela, em vez de todos os dados da lista. Para obter
mais informações sobre a reutilização da exibição, confira Reutilização da exibição de linha.
O método GetView também preenche a instância de View com os dados, incluindo a leitura dos dados de
imagem do nome de arquivo especificado na propriedade ImageFilename .
O layout de cada célula exibida pelo ListView nativo é definido no arquivo de layout
NativeAndroidListViewCell.axml , que é inflado pelo método LayoutInflater.Inflate . O exemplo de código a
seguir mostra a definição do layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="8dp"
android:background="@drawable/CustomSelector">
<LinearLayout
android:id="@+id/Text"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="10dip">
<TextView
android:id="@+id/Text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#FF7F3300"
android:textSize="20dip"
android:textStyle="italic" />
<TextView
android:id="@+id/Text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14dip"
android:textColor="#FF267F00"
android:paddingLeft="100dip" />
</LinearLayout>
<ImageView
android:id="@+id/Image"
android:layout_width="48dp"
android:layout_height="48dp"
android:padding="5dp"
android:src="@drawable/icon"
android:layout_alignParentRight="true" />
</RelativeLayout>
Esse layout especifica que dois controles TextView e um controle ImageView sejam usados para exibir o conteúdo
da célula. Os dois controles TextView têm orientação vertical dentro de um controle LinearLayout , com todos os
controles contidos em um RelativeLayout .
Respondendo a uma alteração de propriedade no controle personalizado
Se a propriedade NativeListView.Items for alterada devido a itens serem adicionados ou removidos da lista, o
renderizador personalizado precisará responder exibindo as alterações. Isso pode ser feito substituindo o método
OnElementPropertyChanged , que é mostrado no exemplo de código a seguir:
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName) {
Control.Adapter = new NativeAndroidListViewAdapter (_context as Android.App.Activity, Element as
NativeListView);
}
}
O método cria uma nova instância da classe NativeAndroidListViewAdapter que fornece dados para o controle
ListView nativo, desde que a propriedade NativeListView.Items vinculável tenha sido alterada.
if (e.OldElement != null)
{
// Unsubscribe
listView.SelectionChanged -= OnSelectedItemChanged;
}
if (e.NewElement != null)
{
listView.SelectionMode = ListViewSelectionMode.Single;
listView.IsItemClickEnabled = false;
listView.ItemsSource = ((NativeListView)e.NewElement).Items;
listView.ItemTemplate = App.Current.Resources["ListViewItemTemplate"] as
Windows.UI.Xaml.DataTemplate;
// Subscribe
listView.SelectionChanged += OnSelectedItemChanged;
}
}
O controle ListView nativo é configurado, desde que o renderizador personalizado esteja anexado a um novo
elemento do Xamarin.Forms. Essa configuração envolve definir como o controle ListView nativo responderá à
seleção de itens, ao preenchimento dos dados exibidos pelo controle, à definição da aparência e do conteúdo de
cada célula e ao registro de um manipulador de eventos para processar o evento SelectionChanged . Por sua vez,
esse manipulador invocará o evento ItemSelected fornecido pelo controle personalizado NativeListView . O
evento SelectionChanged terá a assinatura cancelada se o elemento Xamarin.Forms a que o renderizador está
anexado for alterado.
A aparência e o conteúdo de cada célula ListView nativa são definidos por um DataTemplate denominado
ListViewItemTemplate . Esse DataTemplate é armazenado no dicionário de recursos de nível de aplicativo e é
mostrado no exemplo de código a seguir:
<DataTemplate x:Key="ListViewItemTemplate">
<Grid Background="#DAFF7F">
<Grid.Resources>
<local:ConcatImageExtensionConverter x:Name="ConcatImageExtensionConverter" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.40*" />
<ColumnDefinition Width="0.40*"/>
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Foreground="#7F3300" FontStyle="Italic" FontSize="22"
VerticalAlignment="Top" Text="{Binding Name}" />
<TextBlock Grid.RowSpan="2" Grid.Column="1" Foreground="#267F00" FontWeight="Bold" FontSize="12"
VerticalAlignment="Bottom" Text="{Binding Category}" />
<Image Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center" Source="
{Binding ImageFilename, Converter={StaticResource ConcatImageExtensionConverter}}" Width="50" Height="50" />
<Line Grid.Row="1" Grid.ColumnSpan="3" X1="0" X2="1" Margin="30,20,0,0" StrokeThickness="1"
Stroke="LightGray" Stretch="Fill" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
O DataTemplate especifica os controles usados para exibir o conteúdo da célula, bem como seu layout e aparência.
Dois controles TextBlock e um controle Image são usados para exibir o conteúdo da célula por meio da
associação de dados. Além disso, uma instância do ConcatImageExtensionConverter é usada para concatenar a
extensão de arquivo .jpg a cada nome de arquivo de imagem. Isso garante que o controle Image possa carregar
e renderizar a imagem quando sua propriedade Source estiver definida.
Respondendo a uma alteração de propriedade no controle personalizado
Se a propriedade NativeListView.Items for alterada devido a itens serem adicionados ou removidos da lista, o
renderizador personalizado precisará responder exibindo as alterações. Isso pode ser feito substituindo o método
OnElementPropertyChanged , que é mostrado no exemplo de código a seguir:
if (e.PropertyName == NativeListView.ItemsProperty.PropertyName)
{
listView.ItemsSource = ((NativeListView)Element).Items;
}
}
O método preenche novamente o controle ListView nativo com os dados alterados, desde que a propriedade
NativeListView.Items vinculável tenha sido alterada.
Resumo
Este artigo demonstrou como criar um renderizador personalizado que encapsula os controles de lista e layouts
de célula nativa específicos a uma plataforma, permitindo mais controle sobre o desempenho do controle de lista
nativo.
Links relacionados
CustomRendererListView (amostra)
Personalizando um ViewCell
12/04/2019 • 25 minutes to read • Edit Online
Baixar o exemplo
Um ViewCell do Xamarin.Forms é uma célula que pode ser adicionada a um ListView ou a um TableView, que
contém uma exibição definida pelo desenvolvedor. Este artigo demonstra como criar um renderizador
personalizado para um ViewCell hospedado dentro de um controle ListView do Xamarin.Forms. Isso impede que
os cálculos de layout do Xamarin.Forms sejam chamados repetidamente durante a rolagem de ListView.
Cada uma das células do Xamarin.Forms tem um renderizador que a acompanha para cada plataforma que cria
uma instância de um controle nativo. Quando um ViewCell é renderizado por um aplicativo Xamarin.Forms, no
iOS é criada uma instância da classe ViewCellRenderer , o que por sua vez cria uma instância de um controle
UITableViewCell nativo. Na plataforma Android, a classe ViewCellRenderer cria uma instância de um controle
View nativo. Na UWP ( Plataforma Universal do Windows), a classe ViewCellRenderer cria uma instância de um
DataTemplate nativo. Para obter mais informações sobre as classes de renderizador e de controle nativo para as
quais os controles do Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles nativos.
O seguinte diagrama ilustra a relação entre o ViewCell e os controles nativos correspondentes que o
implementam:
A classe NativeCell é criada no projeto da biblioteca .NET Standard e define a API para a célula personalizada. A
célula personalizada expõe as propriedades Name , Category e ImageFilename , que podem ser exibidas por meio
da associação de dados. Para obter mais informações sobre vinculação de dados, veja Noções básicas de
vinculação de dados.
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
...
<ContentPage.Content>
<StackLayout>
<Label Text="Xamarin.Forms native cell" HorizontalTextAlignment="Center" />
<ListView x:Name="listView" CachingStrategy="RecycleElement" ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<local:NativeCell Name="{Binding Name}" Category="{Binding Category}"
ImageFilename="{Binding ImageFilename}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>
O prefixo do namespace local pode ter qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar a célula personalizada.
O exemplo de código a seguir mostra como a célula personalizada NativeCell pode ser consumida por uma
página C#:
public NativeCellPageCS()
{
listView = new ListView(ListViewCachingStrategy.RecycleElement)
{
ItemsSource = DataSource.GetList(),
ItemTemplate = new DataTemplate(() =>
{
var nativeCell = new NativeCell();
nativeCell.SetBinding(NativeCell.NameProperty, "Name");
nativeCell.SetBinding(NativeCell.CategoryProperty, "Category");
nativeCell.SetBinding(NativeCell.ImageFilenameProperty, "ImageFilename");
return nativeCell;
})
};
switch (Device.RuntimePlatform)
{
case Device.iOS:
Padding = new Thickness(0, 20, 0, 0);
break;
case Device.Android:
case Device.UWP:
Padding = new Thickness(0);
break;
}
Um controle ListView do Xamarin.Forms é usado para exibir uma lista de dados, que é preenchida por meio da
propriedade ItemSource . A estratégia de cache de RecycleElement tenta minimizar o volume de memória de
ListView e a velocidade de execução reciclando células da lista. Para obter mais informações, confira Estratégia
de Cache.
Cada linha na lista contém três itens de dados – um nome, uma categoria e um nome de arquivo de imagem. O
layout de cada linha da lista é definido pelo DataTemplate , que é referenciado por meio da propriedade associável
ListView.ItemTemplate . O DataTemplate define que cada linha de dados na lista será um NativeCell que exibe
suas propriedades Name , Category e ImageFilename por meio da associação de dados. Para obter mais
informações sobre o controle ListView , confira ListView.
Agora, um renderizador personalizado pode ser adicionado a cada projeto de aplicativo para personalizar o layout
específico à plataforma para cada célula.
NOTE
Para a maioria dos elementos do Xamarin.Forms, o fornecimento de um renderizador personalizado em cada projeto de
plataforma é opcional. Se um renderizador personalizado não estiver registrado, será usado o renderizador padrão da classe
base do controle. No entanto, são necessários renderizadores personalizados em cada projeto da plataforma durante a
renderização de um elemento ViewCell.
O seguinte diagrama ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as
relações entre elas:
A célula personalizada NativeCell é renderizada por classes de renderizador específicas da plataforma, que
derivam da classe ViewCellRenderer de cada plataforma. Isso faz com que cada célula personalizada NativeCell
seja renderizada com o layout específico da plataforma, conforme mostrado nas capturas de tela seguir:
A classe ViewCellRenderer expõe métodos específicos da plataforma para renderização da célula personalizada.
Trata-se do método GetCell na plataforma iOS, do método GetCellCore na plataforma Android e do método
GetTemplate na UWP.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo da célula do Xamarin.Forms
que está sendo renderizada e o nome do tipo de renderizador personalizado. O prefixo assembly do atributo
especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a implementação de cada classe de renderizador personalizado específica da
plataforma.
Criando o renderizador personalizado no iOS
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma iOS:
nativeCell.PropertyChanged += OnNativeCellPropertyChanged;
cell.UpdateCell(nativeCell);
return cell;
}
...
}
}
O método GetCell é chamado para compilar cada célula a ser exibida. Cada célula é uma instância de
NativeiOSCell , que define o layout da célula e seus dados. A operação do método GetCell depende da
estratégia de cache de ListView :
Quando a estratégia de cache de ListView é RetainElement , o método GetCell é invocado para cada
célula. Uma instância de NativeiOSCell é criada para cada instância de NativeCell exibida inicialmente na
tela. Conforme o usuário rola pelo ListView , instâncias de NativeiOSCell são reutilizadas. Para obter mais
informações sobre a reutilização de células do iOS, confira Reutilização de células.
NOTE
Esse código de renderizador personalizado reutilizará algumas células mesmo quando o ListView estiver definido
para reter células.
Os dados exibidos por cada instância de NativeiOSCell , quer ela tenha sido criada recentemente ou
reutilizada, serão atualizados com os dados de cada instância de NativeCell pelo método UpdateCell .
NOTE
O método OnNativeCellPropertyChanged nunca será invocado quando a estratégia de cache de ListView
estiver definida para reter as células.
Quando a estratégia de cache de ListView é RecycleElement , o método GetCell é invocado para cada
célula exibida inicialmente na tela. Uma instância de NativeiOSCell é criada para cada instância de
NativeCell exibida inicialmente na tela. Os dados exibidos por cada instância de NativeiOSCell serão
atualizados com os dados da instância de NativeCell pelo método UpdateCell . No entanto, o método
GetCell não será invocado conforme o usuário percorrer o ListView . Em vez disso, as instâncias de
NativeiOSCell serão reutilizadas. Eventos PropertyChanged serão gerados na instância de NativeCell
quando seus dados forem alterados e o manipulador de eventos OnNativeCellPropertyChanged atualizará os
dados em cada instância de NativeiOSCell reutilizada.
namespace CustomRenderer.iOS
{
public class NativeiOSCellRenderer : ViewCellRenderer
{
...
Esse método atualiza os dados exibidos pelas instâncias de NativeiOSCell reutilizadas. É feita uma verificação da
propriedade alterada, pois o método pode ser chamado várias vezes.
A classe NativeiOSCell define o layout para cada célula e é mostrada no exemplo de código a seguir:
internal class NativeiOSCell : UITableViewCell, INativeElementView
{
public UILabel HeadingLabel { get; set; }
public UILabel SubheadingLabel { get; set; }
public UIImageView CellImageView { get; set; }
SelectionStyle = UITableViewCellSelectionStyle.Gray;
ContentView.BackgroundColor = UIColor.FromRGB(255, 255, 224);
CellImageView = new UIImageView();
ContentView.Add(HeadingLabel);
ContentView.Add(SubheadingLabel);
ContentView.Add(CellImageView);
}
Essa classe define os controles usados para renderizar o conteúdo da célula e seu layout. A classe implementa a
interface INativeElementView , o que é necessário quando o ListView usa a estratégia de cache RecycleElement .
Essa interface especifica que a classe deve implementar a propriedade Element , que deve retornar dados da
célula personalizada para células recicladas.
O construtor NativeiOSCell inicializa a aparência das propriedades HeadingLabel , SubheadingLabel e
CellImageView . Essas propriedades são usadas para exibir os dados armazenados na instância de NativeCell ,
com o método UpdateCell sendo chamado para definir o valor de cada propriedade. Além disso, quando o
ListView usa a estratégia de cache RecycleElement , os dados exibidos pelas propriedades HeadingLabel ,
SubheadingLabel e CellImageView podem ser atualizados pelo método OnNativeCellPropertyChanged no
renderizador personalizado.
O layout da célula é executado pela substituição LayoutSubviews , que define as coordenadas de HeadingLabel ,
SubheadingLabel e CellImageView dentro da célula.
nativeCell.PropertyChanged += OnNativeCellPropertyChanged;
cell.UpdateCell(nativeCell);
return cell;
}
...
}
}
O método GetCellCore é chamado para compilar cada célula a ser exibida. Cada célula é uma instância de
NativeAndroidCell , que define o layout da célula e seus dados. A operação do método GetCellCore depende da
estratégia de cache de ListView :
Quando a estratégia de cache de ListView é RetainElement , o método GetCellCore é invocado para cada
célula. Um NativeAndroidCell é criado para cada instância de NativeCell exibida inicialmente na tela.
Conforme o usuário rola pelo ListView , instâncias de NativeAndroidCell são reutilizadas. Para obter mais
informações sobre a reutilização de células no Android, confira Reutilização da exibição de linha.
NOTE
Observe que esse código de renderizador personalizado reutilizará algumas células mesmo quando o ListView
estiver definido para reter células.
Os dados exibidos por cada instância de NativeAndroidCell , quer ela tenha sido criada recentemente ou
reutilizada, serão atualizados com os dados de cada instância de NativeCell pelo método UpdateCell .
NOTE
Observe que, embora o método OnNativeCellPropertyChanged seja invocado quando ListView é configurado
para reter as células, ele não atualizará o valores da propriedade NativeAndroidCell .
Quando a estratégia de cache de ListView é RecycleElement , o método GetCellCore é invocado para cada
célula exibida inicialmente na tela. Uma instância de NativeAndroidCell é criada para cada instância de
NativeCell exibida inicialmente na tela. Os dados exibidos por cada instância de NativeAndroidCell serão
atualizados com os dados da instância de NativeCell pelo método UpdateCell . No entanto, o método
GetCellCore não será invocado conforme o usuário percorrer o ListView . Em vez disso, as instâncias de
NativeAndroidCell serão reutilizadas. Eventos PropertyChanged serão gerados na instância de NativeCell
quando seus dados forem alterados e o manipulador de eventos OnNativeCellPropertyChanged atualizará os
dados em cada instância de NativeAndroidCell reutilizada.
namespace CustomRenderer.Droid
{
public class NativeAndroidCellRenderer : ViewCellRenderer
{
...
Esse método atualiza os dados exibidos pelas instâncias de NativeAndroidCell reutilizadas. É feita uma verificação
da propriedade alterada, pois o método pode ser chamado várias vezes.
A classe NativeAndroidCell define o layout para cada célula e é mostrada no exemplo de código a seguir:
internal class NativeAndroidCell : LinearLayout, INativeElementView
{
public TextView HeadingTextView { get; set; }
public TextView SubheadingTextView { get; set; }
public ImageView ImageView { get; set; }
AddView(view);
}
SetImage(cell.ImageFilename);
}
Esse layout especifica que dois controles TextView e um controle ImageView sejam usados para exibir o conteúdo
da célula. Os dois controles TextView têm orientação vertical dentro de um controle LinearLayout , com todos os
controles contidos em um RelativeLayout .
Criando o renderizador personalizado na UWP
O seguinte exemplo de código mostra o renderizador personalizado para o UWP:
[assembly: ExportRenderer(typeof(NativeCell), typeof(NativeUWPCellRenderer))]
namespace CustomRenderer.UWP
{
public class NativeUWPCellRenderer : ViewCellRenderer
{
public override Windows.UI.Xaml.DataTemplate GetTemplate(Cell cell)
{
return App.Current.Resources["ListViewItemTemplate"] as Windows.UI.Xaml.DataTemplate;
}
}
}
O método GetTemplate é chamado para retornar a célula a ser renderizada para cada linha de dados na lista. Ele
cria um DataTemplate para cada instância de NativeCell que será exibida na tela, com o DataTemplate definindo
a aparência e o conteúdo da célula.
O DataTemplate é armazenado no dicionário de recursos de nível de aplicativo e é mostrado no exemplo de
código a seguir:
<DataTemplate x:Key="ListViewItemTemplate">
<Grid Background="LightYellow">
<Grid.Resources>
<local:ConcatImageExtensionConverter x:Name="ConcatImageExtensionConverter" />
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.40*" />
<ColumnDefinition Width="0.40*"/>
<ColumnDefinition Width="0.20*" />
</Grid.ColumnDefinitions>
<TextBlock Grid.ColumnSpan="2" Foreground="#7F3300" FontStyle="Italic" FontSize="22"
VerticalAlignment="Top" Text="{Binding Name}" />
<TextBlock Grid.RowSpan="2" Grid.Column="1" Foreground="#267F00" FontWeight="Bold" FontSize="12"
VerticalAlignment="Bottom" Text="{Binding Category}" />
<Image Grid.RowSpan="2" Grid.Column="2" HorizontalAlignment="Left" VerticalAlignment="Center"
Source="{Binding ImageFilename, Converter={StaticResource ConcatImageExtensionConverter}}" Width="50"
Height="50" />
<Line Grid.Row="1" Grid.ColumnSpan="3" X1="0" X2="1" Margin="30,20,0,0" StrokeThickness="1"
Stroke="LightGray" Stretch="Fill" VerticalAlignment="Bottom" />
</Grid>
</DataTemplate>
O DataTemplate especifica os controles usados para exibir o conteúdo da célula, bem como seu layout e
aparência. Dois controles TextBlock e um controle Image são usados para exibir o conteúdo da célula por meio
da associação de dados. Além disso, uma instância do ConcatImageExtensionConverter é usada para concatenar a
extensão de arquivo .jpg a cada nome de arquivo de imagem. Isso garante que o controle Image possa carregar
e renderizar a imagem quando sua propriedade Source estiver definida.
Resumo
Este artigo demonstrou como criar um renderizador personalizado para um ViewCell hospedado dentro de um
controle ListView do Xamarin.Forms. Isso impede que os cálculos de layout do Xamarin.Forms sejam chamados
repetidamente durante a rolagem de ListView .
Links relacionados
Desempenho de ListView
CustomRendererViewCell (amostra)
Implementando uma exibição
12/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
Controles de interfaces do usuário personalizadas do Xamarin.Forms devem derivar da classe View, que é usada
para colocar os layouts e controles na tela. Este artigo demonstra como criar um renderizador personalizado para
um controle personalizado do Xamarin.Forms, que é usado para exibir um fluxo de vídeo de visualização com a
câmera do dispositivo.
Cada exibição do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria uma
instância de um controle nativo. Quando um View é renderizado por um aplicativo Xamarin.Forms no iOS, é
criada uma instância da classe ViewRenderer , que, por sua vez, cria uma instância de um controle UIView nativo.
Na plataforma Android, a classe ViewRenderer cria uma instância de um controle View nativo. Na UWP
(Plataforma Universal do Windows), a classe ViewRenderer cria uma instância de um controle FrameworkElement
nativo. Para obter mais informações sobre as classes de renderizador e de controle nativo para as quais os
controles do Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles nativos.
O seguinte diagrama ilustra a relação entre o View e os controles nativos correspondentes que o implementam:
E possível usar o processo de renderização para implementar personalizações específicas da plataforma criando
um renderizador personalizado para um View em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar um controle personalizado do Xamarin.Forms.
2. Consumir o controle personalizado do Xamarin.Forms.
3. Criar o renderizador personalizado para o controle em cada plataforma.
Agora, cada item será discutido separadamente, a fim de implementar um renderizador CameraPreview que exibe
um fluxo de vídeo de visualização usando a câmera do dispositivo. Tocar no fluxo de vídeo o interromperá e
iniciará.
O controle personalizado CameraPreview é criado no projeto de PCL (biblioteca de classes portátil) e define a API
para o controle. O controle personalizado expõe uma propriedade Camera que é usada para controlar se o fluxo de
vídeo deve ser exibido na parte frontal ou traseira da câmera do dispositivo. Se não for especificado um valor para
a propriedade Camera quando o controle for criado, o comportamento padrão será especificar a câmera traseira.
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
...>
<ContentPage.Content>
<StackLayout>
<Label Text="Camera Preview:" />
<local:CameraPreview Camera="Rear"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O prefixo do namespace local pode ser qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar o controle personalizado.
O seguinte exemplo de código mostra como o controle personalizado CameraPreview pode ser consumido por um
página em C#:
public class MainPageCS : ContentPage
{
public MainPageCS ()
{
...
Content = new StackLayout {
Children = {
new Label { Text = "Camera Preview:" },
new CameraPreview {
Camera = CameraOptions.Rear,
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
}
}
};
}
}
Uma instância do controle personalizado CameraPreview será usada para exibir o fluxo de vídeo de visualização da
câmera do dispositivo. Além de, opcionalmente, especificar um valor para a propriedade Camera , a personalização
do controle será realizada no renderizador personalizado.
Agora, é possível adicionar um renderizador personalizado a cada projeto de aplicativo para criar controles de
visualização de câmera específicos da plataforma.
NOTE
Para a maioria dos elementos do Xamarin.Forms, o fornecimento de um renderizador personalizado em cada projeto de
plataforma é opcional. Se um renderizador personalizado não estiver registrado, será usado o renderizador padrão da classe
base do controle. No entanto, são necessários renderizadores personalizados em cada projeto da plataforma durante a
renderização de um elemento View.
O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações
entre elas:
O controle personalizado CameraPreview é renderizado por classes de renderizador específicas da plataforma, que
derivam da classe ViewRenderer para cada plataforma. Isso faz com que cada controle personalizado
CameraPreview seja renderizado com controles específicos da plataforma, conforme mostrado nas capturas de tela
seguir:
A classe ViewRenderer expõe o método OnElementChanged , que é chamado quando um controle personalizado do
Xamarin.Forms é criado para renderizar o controle nativo correspondente. Esse método usa um parâmetro
ElementChangedEventArgs , que contém as propriedades OldElement e NewElement . Essas propriedades representam
o elemento do Xamarin.Forms a que o renderizador estava anexado e o elemento a que o renderizador está
anexado, respectivamente. No aplicativo de exemplo, a propriedade OldElement será null e a propriedade
NewElement conterá uma referência à instância de CameraPreview .
if (Control == null) {
// Instantiate the native control and assign it to the Control property with
// the SetNativeControl method
}
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the control and subscribe to event handlers
}
}
Um novo controle nativo deve ser instanciado apenas uma vez, quando a propriedade Control é null . O
controle deve ser configurado e os manipuladores de eventos devem ser inscritos apenas quando o renderizador
personalizado for anexado a um novo elemento Xamarin.Forms. Da mesma forma, a inscrição de quaisquer
manipuladores de evento inscritos só deve ser cancelada quando o elemento ao qual o renderizador está anexado
for alterado. Adotar essa abordagem ajudará a criar um renderizador personalizado com bom desempenho que
não sofre perdas de memória.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo de controle personalizado do
Xamarin.Forms que está sendo renderizado e o nome do tipo de renderizador personalizado. O prefixo assembly
do atributo especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a implementação de cada classe de renderizador personalizado específica da
plataforma.
Criando o renderizador personalizado no iOS
O exemplo de código a seguir mostra o renderizador personalizado para a plataforma iOS:
if (Control == null) {
uiCameraPreview = new UICameraPreview (e.NewElement.Camera);
SetNativeControl (uiCameraPreview);
}
if (e.OldElement != null) {
// Unsubscribe
uiCameraPreview.Tapped -= OnCameraPreviewTapped;
}
if (e.NewElement != null) {
// Subscribe
uiCameraPreview.Tapped += OnCameraPreviewTapped;
}
}
Desde que a propriedade Control seja null , o método SetNativeControl será chamado para instanciar um novo
controle UICameraPreview e para atribuir uma referência a ele para a propriedade Control . O controle
UICameraPreview é um controle personalizado específico da plataforma que usa as APIs AVCapture para fornecer o
fluxo de visualização da câmera. Ele expõe um evento Tapped que é manipulado pelo método
OnCameraPreviewTapped parar e iniciar a visualização do vídeo quando é tocado. O evento Tapped é assinado
quando o renderizador personalizado é anexado a um novo elemento do Xamarin.Forms e a assinatura é
cancelada apenas quando o elemento a que o renderizador está anexado é alterado.
Criando o renderizador personalizado no Android
O exemplo de código a seguir mostra o renderizador personalizado para a plataforma Android:
if (Control == null)
{
cameraPreview = new CameraPreview(Context);
SetNativeControl(cameraPreview);
}
if (e.OldElement != null)
{
// Unsubscribe
cameraPreview.Click -= OnCameraPreviewClicked;
}
if (e.NewElement != null)
{
Control.Preview = Camera.Open((int)e.NewElement.Camera);
// Subscribe
cameraPreview.Click += OnCameraPreviewClicked;
}
}
Desde que a propriedade Control seja null , o método SetNativeControl será chamado para instanciar um novo
controle CameraPreview e para atribuir uma referência a ele para a propriedade Control . O controle
CameraPreview é um controle personalizado específico da plataforma que usa a API Camera para fornecer o fluxo
de visualização da câmera. O controle CameraPreview é configurado, desde que o renderizador personalizado
esteja anexado a um novo elemento do Xamarin.Forms. Essa configuração envolve a criação de um novo objeto
Camera nativo para acessar uma câmera de hardware específica e registrar um manipulador de eventos para
processar o evento Click . Por sua vez, esse manipulador parará e iniciará a visualização do vídeo quando for
tocado. O evento Click terá a assinatura cancelada se o elemento Xamarin.Forms a que o renderizador está
anexado for alterado.
Criando o renderizador personalizado na UWP
O exemplo de código a seguir mostra o renderizador personalizado para a UWP:
if (Control == null)
{
...
_captureElement = new CaptureElement();
_captureElement.Stretch = Stretch.UniformToFill;
SetupCamera();
SetNativeControl(_captureElement);
}
if (e.OldElement != null)
{
// Unsubscribe
Tapped -= OnCameraPreviewTapped;
...
}
if (e.NewElement != null)
{
// Subscribe
Tapped += OnCameraPreviewTapped;
}
}
Desde que a propriedade Control seja null , um novo CaptureElement será instanciado e o método SetupCamera
será chamado, que usa a API MediaCapture para fornecer o fluxo de visualização da câmera. Em seguida, o método
SetNativeControl é chamado para atribuir uma referência para a instância CaptureElement para a propriedade
Control . O controle CaptureElement expõe um evento Tapped que é manipulado pelo método
OnCameraPreviewTapped para parar e iniciar a visualização do vídeo quando é tocado. O evento Tapped é assinado
quando o renderizador personalizado é anexado a um novo elemento do Xamarin.Forms e a assinatura é
cancelada apenas quando o elemento a que o renderizador está anexado é alterado.
NOTE
É importante parar e descartar os objetos que fornecem acesso à câmera em um aplicativo da UWP. Deixar de fazer isso
pode interferir em outros aplicativos que tentam acessar a câmera do dispositivo. Para obter mais informações, confira Exibir
a visualização da câmera.
Resumo
Este artigo demonstrou como criar um renderizador personalizado para um controle personalizado do
Xamarin.Forms, que é usado para exibir um fluxo de vídeo de visualização com a câmera do dispositivo. Controles
da interface do usuário personalizadas do Xamarin.Forms devem derivar da classe View , que é usada para colocar
os layouts e controles na tela.
Links relacionados
CustomRendererView (amostra)
Implementando um HybridWebView
12/04/2019 • 30 minutes to read • Edit Online
Baixar o exemplo
Controles de interfaces do usuário personalizadas do Xamarin.Forms devem derivar da classe View, que é usada
para colocar os layouts e controles na tela. Este artigo demonstra como criar um renderizador personalizado para
um controle personalizado HybridWebView, que demonstra como aprimorar os controles da Web específicos a
uma plataforma para permitir que código C# seja invocado do JavaScript.
Cada exibição do Xamarin.Forms tem um renderizador que o acompanha para cada plataforma que cria uma
instância de um controle nativo. Quando um View é renderizado por um aplicativo Xamarin.Forms no iOS, é
criada uma instância da classe ViewRenderer , que, por sua vez, cria uma instância de um controle UIView nativo.
Na plataforma Android, a classe ViewRenderer cria uma instância de um controle View . Na UWP (Plataforma
Universal do Windows), a classe ViewRenderer cria uma instância de um controle FrameworkElement nativo. Para
obter mais informações sobre as classes de renderizador e de controle nativo para as quais os controles do
Xamarin.Forms são mapeadas, confira Classes base do renderizador e controles nativos.
O seguinte diagrama ilustra a relação entre o View e os controles nativos correspondentes que o implementam:
E possível usar o processo de renderização para implementar personalizações específicas da plataforma criando
um renderizador personalizado para um View em cada plataforma. O processo para fazer isso é o seguinte:
1. Criar o controle personalizado HybridWebView .
2. Consumir a HybridWebView do Xamarin.Forms.
3. Criar o renderizador personalizado para a página HybridWebView em cada plataforma.
Agora, abordaremos cada item separadamente para implementar um renderizador de HybridWebView que
aprimora os controles da Web específicos da plataforma para permitir que código C# seja invocado do JavaScript.
A instância de HybridWebView será usada para exibir uma página HTML que pede ao usuário para digitar seu
nome. Em seguida, quando o usuário clicar em um botão HTML, uma função de JavaScript invocará um Action
em C# que exibe um pop-up que contém o nome do usuário.
Para obter mais informações sobre o processo de invocar C# do JavaScript, confira Invocando C# do JavaScript.
Para obter mais informações sobre a página HTML, confira Criando a página da Web.
Criando o HybridWebView
É possível criar o controle personalizado HybridWebView criando subclasses da classe View , conforme mostrado
no exemplo de código a seguir:
O controle personalizado HybridWebView é criado no projeto da biblioteca do .NET Standard e define a seguinte
API para o controle:
Uma propriedade Uri que especifica o endereço da página da Web a ser carregada.
Um método RegisterAction que registra um Action com o controle. A ação registrada será invocada do
JavaScript contido no arquivo HTML referenciado por meio da propriedade Uri .
Um método CleanUp que remove a referência ao Action registrado.
Um método InvokeAction que invoca o Action registrado. Esse método será chamado de um renderizador
personalizado em cada projeto específico da plataforma.
Consumindo o HybridWebView
O controle personalizado HybridWebView pode ser referenciado em XAML no projeto da biblioteca .NET Standard
declarando um namespace para sua localização e usando o prefixo do namespace no controle personalizado. O
exemplo de código a seguir mostra como o controle personalizado HybridWebView pode ser consumido por uma
página XAML:
<ContentPage ...
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
x:Class="CustomRenderer.HybridWebViewPage"
Padding="0,20,0,0">
<ContentPage.Content>
<local:HybridWebView x:Name="hybridWebView" Uri="index.html"
HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" />
</ContentPage.Content>
</ContentPage>
O prefixo do namespace local pode ser qualquer nome. No entanto, os valores de clr-namespace e assembly
devem corresponder aos detalhes do controle personalizado. Quando o namespace é declarado, o prefixo é usado
para referenciar o controle personalizado.
O seguinte exemplo de código mostra como o controle personalizado HybridWebView pode ser consumido por um
página em C#:
A instância HybridWebView será usada para exibir um controle da Web nativo em cada plataforma. Sua propriedade
Uri é definida como um arquivo HTML armazenado em cada projeto específico da plataforma, que será exibido
pelo controle da Web nativo. O HTML renderizado solicita que o usuário insira seu nome, com uma função de
JavaScript invocando um Action C# em resposta a um clique no botão HTML.
O HybridWebViewPage registra a ação a ser invocada do JavaScript, conforme mostrado no exemplo de código a
seguir:
Essa ação chama o método DisplayAlert para exibir um pop-up modal que apresenta o nome inserido na página
HTML exibida pela instância de HybridWebView .
Agora, é possível adicionar um renderizador personalizado a cada projeto de aplicativo para aprimorar os
controles da Web específicos da plataforma, permitindo que o código C# seja invocado do JavaScript.
NOTE
Para a maioria dos elementos do Xamarin.Forms, o fornecimento de um renderizador personalizado em cada projeto de
plataforma é opcional. Se um renderizador personalizado não estiver registrado, será usado o renderizador padrão da classe
base do controle. No entanto, são necessários renderizadores personalizados em cada projeto da plataforma durante a
renderização de um elemento View.
O seguinte diagrama ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações
entre elas:
O controle personalizado HybridWebView é renderizado por classes de renderizador específicas da plataforma, que
derivam da classe ViewRenderer para cada plataforma. Isso faz com que cada controle personalizado
HybridWebView seja renderizado com controles da Web específicos da plataforma, conforme mostrado nas
capturas de tela seguir:
A classe ViewRenderer expõe o método OnElementChanged , que é chamado quando um controle personalizado do
Xamarin.Forms é criado para renderizar o controle da Web nativo correspondente. Esse método usa um parâmetro
ElementChangedEventArgs , que contém as propriedades OldElement e NewElement . Essas propriedades representam
o elemento do Xamarin.Forms ao qual o renderizador estava anexado e o elemento do Xamarin.Forms ao qual o
renderizador está anexado, respectivamente. No aplicativo de exemplo, a propriedade OldElement será null e a
propriedade NewElement conterá uma referência à instância de HybridWebView .
Uma versão de substituição do método OnElementChanged , em cada classe de renderizador específica da
plataforma, é o lugar para realização da instanciação e da personalização do controle da Web nativo. O método
SetNativeControl deve ser usado para instanciar o controle da Web nativo e esse método também atribuirá a
referência de controle à propriedade Control . Além disso, é possível obter uma referência ao controle do
Xamarin.Forms que está sendo renderizado por meio da propriedade Element .
Em algumas circunstâncias, o método OnElementChanged pode ser chamado várias vezes. Portanto, para evitar
perdas de memória, é necessário ter cuidado ao instanciar um novo controle nativo. A abordagem a ser usada ao
instanciar um novo controle nativo em um renderizador personalizado é mostrada no exemplo de código a seguir:
if (Control == null) {
// Instantiate the native control and assign it to the Control property with
// the SetNativeControl method
}
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the control and subscribe to event handlers
}
}
Um novo controle nativo deve ser instanciado apenas uma vez, quando a propriedade Control é null . O
controle deve ser configurado e os manipuladores de eventos devem ser inscritos apenas quando o renderizador
personalizado for anexado a um novo elemento Xamarin.Forms. Da mesma forma, a inscrição de quaisquer
manipuladores de evento inscritos só deve ser cancelada quando o elemento ao qual o renderizador está anexado
for alterado. Adotar essa abordagem ajudará a criar um renderizador personalizado com bom desempenho que
não sofre perdas de memória.
Cada classe de renderizador personalizado é decorada com um atributo ExportRenderer que registra o
renderizador no Xamarin.Forms. O atributo aceita dois parâmetros – o nome do tipo de controle personalizado do
Xamarin.Forms que está sendo renderizado e o nome do tipo de renderizador personalizado. O prefixo assembly
do atributo especifica que o atributo se aplica a todo o assembly.
As seções a seguir abordam a estrutura da página da Web carregada por cada controle da Web nativo, o processo
para invocar C# do JavaScript e a implementação disso em cada classe de renderizador personalizado específica
da plataforma.
Criando a página da Web
O exemplo de código a seguir mostra a página da Web que será exibida pelo controle personalizado
HybridWebView :
<html>
<body>
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<h1>HybridWebView Test</h1>
<br/>
Enter name: <input type="text" id="name">
<br/>
<br/>
<button type="button" onclick="javascript:invokeCSCode($('#name').val());">Invoke C# Code</button>
<br/>
<p id="result">Result:</p>
<script type="text/javascript">
function log(str)
{
$('#result').text($('#result').text() + " " + str);
}
function invokeCSCode(data) {
try {
log("Sending Data:" + data);
invokeCSharpAction(data);
}
catch (err){
log(err);
}
}
</script>
</body>
</html>
A página da Web permite que um usuário insira seu nome em um elemento input e fornece um elemento
button que invocará o código C# quando clicado. O processo para fazer isso é o seguinte:
Quando o usuário clica na elemento button , a função invokeCSCode de JavaScript é chamada, com o valor do
elemento input sendo passado para a função.
A função invokeCSCode chama a função log para exibir os dados que está enviando para o Action C#. Em
seguida, ela chama o método invokeCSharpAction para invocar o Action C#, passando o parâmetro recebido
do elemento input .
A função JavaScript invokeCSharpAction não está definida na página da Web e será injetada nela por cada
renderizador personalizado.
No iOS, esse arquivo HTML reside na pasta de conteúdo do projeto de plataforma, com uma ação de build
BundleResource. No Android, esse arquivo HTML reside na pasta de Ativos/Conteúdo do projeto de plataforma,
com uma ação de build AndroidAsset.
Invocando C# do JavaScript
O processo para invocar C# do JavaScript é idêntico em todas as plataformas:
O renderizador personalizado cria um controle da Web nativo e carrega o arquivo HTML especificado pela
propriedade HybridWebView.Uri .
Quando a página da Web é carregada, o renderizador personalizado injeta a função de JavaScript
invokeCSharpAction na página da Web.
Quando o usuário insere seu nome e clica no elemento button HTML, a função invokeCSCode é invocada, que,
por sua vez, invoca a função invokeCSharpAction .
A função invokeCSharpAction invoca um método no renderizador personalizado, que por sua vez invoca o
método HybridWebView.InvokeAction .
O método HybridWebView.InvokeAction invoca o Action registrado.
As seções a seguir abordam como esse processo é implementado em cada plataforma.
Criando o renderizador personalizado no iOS
O seguinte exemplo de código mostra o renderizador personalizado para a plataforma iOS:
if (Control == null) {
userController = new WKUserContentController ();
var script = new WKUserScript (new NSString (JavaScriptFunction),
WKUserScriptInjectionTime.AtDocumentEnd, false);
userController.AddUserScript (script);
userController.AddScriptMessageHandler (this, "invokeAction");
NOTE
A classe WKWebView tem suporte apenas no iOS 8 e posteriores.
Além disso, Info.plist deve ser atualizado para incluir os seguintes valores:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
if (Control == null)
{
var webView = new Android.Webkit.WebView(_context);
webView.Settings.JavaScriptEnabled = true;
webView.SetWebViewClient(new JavascriptWebViewClient($"javascript: {JavascriptFunction}"));
SetNativeControl(webView);
}
if (e.OldElement != null)
{
Control.RemoveJavascriptInterface("jsBridge");
var hybridWebView = e.OldElement as HybridWebView;
hybridWebView.Cleanup();
}
if (e.NewElement != null)
{
Control.AddJavascriptInterface(new JSBridge(this), "jsBridge");
Control.LoadUrl($"file:///android_asset/Content/{Element.Uri}");
}
}
}
}
Quando o usuário insere seu nome e clica no elemento HTML button , a função de JavaScript invokeCSharpAction
é executada. Essa funcionalidade é obtida da seguinte maneira:
Desde que a propriedade Control seja null , as seguintes operações serão executadas:
Uma instância de nativa é criada, o JavaScript é habilitado no controle e uma instância de
WebView
JavascriptWebViewClient é definida como a implementação de WebViewClient .
O método SetNativeControl é chamado para atribuir uma referência ao controle WebView nativo à
propriedade Control .
Desde que o renderizador personalizado esteja anexado a um novo elemento do Xamarin.Forms:
O método WebView.AddJavascriptInterface injeta uma nova instância de JSBridge no quadro principal
do contexto do JavaScript do WebView, denominando-a jsBridge . Isso permite que métodos na classe
JSBridge sejam acessados do JavaScript.
O método WebView.LoadUrl carrega o arquivo HTML que é especificado pela propriedade
HybridWebView.Uri . O código especifica que o arquivo seja armazenado na pasta Content do projeto.
Na classe JavascriptWebViewClient , a função de JavaScript invokeCSharpAction é injetada na página da
Web depois que a página termina de ser carregada.
Quando o elemento a que o renderizador está anexado é alterado:
Recursos são liberados.
Quando a função de JavaScript invokeCSharpAction é executada, por sua vez, ela invoca o método
JSBridge.InvokeAction , que é mostrado no exemplo de código a seguir:
[JavascriptInterface]
[Export ("invokeAction")]
public void InvokeAction (string data)
{
HybridWebViewRenderer hybridRenderer;
A classe deve derivar de Java.Lang.Object , e os métodos que são expostos para o JavaScript devem ser decorados
com os atributos [JavascriptInterface] e [Export] . Portanto, quando a função de JavaScript invokeCSharpAction
é injetada na página da Web e é executada, ela chama o método JSBridge.InvokeAction por ter sido decorada com
os atributos [JavascriptInterface] e [Export("invokeAction")] . Por sua vez, o método InvokeAction invoca o
método HybridWebView.InvokeAction , que invoca a ação registrada para exibir o pop-up.
NOTE
Projetos que usam o atributo [Export] devem incluir uma referência a Mono.Android.Export , ou ocorrerá um erro no
compilador.
Observe que a classe JSBridge mantém um WeakReference para a classe HybridWebViewRenderer . A finalidade é
evitar a criação de uma referência circular entre as duas classes. Para obter mais informações, conste Referências
Fracas no MSDN.
Criando o renderizador personalizado na UWP
O seguinte exemplo de código mostra o renderizador personalizado para o UWP:
if (Control == null)
{
SetNativeControl(new Windows.UI.Xaml.Controls.WebView());
}
if (e.OldElement != null)
{
Control.NavigationCompleted -= OnWebViewNavigationCompleted;
Control.ScriptNotify -= OnWebViewScriptNotify;
}
if (e.NewElement != null)
{
Control.NavigationCompleted += OnWebViewNavigationCompleted;
Control.ScriptNotify += OnWebViewScriptNotify;
Control.Source = new Uri(string.Format("ms-appx-web:///Content//{0}", Element.Uri));
}
}
Resumo
Este artigo demonstrou como criar um renderizador personalizado para um controle personalizado HybridWebView
, que demonstra como aprimorar os controles da Web específicos a uma plataforma para permitir que código C#
seja invocado do JavaScript.
Links relacionados
CustomRendererHybridWebView (amostra)
Chamar C# do JavaScript
Implementar um player de vídeo
12/04/2019 • 5 minutes to read • Edit Online
Baixar o exemplo
Às vezes é desejável reproduzir arquivos de vídeo em um aplicativo Xamarin.Forms. Esta série de artigos aborda
como criar renderizadores personalizados para iOS, Android e o UWP (Plataforma Universal do Windows) para
uma classe do Xamarin.Forms denominada VideoPlayer .
Na amostra VideoPlayerDemos, todos os arquivos que implementam e dão suporte a VideoPlayer estão em
pastas denominadas FormsVideoLibrary e identificadas com o namespace FormsVideoLibrary ou namespaces que
começam com FormsVideoLibrary . Essa organização e nomenclatura devem tornar fácil copiar os arquivos do
player de vídeo para sua própria solução do Xamarin.Forms.
VideoPlayer pode reproduzir arquivos de vídeo de três tipos de fontes:
A Internet, usando uma URL
Um recurso inserido no aplicativo da plataforma
A biblioteca de vídeos do dispositivo
Players de vídeo exigem controles de transporte, que são botões para reproduzir e pausar o vídeo e uma barra de
posicionamento que mostra o andamento no vídeo e permite que o usuário passe rapidamente para um tempo
diferente. VideoPlayer pode usar controles de transporte e a barra de posicionamento fornecidos pela plataforma
(como mostrado abaixo), ou você pode fornecer controles de transporte e uma barra de posicionamento
personalizados. Aqui está o programa em execução no iOS, no Android e na Plataforma Universal do Windows:
É claro que você pode deitar o telefone para obter uma exibição ampliada.
Um player de vídeo mais sofisticado tem alguns recursos adicionais, como controle de volume e um mecanismo
para interromper o vídeo quando chega uma chamada, bem como um meio de manter a tela ativa durante a
reprodução.
A série de artigos a seguir mostra progressivamente como os renderizadores de plataforma e as classes de
suporte são criados:
Criar os players de vídeo de plataforma
Cada plataforma requer uma classe VideoPlayerRenderer que cria e mantém um controle de player de vídeo
compatível com a plataforma. Este artigo mostra a estrutura das classes do renderizador e o modo como os
players são criados.
Links relacionados
Demonstrações do player de vídeo (amostra)
Criando os players de vídeo de plataforma
12/04/2019 • 13 minutes to read • Edit Online
O player de vídeo
A classe VideoPlayer faz parte da biblioteca do .NET Standard VideoPlayerDemos que é compartilhada entre as
plataformas. Ela deriva de View :
using System;
using Xamarin.Forms;
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
}
}
Os membros dessa classe (e a interface IVideoPlayerController ) são descritos nos artigos a seguir.
Cada uma das plataformas contém uma classe chamada VideoPlayerRenderer que contém o código específico da
plataforma para implementar um player de vídeo. A tarefa principal desse renderizador é criar um player de vídeo
para essa plataforma.
O controlador de exibição do player do iOS
Várias classes estão envolvidas ao implementar um player de vídeo no iOS. O aplicativo primeiro cria um
AVPlayerViewController e, em seguida, define a propriedade Player como um objeto do tipo AVPlayer . Classes
adicionais são necessárias quando o player recebe uma fonte de vídeo.
Como todos os renderizadores, o VideoPlayerRenderer do iOS contém um atributo ExportRenderer que identifica
a exibição VideoPlayer com o renderizador:
using System;
using System.ComponentModel;
using System.IO;
using AVFoundation;
using AVKit;
using CoreMedia;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(FormsVideoLibrary.VideoPlayer),
typeof(FormsVideoLibrary.iOS.VideoPlayerRenderer))]
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
}
}
if (args.NewElement != null)
{
if (Control == null)
{
// Create AVPlayerViewController
_playerViewController = new AVPlayerViewController();
using Android.Content;
using Android.Media;
using Android.Widget;
using ARelativeLayout = Android.Widget.RelativeLayout;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(FormsVideoLibrary.VideoPlayer),
typeof(FormsVideoLibrary.Droid.VideoPlayerRenderer))]
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
public VideoPlayerRenderer(Context context) : base(context)
{
}
···
}
}
Do Xamarin.Forms 2.5 em diante, os renderizadores do Android devem incluir um construtor com um argumento
Context .
if (args.NewElement != null)
{
if (Control == null)
{
// Save the VideoView for future reference
videoView = new VideoView(Context);
Um manipulador para o evento Prepared é anexado a esse método e desanexado do método Dispose . Esse
evento é disparado quando a VideoView tem informações suficientes para começar a reprodução de um arquivo
de vídeo.
O elemento de mídia do UWP
No UWP (Plataforma Universal do Windows), o player de vídeo mais comum é o MediaElement . Essa
documentação do MediaElement indica que o MediaPlayerElement deve ser usado quando só é necessário dar
suporte a versões do Windows 10 começando pelo build 1607.
A substituição OnElementChanged precisa criar um MediaElement , definir alguns manipuladores de eventos e passar
o objeto MediaElement para SetNativeControl :
using System;
using System.ComponentModel;
using Windows.Storage;
using Windows.Storage.Streams;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Xamarin.Forms;
using Xamarin.Forms.Platform.UWP;
[assembly: ExportRenderer(typeof(FormsVideoLibrary.VideoPlayer),
typeof(FormsVideoLibrary.UWP.VideoPlayerRenderer))]
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
base.OnElementChanged(args);
if (args.NewElement != null)
{
if (Control == null)
{
MediaElement mediaElement = new MediaElement();
SetNativeControl(mediaElement);
mediaElement.MediaOpened += OnMediaElementMediaOpened;
mediaElement.CurrentStateChanged += OnMediaElementCurrentStateChanged;
}
···
}
···
}
base.Dispose(disposing);
}
···
}
}
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
// AreTransportControlsEnabled property
public static readonly BindableProperty AreTransportControlsEnabledProperty =
BindableProperty.Create(nameof(AreTransportControlsEnabled), typeof(bool), typeof(VideoPlayer),
true);
Embora essa propriedade tenha os acessadores set e get , o renderizador precisa lidar com casos somente
quando a propriedade está definida. O acessador get apenas retorna o valor atual da propriedade.
Propriedades como AreTransportControlsEnabled são tratadas em renderizadores de plataforma de duas maneiras:
A primeira vez é quando o Xamarin.Forms cria um elemento VideoPlayer . Isso é indicado na substituição
OnElementChanged do renderizador quando a propriedade NewElement não é null . Neste momento, o
renderizador pode definir seu próprio player de vídeo da plataforma com base no valor inicial da
propriedade, conforme definido no VideoPlayer .
Se a propriedade em VideoPlayer for alterada posteriormente, o método OnElementPropertyChanged no
renderizador será chamado. Isso permite que o renderizador atualize o player de vídeo da plataforma com
base na nova configuração de propriedade.
As seções a seguir abordam como a propriedade AreTransportControlsEnabled é tratada em cada plataforma.
Controles de reprodução do iOS
A propriedade do AVPlayerViewController do iOS que controla a exibição dos controles de transporte é
ShowsPlaybackControls . É assim como essa propriedade é definida no VideoViewRenderer do iOS:
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
AVPlayerViewController _playerViewController; // solely for ViewController property
if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
{
SetAreTransportControlsEnabled();
}
···
}
void SetAreTransportControlsEnabled()
{
((AVPlayerViewController)ViewController).ShowsPlaybackControls =
Element.AreTransportControlsEnabled;
}
···
}
}
if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
{
SetAreTransportControlsEnabled();
}
···
}
void SetAreTransportControlsEnabled()
{
if (Element.AreTransportControlsEnabled)
{
mediaController = new MediaController(Context);
mediaController.SetMediaPlayer(videoView);
videoView.SetMediaController(mediaController);
}
else
{
videoView.SetMediaController(null);
if (mediaController != null)
{
mediaController.SetMediaPlayer(null);
mediaController = null;
}
}
}
···
}
}
if (args.PropertyName == VideoPlayer.AreTransportControlsEnabledProperty.PropertyName)
{
SetAreTransportControlsEnabled();
}
···
}
void SetAreTransportControlsEnabled()
{
Control.AreTransportControlsEnabled = Element.AreTransportControlsEnabled;
}
···
}
}
Mais uma propriedade é necessária para iniciar a reprodução do vídeo: Essa é a propriedade Source crucial que
faz referência a um arquivo de vídeo. A implementação da propriedade Source é descrita no próximo artigo,
Reproduzindo um vídeo da Web.
Links relacionados
Demonstrações do player de vídeo (exemplo)
Reproduzindo um vídeo da Web
12/04/2019 • 14 minutes to read • Edit Online
using System;
using Xamarin.Forms;
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
// Source property
public static readonly BindableProperty SourceProperty =
BindableProperty.Create(nameof(Source), typeof(VideoSource), typeof(VideoPlayer), null);
[TypeConverter(typeof(VideoSourceConverter))]
public VideoSource Source
{
set { SetValue(SourceProperty, value); }
get { return (VideoSource)GetValue(SourceProperty); }
}
// AutoPlay property
public static readonly BindableProperty AutoPlayProperty =
BindableProperty.Create(nameof(AutoPlay), typeof(bool), typeof(VideoPlayer), true);
A propriedade Source é do tipo VideoSource , que é padronizado após a classe abstrata ImageSource do
Xamarin.Forms e seus três derivados UriImageSource , FileImageSource e StreamImageSource . No entanto,
nenhuma opção de fluxo está disponível para o VideoPlayer , pois o iOS e o Android não dão suporte à
reprodução de um vídeo de um fluxo.
Fontes de vídeo
A classe abstrata VideoSource consiste exclusivamente em três métodos estáticos que criam uma instância das
três classes que derivam de VideoSource :
namespace FormsVideoLibrary
{
[TypeConverter(typeof(VideoSourceConverter))]
public abstract class VideoSource : Element
{
public static VideoSource FromUri(string uri)
{
return new UriVideoSource() { Uri = uri };
}
A classe UriVideoSource é usada para especificar um arquivo de vídeo para download com um URI. Ela define
uma única propriedade do tipo string :
namespace FormsVideoLibrary
{
public class UriVideoSource : VideoSource
{
public static readonly BindableProperty UriProperty =
BindableProperty.Create(nameof(Uri), typeof(string), typeof(UriVideoSource));
namespace FormsVideoLibrary
{
public class ResourceVideoSource : VideoSource
{
public static readonly BindableProperty PathProperty =
BindableProperty.Create(nameof(Path), typeof(string), typeof(ResourceVideoSource));
namespace FormsVideoLibrary
{
public class FileVideoSource : VideoSource
{
public static readonly BindableProperty FileProperty =
BindableProperty.Create(nameof(File), typeof(string), typeof(FileVideoSource));
namespace FormsVideoLibrary
{
[TypeConverter(typeof(VideoSourceConverter))]
public abstract class VideoSource : Element
{
···
}
}
Este conversor de tipo é invocado quando a propriedade Source é definida como uma cadeia de caracteres em
XAML. Esta é a classe VideoSourceConverter :
namespace FormsVideoLibrary
{
public class VideoSourceConverter : TypeConverter
{
public override object ConvertFromInvariantString(string value)
{
if (!String.IsNullOrWhiteSpace(value))
{
Uri uri;
return Uri.TryCreate(value, UriKind.Absolute, out uri) && uri.Scheme != "file" ?
VideoSource.FromUri(value) : VideoSource.FromResource(value);
}
O método ConvertFromInvariantString tenta converter a cadeia de caracteres em um objeto Uri . Se houver êxito
e o esquema não for file: , o método retornará uma UriVideoSource . Caso contrário, ele retornará uma
ResourceVideoSource .
Definindo a fonte de vídeo
Toda a outra lógica que envolve fontes de vídeo é implementada nos renderizadores de plataforma individual. As
seções a seguir mostram como os renderizadores de plataforma reproduzem vídeos quando a propriedade
Source é definida como um objeto UriVideoSource .
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
···
if (args.NewElement != null)
{
···
SetSource();
···
}
}
if (Element.Source is UriVideoSource)
{
string uri = (Element.Source as UriVideoSource).Uri;
if (!String.IsNullOrWhiteSpace(uri))
{
asset = AVAsset.FromUrl(new NSUrl(uri));
}
}
···
if (asset != null)
{
playerItem = new AVPlayerItem(asset);
}
else
{
playerItem = null;
}
player.ReplaceCurrentItemWithPlayerItem(playerItem);
A propriedade AutoPlay não tem nenhuma comparação nas classes de vídeo do iOS e, portanto, a propriedade é
examinada no final do método SetSource para chamar o método Play no objeto AVPlayer .
Em alguns casos, os vídeos continuaram a execução depois que a página com o VideoPlayer foi direcionada para
a home page. Para interromper o vídeo, o ReplaceCurrentItemWithPlayerItem também é definido na substituição
Dispose :
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (player != null)
{
player.ReplaceCurrentItemWithPlayerItem(null);
}
}
···
}
}
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
···
if (args.NewElement != null)
{
···
SetSource();
···
}
}
···
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
{
···
else if (args.PropertyName == VideoPlayer.SourceProperty.PropertyName)
{
SetSource();
}
···
}
···
}
}
O método SetSource manipula objetos do tipo UriVideoSource chamando SetVideoUri na VideoView com um
objeto Uri do Android criado com base no URI da cadeia de caracteres. A classe Uri é totalmente qualificada
aqui para distingui-la da classe Uri do .NET:
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
void SetSource()
{
isPrepared = false;
bool hasSetSource = false;
if (Element.Source is UriVideoSource)
{
string uri = (Element.Source as UriVideoSource).Uri;
if (!String.IsNullOrWhiteSpace(uri))
{
videoView.SetVideoURI(Android.Net.Uri.Parse(uri));
hasSetSource = true;
}
}
···
O VideoView do Android não tem uma propriedade AutoPlay correspondente e, portanto, o método Start é
chamado se um novo vídeo foi definido.
Há uma diferença entre o comportamento dos renderizadores do iOS e do Android se a propriedade Source de
VideoPlayer é definida como null ou se a propriedade Uri de UriVideoSource é definida como null ou uma
cadeia de caracteres em branco. Se o player de vídeo do iOS estiver reproduzindo um vídeo no momento e
Source for definido como null (ou a cadeia de caracteres for null ou em branco),
ReplaceCurrentItemWithPlayerItem será chamado com o valor null . O vídeo atual será substituído e a execução
será interrompida.
O Android não dá suporte a um recurso semelhante. Se a propriedade Source estiver definida como null ,o
método SetSource apenas a ignorará e o vídeo atual continuará sendo reproduzido.
A fonte de vídeo do UWP
O MediaElement do UWP define uma propriedade AutoPlay , que é manipulada no renderizador como qualquer
outra propriedade:
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
···
if (args.NewElement != null)
{
···
SetSource();
SetAutoPlay();
···
}
}
if (Element.Source is UriVideoSource)
{
string uri = (Element.Source as UriVideoSource).Uri;
if (!String.IsNullOrWhiteSpace(uri))
{
Control.Source = new Uri(uri);
hasSetSource = true;
}
}
···
if (!hasSetSource)
{
Control.Source = null;
}
}
void SetAutoPlay()
{
Control.AutoPlay = Element.AutoPlay;
}
···
}
}
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.PlayWebVideoPage"
Title="Play Web Video">
</ContentPage>
A classe VideoSourceConverter converte a cadeia de caracteres em uma UriVideoSource . Quando você navega
para a página Reproduzir um vídeo da Web, o vídeo começa a ser carregado e inicia a execução quando uma
quantidade suficiente de dados é baixada e armazenada em buffer. O vídeo tem cerca de 10 minutos:
Em cada uma das plataformas, os controles de transporte esmaecem se não são usados, mas podem ser
restaurados para exibição com um toque no vídeo.
Você pode impedir que o vídeo seja iniciado automaticamente definindo a propriedade AutoPlay como false :
<video:VideoPlayer Source="https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"
AutoPlay="false" />
<video:VideoPlayer Source="https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"
AreTransportControlsEnabled="False" />
Se você definir ambas as propriedades como false , o vídeo não começará a execução e não haverá nenhuma
maneira de iniciá-lo. Você precisará chamar Play no arquivo code-behind ou criar seus próprios controles de
transporte, conforme descrito no artigo Implementando controles de transporte de vídeo personalizados.
O arquivo App.xaml inclui recursos para dois vídeos adicionais:
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.App">
<Application.Resources>
<ResourceDictionary>
<video:UriVideoSource x:Key="ElephantsDream"
Uri="https://archive.org/download/ElephantsDream/ed_hd_512kb.mp4" />
<video:UriVideoSource x:Key="BigBuckBunny"
Uri="https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4"
/>
<video:UriVideoSource x:Key="Sintel"
Uri="https://archive.org/download/Sintel/sintel-2048-stereo_512kb.mp4" />
</ResourceDictionary>
</Application.Resources>
</Application>
Para referenciar um desses outros filmes, substitua a URL explícita no arquivo PlayWebVideo.xaml com uma
extensão de marcação StaticResource . Nesse caso, VideoSourceConverter não é necessário para criar o objeto
UriVideoSource :
Como alternativa, você pode definir a propriedade Source em um arquivo de vídeo em uma ListView , conforme
descrito no próximo artigo, Associando fontes de vídeo ao player.
Links relacionados
Demonstrações do player de vídeo (exemplo)
Associando fontes de vídeo ao player
12/04/2019 • 3 minutes to read • Edit Online
Baixar o exemplo
Quando a propriedade Source da exibição VideoPlayer for definida como um novo arquivo de vídeo, o vídeo
existente interromperá a execução e o novo vídeo será iniciado. Isso é demonstrado pela página Selecionar
vídeo da Web do exemplo VideoPlayerDemos. A página inclui um ListView com os títulos dos três vídeos
referenciados no arquivo App.xaml:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.SelectWebVideoPage"
Title="Select Web Video">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<video:VideoPlayer x:Name="videoPlayer"
Grid.Row="0" />
<ListView Grid.Row="1"
ItemSelected="OnListViewItemSelected">
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Elephant's Dream</x:String>
<x:String>Big Buck Bunny</x:String>
<x:String>Sintel</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
</Grid>
</ContentPage>
Quando um vídeo for selecionado, o manipulador de eventos ItemSelected no arquivo code-behind será
executado. O manipulador remove quaisquer espaços em branco e apóstrofos do título e usa isso como uma
chave para obter um dos recursos definidos no arquivo App.xaml. Esse objeto UriVideoSource é definido como a
propriedade Source do VideoPlayer .
namespace VideoPlayerDemos
{
public partial class SelectWebVideoPage : ContentPage
{
public SelectWebVideoPage()
{
InitializeComponent();
}
Quando a página é carregada pela primeira vez, nenhum item é selecionado no ListView ; portanto, é necessário
selecionar um para que o vídeo comece a ser reproduzido:
A propriedade Source de VideoPlayer é apoiada por uma propriedade associável, o que significa que ela pode
ser o destino de uma associação de dados. Isso é demonstrado pela página Associar a VideoPlayer. A marcação
no arquivo BindToVideoPlayer.xaml é compatível com a seguinte classe que encapsula um título de um vídeo e
um objeto VideoSource correspondente:
namespace VideoPlayerDemos
{
public class VideoInfo
{
public string DisplayName { set; get; }
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:VideoPlayerDemos"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.BindToVideoPlayerPage"
Title="Bind to VideoPlayer">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<video:VideoPlayer x:Name="videoPlayer"
Grid.Row="0"
Source="{Binding Source={x:Reference listView},
Path=SelectedItem.VideoSource}" />
<ListView x:Name="listView"
Grid.Row="1">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:VideoInfo}">
<local:VideoInfo DisplayName="Elephant's Dream"
VideoSource="{StaticResource ElephantsDream}" />
<local:VideoInfo DisplayName="Sintel"
VideoSource="{StaticResource Sintel}" />
</x:Array>
</ListView.ItemsSource>
</ListView>
</Grid>
</ContentPage>
A propriedade Source do VideoPlayer está associada ao ListView . O Path da associação é especificado como
SelectedItem.VideoSource , que é um demarcador composto que consiste em duas propriedades: SelectedItem é
uma propriedade de ListView . O item selecionado é do tipo VideoInfo , que tem uma propriedade VideoSource .
Assim como acontece com a primeira página Selecionar vídeo da Web, nenhum item é inicialmente selecionado
no ListView ; portanto, é necessário selecionar um dos vídeos antes de começar a reproduzi-lo.
Links relacionados
Demonstrações do player de vídeo (amostra)
Carregando vídeos de recursos do aplicativo
12/04/2019 • 7 minutes to read • Edit Online
Baixar o exemplo
Os renderizadores personalizados para a exibição VideoPlayer podem reproduzir arquivos de vídeo que foram
inseridos nos projetos da plataforma individual como recursos do aplicativo. No entanto, a versão atual do
VideoPlayer não pode acessar os recursos inseridos em uma biblioteca do .NET Standard.
Para carregar esses recursos, crie uma instância da ResourceVideoSource definindo a propriedade Path com o
nome de arquivo (ou o nome de arquivo e a pasta) do recurso. Como alternativa, você pode chamar o método
estático VideoSource.FromResource para referenciar o recurso. Em seguida, defina o objeto ResourceVideoSource
como a propriedade Source de VideoPlayer .
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
void SetSource()
{
AVAsset asset = null;
···
else if (Element.Source is ResourceVideoSource)
{
string path = (Element.Source as ResourceVideoSource).Path;
if (!String.IsNullOrWhiteSpace(path))
{
string directory = Path.GetDirectoryName(path);
string filename = Path.GetFileNameWithoutExtension(path);
string extension = Path.GetExtension(path).Substring(1);
NSUrl url = NSBundle.MainBundle.GetUrlForResource(filename, extension, directory);
asset = AVAsset.FromUrl(url);
}
}
···
}
···
}
}
if (!String.IsNullOrWhiteSpace(path))
{
string filename = Path.GetFileNameWithoutExtension(path).ToLowerInvariant();
string uri = "android.resource://" + package + "/raw/" + filename;
videoView.SetVideoURI(Android.Net.Uri.Parse(uri));
hasSetSource = true;
}
}
···
}
···
}
}
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
···
async void SetSource()
{
bool hasSetSource = false;
···
else if (Element.Source is ResourceVideoSource)
{
string path = "ms-appx:///" + (Element.Source as ResourceVideoSource).Path;
if (!String.IsNullOrWhiteSpace(path))
{
Control.Source = new Uri(path);
hasSetSource = true;
}
}
}
···
}
}
Se o recurso do iOS está armazenado na pasta Resources e se o recurso do UWP está armazenado na pasta raiz
do projeto, você pode usar o mesmo nome de arquivo para cada plataforma. Se esse for o caso, você poderá
definir esse nome diretamente como a propriedade Source de VideoPlayer .
Esta é a página em execução:
Agora você já viu como carregar vídeos de um URI da Web e como reproduzir recursos inseridos. Além disso,
você pode carregar vídeos da biblioteca de vídeos do dispositivo.
Links relacionados
Demonstrações do player de vídeo (amostra)
Acessando a biblioteca de vídeos do dispositivo
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
A maioria dos computadores desktop e dispositivos móveis modernos tem a capacidade de gravar vídeos usando
a câmera do dispositivo. Em seguida, os vídeos criados por um usuário são armazenados como arquivos no
dispositivo. Esses arquivos podem ser recuperados da biblioteca de imagens e reproduzidos pela classe
VideoPlayer , assim como qualquer outro vídeo.
namespace FormsVideoLibrary
{
public interface IVideoPicker
{
Task<string> GetVideoFileAsync();
}
}
Cada uma das plataformas contém uma classe chamada VideoPicker que implementa essa interface.
O seletor de vídeo do iOS
O VideoPicker do iOS usa o UIImagePickerController do iOS para acessar a biblioteca de imagens, especificando
que ela deve ser restrita a vídeos (conhecidos como "filmes") na propriedade MediaType do iOS. Observe que
VideoPicker implementa explicitamente a interface IVideoPicker . Observe também o atributo Dependency que
identifica essa classe como um serviço de dependência. Esses são os dois requisitos que permitem que o
Xamarin.Forms encontre o serviço de dependência no projeto da plataforma:
using System;
using System.Threading.Tasks;
using UIKit;
using Xamarin.Forms;
[assembly: Dependency(typeof(FormsVideoLibrary.iOS.VideoPicker))]
namespace FormsVideoLibrary.iOS
{
public class VideoPicker : IVideoPicker
{
TaskCompletionSource<string> taskCompletionSource;
UIImagePickerController imagePicker;
// Present UIImagePickerController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var viewController = window.RootViewController;
viewController.PresentModalViewController(imagePicker, true);
if (requestCode == PickImageId)
{
if ((resultCode == Result.Ok) && (data != null))
{
// Set the filename as the completion of the Task
PickImageTaskCompletionSource.SetResult(data.DataString);
}
else
{
PickImageTaskCompletionSource.SetResult(null);
}
}
}
}
}
O método OnCreate em MainActivity armazena sua própria instância na propriedade estática Current . Isso
permite a implementação de IVideoPicker para obter a instância MainActivity a fim de iniciar o seletor
Selecionar Vídeo:
using System;
using System.Threading.Tasks;
using Android.Content;
using Xamarin.Forms;
[assembly: Dependency(typeof(FormsVideoLibrary.Droid.VideoPicker))]
namespace FormsVideoLibrary.Droid
{
public class VideoPicker : IVideoPicker
{
public Task<string> GetVideoFileAsync()
{
// Define the Intent for getting images
Intent intent = new Intent();
intent.SetType("video/*");
intent.SetAction(Intent.ActionGetContent);
As adições ao objeto MainActivity são o único código na solução VideoPlayerDemos, em que o código normal
do aplicativo precisa ser alterado para dar suporte às classes FormsVideoLibrary .
O seletor de vídeo do UWP
A implementação do UWP da interface IVideoPicker usa o FileOpenPicker do UWP. Ela inicia a pesquisa de
arquivo com a biblioteca de imagens e restringe os tipos de arquivo a MP4 e WMV (Vídeo do Windows Media):
using System;
using System.Threading.Tasks;
using Windows.Storage;
using Windows.Storage.Pickers;
using Xamarin.Forms;
[assembly: Dependency(typeof(FormsVideoLibrary.UWP.VideoPicker))]
namespace FormsVideoLibrary.UWP
{
public class VideoPicker : IVideoPicker
{
public async Task<string> GetVideoFileAsync()
{
// Create and initialize the FileOpenPicker
FileOpenPicker openPicker = new FileOpenPicker
{
ViewMode = PickerViewMode.Thumbnail,
SuggestedStartLocation = PickerLocationId.PicturesLibrary
};
openPicker.FileTypeFilter.Add(".wmv");
openPicker.FileTypeFilter.Add(".mp4");
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.PlayLibraryVideoPage"
Title="Play Library Video">
<StackLayout>
<video:VideoPlayer x:Name="videoPlayer"
VerticalOptions="FillAndExpand" />
O arquivo code-behind contém o manipulador Clicked para o Button . A invocação do serviço de dependência
exige uma chamada a DependencyService.Get para obter a implementação de uma interface IVideoPicker no
projeto da plataforma. O método GetVideoFileAsync é então chamado nessa instância:
namespace VideoPlayerDemos
{
public partial class PlayLibraryVideoPage : ContentPage
{
public PlayLibraryVideoPage()
{
InitializeComponent();
}
if (!String.IsNullOrWhiteSpace(filename))
{
videoPlayer.Source = new FileVideoSource
{
File = filename
};
}
btn.IsEnabled = true;
}
}
}
Em seguida, o manipulador Clicked usa esse nome de arquivo para criar um objeto FileVideoSource e defini-lo
como a propriedade Source do VideoPlayer .
Cada uma das classes VideoPlayerRenderer contém um código em seu método SetSource para objetos do tipo
FileVideoSource . Elas são mostradas abaixo:
if (!String.IsNullOrWhiteSpace(uri))
{
asset = AVAsset.FromUrl(new NSUrl(uri));
}
}
···
}
···
}
}
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
void SetSource()
{
isPrepared = false;
bool hasSetSource = false;
···
else if (Element.Source is FileVideoSource)
{
string filename = (Element.Source as FileVideoSource).File;
if (!String.IsNullOrWhiteSpace(filename))
{
videoView.SetVideoPath(filename);
hasSetSource = true;
}
}
···
}
···
}
}
if (!String.IsNullOrWhiteSpace(filename))
{
StorageFile storageFile = await StorageFile.GetFileFromPathAsync(filename);
IRandomAccessStreamWithContentType stream = await storageFile.OpenReadAsync();
Control.SetSource(stream, storageFile.ContentType);
hasSetSource = true;
}
}
···
}
···
}
}
Para cada plataforma, o vídeo começa a ser reproduzido quase que imediatamente após a origem do vídeo ser
definida, porque o arquivo está no dispositivo e não precisa ser baixado.
Links relacionados
Demonstrações do player de vídeo (amostra)
Escolhendo uma foto da biblioteca de imagens
Controles personalizados de transporte de vídeo
16/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
Os controles de transporte de um player de vídeo incluem os botões que executam as funções Reproduzir,
Pausar e Parar. Em geral, esses botões são identificados com ícones conhecidos, em vez de um texto, e as funções
Reproduzir e Pausar geralmente são combinadas em um botão.
Por padrão, o VideoPlayer exibe controles de transporte compatíveis com cada plataforma. Quando você define a
propriedade AreTransportControlsEnabled como false , esses controles são suprimidos. Em seguida, você pode
controlar o VideoPlayer de forma programática ou fornecer seus próprios controles de transporte.
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
public event EventHandler PlayRequested;
Os manipuladores de eventos para esses eventos são definidos pela classe VideoPlayerRenderer em cada
plataforma, conforme mostrado abaixo:
Implementações de transporte do iOS
A versão do iOS de VideoPlayerRenderer usa o método OnElementChanged para definir manipuladores para esses
três eventos quando a propriedade NewElement não é null e desanexa os manipuladores de eventos quando
OldElement não é null :
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
AVPlayer player;
···
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
···
if (args.NewElement != null)
{
···
args.NewElement.PlayRequested += OnPlayRequested;
args.NewElement.PauseRequested += OnPauseRequested;
args.NewElement.StopRequested += OnStopRequested;
}
if (args.OldElement != null)
{
···
args.OldElement.PlayRequested -= OnPlayRequested;
args.OldElement.PauseRequested -= OnPauseRequested;
args.OldElement.StopRequested -= OnStopRequested;
}
}
···
// Event handlers to implement methods
void OnPlayRequested(object sender, EventArgs args)
{
player.Play();
}
Os manipuladores de eventos são implementados com uma chamada aos métodos no objeto AVPlayer . Não há
nenhum método Stop para AVPlayer e, portanto, ele é simulado com a pausa do vídeo e movimentação da
posição para o início.
Implementações de transporte do Android
A implementação do Android é semelhante à implementação do iOS. Os manipuladores para as três funções são
definidos quando NewElement não é null e é desanexado quando OldElement não é null :
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
VideoView videoView;
···
protected override void OnElementChanged(ElementChangedEventArgs<VideoPlayer> args)
{
···
if (args.NewElement != null)
{
···
args.NewElement.PlayRequested += OnPlayRequested;
args.NewElement.PauseRequested += OnPauseRequested;
args.NewElement.StopRequested += OnStopRequested;
}
if (args.OldElement != null)
{
···
args.OldElement.PlayRequested -= OnPlayRequested;
args.OldElement.PauseRequested -= OnPauseRequested;
args.OldElement.StopRequested -= OnStopRequested;
}
}
···
void OnPlayRequested(object sender, EventArgs args)
{
videoView.Start();
}
if (args.OldElement != null)
{
···
args.OldElement.PlayRequested -= OnPlayRequested;
args.OldElement.PauseRequested -= OnPauseRequested;
args.OldElement.StopRequested -= OnStopRequested;
}
}
···
// Event handlers to implement methods
void OnPlayRequested(object sender, EventArgs args)
{
Control.Play();
}
A classe VideoPlayer define uma propriedade associável somente real chamada Status do tipo VideoStatus .
Essa propriedade é definida como somente leitura porque só deve ser definida no renderizador da plataforma:
using System;
using Xamarin.Forms;
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
// Status read-only property
private static readonly BindablePropertyKey StatusPropertyKey =
BindableProperty.CreateReadOnly(nameof(Status), typeof(VideoStatus), typeof(VideoPlayer),
VideoStatus.NotReady);
VideoStatus IVideoPlayerController.Status
{
set { SetValue(StatusPropertyKey, value); }
get { return Status; }
}
···
}
}
Normalmente, uma propriedade associável somente leitura terá um acessador set particular na propriedade
Status para permitir que ela seja definida na classe. No entanto, para um derivado de View compatível com
renderizadores, a propriedade precisa ser definida fora da classe, mas apenas pelo renderizador da plataforma.
Por esse motivo, outra propriedade é definida com o nome IVideoPlayerController.Status . Essa é uma
implementação explícita da interface e foi possibilitada pela interface IVideoPlayerController implementada pela
classe VideoPlayer :
namespace FormsVideoLibrary
{
public interface IVideoPlayerController
{
VideoStatus Status { set; get; }
Isso é semelhante ao modo como o controle WebView usa a interface IWebViewController para implementar as
propriedades CanGoBack e CanGoForward . (Confira o código-fonte de WebView e seus renderizadores para obter
detalhes.)
Isso possibilita que uma classe externa a VideoPlayer defina a propriedade Status referenciando a interface
IVideoPlayerController . ( Você verá o código em breve.) A propriedade pode ser definida em outras classes
também, mas é improvável que ela seja definida inadvertidamente. O mais importante é que a propriedade
Status não pode ser definida por meio de uma associação de dados.
Para auxiliar os renderizadores a manter essa propriedade Status atualizada, a classe VideoPlayer define um
evento UpdateStatus que é disparado a cada décimo de segundo:
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
public event EventHandler UpdateStatus;
public VideoPlayer()
{
Device.StartTimer(TimeSpan.FromMilliseconds(100), () =>
{
UpdateStatus?.Invoke(this, EventArgs.Empty);
return true;
});
}
···
}
}
if (args.OldElement != null)
{
args.OldElement.UpdateStatus -= OnUpdateStatus;
···
}
}
···
void OnUpdateStatus(object sender, EventArgs args)
{
VideoStatus videoStatus = VideoStatus.NotReady;
switch (player.Status)
{
case AVPlayerStatus.ReadyToPlay:
switch (player.TimeControlStatus)
{
case AVPlayerTimeControlStatus.Playing:
videoStatus = VideoStatus.Playing;
break;
case AVPlayerTimeControlStatus.Paused:
videoStatus = VideoStatus.Paused;
break;
}
break;
}
}
((IVideoPlayerController)Element).Status = videoStatus;
···
}
···
}
}
Duas propriedades de AVPlayer devem ser acessadas: A propriedade Status do tipo AVPlayerStatus e a
propriedade TimeControlStatus do tipo AVPlayerTimeControlStatus . Observe que a propriedade Element (que é o
VideoPlayer ) precisa ser convertida em IVideoPlayerController para definir a propriedade Status .
if (args.OldElement != null)
{
args.OldElement.UpdateStatus -= OnUpdateStatus;
···
}
base.Dispose(disposing);
}
···
}
}
if (isPrepared)
{
status = videoView.IsPlaying ? VideoStatus.Playing : VideoStatus.Paused;
}
···
}
···
}
}
if (args.NewElement != null)
{
if (Control == null)
{
···
mediaElement.CurrentStateChanged += OnMediaElementCurrentStateChanged;
};
···
}
···
}
base.Dispose(disposing);
}
···
}
}
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
···
void OnMediaElementCurrentStateChanged(object sender, RoutedEventArgs args)
{
VideoStatus videoStatus = VideoStatus.NotReady;
switch (Control.CurrentState)
{
case MediaElementState.Playing:
videoStatus = VideoStatus.Playing;
break;
case MediaElementState.Paused:
case MediaElementState.Stopped:
videoStatus = VideoStatus.Paused;
break;
}
((IVideoPlayerController)Element).Status = videoStatus;
}
···
}
}
Botões Reproduzir, Pausar e Parar
É problemático usar caracteres Unicode para imagens simbólicas de Reproduzir, Pausar e Parar. A seção
Diversos – Técnico do padrão Unicode define três caracteres de símbolo aparentemente apropriados para essa
finalidade. Elas são:
0x23F5 (triângulo médio preto apontando para a direita) ou para Reproduzir
0x23F8 (barra vertical dupla) ou para Pausar
0x23F9 (quadrado preto) ou para Parar
Independentemente de como esses símbolos são exibidos no navegador (e navegadores diferentes os tratarão de
maneiras diferentes), eles não são exibidos de maneira consistente nas plataformas compatíveis com o
Xamarin.Forms. Em dispositivos iOS e UWP, os caracteres Pausar e Parar têm uma aparência gráfica, com uma
tela de fundo 3D azul e um primeiro plano branco. Esse não é o caso no Android, em que o símbolo é
simplesmente azul. No entanto, o ponto de código 0x23F5 para Reproduzir não tem a mesma aparência no UWP
e nem mesmo é compatível com o iOS e o Android.
Por esse motivo, o ponto de código 0x23F5 não pode ser usado para Reproduzir. Um bom substituto é:
0x25B6 (triângulo preto apontando para a direita) ou ▶ para Reproduzir
Há suporte para isso em cada plataforma, exceto que ele é um triângulo preto simples que não se assemelha à
aparência 3D de Pausar e Parar. Uma possibilidade é seguir o ponto de código 0x25B6 com um código de
variante:
0x25B6 seguido por 0xFE0F (variante 16) ou ▶ para Reproduzir
Isso é o que é usado na marcação mostrada abaixo. No iOS, ele fornece o símbolo Reproduzir a mesma
aparência 3D dos botões Pausar e Parar, mas a variante não funciona no Android e no UWP.
A página Transporte personalizado define a propriedade AreTransportControlsEnabled como falso e inclui
um ActivityIndicator exibido quando o vídeo está sendo carregado e dois botões. Os objetos DataTrigger são
usados para habilitar e desabilitar o ActivityIndicator e os botões, bem como para alternar o primeiro botão
entre Reproduzir e Pausar:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.CustomTransportPage"
Title="Custom Transport">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<video:VideoPlayer x:Name="videoPlayer"
Grid.Row="0"
AutoPlay="False"
AreTransportControlsEnabled="False"
Source="{StaticResource BigBuckBunny}" />
<ActivityIndicator Grid.Row="0"
Color="Gray"
IsVisible="False">
<ActivityIndicator.Triggers>
<DataTrigger TargetType="ActivityIndicator"
Binding="{Binding Source={x:Reference videoPlayer},
Path=Status}"
Value="{x:Static video:VideoStatus.NotReady}">
<Setter Property="IsVisible" Value="True" />
<Setter Property="IsRunning" Value="True" />
<Setter Property="IsRunning" Value="True" />
</DataTrigger>
</ActivityIndicator.Triggers>
</ActivityIndicator>
<StackLayout Grid.Row="1"
Orientation="Horizontal"
Margin="0, 10"
BindingContext="{x:Reference videoPlayer}">
<DataTrigger TargetType="Button"
Binding="{Binding Status}"
Value="{x:Static video:VideoStatus.NotReady}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
Como AutoPlay é definido como false no arquivo CustomTransport.xaml, você precisará pressionar o botão
Reproduzir quando ele ficar habilitado para iniciar o vídeo. Os botões são definidos para que os caracteres
Unicode abordados acima sejam acompanhados por seus equivalentes de texto. Os botões têm uma aparência
consistente em cada plataforma durante a reprodução do vídeo:
Porém, no Android e no UWP, o botão Reproduzir é muito diferente quando o vídeo está em pausa:
Em um aplicativo de produção, provavelmente, você desejará usar suas próprias imagens de bitmap para os
botões para alcançar a uniformidade visual.
Links relacionados
Demonstrações do player de vídeo (amostra)
Posicionamento de vídeo personalizado
12/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
Os controles de transporte implementados por cada plataforma incluem uma barra de posição. Essa barra é
semelhante a um controle deslizante ou a uma barra de rolagem e mostra a localização atual do vídeo dentro de
sua duração total. Além disso, o usuário pode manipular a barra de posição para mover para frente ou para trás
para uma nova posição no vídeo.
Este artigo mostra como é possível implementar sua própria barra de posição personalizada.
A propriedade Duration
Um item de informações que o VideoPlayer precisa para dar suporte a uma barra de posição personalizada é a
duração do vídeo. O VideoPlayer define uma propriedade Duration somente leitura do tipo TimeSpan :
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
// Duration read-only property
private static readonly BindablePropertyKey DurationPropertyKey =
BindableProperty.CreateReadOnly(nameof(Duration), typeof(TimeSpan), typeof(VideoPlayer), new
TimeSpan(),
propertyChanged: (bindable, oldValue, newValue) => ((VideoPlayer)bindable).SetTimeToEnd());
TimeSpan IVideoPlayerController.Duration
{
set { SetValue(DurationPropertyKey, value); }
get { return Duration; }
}
···
}
}
Como a propriedade Status descrita no artigo anterior, essa propriedade Duration é somente leitura. É definida
com uma BindablePropertyKey privada e pode ser definida apenas referenciando a interface
IVideoPlayerController , que inclui essa propriedade Duration :
namespace FormsVideoLibrary
{
public interface IVideoPlayerController
{
VideoStatus Status { set; get; }
Além disso, observe o manipulador de propriedade alterada que chama um método chamado SetTimeToEnd
descrito posteriormente neste artigo.
A duração de um vídeo não está disponível imediatamente depois que a propriedade Source de VideoPlayer for
definida. O arquivo de vídeo deve ser baixado parcialmente antes que o player de vídeo subjacente possa
determinar sua duração.
Veja como cada um dos renderizadores de plataforma obtém a duração do vídeo:
Duração do vídeo no iOS
No iOS, a duração de um vídeo é obtida com base na propriedade Duration de AVPlayerItem , mas não
imediatamente após a criação de AVPlayerItem . É possível definir um observador de iOS para a propriedade
Duration , mas o VideoPlayerRenderer obtém a duração no método UpdateStatus , chamado de 10 vezes por
segundo:
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
void OnUpdateStatus(object sender, EventArgs args)
{
···
if (playerItem != null)
{
((IVideoPlayerController)Element).Duration = ConvertTime(playerItem.Duration);
···
}
}
}
···
}
}
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
···
void OnMediaElementMediaOpened(object sender, RoutedEventArgs args)
{
((IVideoPlayerController)Element).Duration = Control.NaturalDuration.TimeSpan;
}
···
}
}
A propriedade Position
VideoPlayer também precisa de uma propriedade Position que aumenta de zero a Duration conforme o vídeo é
reproduzido. VideoPlayer implementa essa propriedade como a propriedade Position no MediaElement UWP,
que é uma propriedade associável normal com acessadores públicos set e get :
namespace FormsVideoLibrary
{
public class VideoPlayer : View, IVideoPlayerController
{
···
// Position property
public static readonly BindableProperty PositionProperty =
BindableProperty.Create(nameof(Position), typeof(TimeSpan), typeof(VideoPlayer), new TimeSpan(),
propertyChanged: (bindable, oldValue, newValue) => ((VideoPlayer)bindable).SetTimeToEnd());
O acessador get retorna a posição atual do vídeo quando ele está sendo reproduzido, mas o acessador set é
projetado para responder à manipulação do usuário da barra de posição movendo a posição de vídeo para frente
ou para trás.
No iOS e Android, a propriedade que obtém a posição atual tem apenas um acessador get , e um método Seek
está disponível para executar essa segunda tarefa. Se você pensar a respeito, um método Seek separado parecerá
ser uma abordagem mais adequada do que uma única propriedade Position . Uma única propriedade Position
tem um problema inerente: Durante a reprodução do vídeo, a propriedade Position deve ser atualizada
continuamente para refletir a nova posição. Mas você não quer que a maioria das alterações à propriedade
Position faça o player de vídeo se mover para uma nova posição no vídeo. Se isso acontecesse, o player de vídeo
responderia buscando o último valor da propriedade Position e o vídeo não avançaria.
Apesar das dificuldades da implementação da propriedade Position com os acessadores set e get , essa
abordagem foi escolhida porque é consistente com a UWP MediaElement e tem uma grande vantagem na
associação de dados: A propriedade Position do VideoPlayer pode ser associada ao controle deslizante usado
para exibir a posição e para procurar uma nova posição. No entanto, várias precauções são necessárias ao
implementar essa propriedade Position para evitar loops de comentários.
Definir e obter a posição do iOS
No iOS, a propriedade CurrentTime do objeto AVPlayerItem indica a posição atual do vídeo sendo reproduzido. O
iOS VideoPlayerRenderer define a propriedade Position no manipulador UpdateStatus ao mesmo tempo em que
ele define a propriedade Duration :
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
void OnUpdateStatus(object sender, EventArgs args)
{
···
if (playerItem != null)
{
···
((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty,
ConvertTime(playerItem.CurrentTime));
}
}
···
}
}
O renderizador detecta quando o conjunto de propriedades Position de VideoPlayer foi alterado na substituição
do OnElementPropertyChanged , e usa esse novo valor para chamar um método Seek no objeto AVPlayer :
namespace FormsVideoLibrary.iOS
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, UIView>
{
···
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
{
···
else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
{
TimeSpan controlPosition = ConvertTime(player.CurrentTime);
Tenha em mente que sempre que a propriedade Position no VideoPlayer for definida com base no manipulador
OnUpdateStatus , a propriedade Position disparará um evento PropertyChanged , detectado na substituição do
OnElementPropertyChanged . Para a maioria dessas alterações, o método OnElementPropertyChanged não deve fazer
nada. Caso contrário, a cada alteração na posição do vídeo, ele seria ser movido para a mesma posição que ela
acabou de atingir!
Para evitar esse loop de comentários, o método OnElementPropertyChanged apenas chamará Seek quando a
diferença entre a propriedade Position e a posição atual do AVPlayer for maior que um segundo.
Definir e obter a posição do Android
Como acontece no renderizador do iOS, o VideoPlayerRenderer do Android define um novo valor para a
propriedade Position no manipulador OnUpdateStatus . A propriedade CurrentPosition de VideoView contém a
nova posição em unidades de milissegundos:
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
void OnUpdateStatus(object sender, EventArgs args)
{
···
TimeSpan timeSpan = TimeSpan.FromMilliseconds(videoView.CurrentPosition);
((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty, timeSpan);
}
···
}
}
Além disso, como acontece no renderizador do iOS, o renderizador do Android chamará o método SeekTo de
VideoView quando a propriedade Position tiver sido alterada, mas somente quando a alteração for mais de um
segundo diferente do valor CurrentPosition de VideoView :
namespace FormsVideoLibrary.Droid
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, ARelativeLayout>
{
···
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
{
···
else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
{
if (Math.Abs(videoView.CurrentPosition - Element.Position.TotalMilliseconds) > 1000)
{
videoView.SeekTo((int)Element.Position.TotalMilliseconds);
}
}
}
···
}
}
namespace FormsVideoLibrary.UWP
{
public class VideoPlayerRenderer : ViewRenderer<VideoPlayer, MediaElement>
{
···
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs args)
{
···
else if (args.PropertyName == VideoPlayer.PositionProperty.PropertyName)
{
if (Math.Abs((Control.Position - Element.Position).TotalSeconds) > 1)
{
Control.Position = Element.Position;
}
}
}
···
void OnUpdateStatus(object sender, EventArgs args)
{
((IElementController)Element).SetValueFromRenderer(VideoPlayer.PositionProperty,
Control.Position);
}
···
}
}
void SetTimeToEnd()
{
TimeToEnd = Duration - Position;
}
···
}
}
public PositionSlider()
{
PropertyChanged += (sender, args) =>
{
if (args.PropertyName == "Value")
{
TimeSpan newPosition = TimeSpan.FromSeconds(Value);
O manipulador de propriedade alterada dos conjuntos de propriedades Duration define a propriedade Maximum
do Slider subjacente como a propriedade TotalSeconds do valor TimeSpan . Da mesma forma, o manipulador de
propriedade alterada de Position define a propriedade Value do Slider . Dessa forma, o Slider subjacente
controla a posição do PositionSlider .
O PositionSlider é atualizado do Slider subjacente em apenas uma instância: Quando o usuário manipula o
Slider para indicar que o vídeo deve ser avançado ou revertido para uma nova posição. Isso é detectado no
manipulador PropertyChanged no construtor do PositionSlider . O manipulador verifica uma alteração na
propriedade Value e, se for diferente da propriedade Position , então a propriedade Position será definida com
base na propriedade Value .
Em teoria, a instrução if interna poderia ser escrita da seguinte forma:
if (newPosition.Seconds != Position.Seconds)
{
Position = newPosition;
}
No entanto, a implementação do Android de Slider tem apenas 1.000 etapas distintas, independentemente das
configurações do Minimum e do Maximum . Se o comprimento de um vídeo for maior que 1.000 segundos, os dois
valores Position diferentes corresponderá à mesma configuração Value do Slider , e essa instrução if
dispararia um falso positivo para a manipulação de um usuário do Slider . É mais seguro verificar se a nova
posição e a existente são maiores do que um centésimo da duração geral.
Usando o PositionSlider
A documentação da UWP MediaElement avisa sobre a associação para a propriedade Position , porque a
propriedade é atualizada com frequência. A documentação recomenda que um temporizador seja usado para
consultar a propriedade Position .
É uma boa recomendação, mas as três classes VideoPlayerRenderer já estão usando indiretamente um
temporizador para atualizar a propriedade Position . A propriedade Position é alterada em um manipulador
para o evento UpdateStatus , que é disparado apenas 10 vezes por segundo.
Portanto, a propriedade Position do VideoPlayer pode ser associada à propriedade Position do PositionSlider
sem problemas de desempenho, conforme demonstrado na página Barra de Posição Personalizada:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
x:Class="VideoPlayerDemos.CustomPositionBarPage"
Title="Custom Position Bar">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<video:VideoPlayer x:Name="videoPlayer"
Grid.Row="0"
AreTransportControlsEnabled="False"
Source="{StaticResource ElephantsDream}" />
···
<StackLayout Grid.Row="1"
Orientation="Horizontal"
Margin="10, 0"
BindingContext="{x:Reference videoPlayer}">
···
<video:PositionSlider Grid.Row="2"
Margin="10, 0, 10, 10"
BindingContext="{x:Reference videoPlayer}"
Duration="{Binding Duration}"
Position="{Binding Position}">
<video:PositionSlider.Triggers>
<DataTrigger TargetType="video:PositionSlider"
Binding="{Binding Status}"
Value="{x:Static video:VideoStatus.NotReady}">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</video:PositionSlider.Triggers>
</video:PositionSlider>
</Grid>
</ContentPage>
Links relacionados
Demonstrações do player de vídeo (amostra)
Associação de dados do Xamarin.Forms
12/04/2019 • 5 minutes to read • Edit Online
Baixar o exemplo
A associação de dados é a técnica de vinculação de propriedades de dois objetos para que as alterações em
uma propriedade sejam automaticamente refletidas na outra propriedade. A associação de dados é parte
integrante da arquitetura do aplicativo MVVM (Model-View -ViewModel).
Associações básicas
Aprenda a diferença entre a origem e o destino da associação de dados e veja associações de dados simples
em código e em XAML.
Modo de associação
Descubra como o modo de associação pode controlar o fluxo de dados entre os dois objetos.
Caminho de associação
Aprofunde-se na propriedade Path da associação de dados para acessar subpropriedades e os membros da
coleção.
Fallbacks de associação
Torne as associações de dados mais robustas definindo valores de fallback que deverão ser usados se o
processo de associação falhar.
A interface de comando
Implemente a propriedade Command com associações de dados.
Associações compiladas
Use associações compiladas para melhorar o desempenho de associação de dados.
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Extensões de marcação XAML
Associações básicas do Xamarin.Forms
12/04/2019 • 18 minutes to read • Edit Online
Baixar o exemplo
A associação de dados do Xamarin.Forms vincula um par de propriedades entre dois objetos e pelo menos um
deles geralmente é um objeto da interface do usuário. Esses dois objetos são chamados de destino e origem:
O destino é o objeto (e a propriedade) no qual a associação de dados é definida.
A origem é o objeto (e propriedade) referenciado pela associação de dados.
Às vezes, essa distinção pode ser um pouco confusa: No caso mais simples, os dados fluem da origem para o
destino, o que significa que o valor da propriedade de destino é definido pelo valor da propriedade da origem. No
entanto, em alguns casos, os dados podem fluir do destino para a origem ou em ambas os sentidos. Para evitar
confusão, tenha em mente que o destino é sempre o objeto no qual a associação de dados está definida, mesmo se
estiver fornecendo os dados em vez de recebendo.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.BasicCodeBindingPage"
Title="Basic Code Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="48"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Slider é definido para um intervalo de 0 a 360. A intenção deste programa é girar o Label manipulando o
Slider .
Sem associações de dados, você definiria o evento ValueChanged do Slider para um manipulador de eventos que
acessa a propriedade Value do Slider e define esse valor para a propriedade Rotation do Label . A associação
de dados automatiza esse trabalho. O manipulador de eventos e o código dentro dele não são mais necessários.
Você pode definir uma associação em uma instância de qualquer classe que deriva de BindableObject , que inclui
os derivativos Element , VisualElement , View e View . A associação é sempre definida no objeto de destino. A
associação faz referência ao objeto de origem. Para definir a associação de dados, use os seguintes dois membros
da classe de destino:
A propriedade BindingContext especifica o objeto de origem.
O método SetBinding especifica a propriedade de destino e a propriedade de origem.
Neste exemplo, o Label é o destino da associação e o Slider é a origem da associação. As alterações na origem
Slider afetam a rotação do destino Label . Os dados fluem da origem para o destino.
O método SetBinding definido pelo BindableObject tem um argumento do tipo BindingBase do qual a classe
Binding deriva, mas há outros métodos SetBinding definidos pela classe BindableObjectExtensions . O arquivo
code-behind no exemplo da Associação de código básica usa um método de extensão SetBinding mais simples
de sua classe.
label.BindingContext = slider;
label.SetBinding(Label.RotationProperty, "Value");
}
}
O objeto Label é o destino da associação, portanto, é o objeto no qual essa propriedade é definida e no qual o
método é chamado. A propriedade BindingContext indica a origem da associação, que é o Slider .
O método SetBinding é chamado no destino da associação, mas especifica a propriedade de destino e a
propriedade de origem. A propriedade de destino é especificada como um objeto BindableProperty :
Label.RotationProperty . A propriedade de origem é especificada como uma cadeia de caracteres e indica a
propriedade Value de Slider .
O método SetBinding revela uma das regras de associações de dados mais importantes:
A propriedade de destino deve ter suporte de uma propriedade associável.
Essa regra implica que o objeto de destino deve ser uma instância de uma classe que deriva de BindableObject .
Confira o artigo Propriedades associáveis para obter uma visão geral de objetos associáveis e propriedades
associáveis.
Não há uma regra para a propriedade de origem, que é especificada como uma cadeia de caracteres.
Internamente, a reflexão é usada para acessar a propriedade real. Nesse caso específico, no entanto, a propriedade
Value também tem suporte de uma propriedade associável.
O código pode ser um pouco simplificado: A propriedade associável RotationProperty é definida por
VisualElement e herdada por Label e também por ContentPage , portanto, o nome de classe não é necessário na
chamada SetBinding :
label.SetBinding(RotationProperty, "Value");
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.BasicXamlBindingPage"
Title="Basic XAML Binding">
<StackLayout Padding="10, 0">
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BindingContext="{x:Reference Name=slider}"
Rotation="{Binding Path=Value}" />
<Slider x:Name="slider"
Maximum="360"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Assim como no código, a associação de dados é definida no objeto de destino, que é o Label . Duas extensões de
marcação XAML estão envolvidas. Estas são instantaneamente reconhecíveis pelos delimitadores de chaves:
A extensão de marcação x:Reference é necessária para fazer referência ao objeto de origem, que é o Slider
denominado slider .
A extensão de marcação Binding vincula a propriedade Rotation do Label à propriedade Value do Slider .
Para obter mais informações sobre extensões de marcação XAML, confira o artigo Extensões de marcação XAML.
A extensão de marcação x:Reference tem suporte da classe ReferenceExtension . Binding tem suporte da classe
BindingExtension . Como os prefixos de namespace de XML indicam, x:Reference faz parte da especificação
XAML 2009, enquanto Binding faz parte do Xamarin.Forms. Observe que não há aspas dentro das chaves.
É fácil esquecer-se da extensão de marcação x:Reference ao definir o BindingContext . É comum definir de modo
incorreto a propriedade diretamente para o nome da origem da associação, do seguinte modo:
BindingContext="slider"
Mas isso não é certo. Essa marcação define a propriedade BindingContext para um objeto string cujos
caracteres formam a palavra "slider".
Observe que a propriedade de origem é especificada com a propriedade Path do BindingExtension , que
corresponde à propriedade Path da classe Binding .
A marcação mostrada na página Associação de XAML básica pode ser simplificada: As extensões de marcação
XAML, como x:Reference e Binding , podem ter atributos de propriedade de conteúdo definidos, o que, para
extensões de marcação XAML, significa que o nome da propriedade não precisa aparecer. A propriedade Name é a
propriedade de conteúdo do x:Reference , e a propriedade Path é a propriedade de conteúdo do Binding , o que
significa que elas podem ser eliminadas das expressões:
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
BindingContext="{x:Reference slider}"
Rotation="{Binding Value}" />
Isso é demonstrado no exemplo Associação de código alternativa. O arquivo XAML é semelhante ao exemplo
Associação de código básica, exceto que o Slider é definido para controlar a propriedade Scale do Label .
Por esse motivo, o Slider é definido para um intervalo de –2 a 2:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.AlternativeCodeBindingPage"
Title="Alternative Code Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Minimum="-2"
Maximum="2"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O arquivo code-behind define a associação com o método SetBinding definido por BindableObject . O argumento
é um construtor para a classe Binding :
A tela do iOS à esquerda mostra como a tela aparece quando a página é exibida pela primeira vez. Onde está o
Label ?
O problema é que o Slider tem um valor inicial de 0. Isso faz com que a propriedade Scale do Label também
seja definida como 0, substituindo o valor padrão de 1. Isso resulta no Label sendo inicialmente invisível. Como
demonstram as capturas de tela do Android e da UWP (Plataforma Universal do Windows), você pode manipular
o Slider para fazer o Label aparecer novamente, mas seu desaparecimento inicial é desconcertante.
Você descobrirá no próximo artigo como evitar esse problema ao inicializar Slider do valor padrão da
propriedade Scale .
NOTE
A classe VisualElement define também as propriedades ScaleX e ScaleY , que podem dimensionar o VisualElement
de forma diferente nos sentidos horizontal e vertical.
<Slider x:Name="slider"
Minimum="-2"
Maximum="2"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Agora a extensão de marcação Binding tem duas propriedades definidas, Source e Path , separadas por uma
vírgula. Se você preferir, elas poderão aparecer na mesma linha:
A propriedade Source está definida para uma extensão de marcação x:Reference inserida que normalmente tem
a mesma sintaxe que a configuração de BindingContext . Observe que não há aspas entre as chaves e as duas
propriedades devem ser separadas por uma vírgula.
A propriedade de conteúdo da extensão de marcação Binding é Path , mas a parte Path= da extensão de
marcação só poderá ser eliminada se for a primeira propriedade na expressão. Para eliminar a parte Path= , você
precisa trocar as duas propriedades:
Embora as extensões de marcação XAML geralmente sejam delimitadas por chaves, elas também podem ser
expressas como elementos de objeto:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label.Scale>
<Binding Source="{x:Reference slider}"
Path="Value" />
</Label.Scale>
</Label>
Agora as propriedades Source e Path são atributos normais de XAML: Os valores aparecem entre aspas e os
atributos não são separados por uma vírgula. A extensão de marcação x:Reference também pode se tornar um
elemento de objeto:
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<Label.Scale>
<Binding Path="Value">
<Binding.Source>
<x:Reference Name="slider" />
</Binding.Source>
</Binding>
</Label.Scale>
</Label>
Essa sintaxe não é comum, mas, às vezes, é necessária quando objetos complexos estão envolvidos.
Os exemplos mostrados até agora definem a propriedade BindingContext e a propriedade Source de Binding
para uma extensão de marcação x:Reference para fazer referência a outra exibição na página. Essas duas
propriedades são do tipo Object , e elas podem ser definidas para qualquer objeto que inclua as propriedades que
são adequadas para as origens da associação.
Nos próximos artigos, você descobrirá que pode definir a propriedade BindingContext ou Source para uma
extensão de marcação x:Static para fazer referência ao valor de uma propriedade estática ou campo ou para
uma extensão de marcação StaticResource para fazer referência a um objeto armazenado em um dicionário de
recursos ou diretamente a um objeto que é normalmente (mas nem sempre) uma instância de um ViewModel.
A propriedade BindingContext também pode ser definida como um objeto Binding , de modo que as
propriedades Source e Path de Binding definem o contexto de associação.
<StackLayout VerticalOptions="FillAndExpand"
BindingContext="{x:Reference slider}">
<Label Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="EndAndExpand"
Rotation="{Binding Value}" />
<BoxView Color="#800000FF"
WidthRequest="180"
HeightRequest="40"
HorizontalOptions="Center"
VerticalOptions="StartAndExpand"
Rotation="{Binding Value}" />
</StackLayout>
<Slider x:Name="slider"
Maximum="360" />
</StackLayout>
</ContentPage>
A propriedade BindingContext do StackLayout é definida para o objeto slider . Esse contexto de associação é
herdado por Label e BoxView , que têm suas propriedades Rotation definidas para a propriedade Value de
Slider :
No próximo artigo, você verá como o modo de associação pode alterar o fluxo de dados entre objetos de origem e
destino.
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Modo de associação do Xamarin.Forms
12/04/2019 • 27 minutes to read • Edit Online
Baixar o exemplo
No artigo anterior, as páginas Associação de código alternativa e Associação de XAML alternativa
apresentavam um Label com sua propriedade Scale associada à propriedade Value de um Slider . Como o
valor inicial de Slider é 0, isso fez com que a propriedade Scale do Label fosse definida como 0 em vez de 1
e o Label desapareceu.
Na amostra DataBindingDemos, a página Associação inversa é semelhante aos programas do artigo anterior,
exceto que a associação de dados é definida no Slider em vez de no Label :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataBindingDemos.ReverseBindingPage"
Title="Reverse Binding">
<StackLayout Padding="10, 0">
<Label x:Name="label"
Text="TEXT"
FontSize="80"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
VerticalOptions="CenterAndExpand"
Value="{Binding Source={x:Reference label},
Path=Opacity}" />
</StackLayout>
</ContentPage>
A princípio, isso pode parecer invertido: Agora o Label é a origem de associação de dados e o Slider é o
destino. A associação referencia a propriedade Opacity do Label , que tem um valor padrão igual a 1.
Como você pode esperar, o Slider é inicializada com o valor 1 do valor inicial Opacity de Label . Isso é
mostrado na captura de tela do iOS à esquerda:
Mas você pode estar surpreso de que o Slider continuará funcionando, como demonstram as capturas de tela
do Android e do UWP. Isso parece sugerir que a associação de dados funciona melhor quando o Slider é o
destino da associação em vez de Label , porque a inicialização funciona como poderíamos esperar.
A diferença entre a amostra Associação inversa e as amostras anteriores envolve o modo de associação.
Cada propriedade associável tem um modo de associação padrão definido quando a propriedade associável é
criada, que está disponível na propriedade DefaultBindingMode do objeto BindableProperty . Esse modo de
associação padrão indica o modo em vigor quando essa propriedade é um destino da associação de dados.
O modo de associação padrão para a maioria das propriedades, como Rotation , Scale e Opacity , é OneWay .
Quando essas propriedades são destinos de associação de dados, a propriedade de destino é definida na origem.
No entanto, o modo de associação padrão para a propriedade Value de Slider é TwoWay . Isso significa que,
quando a propriedade Value é um destino da associação de dados, o destino é definido na origem (como de
costume), mas a origem também é definida no destino. Isso é o que permite que o Slider seja definido com
base no valor inicial Opacity .
Essa associação bidirecional pode parecer criar um loop infinito, mas isso não acontece. As propriedades
vinculáveis não sinalizam uma alteração de propriedade, a menos que a propriedade seja, de fato, alterada. Isso
impede um loop infinito.
Vinculações bidirecionais
A maioria das propriedades vinculáveis tem um modo de associação padrão igual a OneWay , mas as seguintes
propriedades têm um modo de associação padrão igual a TwoWay :
Propriedade Date de DatePicker
Propriedade Text de Editor , Entry , SearchBar e EntryCell
Propriedade IsRefreshing de ListView
Propriedade SelectedItem de MultiPage
Propriedades SelectedIndex e SelectedItem de Picker
Propriedade Value de Slider e Stepper
Propriedade IsToggled de Switch
Propriedade On de SwitchCell
Propriedade Time de TimePicker
Essas propriedades específicas são definidas como TwoWay por um motivo muito válido:
Quando as associações de dados são usadas com a arquitetura do aplicativo MVVM (Model-View -ViewModel), a
classe ViewModel é a origem da associação de dados e a View, que consiste em exibições como Slider , são
destinos de associação de dados. As associações de MVVM se parecem com a amostra Associação inversa
mais do que as associações das amostras anteriores. É muito provável que você deseje que cada exibição na
página seja inicializada com o valor da propriedade correspondente no ViewModel, mas as alterações na exibição
também devem afetar a propriedade de ViewModel.
As propriedades com modos de associação padrão iguais a TwoWay são as propriedades mais prováveis de
serem utilizadas em cenários de MVVM.
Associações unidirecionais para a origem
As propriedades vinculáveis somente leitura têm um modo de associação padrão igual a OneWayToSource . Há
apenas uma propriedade associável de leitura/gravação que tem um modo de associação padrão igual a
OneWayToSource :
A lógica é que uma associação na propriedade SelectedItem deve resultar na definição da origem da associação.
Um exemplo mais adiante neste artigo substitui esse comportamento.
Associações avulsas
Várias propriedades têm um modo de associação padrão do OneTime , incluindo a propriedade
IsTextPredictionEnabled de Entry .
Propriedades de destino com um modo de associação igual a OneTime são atualizadas somente quando o
contexto de associação é alterado. Para as associações nessas propriedades de destino, isso simplifica a
infraestrutura de associação porque não é necessário monitorar as alterações nas propriedades de origem.
Name = NamedColor.GetNearestColorName(color);
}
}
get
{
return color;
}
}
Quando a propriedade Color é alterada, o método GetNearestColorName estático na classe NamedColor (também
incluído na solução DataBindingDemos) obtém a cor nomeada mais próxima e define a propriedade Name .
Essa propriedade Name tem um acessador set particular e, portanto, não pode ser definida fora da classe.
Quando um ViewModel é definido como uma origem da associação, a infraestrutura de associação anexa um
manipulador ao evento PropertyChanged . Dessa forma, a associação pode ser notificada de alterações nas
propriedades e pode então definir as propriedades de destino com base nos valores alterados.
No entanto, quando uma propriedade de destino (ou a definição Binding de uma propriedade de destino) tem
um BindingMode igual a OneTime , não é necessário que a infraestrutura de associação anexe um manipulador no
evento PropertyChanged . A propriedade de destino é atualizada somente quando o BindingContext é alterado e
não quando a propriedade de origem em si é alterada.
O arquivo XAML Seletor de cor simples cria uma instância do HslColorViewModel no dicionário de recursos da
página e inicializa a propriedade Color . A propriedade BindingContext da Grid é definida como uma extensão
de associação StaticResource para referenciar esse recurso:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SimpleColorSelectorPage">
<ContentPage.Resources>
<ResourceDictionary>
<local:HslColorViewModel x:Key="viewModel"
Color="MediumTurquoise" />
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Grid.Row="1"
Margin="10, 0">
Conforme você manipula os controles deslizantes, a BoxView e o Label são atualizados de acordo, conforme
ilustrado pelas capturas de tela do Android e do UWP.
A criação de uma instância do ViewModel no dicionário de recursos é uma abordagem comum. Também é
possível criar uma instância do ViewModel dentro de marcas de elemento de propriedade para a propriedade
BindingContext . No arquivo XAML Seletor de cor simples, tente remover o HslColorViewModel do dicionário
de recursos e defini-lo como a propriedade BindingContext da Grid desta forma:
<Grid>
<Grid.BindingContext>
<local:HslColorViewModel Color="MediumTurquoise" />
</Grid.BindingContext>
···
</Grid>
O contexto de associação pode ser definido em uma variedade de formas. Às vezes, o arquivo code-behind cria
uma instância do ViewModel e o define como a propriedade BindingContext da página. Essas são todas
abordagens válidas.
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=TwoWay}" />
Pode ser esperado que o Slider seja inicializado com o valor inicial da propriedade Scale , que é 1, mas isso
não acontece. Quando uma associação TwoWay é inicializada, o destino é definido na origem primeiro, o que
significa que a propriedade Scale é definida com o valor padrão de Slider igual a 0. Quando a associação
TwoWay é definida no Slider , o Slider inicialmente é definido da origem.
<Label Text="TEXT"
FontSize="40"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Scale="{Binding Source={x:Reference slider},
Path=Value,
Mode=OneWayToSource}" />
Agora o Slider é inicializado como 1 (o valor padrão de Scale ), mas a manipulação do Slider não afeta a
propriedade Scale e, portanto, isso não é muito útil.
NOTE
A classe VisualElement define também as propriedades ScaleX e ScaleY , que podem dimensionar o VisualElement
de forma diferente nos sentidos horizontal e vertical.
Uma aplicação muito útil de substituir o modo de associação padrão com TwoWay envolve a propriedade
SelectedItem de ListView . O modo de associação padrão é OneWayToSource . Quando uma associação de dados
é definida na propriedade SelectedItem para referenciar uma propriedade de origem em um ViewModel, essa
propriedade de origem é definida na seleção de ListView . No entanto, em algumas circunstâncias, também é
recomendável inicializar a ListView no ViewModel.
A página Configurações de exemplo demonstra essa técnica. Essa página representa uma implementação
simples de configurações de aplicativo, que frequentemente são definidas em um ViewModel, como este arquivo
SampleSettingsViewModel :
storage = value;
OnPropertyChanged(propertyName);
return true;
}
// Static members
static NamedColor()
{
List<NamedColor> all = new List<NamedColor>();
StringBuilder stringBuilder = new StringBuilder();
Para obter mais informações sobre os métodos de ciclo de vida do aplicativo, confira o artigo Ciclo de vida do
aplicativo.
Quase todo o restante é manipulado no arquivo SampleSettingsPage.xaml. O BindingContext da página é
definido usando uma extensão de marcação Binding : A origem da associação é a propriedade estática
Application.Current , que é a instância da classe App no projeto e o Path é definido como a propriedade
Settings , que é o objeto SampleSettingsViewModel :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SampleSettingsPage"
Title="Sample Settings"
BindingContext="{Binding Source={x:Static Application.Current},
Path=Settings}">
<StackLayout Orientation="Horizontal">
<Label Text="Name: "
VerticalOptions="Center" />
<StackLayout Orientation="Horizontal">
<Label Text="Birth Date: "
VerticalOptions="Center" />
<StackLayout Orientation="Horizontal">
<Label Text="Do you code in C#? "
VerticalOptions="Center" />
<StackLayout Orientation="Horizontal">
<Label Text="Number of Copies: "
VerticalOptions="Center" />
<ListView x:Name="colorListView"
ItemsSource="{x:Static local:NamedColor.All}"
SelectedItem="{Binding BackgroundNamedColor, Mode=TwoWay}"
VerticalOptions="FillAndExpand"
RowHeight="40">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<BoxView Color="{Binding Color}"
HeightRequest="32"
WidthRequest="32"
VerticalOptions="Center" />
Todos os filhos da página herdam o contexto de associação. A maioria das outras associações nesta página são
propriedades em SampleSettingsViewModel . A propriedade BackgroundColor é usada para definir a propriedade
BackgroundColor do StackLayout e as propriedades Entry , DatePicker , Switch e Stepper são associadas a
outras propriedades no ViewModel.
A propriedade ItemsSource da ListView é definida como a propriedade estática NamedColor.All . Isso preenche
a ListView com todas as instâncias de NamedColor . Para cada item em ListView , o contexto de associação para
o item é definido como um objeto NamedColor . A BoxView e o Label na ViewCell estão associados às
propriedades em NamedColor .
A propriedade SelectedItem da é do tipo
ListView NamedColor e está associada à propriedade
BackgroundNamedColor de SampleSettingsViewModel :
if (colorListView.SelectedItem != null)
{
colorListView.ScrollTo(colorListView.SelectedItem,
ScrollToPosition.MakeVisible,
false);
}
}
}
A captura de tela do iOS à esquerda mostra o programa quando ele é executado pela primeira vez. O construtor
em SampleSettingsViewModel inicializa a cor da tela de fundo como branca e isto é o que é selecionado na
ListView :
As outras duas capturas de tela mostram as configurações alteradas. Ao experimentar com essa página, lembre-
se de colocar o programa no modo de suspensão ou encerrá-lo no dispositivo ou no emulador em que está
sendo executado. O encerramento do programa no depurador do Visual Studio não chamará a substituição
OnSleep na classe App .
No próximo artigo, você verá como especificar a Formatação da cadeia de caracteres de associações de dados
que são definidas na propriedade Text de Label .
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Formatação de cadeia de caracteres do
Xamarin.Forms
12/04/2019 • 8 minutes to read • Edit Online
Baixar o exemplo
Às vezes, é conveniente usar associações de dados para exibir a representação de cadeia de caracteres de um
objeto ou um valor. Por exemplo, talvez você deseje usar um Label para exibir o valor atual de um Slider . Nesta
associação de dados, o Slider é a origem e o destino é a propriedade Text do Label .
Ao exibir cadeias de caracteres no código, a ferramenta mais avançada é o método estático String.Format . A
cadeia de caracteres de formatação inclui códigos de formatação para diversos tipos de objetos, sendo que você
pode incluir outros textos junto com os valores que estão sendo formatados. Confira o artigo Formatando tipos
no .NET para obter mais informações sobre a formatação da cadeia de caracteres.
A propriedade StringFormat
Este recurso é levado para as associações de dados: Você define a propriedade StringFormat de Binding (ou a
propriedade StringFormat da extensão de marcação Binding ) como uma cadeia de caracteres de formatação
padrão do .NET com um espaço reservado:
Observe que a cadeia de caracteres de formatação é delimitada por caracteres de aspas simples (apóstrofo) para
ajudar o analisador de XAML a evitar tratar as chaves como outra extensão de marcação XAML. De outra forma,
essa cadeia de caracteres sem o caractere de aspas simples é a mesma cadeia de caracteres usada para exibir um
valor de ponto flutuante em uma chamada a String.Format . Uma especificação de formatação de F2 faz com
que o valor seja exibido com duas casas decimais.
A propriedade StringFormat só faz sentido quando a propriedade de destino é do tipo string e o modo de
associação é OneWay ou TwoWay . Para vinculações bidirecionais, o StringFormat só é aplicável a valores que
passam da origem para o destino.
Como você verá no próximo artigo sobre o Caminho de associação, as associações de dados podem se tornar
muito complexas e complicadas. Ao depurar essas associações de dados, você pode adicionar um Label ao
arquivo XAML com um StringFormat para exibir alguns resultados intermediários. Mesmo se você usá-lo
somente para exibir o tipo de um objeto, isso pode ser útil.
A página Formatação da cadeia de caracteres ilustra vários usos da propriedade StringFormat :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="DataBindingDemos.StringFormattingPage"
Title="String Formatting">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<Style TargetType="BoxView">
<Setter Property="Color" Value="Blue" />
<Setter Property="HeightRequest" Value="2" />
<Setter Property="Margin" Value="0, 5" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10">
<Slider x:Name="slider" />
<Label Text="{Binding Source={x:Reference slider},
Path=Value,
StringFormat='The slider value is {0:F2}'}" />
<BoxView />
<BoxView />
<BoxView />
<BoxView />
As associações no Slider e no TimePicker mostram o uso de especificações de formato específicas aos tipos de
dados double e TimeSpan . O StringFormat que exibe o texto na exibição Entry demonstra como especificar
aspas duplas na cadeia de caracteres de formatação com o uso da entidade HTML " .
A próxima seção do arquivo XAML é um StackLayout com um BindingContext definido como uma extensão de
marcação x:Static que referencia a propriedade estática DateTime.Now . A primeira associação não tem
nenhuma propriedade:
Isso apenas exibe o valor DateTime do BindingContext com a formatação padrão. A segunda associação exibe a
propriedade Ticks de DateTime , enquanto as outras duas associações exibem o próprio DateTime com
formatação específica. Observe este StringFormat :
Caso precise exibir chaves direitas ou esquerdas na cadeia de caracteres de formatação, basta usar um par de
chaves.
A última seção define o BindingContext com valor de Math.PI e o exibe com a formatação padrão e dois tipos
diferentes de formatação numérica.
Este é o programa em execução:
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout>
<StackLayout.BindingContext>
<local:HslColorViewModel Color="Sienna" />
</StackLayout.BindingContext>
Agora há três pares de elementos Slider e Label associados à mesma propriedade de origem no objeto
HslColorViewModel . A única diferença é que Label tem uma propriedade StringFormat para exibir cada valor
Slider .
Você deve estar se perguntando como poderá exibir valores RGB (vermelho, verde, azul) em formato hexadecimal
tradicional de dois dígitos. Esses valores inteiros não estão diretamente disponíveis na estrutura Color . Uma
solução é calcular valores inteiros dos componentes de cor dentro do ViewModel e expô-los como propriedades.
Em seguida, você pode formatá-los usando a especificação de formatação X2 .
Outra abordagem é mais geral: Você pode gravar um conversor de valor de associação como abordado no artigo
posterior, Conversores de valor de associação.
No entanto, o próximo artigo explora o Caminho de associação com mais detalhes e mostra como você pode
usá-lo para referenciar subpropriedades e itens em coleções.
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Caminho de associação do Xamarin.Forms
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Em todos os exemplos anteriores de associação de dados, a propriedade Path da classe Binding (ou a
propriedade Path da extensão de marcação Binding ) foi definida como uma única propriedade. Na verdade, é
possível definir Path como uma subpropriedade (uma propriedade de uma propriedade) ou como um membro
de uma coleção.
Por exemplo, suponha que a página contenha um TimePicker :
<TimePicker x:Name="timePicker">
A propriedade Time de TimePicker é do tipo TimeSpan , mas talvez você deseje criar uma associação de dados
que referencie a propriedade TotalSeconds desse valor TimeSpan . Esta é a associação de dados:
A propriedade Time é do tipo TimeSpan , que tem uma propriedade TotalSeconds . As propriedades Time e
TotalSeconds são simplesmente conectadas com um ponto. Os itens da cadeia de caracteres Path sempre se
referem a propriedades e não aos tipos dessas propriedades.
Esse exemplo e vários outros são mostrados na página Variações de caminho:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:globe="clr-namespace:System.Globalization;assembly=mscorlib"
x:Class="DataBindingDemos.PathVariationsPage"
Title="Path Variations"
x:Name="page">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="Large" />
<Setter Property="HorizontalTextAlignment" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
No segundo Label , a origem da associação é a página propriamente dita. A propriedade Content é do tipo
StackLayout , que tem uma propriedade Children do tipo IList<View> , que, por sua vez, tem uma propriedade
Count que indica o número de filhos.
<Label>
<Label.Text>
<Binding Path="DateTimeFormat.DayNames[3]"
StringFormat="The middle day of the week in France is {0}">
<Binding.Source>
<globe:CultureInfo>
<x:Arguments>
<x:String>fr-FR</x:String>
</x:Arguments>
</globe:CultureInfo>
</Binding.Source>
</Binding>
</Label.Text>
</Label>
Confira Passando argumentos de construtor para obter mais detalhes sobre como especificar argumentos de
construtor em XAML.
Por fim, o último exemplo é semelhante ao segundo, exceto que ele referencia um dos filhos do StackLayout :
Esse filho é um Label , que tem uma propriedade Text do tipo String , que, por sua vez, tem uma propriedade
Length . O primeiro Label relata o TimeSpan definido no TimePicker ; portanto, quando esse texto é alterado, o
último Label também é alterado.
Este é o programa em execução:
Caminhos complexos de depuração
Definições de caminhos complexos podem ser difíceis de construir: Você precisa saber o tipo de cada
subpropriedade ou o tipo dos itens na coleção para adicionar corretamente a próxima subpropriedade, mas os
tipos propriamente ditos não são exibidos no caminho. Uma boa técnica é criar o caminho de forma incremental e
examinar os resultados intermediários. Para esse último exemplo, você pode começar sem nenhuma definição de
Path :
O tipo da propriedade Content agora é revelado como sendo Xamarin.Forms.StackLayout . Adicione a propriedade
Children ao Path e o tipo será Xamarin.Forms.ElementCollection'1[Xamarin.Forms.View] , que é uma classe interna
do Xamarin.Forms, mas, obviamente, um tipo de coleção. Adicione um índice a ele e o tipo será
Xamarin.Forms.Label . Continue dessa maneira.
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Conversores de valor de associação do
Xamarin.Forms
12/04/2019 • 17 minutes to read • Edit Online
Baixar o exemplo
Normalmente, associações de dados transferem dados de uma propriedade de origem para uma propriedade de
destino e, em alguns casos, da propriedade de destino para a propriedade de origem. Essa transferência é simples
quando as propriedades de origem e de destino são do mesmo tipo ou quando um tipo pode ser convertido para
outro por meio de uma conversão implícita. Quando não é esse o caso, é necessário realizar uma conversão de
tipo.
No artigo Formatação de Cadeia de Caracteres, você viu como é possível usar a propriedade StringFormat de
uma associação de dados para converter qualquer tipo em uma cadeia de caracteres. Para outros tipos de
conversões, você precisa escrever código especializado em uma classe que implementa a interface
IValueConverter . ( A Plataforma Universal do Windows contém uma classe semelhante chamada IValueConverter
no namespace Windows.UI.Xaml.Data , mas essa IValueConverter está no namespace Xamarin.Forms .) As classes
que implementam IValueConverter são denominadas conversores de valor, mas também são conhecidas como
conversores de associação ou conversores de valor de associação.
A interface IValueConverter
Digamos que você queira definir uma associação de dados em que a propriedade de origem é do tipo int , mas a
propriedade de destino é um bool . Você quer que essa associação de dados produza um valor de false quando
a origem do inteiro for igual a 0 e, caso contrário, true .
É possível fazer isso com uma classe que implemente a interface IValueConverter :
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? 1 : 0;
}
}
Você define uma instância dessa classe como a propriedade Converter da classe Binding ou como a propriedade
Converter da extensão de marcação Binding . Essa classe se torna parte da associação de dados.
O método Convert é chamado quando dados são passados da origem para o destino nas associações OneWay ou
TwoWay . O parâmetro value é o objeto ou o valor da origem da associação de dados. O método deve retornar
um valor com o tipo do destino da associação de dados. O método mostrado aqui converte o parâmetro value
para um int e, em seguida, o compara com 0 para um valor retornado de bool .
O método ConvertBack é chamado quando dados são passados do destino para a origem nas associações
TwoWay ou OneWayToSource . ConvertBack realiza a conversão oposta: Ele pressupõe que o parâmetro value é um
bool do destino e o converte em um valor retornado de int para a fonte.
Se a associação de dados também incluir uma configuração de StringFormat , o conversor de valor será invocado
antes que o resultado seja formatado como uma cadeia de caracteres.
A página Habilitar Botões no exemplo Demonstrações de Associação de Dados demonstra como usar esse
conversor de valor em uma associação de dados. É criada uma instância de IntToBoolConverter no dicionário de
recursos da página. Em seguida, ele é referenciado com uma extensão de marcação StaticResource para definir a
propriedade Converter nas duas associações de dados. É muito comum compartilhar conversores de dados entre
várias associações de dados na página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.EnableButtonsPage"
Title="Enable Buttons">
<ContentPage.Resources>
<ResourceDictionary>
<local:IntToBoolConverter x:Key="intToBool" />
</ResourceDictionary>
</ContentPage.Resources>
<Button Text="Search"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
IsEnabled="{Binding Source={x:Reference entry1},
Path=Text.Length,
Converter={StaticResource intToBool}}" />
<Entry x:Name="entry2"
Text=""
Placeholder="enter destination"
VerticalOptions="CenterAndExpand" />
<Button Text="Submit"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
IsEnabled="{Binding Source={x:Reference entry2},
Path=Text.Length,
Converter={StaticResource intToBool}}" />
</StackLayout>
</ContentPage>
Se um conversor de valor for usado em várias páginas de seu aplicativo, você poderá criar uma instância dele no
dicionário de recursos no arquivo App.xaml.
A página Habilitar Botões demonstra uma necessidade comum quando um Button executa uma operação com
base no texto que o usuário digita em uma exibição de Entry . Se nada tiver sido digitado no Entry , o Button
deverá ser desabilitado. Cada Button contém uma associação de dados em sua propriedade IsEnabled . A origem
da associação de dados é a propriedade Length da propriedade Text do Entry correspondente. Se essa
propriedade Length não for 0, o conversor de valor retornará true e Button será habilitado:
Observe que a propriedade Text em cada Entry é inicializada como uma cadeia de caracteres vazia. A
propriedade Text é null por padrão e a associação de dados não funcionará nesse caso.
Alguns conversores de valor são escritos especificamente para aplicativos específicos, enquanto outros são
generalizados. Se você souber que um conversor de valor será usado apenas em associações de OneWay , o
método ConvertBack poderá simplesmente retornar null .
O método Convert mostrado acima supõe implicitamente que o argumento value é do tipo int e que o valor
retornado deve ser do tipo bool . Da mesma forma, o método ConvertBack supõe que o argumento value é do
tipo bool e que o valor retornado é int . Se não for esse o caso, ocorrerá uma exceção de tempo de execução.
Você pode escrever conversores de valor de forma que eles sejam mais generalizados e aceitem vários tipos de
dados diferentes. Os métodos Convert e ConvertBack podem usar os operadores as ou is com o parâmetro
value ou podem chamar GetType nesse parâmetro para determinar seu tipo e, em seguida, fazer algo
apropriado. O tipo esperado do valor retornado de cada método é determinado pelo parâmetro targetType . Às
vezes, conversores de valor são usados com associações de dados com tipos de destino diferentes. O conversor de
valor pode usar o argumento targetType para executar uma conversão para o tipo correto.
Se a conversão que está sendo executada for diferente para culturas diferentes, use o parâmetro culture para
essa finalidade. O argumento parameter para Convert e ConvertBack é abordado posteriormente neste artigo.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (bool)value ? TrueObject : FalseObject;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return ((T)value).Equals(TrueObject);
}
}
A página Alternar Indicadores demonstra como ele pode ser usado para exibir o valor de uma exibição de
Switch . Embora seja comum para instanciar os conversores de valor como recursos em um dicionário de
recursos, esta página demonstra uma alternativa: Cada conversor de valor é instanciado entre marcas de elemento
de propriedade Binding.Converter . O x:TypeArguments indica o argumento genérico e TrueObject e FalseObject
são configurados como objetos desse tipo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.SwitchIndicatorsPage"
Title="Switch Indicators">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="FontSize" Value="18" />
<Setter Property="VerticalOptions" Value="Center" />
</Style>
<Style TargetType="Switch">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Label Text="Allow popups?" />
<Switch x:Name="switch2" />
<Label>
<Label>
<Label.Text>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="x:String"
TrueObject="Yes"
FalseObject="No" />
</Binding.Converter>
</Binding>
</Label.Text>
<Label.TextColor>
<Binding Source="{x:Reference switch2}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="Color"
TrueObject="Green"
FalseObject="Red" />
</Binding.Converter>
</Binding>
</Label.TextColor>
</Label>
</StackLayout>
<StackLayout Orientation="Horizontal"
VerticalOptions="CenterAndExpand">
<Label Text="Learn more?" />
<Switch x:Name="switch3" />
<Label FontSize="18"
VerticalOptions="Center">
<Label.Style>
<Binding Source="{x:Reference switch3}"
Path="IsToggled">
<Binding.Converter>
<local:BoolToObjectConverter x:TypeArguments="Style">
<local:BoolToObjectConverter.TrueObject>
<Style TargetType="Label">
<Setter Property="Text" Value="Indubitably!" />
<Setter Property="FontAttributes" Value="Italic, Bold" />
<Setter Property="TextColor" Value="Green" />
</Style>
</local:BoolToObjectConverter.TrueObject>
<local:BoolToObjectConverter.FalseObject>
<Style TargetType="Label">
<Setter Property="Text" Value="Maybe later" />
<Setter Property="FontAttributes" Value="None" />
<Setter Property="TextColor" Value="Red" />
</Style>
</local:BoolToObjectConverter.FalseObject>
</local:BoolToObjectConverter>
</Binding.Converter>
</Binding>
</Label.Style>
</Label>
</StackLayout>
</StackLayout>
</ContentPage>
No último dos três pares de Switch e Label , o argumento genérico é definido como Style e objetos Style
inteiros são fornecidos para os valores de TrueObject e FalseObject . Eles substituem o estilo implícito de Label
definido no dicionário de recursos, portanto, as propriedades do estilo são atribuídas explicitamente ao Label .
Ativar/desativar o Switch faz com que o Label correspondente reflita a alteração:
Também é possível usar Triggers para implementar alterações semelhantes na interface do usuário com base em
outras exibições.
Name = NamedColor.GetNearestColorName(color);
}
}
get
{
return color;
}
}
As propriedades Red , Green e Blue variam entre 0 e 1. No entanto, talvez você prefira que os componentes
sejam exibidos como valores hexadecimais de dois dígitos.
Para exibi-los como valores hexadecimais em XAML, eles devem ser multiplicados por 255, convertidos em um
inteiro e, em seguida, formatados com uma especificação de "X2" na propriedade StringFormat . As duas
primeiras tarefas (multiplicar por 255 e converter em um número inteiro) podem ser realizadas pelo conversor de
valor. Para tornar o conversor de valor tão generalizado quanto possível, o fator de multiplicação pode ser
especificado com a propriedade ConverterParameter , o que significa que ele insere os métodos Convert e
ConvertBack como o argumento parameter :
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return (int)value / GetParameter(parameter);
}
return 1;
}
}
O Convert é convertido de um double para int ao multiplicar pelo valor de parameter ; o ConvertBack divide o
argumento value inteiro pelo parameter e retorna um resultado double . (No programa mostrado abaixo, o
conversor de valor é usado apenas para formatação da cadeia de caracteres e, portanto, ConvertBack não é
usado.)
O tipo do argumento parameter provavelmente será diferente dependendo de a associação de dados estar
definida no código ou em XAML. Se a propriedade ConverterParameter de Binding estiver definida no código,
será provável que ela esteja definida como um valor numérico:
binding.ConverterParameter = 255;
A propriedade ConverterParameter é do tipo Object , portanto, o compilador de C# interpreta o literal 255 como
um número inteiro e define a propriedade com esse valor.
Em XAML, no entanto, é provável que o ConverterParameter esteja definido desta forma:
O 255 é semelhante a um número, mas como ConverterParameter é do tipo Object , o analisador de XAML trata
o 255 como uma cadeia de caracteres.
Por esse motivo, o conversor de valor mostrado acima inclui um método GetParameter separado que lida com os
casos de parameter ser do tipo double , int ou string .
A página Seletor de Cor RGB cria uma instância de DoubleToIntConverter em seu dicionário de recursos após a
definição de dois estilos implícitos:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.RgbColorSelectorPage"
Title="RGB Color Selector">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Slider">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
</Style>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
<StackLayout>
<StackLayout.BindingContext>
<local:RgbColorViewModel Color="Gray" />
</StackLayout.BindingContext>
Os valores das propriedades Red e Green são exibidos com uma extensão de marcação Binding . A propriedade
Blue , no entanto, instancia a classe Binding para demonstrar como um valor de double explícito pode ser
definido como a propriedade ConverterParameter .
Este é o resultado:
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Fallbacks de associação do Xamarin.Forms
12/04/2019 • 7 minutes to read • Edit Online
Baixar o exemplo
Às vezes, as associações de dados falham porque a origem da associação não pode ser resolvida ou porque a
associação tem êxito, mas retorna um valor null . Embora esses cenários possam ser manipulados com
conversores de valor ou outro código adicional, as associações de dados poderão se tornar mais robustas com a
definição de valores de fallback a serem usados se o processo de associação falhar. Isso pode ser feito com a
definição das propriedades FallbackValue e TargetNullValue em uma expressão de associação. Como essas
propriedades residem na classe BindingBase , elas podem ser usadas com associações, associações compiladas e
com a extensão de marcação Binding .
NOTE
O uso das propriedades FallbackValue e TargetNullValue em uma expressão de associação é opcional.
A associação no Label definirá um valor FallbackValue que será definido no destino se a origem da associação
não puder ser resolvida. Portanto, o valor definido pela propriedade FallbackValue será exibido se a propriedade
Population não existir no objeto associado. Observe que aqui o valor da propriedade FallbackValue é delimitado
por caracteres de aspas simples (apóstrofo).
Em vez de definir os valores da propriedade FallbackValue de forma embutida, recomendamos defini-los como
recursos em um ResourceDictionary . A vantagem dessa abordagem é que esses valores são definidos uma única
vez em uma só localização e são mais facilmente localizáveis. Em seguida, os recursos podem ser recuperados
usando a extensão de marcação StaticResource :
NOTE
Não é possível definir a propriedade FallbackValue com uma expressão de associação.
IMPORTANT
Um conversor de valor definido não é executado em uma expressão de associação quando a propriedade FallbackValue
está definida.
As associações no Image e Label definem valores TargetNullValue que serão aplicados se o caminho de
associação retornar null . Portanto, os valores definidos pelas propriedades TargetNullValue serão exibidos para
todos os objetos na coleção em que as propriedades ImageUrl e Location não estiverem definidas. Observe que
aqui os valores da propriedade TargetNullValue são delimitados por caracteres de aspas simples (apóstrofo).
Em vez de definir os valores da propriedade TargetNullValue de forma embutida, recomendamos defini-los como
recursos em um ResourceDictionary . A vantagem dessa abordagem é que esses valores são definidos uma única
vez em uma só localização e são mais facilmente localizáveis. Em seguida, os recursos podem ser recuperados
usando a extensão de marcação StaticResource :
<Image Source="{Binding ImageUrl, TargetNullValue={StaticResource fallbackImageUrl}}"
... />
<Label Text="{Binding Location, TargetNullValue={StaticResource locationUnknown}}"
... />
NOTE
Não é possível definir a propriedade TargetNullValue com uma expressão de associação.
Quando a propriedade TargetNullValue não estiver definida em uma expressão de associação, um valor de
origem igual a null será convertido se um conversor de valor for definido, formatado se um StringFormat for
definido e o resultado será então definido no destino. No entanto, quando a propriedade TargetNullValue for
definida, um valor de origem igual a null será convertido se um conversor de valor for definido e se ele ainda for
null após a conversão, o valor da propriedade TargetNullValue será definido no destino.
IMPORTANT
A formatação de cadeia de caracteres não é aplicada em uma expressão de associação quando a propriedade
TargetNullValue está definida.
Links relacionados
Demonstrações de associação de dados (amostra)
A interface de comando do Xamarin.Forms
12/04/2019 • 30 minutes to read • Edit Online
Baixar o exemplo
Na arquitetura MVVM (Model-View -ViewModel), as associações de dados são definidas entre propriedades no
ViewModel, que geralmente é uma classe derivada de INotifyPropertyChanged , e propriedades no View, que
geralmente é o arquivo XAML. Às vezes, um aplicativo tem necessidades que vão além dessas associações de
propriedade ao exigir que o usuário inicie os comandos que afetam algo no ViewModel. Esses comandos
geralmente são sinalizados por cliques de botões ou toques de dedos e são tradicionalmente processados no
arquivo code-behind em um manipulador para o evento Clicked do Button ou o evento Tapped de um
TapGestureRecognizer .
A interface de comando oferece uma abordagem alternativa à implementação de comandos, que é bem mais
adequada à arquitetura MVVM. O próprio ViewModel pode conter comandos, que são métodos executados em
reação a uma atividade específica no View, como um clique Button . Associações de dados são definidas entre
esses comandos e o Button .
Para permitir uma associação de dados entre um Button e um ViewModel, o Button define duas propriedades:
Command do tipo System.Windows.Input.ICommand
CommandParameter do tipo Object
Para usar a interface de comando, defina uma associação de dados que direcione a propriedade Command do
Button , em que a origem é uma propriedade no ViewModel do tipo ICommand . O ViewModel contém um código
associado a essa propriedade ICommand executada quando se clica no botão. É possível definir CommandParameter
como dados arbitrários para distinguir entre vários botões se eles forem todos associados à mesma propriedade
ICommand no ViewModel.
SearchBar define uma propriedade SearchCommand do tipo ICommand e uma propriedade SearchCommandParameter
. A propriedade RefreshCommand de ListView também é do tipo ICommand .
Todos esses comandos podem ser manipulados dentro de um ViewModel, de forma que ele não dependa do
objeto específico da interface do usuário no View.
A interface ICommand
A interface System.Windows.Input.ICommand não faz parte do Xamarin.Forms. Ela é definida no lugar do
namespace System.Windows.Input e consiste em dois métodos e um evento:
public interface ICommand
{
public void Execute (Object parameter);
O ViewModel também deve referenciar uma classe que implementa a interface ICommand . Essa classe será
descrita em breve. No View, a propriedade Command de um Button é associada a essa propriedade:
Quando o usuário pressiona o Button , o Button chama o método Execute no objeto ICommand associado a sua
propriedade Command . Essa é a parte mais simples da interface de comando.
O método CanExecute é mais complexo. Quando a associação é definida na propriedade Command do Button
pela primeira vez e quando a associação de dados é alterada de alguma forma, o Button chama o método
CanExecute no objeto ICommand . Se CanExecute retornar false , então o Button se desabilitará. Isso indica que
o comando específico não está disponível no momento ou é inválido.
O Button também anexa um manipulador no evento CanExecuteChanged de ICommand . O evento é acionado de
dentro do ViewModel. Quando o evento é acionado, o Button chama o CanExecute novamente. O Button
habilita a si mesmo se o CanExecute retorna true e desabilita a si mesmo se CanExecute retorna false .
IMPORTANT
Não use a propriedade IsEnabled de Button se estiver usando a interface de comando.
A classe de comando
Quando o ViewModel define uma propriedade do tipo ICommand , ele também deve conter ou referenciar uma
classe que implementa a interface ICommand . Essa classe deverá conter ou referenciar os métodos Execute e
CanExecute e acionar o evento CanExecuteChanged sempre que o método CanExecute puder retornar um valor
diferente.
É possível gravar essa classe sozinho ou usar uma classe que alguém tenha gravado. Como o ICommand faz parte
do Microsoft Windows, ele tem sido usado por anos com aplicativos da MVVM do Windows. Usar uma classe do
Windows que implementa o ICommand permite que você compartilhe seus ViewModels entre aplicativos do
Windows e aplicativos Xamarin.Forms.
Se o compartilhamento de ViewModels entre o Windows e o Xamarin.Forms não for uma preocupação, você
poderá usar a classe Command ou Command<T> incluída no Xamarin.Forms para implementar a interface ICommand .
Essas classes permitem que você especifique os corpos dos métodos Execute e CanExecute em construtores de
classe. Use Command<T> quando você usar a propriedade CommandParameter para distinguir entre vários modos de
exibição associados à mesma propriedade ICommand , e a classe Command mais simples quando isso não for um
requisito.
Comando básico
A página Entrada de pessoa no programa Demonstrações de associação de dados demonstra alguns
comandos simples implementados em um ViewModel.
O PersonViewModel define três propriedades denominadas Name , Age e Skills que definem uma pessoa. Essa
classe não contém nenhuma propriedade ICommand :
storage = value;
OnPropertyChanged(propertyName);
return true;
}
O PersonCollectionViewModel mostrado a seguir cria novos objetos do tipo PersonViewModel e permite que o
usuário preencha os dados. Para essa finalidade, a classe define propriedades IsEditing do tipo bool e
PersonEdit do tipo PersonViewModel . Além disso, a classe define três propriedades do tipo ICommand e uma
propriedade chamada Persons do tipo IList<PersonViewModel> :
public class PersonCollectionViewModel : INotifyPropertyChanged
{
PersonViewModel personEdit;
bool isEditing;
···
storage = value;
OnPropertyChanged(propertyName);
return true;
}
Essa listagem abreviada não inclui o construtor da classe, que é onde as três propriedades do tipo ICommand são
definidas, que serão mostradas em breve. Observe que as alterações nas três propriedades do tipo ICommand e a
propriedade Persons não faz os eventos PropertyChanged serem acionados. Todas essas propriedades são
definidas quando a classe é criada pela primeira vez e não são alteradas depois disso.
Antes de examinar o construtor da classe PersonCollectionViewModel , vamos examinar se há o programa Entrada
de pessoa no arquivo XAML. Ele contém um Grid com sua propriedade BindingContext definida como o
PersonCollectionViewModel . O Grid contém um Button com o texto Novo com sua propriedade Command
associada à propriedade NewCommand no ViewModel, um formulário de entrada com propriedades associadas à
propriedade IsEditing , bem como propriedades de PersonViewModel e mais dois botões associados às
propriedades SubmitCommand e CancelCommand do ViewModel. O último ListView exibe a coleção de pessoas já
que já entraram:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.PersonEntryPage"
Title="Person Entry">
Title="Person Entry">
<Grid Margin="10">
<Grid.BindingContext>
<local:PersonCollectionViewModel />
</Grid.BindingContext>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
</Grid>
<Button Text="Submit"
Grid.Column="0"
Command="{Binding SubmitCommand}"
VerticalOptions="CenterAndExpand" />
<Button Text="Cancel"
Grid.Column="1"
Command="{Binding CancelCommand}"
Command="{Binding CancelCommand}"
VerticalOptions="CenterAndExpand" />
</Grid>
Veja como funciona: O usuário primeiro pressiona o botão Novo. Isso habilita o formulário de entrada, mas
desabilita o botão Novo. O usuário insere, então, um nome, idade e habilidades. A qualquer momento durante a
edição, o usuário pode pressionar o botão Cancelar para recomeçar. Somente depois que um nome e uma idade
válida forem inseridos, o botão Enviar será habilitado. Pressionar esse botão Enviar transfere a pessoa para a
coleção exibida pelo ListView . Depois que o botão Cancelar ou Enviar é pressionado, o formulário de entrada é
limpo e o botão Novo é habilitado novamente.
A tela do iOS à esquerda mostra o layout antes que uma idade válida seja inserida. As telas do Android e da
UWP mostram o botão Enviar habilitado depois que uma idade é definida:
O programa não tem nenhum recurso para editar entradas existentes nem salva as entradas quando você sai da
página.
Toda a lógica dos botões Novo, Enviar, e Cancelar é tratado em PersonCollectionViewModel por meio das
definições das propriedades NewCommand , SubmitCommand e CancelCommand . O construtor do
PersonCollectionViewModel define essas três propriedades para objetos do tipo Command .
Um construtor da classe Command permite que você passe argumentos do tipo Action e Func<bool>
correspondentes aos métodos Execute e CanExecute . É mais fácil definir essas ações e funções como funções
lambda direto no construtor Command . Veja a definição do objeto Command para a propriedade NewCommand :
public class PersonCollectionViewModel : INotifyPropertyChanged
{
···
public PersonCollectionViewModel()
{
NewCommand = new Command(
execute: () =>
{
PersonEdit = new PersonViewModel();
PersonEdit.PropertyChanged += OnPersonEditPropertyChanged;
IsEditing = true;
RefreshCanExecutes();
},
canExecute: () =>
{
return !IsEditing;
});
···
void RefreshCanExecutes()
{
(NewCommand as Command).ChangeCanExecute();
(SubmitCommand as Command).ChangeCanExecute();
(CancelCommand as Command).ChangeCanExecute();
}
···
Quando o usuário clica no botão Novo, a função execute passada para o construtor Command é executada. Isso
cria um novo objeto PersonViewModel , define um manipulador no evento PropertyChanged desse objeto, define
IsEditing como true e chama o método RefreshCanExecutes definido após o construtor.
Além de implementar a interface ICommand , a classe Command também define um método chamado
ChangeCanExecute . O ViewModel deve chamar ChangeCanExecute para uma propriedade ICommand sempre que
acontecer qualquer coisa que possa alterar o valor retornado do método CanExecute . Uma chamada ao
ChangeCanExecute faz a classe Command acionar o método CanExecuteChanged . O Button anexou um manipulador
para o evento, responde chamando CanExecute novamente e permitindo que se baseie no valor retornado desse
método.
Quando o método execute de NewCommand chama RefreshCanExecutes , a propriedade NewCommand obtém uma
chamada a ChangeCanExecute , e o Button chama o método canExecute , que agora retorna false porque a
propriedade IsEditing agora é true .
O manipulador PropertyChanged do novo objeto PersonViewModel chama o método ChangeCanExecute de
SubmitCommand . Veja como essa propriedade de comando é implementada:
public class PersonCollectionViewModel : INotifyPropertyChanged
{
···
public PersonCollectionViewModel()
{
···
···
}
···
A função para SubmitCommand é chamada sempre que há uma propriedade alterada no objeto
canExecute
PersonViewModel que está sendo editado. Ela retorna true somente quando a propriedade Name tem pelo
menos um caractere de comprimento e Age é maior que 0. Nesse momento, o botão Enviar fica habilitado.
A função execute para Enviar remove o manipulador de propriedade alterada do PersonViewModel , adiciona o
objeto à coleção Persons e retorna tudo para as condições iniciais.
A função execute para o botão Cancelar faz tudo o que o botão Enviar faz, exceto adicionar o objeto à coleção:
public class PersonCollectionViewModel : INotifyPropertyChanged
{
···
public PersonCollectionViewModel()
{
···
···
O método canExecute retorna true a qualquer momento que um PersonViewModel está sendo editado.
Essas técnicas poderiam ser adaptadas para cenários mais complexos: Uma propriedade no
PersonCollectionViewModel poderia estar associada à propriedade SelectedItem do ListView para editar itens
existentes e o botão Excluir poderia ser adicionado para excluir esses itens.
Não é necessário definir os métodos execute e canExecute como funções lambda. É possível gravá-los como
métodos privados regulares no ViewModel e referenciá-los nos construtores Command . No entanto, essa
abordagem tende a resultar em uma grande quantidade de métodos referenciados apenas uma vez no
ViewModel.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.DecimalKeypadPage"
Title="Decimal Keyboard">
<Grid WidthRequest="240"
HeightRequest="480"
ColumnSpacing="2"
RowSpacing="2"
HorizontalOptions="Center"
VerticalOptions="Center">
<Grid.BindingContext>
<local:DecimalKeypadViewModel />
</Grid.BindingContext>
<Grid.Resources>
<ResourceDictionary>
<Style TargetType="Button">
<Setter Property="FontSize" Value="32" />
<Setter Property="BorderWidth" Value="1" />
<Setter Property="BorderColor" Value="Black" />
</Style>
</ResourceDictionary>
</Grid.Resources>
<Button Text="CLEAR"
Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Command="{Binding ClearCommand}" />
<Button Text="⇦"
Grid.Row="1" Grid.Column="2"
Command="{Binding BackspaceCommand}" />
<Button Text="7"
Grid.Row="2" Grid.Column="0"
Command="{Binding DigitCommand}"
CommandParameter="7" />
<Button Text="8"
Grid.Row="2" Grid.Column="1"
Command="{Binding DigitCommand}"
CommandParameter="8" />
<Button Text="9"
Grid.Row="2" Grid.Column="2"
Command="{Binding DigitCommand}"
CommandParameter="9" />
<Button Text="4"
Grid.Row="3" Grid.Column="0"
Command="{Binding DigitCommand}"
CommandParameter="4" />
<Button Text="5"
Grid.Row="3" Grid.Column="1"
Command="{Binding DigitCommand}"
CommandParameter="5" />
<Button Text="6"
Grid.Row="3" Grid.Column="2"
Command="{Binding DigitCommand}"
CommandParameter="6" />
CommandParameter="6" />
<Button Text="1"
Grid.Row="4" Grid.Column="0"
Command="{Binding DigitCommand}"
CommandParameter="1" />
<Button Text="2"
Grid.Row="4" Grid.Column="1"
Command="{Binding DigitCommand}"
CommandParameter="2" />
<Button Text="3"
Grid.Row="4" Grid.Column="2"
Command="{Binding DigitCommand}"
CommandParameter="3" />
<Button Text="0"
Grid.Row="5" Grid.Column="0" Grid.ColumnSpan="2"
Command="{Binding DigitCommand}"
CommandParameter="0" />
<Button Text="·"
Grid.Row="5" Grid.Column="2"
Command="{Binding DigitCommand}"
CommandParameter="." />
</Grid>
</ContentPage>
Observe que o botão para o ponto decimal em todas as três capturas de tela está desabilitado, porque o número
inserido já contém um ponto decimal.
O DecimalKeypadViewModel define uma propriedade Entry do tipo string (que é a única propriedade que
dispara um evento PropertyChanged ) e três propriedades do tipo ICommand :
public class DecimalKeypadViewModel : INotifyPropertyChanged
{
string entry = "0";
···
O botão correspondente ao ClearCommand está sempre habilitado e simplesmente define a entrada de volta para
"0":
···
public DecimalKeypadViewModel()
{
ClearCommand = new Command(
execute: () =>
{
Entry = "0";
RefreshCanExecutes();
});
···
void RefreshCanExecutes()
{
((Command)BackspaceCommand).ChangeCanExecute();
((Command)DigitCommand).ChangeCanExecute();
}
···
Como o botão sempre está habilitado, não é necessário especificar um argumento canExecute no construtor
Command .
A lógica para inserir números e backspace é um pouco complicada, porque se nenhum dígito foi inserido, a
propriedade Entry será a cadeia de caracteres "0". Se o usuário digitar mais zeros, então o Entry ainda conterá
apenas um zero. Se o usuário digita qualquer outro dígito, esse dígito substitui o zero. Mas se o usuário digita um
ponto decimal antes de qualquer outro dígito, então Entry é a cadeia de caracteres "0".
O botão Backspace é habilitado apenas quando o comprimento da entrada é maior que 1 ou se Entry não é
igual à cadeia de caracteres "0":
···
public DecimalKeypadViewModel()
{
···
···
···
A lógica para a função execute do botão Backspace garante que o Entry é pelo menos uma cadeia de
caracteres de comprimento "0".
A propriedade DigitCommandestá associada a 11 botões, cada um dos quais identifica-se com a propriedade
CommandParameter . O DigitCommand poderia ser definido como uma instância da classe Command regular, mas é
mais fácil usar a classe genérica Command<T> . Ao usar a interface de comando com o XAML, as propriedades
CommandParameter geralmente são cadeias de caracteres e esse é o tipo de argumento genérico. As funções
execute e canExecute têm argumentos do tipo string :
public class DecimalKeypadViewModel : INotifyPropertyChanged
{
···
public DecimalKeypadViewModel()
{
···
···
···
</TableSection>
</TableRoot>
</TableView>
</ContentPage>
Ao usar comandos com XAML, as propriedades CommandParameter geralmente são definidas como cadeias de
caracteres. No entanto, nesse caso, uma extensão de marcação XAML é usada para que o CommandParameter seja
do tipo System.Type .
Cada propriedade Command está associada a uma propriedade chamada NavigateCommand . Se a propriedade
estiver definida no arquivo code-behind, MainPage.xaml.cs:
BindingContext = this;
}
O construtor define a propriedade NavigateCommand como um método execute que cria a instância do parâmetro
System.Type e navega até ela. Como a chamada PushAsync requer um operador await , o método execute deve
ser sinalizado como assíncrono. Isso é feito com a palavra-chave async antes da lista de parâmetros.
O construtor também define o BindingContext da página como a si mesmo para que as associações referenciem
o NavigateCommand nessa classe.
A ordem do código nesse construtor faz a diferença: A chamada InitializeComponent causa a análise do XAML,
mas, nesse momento, a associação a uma propriedade denominada NavigateCommand não pode ser resolvida,
porque BindingContext está definido como null . Se o BindingContext for definido no construtor antes de
NavigateCommand ser definido, a associação poderá ser resolvida quando BindingContext for definido, mas, nesse
momento, NavigateCommand ainda será null . Definir NavigateCommand após BindingContext não terá efeito na
associação, porque uma alteração no NavigateCommand não dispara um evento PropertyChanged , e a associação
não sabe que NavigateCommand é válido agora.
Definir NavigateCommand e BindingContext (em qualquer ordem) antes da chamada a InitializeComponent
funcionará, porque os componentes da associação são definidos quando o analisador XAML encontra a definição
da associação.
Às vezes, as associações de dados podem ser complicadas, mas, como você viu nessa série de artigos, elas são
poderosas e versáteis e ajudam bastante a organizar seu código separando a lógica subjacente da interface do
usuário.
Links relacionados
Demonstrações de associação de dados (amostra)
Capítulo de associação de dados do catálogo de Xamarin.Forms
Associações compiladas do Xamarin.Forms
12/04/2019 • 13 minutes to read • Edit Online
Baixar o exemplo
Associações compiladas são resolvidas mais rapidamente do que associações clássicas, melhorando assim o
desempenho da associação de dados em aplicativos do Xamarin.Forms.
Associações de dados têm dois problemas principais:
1. Não há validação em tempo de compilação para expressões de associação. Em vez disso, as associações são
resolvidas em tempo de execução. Sendo assim, associações inválidas não são detectadas até o tempo de
execução, quando o aplicativo não se comporta conforme esperado ou mensagens de erro são exibidas.
2. Elas não são econômicas. Associações são resolvidas em tempo de execução usando a inspeção de objeto para
uso geral (reflexão), e a sobrecarga de fazer isso varia de uma plataforma para outra.
Associações compiladas melhoram o desempenho de associação de dados em aplicativos do Xamarin.Forms
resolvendo expressões de associação em tempo de compilação, em vez de tempo de execução. Além disso, essa
validação em tempo de compilação das expressões de associação permite uma melhor experiência de solução de
problemas para o desenvolvedor porque associações inválidas são relatadas como erros de build.
O processo para usar associações compiladas é:
1. Habilitar a compilação de XAML. Para obter mais informações sobre a compilação de XAML, confira
Compilação de XAML.
2. Definir um atributo x:DataType em um VisualElement como o tipo do objeto ao qual VisualElement e seus
filhos se associarão. Observe que esse atributo pode ser redefinido em qualquer localização de uma hierarquia
de exibição.
NOTE
É recomendável definir o atributo x:DataType no mesmo nível da hierarquia de exibição em que BindingContext está
definido.
No tempo de compilação de XAML, as expressões de associação inválidas serão relatadas como erros de build.
No entanto, o compilador XAML relatará um erro de build somente para a primeira expressão de associação
inválida que encontrar. Expressões de associação válidas definidas no VisualElement ou em seus filhos serão
compiladas, independentemente de BindingContext estar definido no XAML ou no código. Compilar uma
expressão de associação gera o código compilado que obterá um valor de uma propriedade na origem e o
definirá na propriedade de destino especificada na marcação. Além disso, dependendo da expressão de
associação, o código gerado poderá observar alterações no valor da propriedade de origem e atualizar a
propriedade de destino, e pode enviar por push alterações do destino para a origem.
IMPORTANT
Atualmente, associações compiladas estão desabilitadas para expressões de associação que definem a propriedade Source
. Isso acontece porque a propriedade Source sempre é definida usando a extensão de marcação x:Reference , que não
pode ser resolvida em tempo de compilação.
Usando associações compiladas
A página Seletor de Cores Compilado demonstra como usar associações compiladas entre as exibições do
Xamarin.Forms e as propriedades de ViewModel:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.CompiledColorSelectorPage"
Title="Compiled Color Selector">
...
<StackLayout x:DataType="local:HslColorViewModel">
<StackLayout.BindingContext>
<local:HslColorViewModel Color="Sienna" />
</StackLayout.BindingContext>
<BoxView Color="{Binding Color}"
... />
<StackLayout Margin="10, 0">
<Label Text="{Binding Name}" />
<Slider Value="{Binding Hue}" />
<Label Text="{Binding Hue, StringFormat='Hue = {0:F2}'}" />
<Slider Value="{Binding Saturation}" />
<Label Text="{Binding Saturation, StringFormat='Saturation = {0:F2}'}" />
<Slider Value="{Binding Luminosity}" />
<Label Text="{Binding Luminosity, StringFormat='Luminosity = {0:F2}'}" />
</StackLayout>
</StackLayout>
</ContentPage>
IMPORTANT
O atributo x:DataType pode ser redefinido em qualquer ponto de uma hierarquia de exibição.
Os elementos BoxView , Label e as exibições Slider herdam o contexto de associação da StackLayout . Essas
exibições são destinos de associação que referenciam as propriedades de origem no ViewModel. Para as
propriedades BoxView.Color e Label.Text , as associações de dados são OneWay – as propriedades na exibição
são definidas nas propriedades do ViewModel. No entanto, a propriedade Slider.Value usa uma associação
TwoWay . Isso permite que cada Slider seja definido no ViewModel e também que o ViewModel seja definido
em cada Slider .
Quando o aplicativo é executado pela primeira vez, os elementos BoxView , Label e Slider são definidos no
ViewModel com base na propriedade Color inicial definida quando foi criada uma instância do ViewModel. Isso
é mostrado nas seguintes capturas de tela:
Conforme os controles deslizantes são manipulados, os elementos BoxView e Label são atualizados.
Para obter mais informações sobre o seletor de cores, confira ViewModels e notificações de alteração de
propriedade.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataBindingDemos"
x:Class="DataBindingDemos.CompiledColorListPage"
Title="Compiled Color List">
<Grid>
...
<ListView x:Name="colorListView"
ItemsSource="{x:Static local:NamedColor.All}"
... >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:NamedColor">
<ViewCell>
<StackLayout Orientation="Horizontal">
<BoxView Color="{Binding Color}"
... />
<Label Text="{Binding FriendlyName}"
... />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!-- The BoxView doesn't use compiled bindings -->
<BoxView Color="{Binding Source={x:Reference colorListView}, Path=SelectedItem.Color}"
... />
</Grid>
</ContentPage>
O StackLayout raiz define o atributo x:DataType como o tipo HslColorViewModel , indicando que as expressões
de associação na hierarquia de exibição StackLayout raiz serão compiladas. No entanto, o StackLayout interno
redefine o atributo x:DataType como null com a expressão de marcação x:Null . Portanto, as expressões de
associação no StackLayout interno usam associações clássicas. Somente o BoxView , dentro da hierarquia de
exibição StackLayout raiz, usa associações compiladas.
Para obter mais informações sobre a expressão de marcação x:Null , confira Extensão de marcação x:Null.
Desempenho
Associações compiladas melhoram o desempenho da associação de dados, com benefícios de desempenho
variáveis. Testes de unidade revelam que:
Uma associação compilada que usa notificação de alteração de propriedade (ou seja, uma associação OneWay ,
OneWayToSource ou TwoWay ) é resolvida aproximadamente oito vezes mais rápido do que uma associação
clássica.
Uma associação compilada que não usa notificação de alteração de propriedade (ou seja, uma associação
OneTime ) é resolvida aproximadamente vinte vezes mais rápido do que uma associação clássica.
Definir o BindingContext em uma associação compilada que usa notificação de alteração de propriedade (ou
seja, uma associação OneWay , OneWayToSource ou TwoWay ) é aproximadamente cinco vezes mais rápido do
que definir o BindingContext em uma associação clássica.
Definir o BindingContext em uma associação compilada que não usa notificação de alteração de propriedade
(ou seja, uma associação OneTime ), é aproximadamente sete vezes mais rápido do que definir o
BindingContext em uma associação clássica.
Essas diferenças de desempenho podem aumentar em dispositivos móveis, dependendo da plataforma usada, da
versão do sistema operacional usado e do dispositivo no qual o aplicativo está em execução.
Links relacionados
Demonstrações de associação de dados (amostra)
Xamarin.Forms DependencyService
12/04/2019 • 2 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms permite aos desenvolvedores definir o comportamento em projetos específicos a uma
plataforma. O DependencyService, em seguida, localiza a implementação de plataforma certa, permitindo que
o código compartilhado acesse a funcionalidade nativa.
Este guia é composto dos seguintes artigos:
Introdução – apresenta a arquitetura geral do conceito DependencyService .
Implementando a conversão de texto em fala – apresenta um exemplo de como usar o sistema de texto
em fala nativo de cada plataforma.
Verificando a orientação do dispositivo – apresenta um exemplo de como usar APIs da plataforma nativa
para determinar a orientação do dispositivo.
Obtendo informações sobre a bateria – apresenta um exemplo de como usar APIs nativas para obter
informações sobre o status da bateria.
Escolhendo uma foto na biblioteca – apresenta um exemplo de como usar APIs nativas para escolher
uma foto da biblioteca de imagens do telefone.
Links relacionados
Usando o DependencyService (amostra)
DependencyService (amostra)
Amostras do Xamarin.Forms
Introdução a DependencyService
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Visão geral
O DependencyService permite que os aplicativos chamem a funcionalidade específica da plataforma usando código
compartilhado. Essa funcionalidade permite que os aplicativos do Xamarin.Forms façam qualquer coisa que um
aplicativo nativo pode fazer.
DependencyServiceé um localizador de serviço. Na prática, uma interface é definida e DependencyService localiza a
implementação correta da interface entre os vários projetos da plataforma.
NOTE
Por padrão, o DependencyService resolverá somente as implementações de plataforma que têm construtores sem
parâmetros. No entanto, é possível injetar no Xamarin.Forms um método de resolução de dependência que um contêiner de
injeção de dependências ou métodos de fábrica para resolver implementações da plataforma. Essa abordagem pode ser
usada para resolver implementações da plataforma que têm construtores com parâmetros. Para obter mais informações,
confira Resolução de dependências no Xamarin.Forms.
namespace UsingDependencyService.iOS
{
public class TextToSpeech_iOS : ITextToSpeech
{
public void Speak (string text)
{
var speechSynthesizer = new AVSpeechSynthesizer ();
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
}
Registro
Cada implementação da interface precisa ser registrada no DependencyService com um atributo de metadados. O
código a seguir registra a implementação para o iOS:
speechSynthesizer.SpeakUtterance (speechUtterance);
}
}
}
Xamarin.Forms.Forms.Init(e, assembliesToInclude);
// register the dependencies in the same
Xamarin.Forms.DependencyService.Register<TextToSpeechImplementation>();
Observação: o registro manual usando Register<T> é eficaz somente em builds de Versão que usam a compilação
.NET Native. Se você omitir essa linha, builds de Depuração ainda funcionarão, mas builds de Versão falharão ao
carregar o serviço de dependência.
Chamada para DependencyService
Após o projeto ter sido configurado com uma interface comum e com implementações para cada plataforma, use
DependencyService para obter a implementação correta em tempo de execução:
NOTE
Você precisa fornecer uma implementação no projeto de cada plataforma. Se nenhuma implementação da Interface estiver
registrada, o DependencyService não poderá resolver o método Get<T>() em tempo de execução.
Links relacionados
DependencyServiceSample
Amostras do Xamarin.Forms
Implementando a conversão de texto em fala
12/04/2019 • 5 minutes to read • Edit Online
Baixar o exemplo
Este artigo orientará você na criação de um aplicativo multiplataforma que usa DependencyService para acessar
APIs de conversão de texto em fala nativas:
Criando a Interface – compreenda como a interface é criada em código compartilhado.
Implementação de iOS – saiba como implementar a interface em código nativo para iOS.
Implementação de Android – saiba como implementar a interface em código nativo para Android.
Implementação de UWP – saiba como implementar a interface em código nativo para a UWP (Plataforma
Universal do Windows).
Implementação em código compartilhado – saiba como usar DependencyService para fazer chamadas na
implementação nativa usando código compartilhado.
O aplicativo que usa DependencyService terá a seguinte estrutura:
Criando a Interface
Primeiro, crie no código compartilhado uma interface que expressa a funcionalidade que você planeja
implementar. Neste exemplo, a interface contém um único método, Speak :
A codificação nessa interface no código compartilhado permitirá que o aplicativo Xamarin.Forms acesse as APIs
de fala em cada plataforma.
NOTE
Classes que implementam a interface devem ter um construtor sem parâmetros para trabalhar com DependencyService .
Implementação de iOS
A interface deve ser implementada em cada projeto de aplicativo específico da plataforma. Observe que a classe
tem um construtor sem parâmetros, de modo que DependencyService pode criar novas instâncias.
[assembly: Dependency(typeof(TextToSpeechImplementation))]
namespace DependencyServiceSample.iOS
{
speechSynthesizer.SpeakUtterance(speechUtterance);
}
}
}
O atributo [assembly] registra a classe como uma implementação da interface de ITextToSpeech , o que significa
que DependencyService.Get<ITextToSpeech>() pode ser usado no código compartilhado para criar uma instância
dele.
Implementação de Android
O código do Android é mais complexo que a versão do iOS. Ele precisa ter acesso ao contexto do Android atual,
que é exposto pela propriedade MainActivity.Instance :
ele requer a implementação da classe para herdar do Java.Lang.Object específico ao Android e implementar a
interface de IOnInitListener .
[assembly: Dependency(typeof(TextToSpeechImplementation))]
namespace DependencyServiceSample.Droid
{
public class TextToSpeechImplementation : Java.Lang.Object, ITextToSpeech, TextToSpeech.IOnInitListener
{
TextToSpeech speaker;
string toSpeak;
O atributo [assembly] registra a classe como uma implementação da interface de ITextToSpeech , o que significa
que DependencyService.Get<ITextToSpeech>() pode ser usado no código compartilhado para criar uma instância
dele.
[assembly:Dependency(typeof(TextToSpeechImplementation))]
public class TextToSpeechImplementation : ITextToSpeech
{
public async void Speak(string text)
{
var mediaElement = new MediaElement();
var synth = new Windows.Media.SpeechSynthesis.SpeechSynthesizer();
var stream = await synth.SynthesizeTextToStreamAsync(text);
mediaElement.SetSource(stream, stream.ContentType);
mediaElement.Play();
}
}
O atributo [assembly] registra a classe como uma implementação da interface de ITextToSpeech , o que significa
que DependencyService.Get<ITextToSpeech>() pode ser usado no código compartilhado para criar uma instância
dele.
public MainPage ()
{
var speak = new Button {
Text = "Hello, Forms !",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
speak.Clicked += (sender, e) => {
DependencyService.Get<ITextToSpeech>().Speak("Hello from Xamarin Forms");
};
Content = speak;
}
Executar esse aplicativo no iOS, no Android ou na UWP e pressionar o botão fará com que o aplicativo fale com
você usando o SDK de fala nativo de cada plataforma.
Links relacionados
Usando DependencyService (amostra)
DependencyServiceSample
Verificando a orientação do dispositivo
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Este artigo mostra como usar DependencyService para verificar a orientação do dispositivo do código
compartilhado usando as APIs nativas de cada plataforma. Este passo a passo se baseia no plug-in
DeviceOrientation de Ali Özgür. Confira o Repositório do GitHub para obter mais informações.
NOTE
É possível detectar se o dispositivo está com orientação de retrato ou paisagem no código compartilhado, conforme
demonstrado em Orientação do Dispositivo. O método descrito neste artigo usa recursos nativos para obter mais
informações sobre a orientação, incluindo se o dispositivo está de cabeça para baixo.
Criando a Interface
Primeiro, crie no código compartilhado uma interface que expressa a funcionalidade que você planeja
implementar. Neste exemplo, a interface contém um único método:
namespace DependencyServiceSample.Abstractions
{
public enum DeviceOrientations
{
Undefined,
Landscape,
Portrait
}
A codificação nessa interface no código compartilhado permitirá que o aplicativo Xamarin.Forms acesse as APIs
de orientação do dispositivo em cada plataforma.
NOTE
Classes que implementam a interface devem ter um construtor sem parâmetros para trabalhar com DependencyService .
Implementação de iOS
A Interface deve ser implementada em cada projeto de aplicativo específico da plataforma. Observe que a classe
tem um construtor sem parâmetros, de modo que DependencyService pode criar novas instâncias:
using UIKit;
using Foundation;
namespace DependencyServiceSample.iOS
{
public class DeviceOrientationImplementation : IDeviceOrientation
{
public DeviceOrientationImplementation(){ }
Por fim, adicione este atributo [assembly] acima da classe (e fora dos namespaces definidos), incluindo as
instruções using :
using UIKit;
using Foundation;
using DependencyServiceSample.iOS; //enables registration outside of namespace
Esse atributo registra a classe como uma implementação da Interface de IDeviceOrientation , o que significa que
DependencyService.Get<IDeviceOrientation> pode ser usado no código compartilhado para criar uma instância
dele.
Implementação de Android
O código a seguir implementa IDeviceOrientation no Android:
using DependencyServiceSample.Droid;
using Android.Hardware;
namespace DependencyServiceSample.Droid
{
public class DeviceOrientationImplementation : IDeviceOrientation
{
public DeviceOrientationImplementation() { }
Adicione este atributo [assembly] acima da classe (e fora dos namespaces definidos), incluindo as instruções
using :
Esse atributo registra a classe como uma implementação da Interface de IDeviceOrientaiton , o que significa que
DependencyService.Get<IDeviceOrientation> pode ser usado no código compartilhado para criar uma instância
dele.
Adicione o atributo [assembly] acima da classe (e fora dos namespaces definidos), incluindo as instruções using :
[assembly: Dependency(typeof(DeviceOrientationImplementation))]
namespace DependencyServiceSample.WindowsPhone {
...
Esse atributo registra a classe como uma implementação da Interface de DeviceOrientationImplementation , o que
significa que DependencyService.Get<IDeviceOrientation> pode ser usado no código compartilhado para criar uma
instância dele.
Executar esse aplicativo no iOS, no Android ou na plataformas Windows e pressionar o botão fará com que o
texto do botão seja atualizado com a orientação do dispositivo.
Links relacionados
Usando o DependencyService (amostra)
DependencyService (amostra)
Amostras do Xamarin.Forms
Verificando o status da bateria
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
Este artigo descreve como criar um aplicativo que verifica o status da bateria. Este artigo se baseia o plug-in
Battery de James Montemagno. Para obter mais informações, confira o Repositório do GitHub.
Como o Xamarin.Forms não inclui a funcionalidade para verificar o status atual da bateria, esse aplicativo
precisará usar DependencyService para tirar proveito de APIs nativas. Este artigo abordará as etapas a seguir para
usar DependencyService :
Criando a Interface – compreenda como a interface é criada em código compartilhado.
Implementação de iOS – saiba como implementar a interface em código nativo para iOS.
Implementação de Android – saiba como implementar a interface em código nativo para Android.
Implementação da Plataforma Universal do Windows – saiba como implementar a interface em código
nativo para a UWP (Plataforma Universal do Windows).
Implementação em código compartilhado – saiba como usar DependencyService para fazer chamadas na
implementação nativa usando código compartilhado.
Quando concluído, o aplicativo que usa DependencyService terá a seguinte estrutura:
Criando a Interface
Primeiro, crie no código compartilhado uma interface que expressa a funcionalidade desejada. No caso de um
aplicativo de verificação de bateria, as informações relevantes são o percentual de bateria restante, se o dispositivo
está sendo carregado ou não e como o dispositivo está recebendo energia:
namespace DependencyServiceSample
{
public enum BatteryStatus
{
Charging,
Discharging,
Full,
NotCharging,
Unknown
}
A codificação nessa interface no código compartilhado permitirá que o aplicativo Xamarin.Forms acesse as APIs
de gerenciamento de energia em cada plataforma.
NOTE
Classes que implementam a interface devem ter um construtor sem parâmetros para trabalhar com DependencyService .
Construtores não podem ser definidos pelas interfaces.
Implementação de iOS
A interface IBattery deve ser implementada em cada projeto de aplicativo específico da plataforma. A
implementação do iOS usará as APIs de UIDevice nativas para acessar as informações da bateria. Observe que a
classe a seguir tem um construtor sem parâmetros, de modo que DependencyService pode criar novas instâncias:
using UIKit;
using Foundation;
using DependencyServiceSample.iOS;
namespace DependencyServiceSample.iOS
{
public class BatteryImplementation : IBattery
{
public BatteryImplementation()
{
UIDevice.CurrentDevice.BatteryMonitoringEnabled = true;
}
Por fim, adicione este atributo [assembly] acima da classe (e fora dos namespaces definidos), incluindo as
instruções using :
using UIKit;
using Foundation;
using DependencyServiceSample.iOS;//necessary for registration outside of namespace
Esse atributo registra a classe como uma implementação da Interface de IBattery , o que significa que
DependencyService.Get<IBattery> pode ser usado em código compartilhado para criar uma instância dele:
Implementação de Android
A implementação do Android usa a API Android.OS.BatteryManager . Essa implementação é mais complexa do que
a versão do iOS, exigindo verificações para lidar com a falta de permissões da bateria:
using System;
using Android;
using Android.Content;
using Android.App;
using Android.OS;
using BatteryStatus = Android.OS.BatteryStatus;
using DependencyServiceSample.Droid;
namespace DependencyServiceSample.Droid
{
public class BatteryImplementation : IBattery
{
private BatteryBroadcastReceiver batteryReceiver;
public BatteryImplementation() { }
}
}
switch(status)
{
case (int)BatteryStatus.Charging:
return DependencyServiceSample.BatteryStatus.Charging;
case (int)BatteryStatus.Discharging:
return DependencyServiceSample.BatteryStatus.Discharging;
case (int)BatteryStatus.Full:
return DependencyServiceSample.BatteryStatus.Full;
case (int)BatteryStatus.NotCharging:
return DependencyServiceSample.BatteryStatus.NotCharging;
default:
return DependencyServiceSample.BatteryStatus.Unknown;
}
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine ("Ensure you have android.permission.BATTERY_STATS");
throw;
}
}
}
if (!isCharging)
return DependencyServiceSample.PowerSource.Battery;
else if (usbCharge)
return DependencyServiceSample.PowerSource.Usb;
else if (acCharge)
return DependencyServiceSample.PowerSource.Ac;
else if (wirelessCharge)
return DependencyServiceSample.PowerSource.Wireless;
else
return DependencyServiceSample.PowerSource.Other;
}
}
}
catch
{
System.Diagnostics.Debug.WriteLine ("Ensure you have android.permission.BATTERY_STATS");
throw;
}
}
}
}
}
Adicione este atributo [assembly] acima da classe (e fora dos namespaces definidos), incluindo as instruções
using :
...
using BatteryStatus = Android.OS.BatteryStatus;
using DependencyServiceSample.Droid; //enables registration outside of namespace
Esse atributo registra a classe como uma implementação da Interface de IBattery , o que significa que
DependencyService.Get<IBattery> pode ser usado no código compartilhado para criar uma instância dele.
using DependencyServiceSample.UWP;
using Xamarin.Forms;
[assembly: Dependency(typeof(BatteryImplementation))]
namespace DependencyServiceSample.UWP
{
public class BatteryImplementation : IBattery
{
private BatteryStatus status = BatteryStatus.Unknown;
Windows.Devices.Power.Battery battery;
public BatteryImplementation()
{
}
if (finalReport.RemainingCapacityInMilliwattHours.HasValue &&
finalReport.FullChargeCapacityInMilliwattHours.HasValue)
{
finalPercent = (int)((finalReport.RemainingCapacityInMilliwattHours.Value /
(double)finalReport.FullChargeCapacityInMilliwattHours.Value) * 100);
}
return finalPercent;
}
}
public MainPage ()
{
var button = new Button {
Text = "Click for battery info",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.CenterAndExpand,
};
button.Clicked += (sender, e) => {
var bat = DependencyService.Get<IBattery>();
switch (bat.PowerSource){
case PowerSource.Battery:
button.Text = "Battery - ";
break;
case PowerSource.Ac:
button.Text = "AC - ";
break;
case PowerSource.Usb:
button.Text = "USB - ";
break;
case PowerSource.Wireless:
button.Text = "Wireless - ";
break;
case PowerSource.Other:
default:
button.Text = "Other - ";
break;
}
switch (bat.Status){
case BatteryStatus.Charging:
button.Text += "Charging";
break;
case BatteryStatus.Discharging:
button.Text += "Discharging";
break;
case BatteryStatus.NotCharging:
button.Text += "Not Charging";
break;
case BatteryStatus.Full:
button.Text += "Full";
break;
case BatteryStatus.Unknown:
default:
button.Text += "Unknown";
break;
}
};
Content = button;
}
Executar esse aplicativo no iOS, no Android ou na UWP e pressionar o botão fará com que o texto do botão seja
atualizado para refletir o status de alimentação atual do dispositivo.
Links relacionados
DependencyService (amostra)
Usando o DependencyService (amostra)
Amostras do Xamarin.Forms
Escolhendo uma foto da biblioteca de imagens
12/04/2019 • 11 minutes to read • Edit Online
Baixar o exemplo
Este artigo descreve a criação de um aplicativo que permite que o usuário escolha uma foto da biblioteca de
imagens de seu telefone. Como o Xamarin.Forms não inclui essa funcionalidade, é necessário usar
DependencyService para acessar APIs nativas em cada plataforma. Este artigo abordará as etapas a seguir para
usar DependencyService para essa tarefa:
Criando a Interface – compreenda como a interface é criada em código compartilhado.
Implementação de iOS – saiba como implementar a interface em código nativo para iOS.
Implementação de Android – saiba como implementar a interface em código nativo para Android.
Implementação da Plataforma Universal do Windows – saiba como implementar a interface em código
nativo para a UWP (Plataforma Universal do Windows).
Implementação em código compartilhado – saiba como usar DependencyService para fazer chamadas na
implementação nativa usando código compartilhado.
Criando a Interface
Primeiro, crie no código compartilhado uma interface que expressa a funcionalidade desejada. No caso de um
aplicativo de seleção de fotos, é necessário apenas um método. Ele é definido na interface IPicturePicker na
biblioteca do .NET Standard do código de exemplo:
namespace DependencyServiceSample
{
public interface IPicturePicker
{
Task<Stream> GetImageStreamAsync();
}
}
O método GetImageStreamAsync é definido como assíncrono porque ele deve ser retornado rapidamente, mas ele
não pode retornar um objeto Stream para a foto selecionada até que o usuário tenha navegado na biblioteca de
imagens e selecionado uma.
Essa interface é implementada em todas as plataformas usando código específico da plataforma.
Implementação de iOS
A implementação de iOS da interface IPicturePicker usa o UIImagePickerController conforme descrito em
Escolher uma foto da galeria e no código de exemplo.
A implementação de iOS está contida na classe PicturePickerImplementation no projeto do iOS do código de
exemplo. Para tornar essa classe visível para o gerenciador do DependencyService , ela deve ser identificada com
um atributo [ assembly ] do tipo Dependency , e a classe deve ser pública e implementar explicitamente a interface
IPicturePicker :
[assembly: Dependency (typeof (PicturePickerImplementation))]
namespace DependencyServiceSample.iOS
{
public class PicturePickerImplementation : IPicturePicker
{
TaskCompletionSource<Stream> taskCompletionSource;
UIImagePickerController imagePicker;
// Present UIImagePickerController;
UIWindow window = UIApplication.SharedApplication.KeyWindow;
var viewController = window.RootViewController;
viewController.PresentModalViewController(imagePicker, true);
if (image != null)
{
// Convert UIImage to .NET Stream object
NSData data = image.AsJPEG(1);
Stream stream = data.AsStream();
UnregisterEventHandlers();
void UnregisterEventHandlers()
{
imagePicker.FinishedPickingMedia -= OnImagePickerFinishedPickingMedia;
imagePicker.Canceled -= OnImagePickerCancelled;
}
}
}
Um aplicativo iOS requer permissão do usuário para acessar a biblioteca de fotos do telefone. Adicione o
seguinte à seção dict do arquivo Info.plist:
<key>NSPhotoLibraryUsageDescription</key>
<string>Picture Picker uses photo library</string>
Implementação de Android
A implementação de Android usa a técnica descrita em Selecionar uma imagem e o código de exemplo. No
entanto, o método que é chamado quando o usuário selecionou uma imagem da biblioteca de imagens é uma
substituição de OnActivityResult em uma classe que deriva de Activity . Por esse motivo, a classe
MainActivity normal no projeto do Android foi complementada com um campo, uma propriedade e uma
substituição do método OnActivityResult :
public class MainActivity : FormsAppCompatActivity
{
...
// Field, property, and method for Picture Picker
public static readonly int PickImageId = 1000;
if (requestCode == PickImageId)
{
if ((resultCode == Result.Ok) && (intent != null))
{
Android.Net.Uri uri = intent.Data;
Stream stream = ContentResolver.OpenInputStream(uri);
A substituição OnActivityResult indica o arquivo de imagem selecionado com um objeto Uri do Android, mas
ele pode ser convertido em um objeto Stream do .NET chamando o método OpenInputStream do objeto
ContentResolver que foi obtido da propriedade ContentResolver da atividade.
Assim como a implementação do iOS, a implementação do Android usa um TaskCompletionSource para sinalizar
quando a tarefa foi concluída. Esse objeto TaskCompletionSource é definido como uma propriedade pública na
classe MainActivity . Isso permite que a propriedade seja referenciada na classe PicturePickerImplementation no
projeto do Android. Essa é a classe com o método GetImageStreamAsync :
[assembly: Dependency(typeof(PicturePickerImplementation))]
namespace DependencyServiceSample.Droid
{
public class PicturePickerImplementation : IPicturePicker
{
public Task<Stream> GetImageStreamAsync()
{
// Define the Intent for getting images
Intent intent = new Intent();
intent.SetType("image/*");
intent.SetAction(Intent.ActionGetContent);
Esse método acessa a classe MainActivity para várias finalidades: para a propriedade Instance , para o campo
PickImageId , para a propriedade TaskCompletionSource e para chamar StartActivityForResult . O método é
definido pela classe FormsAppCompatActivity , que é a classe base de MainActivity .
Implementação da UWP
Diferente das implementações de iOS e Android, a implementação do seletor de fotos na Plataforma Universal
do Windows não requer a classe TaskCompletionSource . A classe PicturePickerImplementation usa a classe
FileOpenPicker para ter acesso à biblioteca de fotos. Como o método PickSingleFileAsync de FileOpenPicker é
assíncrono, o método GetImageStreamAsync pode simplesmente usar await com esse método (e outros métodos
assíncronos) e retornar um objeto Stream :
[assembly: Dependency(typeof(PicturePickerImplementation))]
namespace DependencyServiceSample.UWP
{
public class PicturePickerImplementation : IPicturePicker
{
public async Task<Stream> GetImageStreamAsync()
{
// Create and initialize the FileOpenPicker
FileOpenPicker openPicker = new FileOpenPicker
{
ViewMode = PickerViewMode.Thumbnail,
SuggestedStartLocation = PickerLocationId.PicturesLibrary,
};
openPicker.FileTypeFilter.Add(".jpg");
openPicker.FileTypeFilter.Add(".jpeg");
openPicker.FileTypeFilter.Add(".png");
if (storageFile == null)
{
return null;
}
O manipulador Clicked usa a classe DependencyService para chamar GetImageStreamAsync . Isso resulta em uma
chamada no projeto da plataforma. Se o método retornar um objeto Stream , o manipulador criará um elemento
Image para a imagem com um TapGestureRecognizer e substituirá o StackLayout na página pelo Image :
pickPictureButton.Clicked += async (sender, e) =>
{
pickPictureButton.IsEnabled = false;
Stream stream = await DependencyService.Get<IPicturePicker>().GetImageStreamAsync();
if (stream != null)
{
Image image = new Image
{
Source = ImageSource.FromStream(() => stream),
BackgroundColor = Color.Gray
};
Links relacionados
Escolher uma foto na galeria (iOS )
Selecionar uma imagem (Android)
DependencyService (amostra)
Efeitos do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Criar um efeito
Efeitos simplificam a personalização de um controle. Este artigo demonstra como criar um efeito que altera a
cor da tela de fundo do controle Entry quando o controle obtém foco.
Efeitos permitem que os controles nativos em cada plataforma sejam personalizados e são geralmente usados
para pequenas alterações de estilo. Este artigo fornece uma introdução aos efeitos, descreve o limite entre efeitos e
renderizadores personalizados e descreve a classe PlatformEffect.
Páginas, Layouts e Controles do Xamarin.Forms apresenta uma API comum para descrever interfaces do usuário
móveis multiplataforma. Cada página, layout e controle é renderizado de maneira diferente em cada plataforma
usando uma classe Renderer , que por sua vez cria um controle nativo (correspondente à representação no
Xamarin.Forms), organiza sua disposição na tela e adiciona o comportamento especificado no código
compartilhado.
Os desenvolvedores podem implementar suas próprias classes Renderer personalizadas para personalizar a
aparência e/ou o comportamento de um controle. No entanto, implementar uma classe de renderizador
personalizado para executar uma personalização de controle simples geralmente gera uma resposta pesada. Os
efeitos simplificam esse processo, permitindo que os controles nativos em cada plataforma sejam personalizado
mais facilmente.
Os efeitos são criados em projetos específicos da plataforma criando subclasses do controle PlatformEffect e, em
seguida, os controles são consumidos anexando-os a um controle apropriado em uma biblioteca .NET Standard do
Xamarin.Forms ou um projeto de Biblioteca compartilhada.
Os efeitos não têm informações de tipo sobre o contêiner, o controle ou o elemento a que estão anexados porque
eles podem ser anexados a qualquer elemento. Portanto, quando um efeito é anexado a um elemento
incompatível, ele deve ter o desempenho reduzido discretamente ou lançar uma exceção. No entanto, as
propriedades Container , Control e Element podem ser convertidas em seu tipo de implementação. Para obter
mais informações sobre esses tipos, confira Classes base do renderizador e controles nativos.
Cada classe PlatformEffect específica da plataforma expõe os métodos a seguir, que devem ser substituídos para
implementar um efeito:
OnAttached – chamado quando um efeito é anexado a um controle do Xamarin.Forms. Uma versão de
substituição desse método, em cada classe de efeito específica da plataforma, é o lugar para realizar a
personalização do controle, bem como a manipulação de exceções caso o efeito não possa ser aplicado ao
controle do Xamarin.Forms especificado.
OnDetached – chamado quando um efeito é desanexado de um controle do Xamarin.Forms. Uma versão de
substituição deste método, em cada classe de efeito específica da plataforma, é o lugar para executar qualquer
limpeza de efeito, como cancelar o registro de um manipulador de eventos.
Além disso, o PlatformEffect expõe o método OnElementPropertyChanged , que também pode ser substituído. Esse
método é chamado quando uma propriedade do elemento foi alterada. Uma versão de substituição do método,
em cada classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis
sobre o controle do Xamarin.Forms. Uma verificação da propriedade alterada sempre deve ser feita, pois essa
substituição pode ser chamada várias vezes.
Links relacionados
Renderizadores personalizados
Criando um efeito
12/04/2019 • 12 minutes to read • Edit Online
Baixar o exemplo
Efeitos simplificam a personalização de um controle. Este artigo demonstra como criar um efeito que altera a cor
da tela de fundo do controle Entry quando o controle obtém foco.
O processo para criar um efeito em cada projeto específico da plataforma é o seguinte:
1. Crie uma subclasse da classe PlatformEffect .
2. Substitua o método OnAttached e escreva a lógica para personalizar o controle.
3. Substitua o método OnDetached e escreva a lógica para limpar a personalização do controle se necessário.
4. Adicione um atributo ResolutionGroupName à classe do efeito. Esse atributo define um namespace para os
efeitos que abrange toda a empresa, evitando conflitos com outros efeitos de mesmo nome. Observe que esse
atributo só pode ser aplicado uma vez por projeto.
5. Adicione um atributo ExportEffect à classe do efeito. Este atributo registra o efeito com uma ID exclusiva que
é usada pelo Xamarin.Forms, em conjunto com o nome do grupo, para localizar o efeito antes de aplicá-lo a
um controle. O atributo utiliza dois parâmetros – o nome do tipo de efeito e uma cadeia de caracteres exclusiva
que será usada para localizar o efeito antes de aplicá-lo a um controle.
O efeito, em seguida, poderá ser consumido sendo anexado ao controle apropriado.
NOTE
O fornecimento de um efeito em cada projeto de plataforma é opcional. Tentar usar um efeito quando não há um efeito
registrado retornará um valor não nulo que não faz nada.
O aplicativo de exemplo demonstra um FocusEffect que altera a cor da tela de fundo de um controle quando ele
obtém o foco. O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem
como as relações entre elas:
Um controle Entry no HomePage é personalizado pela classe FocusEffect em cada projeto específico da
plataforma. Cada classe FocusEffect é derivada da classe PlatformEffect de cada plataforma. Isso faz com que o
controle Entry seja renderizado com uma cor da tela de fundo específica da plataforma, que muda quando o
controle obtém foco, conforme mostrado nas capturas de tela seguir:
Criando o efeito em cada plataforma
As seções a seguir abordam a implementação da classe FocusEffect específica da plataforma.
Projeto do iOS
O exemplo de código a seguir mostra a implementação de FocusEffect para o projeto do iOS:
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(FocusEffect), nameof(FocusEffect))]
namespace EffectsDemo.iOS
{
public class FocusEffect : PlatformEffect
{
UIColor backgroundColor;
try {
if (args.PropertyName == "IsFocused") {
if (Control.BackgroundColor == backgroundColor) {
Control.BackgroundColor = UIColor.White;
} else {
Control.BackgroundColor = backgroundColor;
}
}
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
}
}
O método OnAttached define a propriedade BackgroundColor do controle como roxo claro com o método
UIColor.FromRGB e também armazena essa cor em um campo. Essa funcionalidade é encapsulada em um bloco
try / catch caso o controle a que o efeito está anexado não tenha uma propriedade de BackgroundColor .
Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.
A substituição OnElementPropertyChanged responde às alterações de propriedade associáveis no controle do
Xamarin.Forms. Quando a propriedade IsFocused é alterada, a propriedade BackgroundColor do controle será
alterada para branco se o controle estiver em foco, caso contrário, é alterada para roxo claro. Essa funcionalidade é
encapsulada em um bloco try / catch caso o controle a que o efeito está anexado não tenha uma propriedade de
BackgroundColor .
Projeto do Android
O exemplo de código a seguir mostra a implementação de FocusEffect para o projeto do Android:
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect(typeof(FocusEffect), nameof(FocusEffect))]
namespace EffectsDemo.Droid
{
public class FocusEffect : PlatformEffect
{
Android.Graphics.Color backgroundColor;
O método OnAttached chama o método SetBackgroundColor para definir a cor da tela de fundo do controle como
verde claro e também armazena essa cor em um campo. Essa funcionalidade é encapsulada em um bloco try /
catch caso o controle a que o efeito está anexado não tenha uma propriedade de SetBackgroundColor . Nenhuma
implementação é fornecida pelo método OnDetached porque nenhuma limpeza é necessária.
A substituição OnElementPropertyChanged responde às alterações de propriedade associáveis no controle do
Xamarin.Forms. Quando a propriedade IsFocused é alterada, a cor da tela de fundo do controle será alterada
para branco se o controle estiver em foco, caso contrário, é alterada para verde claro. Essa funcionalidade é
encapsulada em um bloco try / catch caso o controle a que o efeito está anexado não tenha uma propriedade de
BackgroundColor .
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(FocusEffect), nameof(FocusEffect))]
namespace EffectsDemo.UWP
{
public class FocusEffect : PlatformEffect
{
protected override void OnAttached()
{
try
{
(Control as Windows.UI.Xaml.Controls.Control).Background = new SolidColorBrush(Colors.Cyan);
(Control as FormsTextBox).BackgroundFocusBrush = new SolidColorBrush(Colors.White);
}
catch (Exception ex)
{
Debug.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
O método OnAttached define a propriedade Background do controle como ciano e define a propriedade
BackgroundFocusBrush como branco. Essa funcionalidade é encapsulada em um bloco try / catch caso o controle
a que o efeito está anexado não tenha essas propriedades. Nenhuma implementação é fornecida pelo método
OnDetached porque nenhuma limpeza é necessária.
Consumindo o efeito
O processo para consumir um efeito de uma biblioteca .NET Standard do Xamarin.Forms ou de um projeto de
Biblioteca compartilhada é o seguinte:
1. Declare um controle que será personalizado pelo efeito.
2. Anexe o efeito ao controle adicionando-o à coleção Effects do controle.
NOTE
Uma instância de efeito pode ser anexada somente a um único controle. Portanto, um efeito deve ser resolvido duas vezes
para usá-lo em dois controles.
A classe FocusEffect na biblioteca do .NET Standard dá suporte ao consumo do efeito em XAML e é mostrado
no exemplo de código a seguir:
A classe FocusEffect cria subclasses da classe RoutingEffect , que representa um efeito independente de
plataforma que encapsula um efeito interno, que é geralmente é específico da plataforma. A classe FocusEffect
chama o construtor da classe base, passando um parâmetro composto por uma concatenação do nome do grupo
de resolução (especificado usando o atributo ResolutionGroupName na classe do efeito) e pela ID exclusiva que foi
especificada usando o atributo ExportEffect na classe do efeito. Portanto, quando o Entry é inicializado em
tempo de execução, uma nova instância do MyCompany.FocusEffect é adicionada à coleção Effects do controle.
Efeitos também podem ser anexados a controles usando um comportamento ou usando propriedades anexadas.
Para obter mais informações sobre como anexar um efeito a um controle usando um comportamento, confira
EffectBehavior reutilizável. Para obter mais informações sobre como anexar um efeito a um controle usando
propriedades anexadas, confira Passar parâmetros para um efeito.
Consumindo o efeito em C#
O Entry equivalente em C# é mostrado no exemplo de código a seguir:
O FocusEffect é anexado à instância de Entry adicionando o efeito à coleção Effects do controle, conforme
demonstrado no exemplo de código a seguir:
public HomePageCS ()
{
...
entry.Effects.Add (Effect.Resolve ($"MyCompany.{nameof(FocusEffect)}"));
...
}
O Effect.Resolve retorna um Effect para o nome especificado, que é uma concatenação do nome do grupo de
resolução (especificado usando o atributo ResolutionGroupName na classe do efeito) e pela ID exclusiva que foi
especificada usando o atributo ExportEffect na classe do efeito. Se uma plataforma não fornecer o efeito, o
método Effect.Resolve retornará um valor não null .
Resumo
Este artigo demonstrou como criar um efeito que altera a cor da tela de fundo do controle Entry quando o
controle obtém foco.
Links relacionados
Renderizadores personalizados
Effect
PlatformEffect
Efeito de cor da tela de fundo (amostra)
Efeito de foco (amostra)
Passando parâmetros para um efeito
12/04/2019 • 2 minutes to read • Edit Online
Parâmetros de efeito podem ser definidos por propriedades, habilitando o efeito para ser reutilizado. Parâmetros
podem ser passados para o efeito, especificando valores para cada propriedade ao instanciar o efeito.
Baixar o exemplo
Propriedades de CLR (Common Language Runtime) podem ser usadas para definir parâmetros de efeito que não
respondem a alterações de propriedade de tempo de execução. Este artigo demonstra como usar propriedades de
CLR para passar parâmetros para um efeito.
O processo para criar parâmetros de efeito que não respondem a alterações de propriedade de tempo de execução
é o seguinte:
1. Criar uma public que cria subclasses da classe RoutingEffect . A classe RoutingEffect representa um efeito
independente de plataforma que encapsula um efeito interno, que é geralmente é específico da plataforma.
2. Crie um construtor que chama o construtor da classe base, passando uma concatenação do nome do grupo de
resolução e a ID exclusiva que foi especificada em cada classe de efeito específica da plataforma.
3. Adicione propriedades à classe para cada parâmetro a ser passado para o efeito.
Em seguida, os parâmetros podem ser passados para o efeito especificando valores para cada propriedade ao
instanciar o efeito.
O aplicativo de exemplo demonstra um ShadowEffect que adiciona uma sombra ao texto exibido por um controle
Label . O diagrama a seguir ilustra as responsabilidades de cada projeto no aplicativo de exemplo, bem como as
relações entre elas:
O ShadowEffect contém quatro propriedades que representam os parâmetros a serem passados para cada
LabelShadowEffect específico da plataforma. O construtor de classe chama o construtor da classe base, passando
um parâmetro composto por uma concatenação do nome do grupo de resolução e pela ID exclusiva que foi
especificada em cada classe de efeito específica da plataforma. Portanto, uma nova instância de
MyCompany.LabelShadowEffect será adicionada à coleção Effects do controle quando um ShadowEffect for
instanciado.
Consumindo o efeito
O exemplo de código XAML abaixo mostra um controle Label ao qual o ShadowEffect está anexado:
Nos dois exemplos de código, uma instância da classe ShadowEffect é criada, com valores especificados para cada
propriedade, antes de ser adicionada à coleção Effects do controle. Observe que a propriedade
ShadowEffect.Color usa valores de cor específicos da plataforma. Para obter mais informações, confira Classe do
dispositivo.
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.Droid
{
public class LabelShadowEffect : PlatformEffect
{
protected override void OnAttached ()
{
try {
var control = Control as Android.Widget.TextView;
var effect = (ShadowEffect)Element.Effects.FirstOrDefault (e => e is ShadowEffect);
if (effect != null) {
float radius = effect.Radius;
float distanceX = effect.DistanceX;
float distanceY = effect.DistanceY;
Android.Graphics.Color color = effect.Color.ToAndroid ();
control.SetShadowLayer (radius, distanceX, distanceY, color);
}
} catch (Exception ex) {
Console.WriteLine ("Cannot set property on attached control. Error: ", ex.Message);
}
}
A Plataforma Universal do Windows não fornece um efeito de sombra, de forma que a implementação de
LabelShadowEffect nas duas plataformas simula o efeito adicionando um segundo deslocamento Label atrás do
Label principal. O método OnAttached recupera a instância de ShadowEffect , cria o novo Label e define algumas
propriedades de layout no Label . Depois, ele cria a sombra definindo as propriedades TextColor , TranslationX e
TranslationY para controlar a cor e a localização do Label . Em seguida, o shadowLabel é inserido deslocado atrás
do Label principal. Essa funcionalidade é encapsulada em um bloco try / catch caso o controle a que o efeito
está anexado não tenha as propriedades de Control.Layer . Nenhuma implementação é fornecida pelo método
OnDetached porque nenhuma limpeza é necessária.
Resumo
Este artigo demonstrou como usar propriedades de CLR para passar parâmetros para um efeito. Propriedades de
CLR podem ser usadas para definir parâmetros de efeito que não respondem a alterações de propriedade de
tempo de execução.
Links relacionados
Renderizadores personalizados
Effect
PlatformEffect
RoutingEffect
Efeito de sombra (amostra)
Passando parâmetros de efeito como propriedades
anexadas
12/04/2019 • 18 minutes to read • Edit Online
Baixar o exemplo
Propriedades anexadas podem ser usadas para definir parâmetros de efeito que respondem a alterações de
propriedade de tempo de execução. Este artigo demonstra o uso de propriedades anexadas para passar
parâmetros para um efeito e a alteração de um parâmetro em tempo de execução.
O processo para criar parâmetros de efeito que respondem a alterações de propriedade de tempo de execução é o
seguinte:
1. Crie uma classe static que contém uma propriedade anexada para cada parâmetro a ser passado para o
efeito.
2. Adicione outra propriedade anexada à classe que será usada para controlar a adição ou remoção do efeito para
o controle a que a classe será anexada. Certifique-se de que a propriedade anexada registre um delegado
propertyChanged que será executado quando o valor da propriedade for alterado.
3. Crie getters e setters static para cada propriedade anexada.
4. Implemente a lógica no delegado propertyChanged para adicionar e remover o efeito.
5. Implemente uma classe aninhada dentro da classe static , com o mesmo nome do efeito, que cria uma
subclasse da classe RoutingEffect . Para o construtor, chame o construtor da classe base passando uma
concatenação do nome do grupo de resolução e a ID exclusiva que foi especificada em cada classe de efeito
específica da plataforma.
Em seguida, é possível passar parâmetros para o efeito adicionando as propriedades anexadas e valores de
propriedade ao controle apropriado. Além disso, os parâmetros podem ser alterados no tempo de execução
especificando um novo valor da propriedade anexada.
NOTE
Uma propriedade anexada é um tipo especial de propriedade associável, definida em uma classe, mas anexada a outros
objetos e reconhecível no XAML como atributos que contêm uma classe e um nome de propriedade separados por um
ponto. Para obter mais informações, confira Propriedades anexadas.
O aplicativo de exemplo demonstra um ShadowEffect que adiciona uma sombra ao texto exibido por um controle
Label . Além disso, a cor da sombra pode ser alterada em tempo de execução. O diagrama a seguir ilustra as
responsabilidades de cada projeto no aplicativo de exemplo, bem como as relações entre elas:
Um controle Label no HomePage é personalizado pelo LabelShadowEffect em cada projeto específico da
plataforma. Os parâmetros são passados para cada LabelShadowEffect por meio das propriedades anexadas na
classe ShadowEffect . Cada classe LabelShadowEffect é derivada da classe PlatformEffect de cada plataforma. Isso
faz com que uma sombra seja adicionada ao texto exibido pelo controle Label , conforme mostrado nas capturas
de tela seguir:
O ShadowEffect contém cinco propriedades anexadas, com getters e setters static para cada propriedade
anexada. Quatro dessas propriedades representam parâmetros a serem passados para cada LabelShadowEffect
específico da plataforma. A classe ShadowEffect também define uma propriedade anexada HasShadow que é usada
para controlar a adição ou remoção do efeito para o controle a que a classe ShadowEffect é anexada. Essa
propriedade anexada registra o método OnHasShadowChanged que será executado quando o valor da propriedade
for alterado. Esse método adiciona ou remove o efeito com base no valor da propriedade anexada HasShadow .
A classe LabelShadowEffect aninhada, que cria uma subclasse da classe RoutingEffect , dá suporte à adição e à
remoção de efeitos. A classe RoutingEffect representa um efeito independente de plataforma que encapsula um
efeito interno, que é geralmente é específico da plataforma. Isso simplifica o processo de remoção do efeito,
porque não há nenhum acesso de tempo de compilação às informações de tipo para um efeito específico da
plataforma. O construtor LabelShadowEffect chama o construtor da classe base, passando um parâmetro
composto por uma concatenação do nome do grupo de resolução e pela ID exclusiva que foi especificada em cada
classe de efeito específica da plataforma. Isso habilita a adição e a remoção do efeito no método
OnHasShadowChanged , da seguinte maneira:
Adição de efeito – uma nova instância do LabelShadowEffect é adicionada à coleção Effects do controle.
Isso substitui o uso do método Effect.Resolve para adicionar o efeito.
Remoção de efeito – a primeira instância do LabelShadowEffect na coleção Effects do controle é recuperada
e removida.
Consumindo o efeito
Cada LabelShadowEffect específico da plataforma pode ser consumido adicionando as propriedades anexadas a
um controle Label , conforme demonstrado no exemplo de código XAML a seguir:
O Style pode ser aplicado a um Label definindo sua propriedade Style para a instância de Style usando a
extensão de marcação StaticResource , conforme demonstrado no exemplo de código a seguir:
void UpdateRadius ()
{
Control.Layer.CornerRadius = (nfloat)ShadowEffect.GetRadius (Element);
}
void UpdateColor ()
{
Control.Layer.ShadowColor = ShadowEffect.GetColor (Element).ToCGColor ();
}
void UpdateOffset ()
{
Control.Layer.ShadowOffset = new CGSize (
(double)ShadowEffect.GetDistanceX (Element),
(double)ShadowEffect.GetDistanceY (Element));
}
}
O método OnAttachedchama métodos que recuperam os valores de propriedade anexada usando os getters
ShadowEffect e que definem as propriedades de Control.Layer com os valores da propriedade para criar a
sombra. Essa funcionalidade é encapsulada em um bloco try / catch caso o controle a que o efeito está anexado
não tenha as propriedades de Control.Layer . Nenhuma implementação é fornecida pelo método OnDetached
porque nenhuma limpeza é necessária.
Respondendo a alterações de propriedade
Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito
precisará responder exibindo as alterações. Uma versão de substituição do método OnElementPropertyChanged , na
classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis,
conforme demonstrado no código de exemplo a seguir:
public class LabelShadowEffect : PlatformEffect
{
...
protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
{
if (args.PropertyName == ShadowEffect.RadiusProperty.PropertyName) {
UpdateRadius ();
} else if (args.PropertyName == ShadowEffect.ColorProperty.PropertyName) {
UpdateColor ();
} else if (args.PropertyName == ShadowEffect.DistanceXProperty.PropertyName ||
args.PropertyName == ShadowEffect.DistanceYProperty.PropertyName) {
UpdateOffset ();
}
}
...
}
O método OnElementPropertyChanged atualiza o raio, a cor ou o deslocamento da sombra, desde que o valor da
propriedade anexada ShadowEffect tenha sido alterado. Uma verificação da propriedade alterada sempre deve ser
feita, pois essa substituição pode ser chamada várias vezes.
Projeto do Android
O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto do Android:
[assembly:ResolutionGroupName ("MyCompany")]
[assembly:ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.Droid
{
public class LabelShadowEffect : PlatformEffect
{
Android.Widget.TextView control;
Android.Graphics.Color color;
float radius, distanceX, distanceY;
void UpdateControl ()
{
if (control != null) {
control.SetShadowLayer (radius, distanceX, distanceY, color);
}
}
void UpdateRadius ()
{
radius = (float)ShadowEffect.GetRadius (Element);
}
void UpdateColor ()
{
color = ShadowEffect.GetColor (Element).ToAndroid ();
}
void UpdateOffset ()
{
distanceX = (float)ShadowEffect.GetDistanceX (Element);
distanceY = (float)ShadowEffect.GetDistanceY (Element);
}
}
O método OnAttached chama métodos que recuperam os valores de propriedade anexada usando os getters
ShadowEffect e chama um método que chama o método TextView.SetShadowLayer para criar uma sombra usando
os valores da propriedade. Essa funcionalidade é encapsulada em um bloco try / catch caso o controle a que o
efeito está anexado não tenha as propriedades de Control.Layer . Nenhuma implementação é fornecida pelo
método OnDetached porque nenhuma limpeza é necessária.
Respondendo a alterações de propriedade
Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito
precisará responder exibindo as alterações. Uma versão de substituição do método OnElementPropertyChanged , na
classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis,
conforme demonstrado no código de exemplo a seguir:
public class LabelShadowEffect : PlatformEffect
{
...
protected override void OnElementPropertyChanged (PropertyChangedEventArgs args)
{
if (args.PropertyName == ShadowEffect.RadiusProperty.PropertyName) {
UpdateRadius ();
UpdateControl ();
} else if (args.PropertyName == ShadowEffect.ColorProperty.PropertyName) {
UpdateColor ();
UpdateControl ();
} else if (args.PropertyName == ShadowEffect.DistanceXProperty.PropertyName ||
args.PropertyName == ShadowEffect.DistanceYProperty.PropertyName) {
UpdateOffset ();
UpdateControl ();
}
}
...
}
O método OnElementPropertyChanged atualiza o raio, a cor ou o deslocamento da sombra, desde que o valor da
propriedade anexada ShadowEffect tenha sido alterado. Uma verificação da propriedade alterada sempre deve ser
feita, pois essa substituição pode ser chamada várias vezes.
Projeto da Plataforma Universal do Windows
O exemplo de código a seguir mostra a implementação de LabelShadowEffect para o projeto da UWP (Plataforma
Universal do Windows):
[assembly: ResolutionGroupName ("MyCompany")]
[assembly: ExportEffect (typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace EffectsDemo.UWP
{
public class LabelShadowEffect : PlatformEffect
{
Label shadowLabel;
bool shadowAdded = false;
UpdateColor ();
UpdateOffset ();
void UpdateColor ()
{
shadowLabel.TextColor = ShadowEffect.GetColor (Element);
}
void UpdateOffset ()
{
shadowLabel.TranslationX = ShadowEffect.GetDistanceX (Element);
shadowLabel.TranslationY = ShadowEffect.GetDistanceY (Element);
}
}
}
A Plataforma Universal do Windows não fornece um efeito de sombra, de forma que a implementação de
LabelShadowEffect nas duas plataformas simula o efeito adicionando um segundo deslocamento Label atrás do
Label principal. O método OnAttached cria o novo Label e define algumas propriedades de layout no Label .
Em seguida, ele chama métodos que recuperam os valores da propriedade anexada usando os getters
ShadowEffect e cria a sombra definindo as propriedades TextColor , TranslationX e TranslationY para controlar
a cor e a localização do Label . Em seguida, o shadowLabel é inserido deslocado atrás do Label principal. Essa
funcionalidade é encapsulada em um bloco try / catch caso o controle a que o efeito está anexado não tenha as
propriedades de Control.Layer . Nenhuma implementação é fornecida pelo método OnDetached porque nenhuma
limpeza é necessária.
Respondendo a alterações de propriedade
Se qualquer um dos valores da propriedade anexada ShadowEffect for alterado em tempo de execução, o efeito
precisará responder exibindo as alterações. Uma versão de substituição do método OnElementPropertyChanged , na
classe de efeito específica da plataforma, é o lugar para responder a alterações de propriedade vinculáveis,
conforme demonstrado no código de exemplo a seguir:
Resumo
Este artigo demonstrou o uso de propriedades anexadas para passar parâmetros para um efeito e a alteração de
um parâmetro em tempo de execução. Propriedades anexadas podem ser usadas para definir parâmetros de efeito
que respondem a alterações de propriedade de tempo de execução.
Links relacionados
Renderizadores personalizados
Effect
PlatformEffect
RoutingEffect
Efeito de sombra (amostra)
Invocando eventos por meio de efeitos
12/04/2019 • 37 minutes to read • Edit Online
Baixar o exemplo
Um efeito pode definir e invocar um evento, sinalizando as alterações na exibição nativa subjacente. Este artigo
mostra como implementar o acompanhamento de dedos multitoque de nível baixo e como gerar eventos que
sinalizam a atividade de toque.
O efeito descrito neste artigo fornece acesso aos eventos de toque de nível baixo. Esses eventos de nível baixo não
estão disponíveis por meio das classes GestureRecognizer existentes, mas elas são vitais para alguns tipos de
aplicativos. Por exemplo, um aplicativo de pintura a dedo precisa acompanhar dedos individuais à medida que eles
se movem na tela. Um teclado musical precisa detectar toques e liberações em teclas individuais, bem como o
deslize de um dedo de uma tecla a outra em um glissando.
Um efeito é ideal para o acompanhamento de dedos multitoque porque ele pode ser anexado a qualquer
elemento do Xamarin.Forms.
As plataformas iOS e Android são diferentes do UWP: A exibição que primeiro obtém a chamada a TouchesBegan
ou OnTouchEvent quando um dedo toca a exibição continua obtendo todas as atividades de toque, mesmo se o
dedo se mover para diferentes exibições. O UWP pode se comportar de forma semelhante se o aplicativo capturar
o ponteiro: No manipulador de eventos PointerEntered , o elemento chama CapturePointer e, em seguida, obtém
todas as atividades de toque desse dedo.
A abordagem do UWP prova ser muito útil para alguns tipos de aplicativos, por exemplo, um teclado musical.
Cada tecla pode manipular os eventos de toque dessa tecla e detectar quando um dedo deslizou de uma tecla para
outra usando os eventos PointerEntered e PointerExited .
Por esse motivo, o efeito do acompanhamento de toque descrito neste artigo implementa a abordagem do UWP.
Todas as plataformas também incluem um evento que indica que o evento de toque foi cancelado.
A classe na biblioteca do .NET Standard deriva de RoutingEffect e define um evento chamado
TouchEffect
TouchAction e um método chamado OnTouchAction que invoca o evento TouchAction :
Um aplicativo pode usar a propriedade Id para acompanhar dedos individuais. Observe a propriedade
IsInContact . Essa propriedade é sempre true para eventos Pressed e false para eventos Released . Ela
também é sempre true para eventos Moved no iOS e no Android. A propriedade IsInContact pode ser false
para eventos Moved na Plataforma Universal do Windows quando o programa está em execução na área de
trabalho e o ponteiro do mouse se move sem um botão pressionado.
Você pode usar a classe TouchEffect em seus próprios aplicativos incluindo o arquivo no projeto de biblioteca do
.NET Standard da solução e adicionando uma instância à coleção Effects de qualquer elemento do
Xamarin.Forms. Anexe um manipulador ao evento TouchAction para obter os eventos de toque.
Para usar TouchEffect em seu próprio aplicativo, você também precisará das implementações de plataforma
incluídas na solução TouchTrackingEffectDemos.
namespace TouchTracking.UWP
{
public class TouchEffect : PlatformEffect
{
...
}
}
A substituição OnAttached salva algumas informações como campos e anexa manipuladores a todos os eventos
de ponteiro:
OnPointerPressed também verifica o valor da propriedade Capture na classe de efeito na biblioteca do .NET
Standard e chama CapturePointer se ele é true .
A implementação do Android
As implementações do Android e do iOS são necessariamente mais complexas, porque precisam implementar os
eventos Exited e Entered quando um dedo se move de um elemento para outro. Ambas as implementações são
estruturadas de forma semelhante.
A classe TouchEffect do Android instala um manipulador para o evento Touch :
O viewDictionary obtém uma nova entrada sempre que a substituição OnAttached é chamada:
viewDictionary.Add(view, this);
A entrada é removida do dicionário em OnDetached . Todas as instâncias de TouchEffect são associadas a uma
exibição específica à qual o efeito é anexado. O dicionário estático permite que qualquer instância TouchEffect
enumere todas as outras exibições e suas instâncias TouchEffect correspondentes. Isso é necessário para permitir
a transferência dos eventos de uma exibição para outra.
O Android atribui um código de ID a eventos de toque, que permite que um aplicativo acompanhe dedos
individuais. O idToEffectDictionary associa esse código de ID a uma instância TouchEffect . Um item é
adicionado a esse dicionário quando o manipulador Touch é chamado para um pressionamento de dedo:
idToEffectDictionary.Add(id, this);
capture = libTouchEffect.Capture;
break;
O item é removido do idToEffectDictionary quando o dedo é liberado da tela. O método FireEvent apenas
acumula todas as informações necessárias para chamar o método OnTouchAction :
void FireEvent(TouchEffect touchEffect, int id, TouchActionType actionType, Point pointerLocation, bool
isInContact)
{
// Get the method to call for firing events
Action<Element, TouchActionEventArgs> onTouchAction = touchEffect.libTouchEffect.OnTouchAction;
Todos os outros tipos de toque são processados de duas maneiras diferentes: Se a propriedade Capture for true ,
o evento de toque é uma tradução bastante simples para as informações de TouchEffect . Isso fica mais
complicado quando Capture é false porque os eventos de toque talvez precisem ser movidos de uma exibição
para outra. Essa é a responsabilidade do método CheckForBoundaryHop , que é chamado durante eventos de
movimentação. Esse método faz uso de ambos os dicionários estáticos. Ele enumera pelo viewDictionary para
determinar a exibição que o dedo está tocando no momento e, em seguida, ele usa idToEffectDictionary para
armazenar a instância TouchEffect atual (e, portanto, a exibição atual) associado a uma ID específica:
if (viewRect.Contains(pointerLocation))
{
touchEffectHit = viewDictionary[view];
}
}
if (touchEffectHit != idToEffectDictionary[id])
{
if (idToEffectDictionary[id] != null)
{
FireEvent(idToEffectDictionary[id], id, TouchActionType.Exited, pointerLocation, true);
}
if (touchEffectHit != null)
{
FireEvent(touchEffectHit, id, TouchActionType.Entered, pointerLocation, true);
}
idToEffectDictionary[id] = touchEffectHit;
}
}
Grande parte da estrutura desta classe TouchRecognizer é semelhante à classe TouchEffect do Android.
IMPORTANT
Muitas das exibições na UIKitnão têm toque habilitado por padrão. O toque pode ser habilitado adicionando
view.UserInteractionEnabled = true; para substituir OnAttached na classe TouchEffect no projeto do iOS. Isso
deve ocorrer após a obtenção do UIView , que corresponde ao elemento ao qual o efeito está anexado.
void AddBoxViewToLayout()
{
BoxView boxView = new BoxView
{
WidthRequest = 100,
HeightRequest = 100,
Color = new Color(random.NextDouble(),
random.NextDouble(),
random.NextDouble())
};
O manipulador TouchAction processa todos os eventos de toque para todos os elementos BoxView , mas é
necessário ter algum cuidado: Ele não pode permitir dois dedos em uma única BoxView porque o programa
implementa apenas a operação de arrastar e os dois dedos interferirão um com o outro. Por esse motivo, a página
define uma classe inserida para cada dedo acompanhado no momento:
class DragInfo
{
public DragInfo(long id, Point pressPoint)
{
Id = id;
PressPoint = pressPoint;
}
O dragDictionary contém uma entrada para cada BoxView que está sendo arrastado no momento.
A ação de toque Pressed adiciona um item a esse dicionário e a ação Released remove-o. A lógica Pressed
precisa verificar se já há um item no dicionário para esse BoxView . Nesse caso, a BoxView já está sendo arrastada
e o novo evento é um segundo dedo sobre essa mesma BoxView . Para as ações Moved e Released , o
manipulador de eventos precisa verificar se o dicionário tem uma entrada para essa BoxView e se a propriedade
Id do toque para essa BoxView arrastada corresponde à entrada do dicionário:
switch (args.Type)
{
case TouchActionType.Pressed:
// Don't allow a second touch on an already touched BoxView
if (!dragDictionary.ContainsKey(boxView))
{
dragDictionary.Add(boxView, new DragInfo(args.Id, args.Location));
case TouchActionType.Moved:
if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
{
Rectangle rect = AbsoluteLayout.GetLayoutBounds(boxView);
Point initialLocation = dragDictionary[boxView].PressPoint;
rect.X += args.Location.X - initialLocation.X;
rect.Y += args.Location.Y - initialLocation.Y;
AbsoluteLayout.SetLayoutBounds(boxView, rect);
}
break;
case TouchActionType.Released:
if (dragDictionary.ContainsKey(boxView) && dragDictionary[boxView].Id == args.Id)
{
dragDictionary.Remove(boxView);
}
break;
}
}
A lógica Pressed define a propriedade Capture do objeto TouchEffect como true . Isso tem o efeito de fornecer
todos os eventos seguintes desse dedo ao mesmo manipulador de eventos.
A lógica Moved move a BoxView alterando a propriedade anexada LayoutBounds . A propriedade Location dos
argumentos do evento sempre é relativa à BoxView que está sendo arrastada e, se a BoxView estiver sendo
arrastada a uma taxa constante, as propriedades Location dos eventos consecutivos serão aproximadamente as
mesmas. Por exemplo, se um dedo pressiona a BoxView em seu centro, a ação Pressed armazena uma
propriedade PressPoint de (50, 50), que permanece a mesma para eventos seguintes. Se a BoxView é arrastada
diagonalmente a uma taxa constante, as propriedades Location seguintes durante a ação Moved podem ser
valores de (55, 55); nesse caso, a lógica Moved adiciona 5 à posição horizontal e vertical da BoxView . Isso move a
BoxView para que seu centro fique novamente diretamente sob o dedo.
Você pode mover vários elementos BoxView simultaneamente usando dedos diferentes.
public DraggableBoxView()
{
TouchEffect touchEffect = new TouchEffect
{
Capture = true
};
touchEffect.TouchAction += OnTouchEffectAction;
Effects.Add(touchEffect);
}
case TouchActionType.Moved:
if (isBeingDragged && touchId == args.Id)
{
TranslationX += args.Location.X - pressPoint.X;
TranslationY += args.Location.Y - pressPoint.Y;
}
break;
case TouchActionType.Released:
if (isBeingDragged && touchId == args.Id)
{
isBeingDragged = false;
}
break;
}
}
}
O construtor cria e anexa o TouchEffect e define a propriedade Capture quando é criada uma instância desse
objeto pela primeira vez. Nenhum dicionário é necessário porque a própria classe armazena os valores
isBeingDragged , pressPoint e touchId associados a cada dedo. A manipulação de Moved altera as propriedades
TranslationX e TranslationY e, portanto, a lógica funcionará mesmo se o pai da DraggableBoxView não for um
AbsoluteLayout .
O arquivo EllipseDrawPage.xaml cria uma instância da SKCanvasView em uma Grid de célula única. O objeto
TouchEffect é anexado a esse Grid :
<Grid x:Name="canvasViewGrid"
Grid.Row="1"
BackgroundColor="White">
<skia:SKCanvasView x:Name="canvasView"
PaintSurface="OnCanvasViewPaintSurface" />
<Grid.Effects>
<tt:TouchEffect Capture="True"
TouchAction="OnTouchEffectAction" />
</Grid.Effects>
</Grid>
public EllipseDrawingFigure()
{
}
void MakeRectangle()
{
Rectangle = new SKRect(pt1.X, pt1.Y, pt2.X, pt2.Y).Standardized;
}
As propriedades StartPoint e EndPoint são usadas quando o programa está processando a entrada por toque; a
propriedade Rectangle é usada para desenhar a elipse. A propriedade LastFingerLocation entra em jogo quando
a elipse está sendo arrastada e o método IsInEllipse ajuda no teste de clique. O método retorna true se o
ponto está dentro da elipse.
O arquivo code-behind mantém três coleções:
A parte mais complicada do processamento de toque é a manipulação de Pressed . É nesse momento que o teste
de clique é executado, mas se o código detectar uma elipse sob o dedo do usuário, essa elipse só poderá ser
arrastada se não estiver sendo arrastada por outro dedo. Se não houver nenhuma elipse sob o dedo do usuário, o
código iniciará o processo de desenho de uma nova elipse:
case TouchActionType.Pressed:
bool isDragOperation = false;
if (isDragOperation)
{
fig.LastFingerLocation = args.Location;
draggingFigures.Add(args.Id, fig);
break;
}
}
}
if (isDragOperation)
{
// Move the dragged ellipse to the end of completedFigures so it's drawn on top
EllipseDrawingFigure fig = draggingFigures[args.Id];
completedFigures.Remove(fig);
completedFigures.Add(fig);
}
else // start making a new ellipse
{
// Random bytes for random color
byte[] buffer = new byte[4];
random.NextBytes(buffer);
Outro exemplo do SkiaSharp é a página Pintura a dedo. Você pode selecionar uma cor e uma largura do traço
em duas exibições Picker e, em seguida, desenhar com um ou mais dedos:
Este exemplo também exige uma classe separada para representar cada linha pintada na tela:
class FingerPaintPolyline
{
public FingerPaintPolyline()
{
Path = new SKPath();
}
Um objeto SKPath é usado para renderizar cada linha. O arquivo FingerPaint.xaml.cs mantém duas coleções
desses objetos, uma para essas polilinhas desenhadas no momento e outra para as polilinhas concluídas:
O processamento de Pressed cria uma nova FingerPaintPolyline , chama MoveTo no objeto de caminho para
armazenar o ponto inicial e adiciona esse objeto ao dicionário inProgressPolylines . O processamento de Moved
chama LineTo no objeto de caminho com a nova posição do dedo e o processamento de Released transfere a
polilinha concluída de inProgressPolylines para completedPolylines . Mais uma vez, o código de desenho real do
SkiaSharp é relativamente simples:
SKPaint paint = new SKPaint
{
Style = SKPaintStyle.Stroke,
StrokeCap = SKStrokeCap.Round,
StrokeJoin = SKStrokeJoin.Round
};
...
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKCanvas canvas = args.Surface.Canvas;
canvas.Clear();
Esse tipo de processamento de toque é muito útil para um teclado musical. Uma tecla deve conseguir detectar
quando ela é pressionada, mas também quando um dedo deslizar de uma tecla para outra.
A página Teclado silencioso define classes WhiteKey e BlackKey pequenas que derivam de Key , que, por sua
vez, deriva de BoxView .
A classe Key está pronta para ser usada em um programa real de música. Ela define as propriedades públicas
chamadas IsPressed e KeyNumber , que se destinam a ser definidas como o código de teclas estabelecido pelo
padrão MIDI. A classe Key também define um evento chamado StatusChanged , que é invocado quando a
propriedade IsPressed é alterada.
Vários dedos são permitidos em cada tecla. Por esse motivo, a classe Key mantém uma List dos números de ID
de toque dos dedos que estão tocando essa tecla:
O manipulador de eventos TouchAction adiciona uma ID à lista ids para um tipo de evento Pressed e um tipo
Entered , mas somente quando a propriedade IsInContact é true para o evento Entered . A ID é removida da
List para um evento Released ou Exited :
void OnTouchEffectAction(object sender, TouchActionEventArgs args)
{
switch (args.Type)
{
case TouchActionType.Pressed:
AddToList(args.Id);
break;
case TouchActionType.Entered:
if (args.IsInContact)
{
AddToList(args.Id);
}
break;
case TouchActionType.Moved:
break;
case TouchActionType.Released:
case TouchActionType.Exited:
RemoveFromList(args.Id);
break;
}
}
Os métodos AddToList e RemoveFromList verificam se a List foi alterada entre vazia e não vazia e, nesse caso,
invoca o evento StatusChanged .
Os vários elementos WhiteKey e BlackKey são organizados no arquivo XAML da página, que tem uma melhor
aparência quando o telefone é segurado em um modo paisagem:
Se você passar o dedo entre as teclas, pelas pequenas alterações nas cores, você verá que os eventos de toque são
transferidos de uma tecla para outra.
Resumo
Este artigo demonstrou como invocar eventos em um efeito e como gravar e usar um efeito que implementa o
processamento multitoque de nível baixo.
Links relacionados
Acompanhamento de dedo multitoque no iOS
Acompanhamento de dedo multitoque no Android
Efeito de acompanhamento de toque (amostra)
Manipulação de arquivos no Xamarin.Forms
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
O tratamento de arquivos com o Xamarin.Forms pode ser alcançado usando código em uma biblioteca .NET
Standard ou usando recursos inseridos.
Visão geral
Código do Xamarin.Forms são executados em várias plataformas e cada uma delas tem seu próprio sistema de
arquivos. Anteriormente, isso significava que ler e gravar arquivos era realizado mais facilmente usando as APIs
de arquivo nativo em cada plataforma. Como alternativa, os recursos inseridos são uma solução mais simples para
distribuir os arquivos de dados com um aplicativo. No entanto, com o .NET Standard 2.0, é possível compartilhar o
código de acesso de arquivo nas bibliotecas .NET Standard.
Para saber mais sobre o tratamento de arquivos de imagem, confira a página Trabalhando com imagens.
File.WriteAllText(fileName, text);
O caminho do arquivo em cada plataforma pode ser determinado com base em uma biblioteca .NET Standard
usando um valor da enumeração Environment.SpecialFolder como o primeiro argumento para o método
Environment.GetFolderPath . Isso pode ser combinado com um nome de arquivo com o método Path.Combine :
Essas operações são demonstradas no aplicativo de exemplo, que inclui uma página que salva e carrega texto:
Carregamento de arquivos inseridos como recursos
Para inserir um arquivo em um assembly do .NET Standard, crie ou adicione um arquivo e certifique-se de que
seja Ação de build: EmbeddedResource.
Visual Studio
Visual Studio para Mac
GetManifestResourceStream é usado para acessar o arquivo inserido usando sua ID de recurso. Por padrão, a ID
de recurso é o nome do arquivo com o prefixo do namespace padrão para o projeto no qual ele está inserido –
nesse caso, o assembly é WorkingWithFiles e o nome do arquivo é PCLTextResource.txt; portanto, a ID de
recurso é WorkingWithFiles.PCLTextResource.txt .
A variável text pode ser usada para exibir o texto ou, caso contrário, usá-lo no código. Esta captura de tela do
aplicativo de exemplo mostra o texto renderizado em um controle Label .
Carregar e desserializar um XML é igualmente simples. O código a seguir mostra um arquivo XML sendo
carregado e desserializado de um recurso, associado a um ListView para exibição. O arquivo XML contém uma
matriz de objetos Monkey (a classe é definida no código de exemplo).
#if __IOS__
var resourcePrefix = "WorkingWithFiles.iOS.";
#endif
#if __ANDROID__
var resourcePrefix = "WorkingWithFiles.Droid.";
#endif
Organização de recursos
Os exemplos acima supõem que o arquivo é inserido na raiz do projeto da biblioteca .NET Standard, em cujo caso
a ID de recurso é do formato Namespace.Filename.Extension, como WorkingWithFiles.PCLTextResource.txt e
WorkingWithFiles.iOS.SharedTextResource.txt .
É possível organizar os recursos inseridos em pastas. Quando um recurso inserido é colocado em uma pasta, o
nome da pasta se torna parte da ID de recurso (separado por pontos) para que o formato de ID de recurso se
torne Namespace.Folder.Filename.Extension. Colocar os arquivos usados no aplicativo de exemplo em uma
pasta MyFolder tornaria as IDs de recurso correspondentes WorkingWithFiles.MyFolder.PCLTextResource.txt e
WorkingWithFiles.iOS.MyFolder.SharedTextResource.txt .
using System.Reflection;
// ...
// use for debugging, not in released app code!
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(SharedPage)).Assembly;
foreach (var res in assembly.GetManifestResourceNames()) {
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
Resumo
Este artigo mostrou algumas operações de arquivo simples para salvar e carregar texto no dispositivo e para
carregar recursos inseridos. Com o .NET Standard 2.0, é possível compartilhar o código de acesso de arquivo nas
bibliotecas .NET Standard.
Links relacionados
FilesSample
Amostras do Xamarin.Forms
Trabalhando com o sistema de arquivos no Xamarin.iOS
Gestos do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Reconhecedores de gestos podem ser usados para detectar a interação do usuário com exibições em um aplicativo
Xamarin.Forms.
A classe GestureRecognizer do Xamarin.Forms dá suporte a gestos de toque, de pinçagem, de panorâmica e de
passar o dedo em instâncias de View .
Baixar o exemplo
O gesto de toque é usado para detecção de toque e é implementado com a classe TapGestureRecognizer.
Para que seja possível clicar em um elemento da interface do usuário com um gesto de toque, crie uma instância
de TapGestureRecognizer , manipule o evento Tapped e adicione o novo reconhecedor de gestos à coleção
GestureRecognizers no elemento de interface do usuário. O exemplo de código a seguir mostra um
TapGestureRecognizer anexado a um elemento Image :
Por padrão, a imagem responderá a toques único. Configure a propriedade NumberOfTapsRequired para aguardar
um toque duplo (ou mais toques se necessário).
tapGestureRecognizer.NumberOfTapsRequired = 2; // double-tap
Quando NumberOfTapsRequired é configurado como mais de um, o manipulador de eventos é executado somente
quando os toques ocorrem em um período definido (esse período não é configurável). Se o segundo toque (ou os
toques posteriores) não ocorrerem dentro desse período, eles serão ignorados e a “contagem de toques” será
reiniciada.
Usando XAML
Um reconhecedor de gestos pode ser adicionado a um controle em XAML usando propriedades anexadas. A
sintaxe para adicionar um TapGestureRecognizer a uma imagem é mostrada abaixo (nesse caso, definindo um
evento de toque duplo):
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Tapped="OnTapGestureRecognizerTapped"
NumberOfTapsRequired="2" />
</Image.GestureRecognizers>
</Image>
O código para o manipulador de eventos (no exemplo) incrementa um contador e altera a imagem de colorida
para preto & branca.
void OnTapGestureRecognizerTapped(object sender, EventArgs args)
{
tapCount++;
var imageSender = (Image)sender;
// watch the monkey go from color to black&white!
if (tapCount % 2 == 0) {
imageSender.Source = "tapped.jpg";
} else {
imageSender.Source = "tapped_bw.jpg";
}
}
Usando ICommand
Aplicativos que usam o padrão MVVM (Model-View -ViewModel) normalmente usam ICommand em vez de
conectar manipuladores de eventos diretamente. O TapGestureRecognizer pode facilmente dar suporte a ICommand
definindo a associação no código:
ou usando XAML:
<Image Source="tapped.jpg">
<Image.GestureRecognizers>
<TapGestureRecognizer
Command="{Binding TapCommand}"
CommandParameter="Image1" />
</Image.GestureRecognizers>
</Image>
O código completo para esse modelo de exibição pode ser encontrado na amostra. Os detalhes relevantes da
implementação de Command são mostrados abaixo:
Links relacionados
TapGesture (amostra)
GestureRecognizer
TapGestureRecognizer
Adicionando um reconhecedor de gestos de
pinçagem
12/04/2019 • 5 minutes to read • Edit Online
Baixar o exemplo
O gesto de pinçagem é usado para aplicar zoom de forma interativa e é implementado com a classe
PinchGestureRecognizer. Um cenário comum para o gesto de pinçagem é aplicar zoom de forma interativa a uma
imagem na localização da pinçagem. Isso é feito dimensionando o conteúdo do visor e é demonstrado neste
artigo.
Para que seja possível ampliar um elemento da interface do usuário com um gesto de pinçagem, crie uma
instância de PinchGestureRecognizer , manipule o evento PinchUpdated e adicione o novo reconhecedor de gestos à
coleção GestureRecognizers no elemento de interface do usuário. O exemplo de código a seguir mostra um
PinchGestureRecognizer anexado a um elemento Image :
Isso também pode ser feito em XAML, conforme mostrado no exemplo de código a seguir:
<Image Source="waterfront.jpg">
<Image.GestureRecognizers>
<PinchGestureRecognizer PinchUpdated="OnPinchUpdated" />
</Image.GestureRecognizers>
</Image>
public PinchToZoomContainer ()
{
var pinchGesture = new PinchGestureRecognizer ();
pinchGesture.PinchUpdated += OnPinchUpdated;
GestureRecognizers.Add (pinchGesture);
}
Essa classe pode ser encapsulada em torno de um elemento de interface do usuário para que o gesto de pinçagem
aplique zoom ao elemento de interface do usuário encapsulado. O exemplo de código XAML a seguir mostra o
PinchToZoomContainer encapsulando um elemento Image :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PinchGesture;assembly=PinchGesture"
x:Class="PinchGesture.HomePage">
<ContentPage.Content>
<Grid Padding="20">
<local:PinchToZoomContainer>
<local:PinchToZoomContainer.Content>
<Image Source="waterfront.jpg" />
</local:PinchToZoomContainer.Content>
</local:PinchToZoomContainer>
</Grid>
</ContentPage.Content>
</ContentPage>
O exemplo de código a seguir mostra como o PinchToZoomContainer encapsula um elemento Image em uma
página de C#:
Quando o elemento Image receber um gesto de pinçagem, a imagem exibida será ampliada ou reduzida. A
aplicação de zoom é realizada pelo método PinchZoomContainer.OnPinchUpdated , que é mostrado no exemplo de
código a seguir:
void OnPinchUpdated (object sender, PinchGestureUpdatedEventArgs e)
{
if (e.Status == GestureStatus.Started) {
// Store the current scale factor applied to the wrapped user interface element,
// and zero the components for the center point of the translate transform.
startScale = Content.Scale;
Content.AnchorX = 0;
Content.AnchorY = 0;
}
if (e.Status == GestureStatus.Running) {
// Calculate the scale factor to be applied.
currentScale += (e.Scale - 1) * startScale;
currentScale = Math.Max (1, currentScale);
Esse método atualiza o nível de aplicação de zoom do elemento da interface do usuário encapsulado, com base no
gesto de pinçagem do usuário. Isso é feito usando os valores das propriedades Scale , ScaleOrigin e Status da
instância de PinchGestureUpdatedEventArgs para calcular o fator de escala a ser aplicado na origem do gesto de
pinçagem. O elemento do usuário encapsulado, então, é ampliado na origem do gesto de pinçagem definindo suas
propriedades TranslationX , TranslationY e Scale como os valores calculados.
Links relacionados
PinchGesture (amostra)
GestureRecognizer
PinchGestureRecognizer
Adicionando um reconhecedor de gesto de
panorâmica
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
O gesto de panorâmica é usado para detectar a movimentação dos dedos na tela e aplicar essa movimentação ao
conteúdo e é implementado com a classe PanGestureRecognizer . Um cenário comum para o gesto de panorâmica
é percorrer uma imagem horizontal e verticalmente, para que todo o conteúdo da imagem pode ser exibido
quando ela estiver sendo exibida em um visor menor do que as dimensões da imagem. Isso é feito movendo a
imagem dentro do visor e é demonstrado neste artigo.
Para que seja possível mover um elemento da interface do usuário com um gesto de panorâmica, crie uma
instância de PanGestureRecognizer , manipule o evento PanUpdated e adicione o novo reconhecedor de gestos à
coleção GestureRecognizers no elemento de interface do usuário. O exemplo de código a seguir mostra um
PanGestureRecognizer anexado a um elemento Image :
Isso também pode ser feito em XAML, conforme mostrado no exemplo de código a seguir:
<Image Source="MonoMonkey.jpg">
<Image.GestureRecognizers>
<PanGestureRecognizer PanUpdated="OnPanUpdated" />
</Image.GestureRecognizers>
</Image>
NOTE
Para usar a panorâmica corretamente no Android, é necessário ter no mínimo o Pacote NuGet 2.1.0-pre1 do Xamarin.Forms.
public PanContainer ()
{
// Set PanGestureRecognizer.TouchPoints to control the
// number of touch points needed to pan
var panGesture = new PanGestureRecognizer ();
panGesture.PanUpdated += OnPanUpdated;
GestureRecognizers.Add (panGesture);
}
Essa classe pode ser encapsulada em torno de um elemento de interface do usuário para que o gesto percorra o
elemento de interface do usuário encapsulado. O exemplo de código XAML a seguir mostra o PanContainer
encapsulando um elemento Image :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PanGesture"
x:Class="PanGesture.HomePage">
<ContentPage.Content>
<AbsoluteLayout>
<local:PanContainer>
<Image Source="MonoMonkey.jpg" WidthRequest="1024" HeightRequest="768" />
</local:PanContainer>
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
O exemplo de código a seguir mostra como o PanContainer encapsula um elemento Image em uma página de
C#:
Nos dois exemplos, as propriedades WidthRequest e HeightRequest são definidas como os valores de largura e
altura da imagem que está sendo exibida.
Quando o elemento Image receber um gesto de panorâmica, a imagem exibida será deslocada. A panorâmica é
realizada pelo método PanContainer.OnPanUpdated , que é mostrado no exemplo de código a seguir:
case GestureStatus.Completed:
// Store the translation applied during the pan
x = Content.TranslationX;
y = Content.TranslationY;
break;
}
}
Esse método atualiza o conteúdo visível do elemento de interface do usuário encapsulado, com base no gesto de
panorâmica do usuário. Isso é feito usando os valores das propriedades TotalX e TotalY da instância de
PanUpdatedEventArgs para calcular a direção e a distância da panorâmica. As propriedades App.ScreenWidth e
App.ScreenHeight fornecem a altura e largura do visor e são definidas com os valores da largura e da altura da tela
do dispositivo pelos respectivos projetos específicos da plataforma. O elemento de usuário encapsulado, então, é
percorrido definindo suas propriedades TranslationX e TranslationY como os valores calculados.
Quando o movimento panorâmico no conteúdo de um elemento que não ocupa a tela inteira, a altura e a largura
do visor podem ser obtidas das propriedades Height e Width do elemento.
NOTE
Exibir imagens de alta resolução pode aumentar significativamente o volume de memória de um aplicativo. Portanto, elas só
devem ser criadas quando necessário e devem ser liberadas assim que o aplicativo não precisar mais delas. Para saber mais,
consulte Otimizar recursos de imagem.
Links relacionados
PanGesture (amostra)
GestureRecognizer
PanGestureRecognizer
Adicionando um reconhecedor de gesto de passar o
dedo
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
Um gesto de passar o dedo ocorre quando um dedo é movido pela tela na direção horizontal ou vertical e
geralmente é usado para iniciar a navegação pelo conteúdo. Os exemplos de código neste artigo são provenientes
do exemplo Gesto de passar o dedo.
Para fazer com que um View reconheça um gesto de passar o dedo, crie uma instância de SwipeGestureRecognizer
, defina a propriedade Direction como um valor de enumeração SwipeDirection ( Left , Right , Up ou Down ),
opcionalmente, defina a propriedade Threshold , manipule o evento Swiped e adicione o novo reconhecedor de
gestos à coleção GestureRecognizers na exibição. O exemplo de código a seguir mostra um
SwipeGestureRecognizer anexado a um BoxView :
boxView.GestureRecognizers.Add(leftSwipeGesture);
A classe SwipeGestureRecognizer também inclui uma propriedade Threshold que pode, opcionalmente, ser
definida como um valor de uint que representa a distância mínima que gesto deve percorrer para ser
reconhecido, em unidades independentes do dispositivo. O valor padrão dessa propriedade é 100, o que significa
que qualquer gesto de passar o dedo com menos de 100 unidades independentes do dispositivo será ignorado.
De forma semelhante, gestos que ocorrem no eixo vertical podem ser reconhecidos definindo a propriedade
Direction como Up e Down :
var swipeGesture = new SwipeGestureRecognizer { Direction = SwipeDirection.Up | SwipeDirection.Down };
Como alternativa, é possível criar um SwipeGestureRecognizer para o gesto de passar o dedo em cada direção a fim
de reconhecer o gesto em todas as direções:
boxView.GestureRecognizers.Add(leftSwipeGesture);
boxView.GestureRecognizers.Add(rightSwipeGesture);
boxView.GestureRecognizers.Add(upSwipeGesture);
boxView.GestureRecognizers.Add(downSwipeGesture);
NOTE
Nos exemplos acima, o mesmo manipulador de eventos responde ao acionamento do evento Swiped . No entanto, cada
instância de SwipeGestureRecognizer pode usar um manipulador de eventos diferente se necessário.
O SwipedEventArgs pode ser examinado para determinar a direção do gesto de passar o dedo, com a lógica
personalizada respondendo ao gesto conforme necessário. A direção do gesto de passar o dedo pode ser obtida da
propriedade Direction dos argumentos do evento, que será definida como um dos valores da enumeração
SwipeDirection . Além disso, os argumentos do evento também têm uma propriedade Parameter que será
definida com o valor da propriedade CommandParameter , se definida.
Usando comandos
A classe SwipeGestureRecognizer também inclui propriedades Command e CommandParameter . Essas propriedades
geralmente são usadas em aplicativos que usam o padrão MVVM (Model-View -ViewModel). A propriedade
Command define o ICommand a ser invocado quando um gesto de passar o dedo for reconhecido, com a
propriedade CommandParameter definindo um objeto a ser passado para o ICommand. . O exemplo de código a
seguir mostra como associar a propriedade Command a um ICommand definido no modelo de exibição cuja instância
é definida como a página BindingContext :
SwipeCommand é uma propriedade do tipo ICommand definida na instância do modelo de exibição que é definida
como o BindingContext da página. Quando um gesto de passar o dedo é reconhecido, o método Execute do
objeto SwipeCommand é executado. O argumento para o método Execute assume o valor da propriedade
CommandParameter . Para obter mais informações sobre comandos, confira A Interface de Comando.
public SwipeContainer()
{
GestureRecognizers.Add(GetSwipeGestureRecognizer(SwipeDirection.Left));
GestureRecognizers.Add(GetSwipeGestureRecognizer(SwipeDirection.Right));
GestureRecognizers.Add(GetSwipeGestureRecognizer(SwipeDirection.Up));
GestureRecognizers.Add(GetSwipeGestureRecognizer(SwipeDirection.Down));
}
A classe SwipeContainer cria objetos SwipeGestureRecognizer para os quatro sentidos do gesto de passar o dedo e
anexa manipuladores de eventos Swipe . Esses manipuladores de eventos invocam o evento Swipe definido pelo
SwipeContainer .
<ContentPage ...>
<StackLayout>
<local:SwipeContainer Swipe="OnSwiped" ...>
<BoxView Color="Teal" ... />
</local:SwipeContainer>
</StackLayout>
</ContentPage>
O exemplo de código a seguir mostra como o SwipeContainer encapsula um BoxView em uma página de C#:
Quando o BoxView recebe um gesto de passar o dedo, o evento Swiped no SwipeGestureRecognizer é acionado.
Isso é manipulado pela classe SwipeContainer , que aciona seu próprio evento Swipe . Esse evento Swipe é
manipulado na página. O SwipedEventArgs pode, então, ser examinado para determinar a direção do gesto de
passar o dedo, com a lógica personalizada respondendo ao gesto conforme necessário.
Links relacionados
Gesto de passar o dedo (amostra)
GestureRecognizer
SwipeGestureRecognizer
Localização do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
A estrutura de localização interna do .NET pode ser usada para criar aplicativos multilíngues multiplataforma
com o Xamarin.Forms.
Baixar o exemplo
Aplicativos do Xamarin.Forms podem ser localizados usando arquivos de recursos do .NET.
Visão geral
O mecanismo interno para localização de usos de aplicativos .NET arquivos RESX e as classes nos namespaces
System.Resources e System.Globalization . Arquivos RESX que contêm cadeias de caracteres traduzidas são
inseridos no assembly do Xamarin.Forms, junto com uma classe gerada pelo compilador que fornece acesso
fortemente tipado para as traduções. O texto traduzido pode ser então recuperado no código.
Código de exemplo
Há dois exemplos associados a este documento:
UsingResxLocalization é uma demonstração muito simples dos conceitos explicados. Todos os trechos de
código mostrados abaixo são provenientes deste exemplo.
TodoLocalized é um aplicativo de trabalho básico que usa essas técnicas de localização.
Não é recomendado o uso de Projetos compartilhados
O exemplo TodoLocalized inclui uma Demonstração de Projeto compartilhado. No entanto, devido a limitações do
sistema de build, os arquivos de recurso não geram um arquivo .designer.cs, o que impossibilita o acesso a
cadeias de caracteres traduzidas fortemente tipadas no código.
O restante deste documento aborda projetos que usam o modelo de biblioteca .NET Standard do Xamarin.Forms.
NOTE
Na Plataforma Universal do Windows, é necessário usado arquivos RESW para localização de notificações por push, em vez de
arquivos RESX. Para obter mais informações, confira Localização da UWP.
Adicionando recursos
A primeira etapa da globalização de um aplicativo de biblioteca .NET Standard do Xamarin.Forms é adicionar os
arquivos de recursos RESX que serão usados para armazenar todo o texto usado no aplicativo. Precisamos
adicionar um arquivo RESX que contém o texto padrão e, em seguida, adicionar arquivos RESX adicionais para
cada idioma a que desejamos dar suporte.
Recurso de idioma base
O arquivo de recursos base (RESX) contém as cadeias de caracteres de idioma padrão (os exemplos pressupõem o
que inglês seja o idioma padrão). Adicione o arquivo ao projeto de código comum do Xamarin.Forms clicando com
o botão direito do mouse no projeto e escolhendo Adicionar > Novo Arquivo....
Escolha um nome significativo, como AppResources, e pressione OK.
Vi si b i l i d a d e d a c a d e i a d e c a r a c t e r e s
Por padrão, quando são geradas referências fortemente tipadas a cadeias de caracteres, elas são o internal para
o assembly. Isso ocorre porque a ferramenta de build padrão para arquivos RESX gera o arquivo .designer.cs com
propriedades internal .
Selecione o arquivo AppResources.resx e mostre o painel Propriedades para ver onde a ferramenta de build
está configurada. A captura de tela abaixo mostra a Ferramenta Personalizada: ResXFileCodeGenerator.
Visual Studio
Visual Studio para Mac
Para tornar as propriedades public da cadeia de caracteres fortemente tipadas, você deve alterar manualmente a
configuração da Ferramenta Personalizada: PublicResXFileCodeGenerator, como mostrado na captura de
tela abaixo:
Visual Studio
Visual Studio para Mac
Essa alteração é opcional e só é necessária se você deseja fazer referência a cadeias de caracteres localizadas em
assemblies diferentes (por exemplo, se você colocar os arquivos RESX em um assembly diferente de seu código).
O exemplo deste tópico deixa as cadeias de caracteres internal porque elas são definidas no mesmo assembly de
biblioteca .NET Standard do Xamarin.Forms em que são usadas.
Você só precisa definir a ferramenta personalizada no arquivo RESX base, conforme mostrado acima. Não é
necessário definir nenhuma ferramenta de build nos arquivos RESX específicos a um idioma discutidos nas seções
a seguir.
Ed i t a n d o o a r q u i v o R E SX
Infelizmente, não há um editor de RESX interno no Visual Studio para Mac. Adicionar novas cadeias de caracteres
traduzíveis requer a adição de um novo elemento data XML para cada cadeia de caracteres. Cada elemento data
pode conter os seguintes elementos:
O atributo name (obrigatório) é a chave para essa cadeia de caracteres traduzível. Ele deve ser um nome de
propriedade C# válido, de modo que não são permitidos espaços nem caracteres especiais.
Elemento value (obrigatório), que é a cadeia de caracteres que de fato é exibida no aplicativo.
O elemento comment (opcional) pode conter instruções para o tradutor explicando como a cadeia de caracteres
é usada.
O atributo xml:space (opcional), para controlar como o espaçamento na cadeia de caracteres é preservado.
Conforme o aplicativo é escrito, cada parte do texto exibido para o usuário deve ser adicionada ao arquivo de
recursos RESX base em um novo elemento data . É recomendável que você inclua tantos comment s quanto
possível para garantir uma tradução de alta qualidade.
NOTE
O Visual Studio (incluindo a edição Community gratuita) contém um editor do RESX básico. Se você tem acesso a um
computador com Windows, essa pode ser uma maneira conveniente de adicionar e editar cadeias de caracteres em arquivos
RESX.
Conforme o aplicativo é desenvolvido e o texto é adicionado ao arquivo RESX base, você deve enviá-lo para os
tradutores, que traduzirão cada elemento data e retornarão um arquivo de recurso específico a um idioma
(usando a convenção de nomenclatura mostrada) para ser incluído no aplicativo. Alguns exemplos 'traduzidos de
maneira automática' são mostrados abaixo:
AppResources.es.resx (espanhol)
<data name="AddButton" xml:space="preserve">
<value>Escribir un artículo</value>
<comment>this string appears on a button to add a new item to the list</comment>
</data>
AppResources.ja.resx ( japonês)
Somente o elemento value precisa ser atualizado pelo tradutor – o comment não se destina a ser traduzido.
Lembre-se: ao editar arquivos XML, faça o escape de caracteres reservados como < , > , & com < , > e
& se eles aparecerem no value ou comment .
A interface do usuário no iOS, no Android e na UWP (Plataforma Universal do Windows) é renderizada da forma
esperada, mas agora é possível traduzir o aplicativo para vários idiomas, porque o texto está sendo carregado de
um recurso em vez de ser embutido em código. Veja uma captura de tela que mostra a interface do usuário em
cada plataforma antes da tradução:
Solução de problemas
Testando um idioma específico
Pode ser complicado passar o simulador ou um dispositivo para idiomas diferentes, especialmente durante o
desenvolvimento, quando você deseja testar rapidamente diferentes culturas.
É possível forçar o carregamento de um idioma específico definindo o Culture , conforme mostrado neste snippet
de código:
Essa abordagem – configurar a cultura diretamente na classe AppResources – também pode ser usada para
implementar um seletor de idioma dentro de seu aplicativo (em vez de usar a localidade do dispositivo).
Carregando recursos inseridos
O snippet de código a seguir é útil ao tentar depurar problemas com os recursos inseridos (como arquivos RESX).
Adicione este código ao seu aplicativo (no início do ciclo de vida do aplicativo) e ele listará todos os recursos
inseridos no assembly, mostrando o identificador de recurso completo:
using System.Reflection;
// ...
// NOTE: use for debugging, not in released app code!
var assembly = typeof(EmbeddedImages).GetTypeInfo().Assembly; // "EmbeddedImages" should be a class in your
app
foreach (var res in assembly.GetManifestResourceNames())
{
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
System.Resources.ResourceManager temp =
new System.Resources.ResourceManager(
"UsingResxLocalization.Resx.AppResources",
typeof(AppResources).GetTypeInfo().Assembly);
Verifique na Saída do Aplicativo os resultados do código de depuração mostrado acima para confirmar se os
recursos corretos estão listados (por exemplo, "UsingResxLocalization.Resx.AppResources" ).
Se não estiverem, a classe AppResources não poderá carregar seus recursos. Verifique o seguinte para resolver
problemas em que os recursos não podem ser encontrados:
O namespace padrão do projeto corresponde ao namespace raiz no arquivo AppResources.Designer.cs.
Se o arquivo AppResources.resx estiver localizado em um subdiretório, o nome do subdiretório deverá fazer
parte do namespace e do identificador do recurso.
O arquivo AppResources.resx tem Compilar Ação: EmbeddedResource.
A configuração Opções do Projeto > Código-fonte > Políticas de Nomenclatura do .NET > Usar nomes
de recursos com estilo do Visual Studio está marcada. Você pode desmarcar essa opção se preferir, mas os
namespaces usados ao fazer referência a seus recursos RESX precisarão ser atualizados em todo o aplicativo.
Não funciona no modo de depuração (somente Android)
Se as cadeias de caracteres traduzidas estiverem funcionando em seus builds de VERSÃO do Android, mas não
durante a depuração, clique com o botão direito do mouse em Projeto do Android e selecione Opções > Build
> Build do Android e certifique-se de que Implantação de Assembly Rápida NÃO esteja marcado. Essa opção
causa problemas ao carregar recursos e não deverá ser usada se você estiver testando aplicativos localizados.
Exibindo o idioma correto
Até agora, examinamos como escrever código para que as traduções possam ser fornecidas, mas não como
realmente fazê-las aparecer. O código do Xamarin.Forms pode tirar proveito de recursos do .NET para carregar as
traduções no idioma correto, mas é necessário consultar o sistema operacional de cada plataforma para
determinar qual idioma foi selecionado pelo usuário.
Como são necessários alguns códigos específicos da plataforma para obter a preferência de idioma do usuário, use
um serviço de dependência para expor essas informações no aplicativo do Xamarin.Forms e implementá-las para
cada plataforma.
Primeiro, defina uma interface para expor a cultura preferencial do usuário, semelhante ao código a seguir:
Depois, use o DependencyService na classe App do Xamarin.Forms para chamar a interface e definir nossa cultura
de recursos RESX com o valor correto. Observe que não precisamos definir manualmente esse valor para a
Plataforma Universal do Windows, pois a estrutura de recursos reconhece automaticamente o idioma selecionado
nessas plataformas.
O recurso Culture precisa ser definido quando o aplicativo é carregado pela primeira vez para que as cadeias de
caracteres no idioma correto sejam usadas. Você pode, opcionalmente, atualizar esse valor de acordo com eventos
específicos da plataforma que podem ser acionados no iOS ou no Android se o usuário atualizar suas preferências
de idioma enquanto o aplicativo está em execução.
As implementações para a interface ILocalize são mostradas na seção Código específico da plataforma abaixo.
Essas implementações tiram proveito dessa classe auxiliar PlatformCulture :
public class PlatformCulture
{
public PlatformCulture (string platformCultureString)
{
if (String.IsNullOrEmpty(platformCultureString))
{
throw new ArgumentException("Expected culture identifier", "platformCultureString"); // in C# 6
use nameof(platformCultureString)
}
PlatformString = platformCultureString.Replace("_", "-"); // .NET expects dash, not underscore
var dashIndex = PlatformString.IndexOf("-", StringComparison.Ordinal);
if (dashIndex > 0)
{
var parts = PlatformString.Split('-');
LanguageCode = parts[0];
LocaleCode = parts[1];
}
else
{
LanguageCode = PlatformString;
LocaleCode = "";
}
}
public string PlatformString { get; private set; }
public string LanguageCode { get; private set; }
public string LocaleCode { get; private set; }
public override string ToString()
{
return PlatformString;
}
}
[assembly:Dependency(typeof(UsingResxLocalization.iOS.Localize))]
namespace UsingResxLocalization.iOS
{
public class Localize : UsingResxLocalization.ILocalize
{
public void SetLocale (CultureInfo ci)
{
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
NOTE
Os blocos try/catch no método GetCurrentCultureInfo imitam o comportamento de fallback usado normalmente com
especificadores de localidade – se a correspondência exata não for encontrada, procure uma correspondência aproximada
com base apenas no idioma (primeiro bloco de caracteres na localidade).
No caso do Xamarin.Forms, algumas localidades são válidas no iOS, mas não correspondem a um CultureInfo válido no
.NET e o código acima tenta lidar com isso.
Por exemplo, a tela Configurações > Idioma Geral & Região do iOS permite que você defina o Idioma de seu telefone
como Inglês e a Região como Espanha, o que resulta na cadeia de caracteres de localidade "en-ES" . Quando a criação de
CultureInfo falha, o código volta a usar apenas as primeiras duas letras para selecionar o idioma de exibição.
Há alguns elementos da interface do usuário definidos pelo sistema que são traduzidos automaticamente pelo
iOS, como o botão Concluído no controle Picker . Para forçar o iOS a traduzir esses elementos, precisamos
indicar a quais idiomas damos suporte no arquivo Info.plist. Você pode adicionar esses valores usando Info.plist
> Origem, conforme mostrado aqui:
Como alternativa, abra o arquivo Info.plist em um editor de XML e edite os valores diretamente:
<key>CFBundleLocalizations</key>
<array>
<string>de</string>
<string>es</string>
<string>fr</string>
<string>ja</string>
<string>pt</string> <!-- Brazil -->
<string>pt-PT</string> <!-- Portugal -->
<string>ru</string>
<string>zh-Hans</string>
<string>zh-Hant</string>
</array>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
Após você ter implementado o serviço de dependência e atualizado Info.plist, o aplicativo do iOS poderá exibir o
texto localizado.
NOTE
Observe que a Apple trata o idioma português um pouco diferente da forma esperada. Nos documentos a Apple: "use pt
como a ID do idioma português usado no Brasil e pt-PT como a ID do idioma português usado em Portugal". Isso significa
que, quando o idioma português é escolhido em uma localidade não padrão, o idioma de fallback é o português brasileiro no
iOS, a menos que seja escrito um código para alterar esse comportamento (como o ToDotnetFallbackLanguage acima).
Para obter mais informações sobre a localização no iOS, confira Localização no iOS.
Projeto de Aplicativo Android
O Android expõe a localidade selecionada por meio de Java.Util.Locale.Default e também usa o sublinhado
como caractere separador, em vez do traço (que é substituído pelo código a seguir). Adicione essa implementação
do serviço de dependência ao projeto de aplicativo do Android:
[assembly:Dependency(typeof(UsingResxLocalization.Android.Localize))]
namespace UsingResxLocalization.Android
{
public class Localize : UsingResxLocalization.ILocalize
{
public void SetLocale(CultureInfo ci)
{
Thread.CurrentThread.CurrentCulture = ci;
Thread.CurrentThread.CurrentUICulture = ci;
}
public CultureInfo GetCurrentCultureInfo()
{
var netLanguage = "en";
var androidLocale = Java.Util.Locale.Default;
netLanguage = AndroidToDotnetLanguage(androidLocale.ToString().Replace("_", "-"));
// this gets called a lot - try/catch can be expensive so consider caching or something
System.Globalization.CultureInfo ci = null;
try
{
ci = new System.Globalization.CultureInfo(netLanguage);
}
catch (CultureNotFoundException e1)
{
// iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
// fallback to first characters, in this case "en"
try
{
var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
ci = new System.Globalization.CultureInfo(fallback);
}
catch (CultureNotFoundException e2)
{
// iOS language not valid .NET culture, falling back to English
ci = new System.Globalization.CultureInfo("en");
}
}
return ci;
}
string AndroidToDotnetLanguage(string androidLanguage)
{
var netLanguage = androidLanguage;
//certain languages need to be converted to CultureInfo equivalent
switch (androidLanguage)
{
case "ms-BN": // "Malaysian (Brunei)" not supported .NET culture
case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture
case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture
case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture
netLanguage = "ms"; // closest supported
break;
case "in-ID": // "Indonesian (Indonesia)" has different code in .NET
netLanguage = "id-ID"; // correct code for .NET
break;
case "gsw-CH": // "Schwiizertüütsch (Swiss German)" not supported .NET culture
netLanguage = "de-CH"; // closest supported
break;
// add more application-specific cases here (if required)
// ONLY use cultures that have been tested and known to work
}
return netLanguage;
}
string ToDotnetFallbackLanguage(PlatformCulture platCulture)
{
var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars,
usually);
switch (platCulture.LanguageCode)
{
case "gsw":
netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
break;
// add more application-specific cases here (if required)
// ONLY use cultures that have been tested and known to work
}
return netLanguage;
}
}
}
NOTE
Os blocos try/catch no método GetCurrentCultureInfo imitam o comportamento de fallback usado normalmente com
especificadores de localidade – se a correspondência exata não for encontrada, procure uma correspondência aproximada
com base apenas no idioma (primeiro bloco de caracteres na localidade).
No caso do Xamarin.Forms, algumas localidades são válidas no Android, mas não correspondem a um CultureInfo válido
no .NET e o código acima tenta lidar com isso.
Os desenvolvedores devem modificar os métodos iOSToDotnetLanguage e ToDotnetFallbackLanguage para lidar com
casos específicos necessários em seus idiomas com suporte.
Após esse código ter sido adicionado ao projeto de aplicativo do Android, ele será capaz de exibir
automaticamente as cadeias de caracteres traduzidas.
NOTE
AVISO: Se as cadeias de caracteres traduzidas estiverem funcionando em seus builds de VERSÃO do Android, mas não
durante a depuração, clique com o botão direito do mouse em Projeto do Android e selecione Opções > Build > Build
do Android e certifique-se de que Implantação de Assembly Rápida NÃO esteja marcado. Essa opção causa problemas
ao carregar recursos e não deverá ser usada se você estiver testando aplicativos localizados.
Para obter mais informações sobre a localização no Android, confira Localização no Android.
Plataforma Universal do Windows
Projetos da UWP (Plataforma Universal do Windows) não requerem o serviço de dependência. Em vez disso, a
plataforma define automaticamente a cultura do recurso corretamente.
A sse m b l y I n fo .c s
Expanda o nó Propriedades no projeto da biblioteca .NET Standard e clique duas vezes no arquivo
AssemblyInfo.cs. Adicione a seguinte linha ao arquivo para definir o idioma do assembly de recursos neutro
como inglês:
[assembly: NeutralResourcesLanguage("en")]
Isso informa ao gerenciador de recursos a cultura padrão do aplicativo, garantindo assim que as cadeias de
caracteres definidas no arquivo RESX de idioma neutro (AppResources.resx) sejam exibidas quando o aplicativo
estiver em execução em uma das localidades de idioma inglês.
Exemplo
Depois de atualizar projetos específicos da plataforma conforme mostrado acima e recompilar o aplicativo com
arquivos RESX traduzidos, traduções atualizadas serão disponibilizadas em cada aplicativo. Está é uma captura de
tela do código de exemplo traduzido para chinês simplificado:
Para obter mais informações sobre a localização na UWP, confira Localização na UWP.
Localizando XAML
Ao compilar uma interface do usuário do Xamarin.Forms em XAML, a marcação teria uma aparência semelhante a
esta, com cadeias de caracteres inseridas diretamente no XML:
Idealmente, poderíamos traduzir os controles da interface do usuário diretamente no XAML, o que pode ser feito
criando uma extensão de marcação. O código de uma extensão de marcação que expõe os recursos RESX para
XAML é mostrado abaixo. Essa classe deve ser adicionada ao código comum do Xamarin.Forms (juntamente com
as páginas XAML ):
using System;
using System.Globalization;
using System.Reflection;
using System.Resources;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace UsingResxLocalization
{
// You exclude the 'Extension' suffix when using in XAML
[ContentProperty("Text")]
public class TranslateExtension : IMarkupExtension
{
readonly CultureInfo ci = null;
const string ResourceId = "UsingResxLocalization.Resx.AppResources";
public TranslateExtension()
{
if (Device.RuntimePlatform == Device.iOS || Device.RuntimePlatform == Device.Android)
{
ci = DependencyService.Get<ILocalize>().GetCurrentCultureInfo();
}
}
O snippet de XAML a seguir mostra como usar a extensão de marcação. Há duas etapas para fazê-la funcionar:
1. Declarar o namespace xmlns:i18n personalizado no nó raiz. namespace e assembly devem corresponder
exatamente às configurações do projeto – neste exemplo, são idênticos, mas podem ser diferentes em seu
projeto.
2. Use a sintaxe {Binding} em atributos que normalmente conteriam texto para chamar a extensão de marcação
Translate . A chave de recurso é o único parâmetro necessário.
<Image>
<Image.Source>
<OnPlatform x:TypeArguments="ImageSource">
<On Platform="iOS, Android" Value="flag.png" />
<On Platform="UWP" Value="Assets/Images/flag.png" />
</OnPlatform>
</Image.Source>
</Image>
Todas as plataformas resolverão automaticamente referências de imagem como essa para versões localizadas das
imagens, desde que as estruturas de projeto explicadas abaixo sejam implementadas.
Projeto de Aplicativo iOS
O iOS usa um padrão de nomenclatura chamado Localization Projects ou diretórios .lproj para conter os recursos
de imagem e cadeia de caracteres. Esses diretórios podem conter versões localizadas de imagens usadas no
aplicativo e também o arquivo InfoPlist.strings, que pode ser usado para localizar o nome do aplicativo. Para
obter mais informações sobre a localização no iOS, confira Localização no iOS.
Imagens
Esta captura de tela mostra o aplicativo de exemplo do iOS com os diretórios .lproj específicos a um idioma. O
diretório do idioma espanhol, chamado es.lproj, contém as versões localizadas da imagem padrão, bem como
flag.png:
Cada diretório de idioma contém uma cópia de flag.png, localizada para esse idioma. Se nenhuma imagem for
fornecida, o sistema operacional, por padrão, usará a imagem no diretório de idioma padrão. Para ter suporte
completo do Retina, você precisa fornecer cópias de @2x e @3x de cada imagem.
Nome do Aplicativo
O conteúdo de InfoPlist.strings é apenas um par de chave-valor para configurar o nome do aplicativo:
"CFBundleDisplayName" = "ResxEspañol";
Observe que o Android não usa os códigos zh-Hans e zh-Hant para chinês simplificado e chinês tradicional. Em
vez disso, ele dá suporte apenas aos códigos específicos do país zh-CN e zh-TW.
Para dar suporte a imagens com resolução diferente para telas de alta densidade, crie pastas adicionais com os
sufixos -*dpi , como drawables-es-mdpi, drawables-es-xdpi, drawables-es-xxdpi etc. Confira Fornecendo
recursos alternativos do Android para obter mais informações.
Nome do Aplicativo
O conteúdo de strings.xml é apenas um par de chave-valor para configurar o nome do aplicativo:
Agora, o aplicativo localiza o nome do aplicativo e a imagem. Veja uma captura de tela do resultado (em espanhol):
Em tempo de execução, a infraestrutura de recursos do Windows selecionará a imagem apropriada com base na
localidade do usuário.
Resumo
Aplicativos do Xamarin.Forms podem ser localizados usando arquivos RESX e classes de globalização do .NET.
Exceto por uma pequena quantidade de código específico da plataforma para detectar qual é o idioma preferido
pelo usuário, a maior parte do esforço de localização está centralizado no código comum.
Normalmente, as imagens são manipuladas de forma específica à plataforma para tirar proveito do suporte de
resolução múltipla fornecido no iOS e no Android.
Links relacionados
Exemplo de localização de RESX
Aplicativo de exemplo TodoLocalized
Localização multiplataforma
Localização no iOS
Localização no Android
Localização na UWP
Usando a classe CultureInfo (MSDN )
Localizando e usando recursos para uma cultura específica (MSDN )
Localização da direita para a esquerda
12/04/2019 • 9 minutes to read • Edit Online
Baixar o exemplo
A localização da direita para a esquerda adiciona suporte para a direção do fluxo da direita para a esquerda aos
aplicativos Xamarin.Forms.
NOTE
A localização da direita para a esquerda exige o uso do iOS 9 ou superior e da API 17 ou superior no Android.
A direção do fluxo é a direção na qual os elementos de interface do usuário na página são detectados pelos olhos.
Alguns idiomas, como árabe e hebraico, exigem que os elementos de interface do usuário sejam dispostos em
uma direção de fluxo da direita para a esquerda. Isso pode ser feito com a definição da propriedade
VisualElement.FlowDirection . Essa propriedade obtém ou define a direção na qual os elementos de interface do
usuário fluem nos elementos pai que controlam seu layout e deve ser definida com um dos valores de
enumeração FlowDirection :
LeftToRight
RightToLeft
MatchParent
TIP
Você só deve definir a propriedade FlowDirection no layout inicial. A alteração desse valor em tempo de execução causa
um processo caro de layout que afetará o desempenho.
TIP
Ao localizar um aplicativo para idiomas da direita para a esquerda, defina a propriedade FlowDirection em uma página ou
um layout raiz. Isso faz com que todos os elementos contidos na página ou layout raiz respondam de forma apropriada à
direção do fluxo.
this.FlowDirection = Device.FlowDirection;
Em seguida, todos os elementos filho da página ou o layout raiz, por padrão, herdarão o valor
Device.FlowDirection .
Instalação da plataforma
A instalação da plataforma específica é necessária para habilitar localidades com leitura da direita para a esquerda.
iOS
A localidade com leitura da direita para a esquerda necessária deve ser adicionada como um idioma compatível
aos itens de matriz da chave CFBundleLocalizations em Info.plist. O seguinte exemplo mostra o árabe
adicionado à matriz da chave CFBundleLocalizations :
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>ar</string>
</array>
Android
O arquivo AndroidManifest.xml do aplicativo deve ser atualizado para que o nó <uses-sdk> defina o atributo
android:minSdkVersion como 17 e o nó <application> defina o atributo android:supportsRtl como true :
A localização da direita para a esquerda pode então ser testada, alterando o dispositivo/emulador para usar o
idioma da direita para a esquerda ou habilitando a opção Forçar direção do layout da direita para esquerda
em Configurações > Opções do Desenvolvedor.
UWP (Plataforma Universal do Windows)
Os recursos de idioma necessários devem ser especificados no nó <Resources> do arquivo
Package.appxmanifest. O seguinte exemplo mostra o árabe adicionado ao nó <Resources> :
<Resources>
<Resource Language="x-generate"/>
<Resource Language="en" />
<Resource Language="ar" />
</Resources>
Além disso, o UWP exige que a cultura padrão do aplicativo seja explicitamente definida na biblioteca do .NET
Standard. Isso pode ser feito com a definição do atributo NeutralResourcesLanguage em AssemblyInfo.cs , ou em
outra classe, como a cultura padrão:
using System.Resources;
[assembly: NeutralResourcesLanguage("en")]
A localização da direita para a esquerda pode então ser testada, alterando o idioma e a região no dispositivo para
a localidade da direita para a esquerda apropriada.
Limitações
Atualmente, a localização da direita para a esquerda do Xamarin.Forms tem várias limitações:
A localização do botão NavigationPage , a localização do item da barra de ferramentas e a animação de
transição são controlados pela localidade do dispositivo, em vez de pela propriedade FlowDirection .
A direção de passar o dedo de CarouselPage não é invertida.
O conteúdo visual de Image não é invertido.
A orientação de DisplayAlert e DisplayActionSheet é controlada pela localidade do dispositivo, em vez de
pela propriedade FlowDirection .
O conteúdo de WebView não respeita a propriedade FlowDirection .
Uma propriedade TextDirection precisa ser adicionada, para controlar o alinhamento do texto.
iOS
A orientação de Stepper é controlada pela localidade do dispositivo, em vez de pela propriedade
FlowDirection .
O alinhamento do texto de EntryCell é controlado pela localidade do dispositivo, em vez de pela propriedade
FlowDirection .
Os gestos e o alinhamento de ContextActions não são revertidos.
Android
A orientação de SearchBar é controlada pela localidade do dispositivo, em vez de pela propriedade
FlowDirection .
O posicionamento de ContextActions é controlado pela localidade do dispositivo, em vez de pela propriedade
FlowDirection .
UWP
O alinhamento do texto de Editor é controlado pela localidade do dispositivo, em vez de pela propriedade
FlowDirection .
A propriedade de FlowDirection não é herdada pelos filhos de MasterDetailPage .
O alinhamento do texto de ContextActions é controlado pela localidade do dispositivo, em vez de pela
propriedade FlowDirection .
Links relacionados
Aplicativo de exemplo TodoLocalizedRTL
Bancos de dados locais do Xamarin.Forms
12/04/2019 • 4 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms dá suporte a aplicativos controlados por banco de dados usando o mecanismo de banco de
dados SQLite, que torna possível carregar e salvar objetos em código compartilhado. Este artigo descreve como
os aplicativos Xamarin.Forms podem ler e gravar dados em um banco de dados SQLite local usando o
SQLite.Net.
Visão geral
Os aplicativos Xamarin.Forms podem usar o pacote NuGet SQLite.NET PCL para incorporar operações de banco
de dados no código compartilhado referenciando as classes SQLite que acompanham o NuGet. As operações de
banco de dados podem ser definidas no projeto de biblioteca do .NET Standard da solução Xamarin.Forms.
O aplicativo de exemplo que acompanha é um aplicativo simples de lista de tarefas. As capturas de tela a seguir
mostram como o exemplo é exibido em cada plataforma:
Usando o SQLite
Para adicionar o suporte do SQLite em uma biblioteca do .NET Standard Xamarin.Forms, use a função de
pesquisa do NuGet para localizar sqlite-net-pcl e instalar o pacote mais recente:
Há inúmeros pacotes NuGet com nomes semelhantes. O pacote correto tem estes atributos:
Criado por: Frank A. Krueger
Id: sqlite-net-pcl
Link do NuGet: sqlite-net-pcl
NOTE
Apesar do nome do pacote, use o pacote NuGet sqlite-net-pcl, mesmo em projetos do .NET Standard.
Depois que a referência tiver sido adicionada, adicione uma propriedade à classe App que retorna um caminho
de arquivo local para armazenar o banco de dados:
O construtor TodoItemDatabase , que usa o caminho para o arquivo de banco de dados como um argumento, é
mostrado abaixo:
A vantagem de expor o banco de dados como um singleton é que uma conexão de banco de dados individual
criada é mantida aberta enquanto o aplicativo é executado, evitando, portanto, o trabalho de abrir e fechar o
arquivo de banco de dados cada vez que uma operação de banco de dados é realizada.
O restante da classe TodoItemDatabase contém consultas SQLite em execução multiplataforma. O código de
consulta de exemplo é mostrado abaixo (mais detalhes sobre a sintaxe podem ser encontrados em Usando
SQLite.NET com o Xamarin.iOS.
public Task<List<TodoItem>> GetItemsAsync()
{
return database.Table<TodoItem>().ToListAsync();
}
NOTE
A vantagem de usar a API do SQLite.Net assíncrona é que as operações de banco de dados são movidas para ameaças em
segundo plano. Além disso, não há nenhuma necessidade de escrever código de tratamento de simultaneidade adicional,
porque a API faz isso.
Resumo
O Xamarin.Forms dá suporte a aplicativos controlados por banco de dados usando o mecanismo de banco de
dados SQLite, que torna possível carregar e salvar objetos em código compartilhado.
O foco deste artigo foi o acesso a um banco de dados SQLite que usa o Xamarin.Forms. Para saber mais sobre
trabalhar com o próprio SQLite, confira a documentação SQLite.NET no Android ou SQLite.NET no iOS.
Links relacionados
Exemplo de tarefas pendentes
Amostras do Xamarin.Forms
Xamarin.Forms MessagingCenter
18/04/2019 • 5 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms inclui um serviço de mensagens simples para enviar e receber mensagens.
Visão geral
O MessagingCenter do Xamarin.Forms habilita a exibição de modelos e outros componentes para se comunicar
sem que eles precisem saber nada uns sobre os outros, além de um contrato de mensagem simples.
Usar o MessagingCenter
As mensagens podem ser enviadas como resultado da interação do usuário (como um clique de botão), um
evento do sistema (como controles alterando um estado) ou alguns outros incidentes (como um download
assíncrono sendo concluído). Os assinantes podem estar escutando para alterar a aparência da interface do
usuário, salvar os dados ou disparar alguma outra operação.
Para obter mais informações sobre como usar a classe MessagingCenter , confira Comunicação entre componentes
fracamente acoplados.
Mensagem de cadeia de caracteres simples
A mensagem mais simples contém apenas uma cadeia de caracteres no parâmetro message . Um método
Subscribe que escuta uma mensagem de cadeia de caracteres simples é mostrado abaixo. Observe o tipo
genérico especificando que o remetente deve ser do tipo MainPage . As classes na solução podem assinar a
mensagem usando esta sintaxe:
Na classe MainPage , o código a seguir envia a mensagem. O parâmetro this é uma instância de MainPage .
A cadeia de caracteres não é alterada. Ela indica o tipo de mensagem e é usada para determinar quais assinantes
notificar. Esse tipo de mensagem é usado para indicar que algum evento ocorreu, como "upload concluído", em
que nenhuma informação adicional é necessária.
Passar um argumento
Para passar um argumento com a mensagem, especifique o tipo de argumento nos argumentos genéricos
Subscribe e na assinatura Ação.
Para enviar a mensagem com o argumento, inclua o parâmetro Tipo genérico e o valor do argumento na chamada
de método Send .
Este exemplo simples usa um argumento string , mas qualquer objeto C# pode ser passado.
Cancelar assinatura
Um objeto pode cancelar uma assinatura de uma mensagem para que nenhuma mensagem futura seja entregue.
A sintaxe do método Unsubscribe deve refletir a assinatura da mensagem (portanto, talvez seja necessário incluir
o parâmetro Tipo genérico para o argumento de mensagem).
Resumo
O MessagingCenter é uma maneira simples de reduzir o acoplamento, especialmente entre modelos de exibição.
Ele pode ser usado para enviar e receber mensagens simples ou passar um argumento entre classes. As classes
devem cancelar a assinatura de mensagens que não desejam receber.
Links relacionados
MessagingCenterSample
Amostras do Xamarin.Forms
Comunicação entre componentes flexíveis
Navegação do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
O Xamarin.Forms oferece uma série de experiências de navegação de página diferentes, dependendo do tipo de
página sendo usado.
Navegação hierárquica
A classe NavigationPage oferece uma experiência de Navegação hierárquica em que o usuário é capaz de navegar
pelas páginas para frente e para trás, conforme desejado. A classe implementa navegação como uma pilha UEPS
(último a entrar, primeiro a sair) de objetos Page .
TabbedPage
O TabbedPage do Xamarin.Forms consiste em uma lista de guias e uma área de detalhes maior, com cada guia
carregando conteúdo na área de detalhes.
CarouselPage
O CarouselPage do Xamarin.Forms é uma página em que os usuários podem passar o dedo de um lado ao outro
para navegar por páginas de conteúdo, assim como uma galeria.
MasterDetailPage
O MasterDetailPage do Xamarin.Forms é uma página que gerencia duas páginas de informações relacionadas –
uma página mestra que apresenta itens e uma página de detalhes que apresenta detalhes sobre os itens na página
mestra.
Páginas modais
O Xamarin.Forms também dá suporte a páginas modais. Uma página modal incentiva os usuários a concluir uma
tarefa independente da qual não se pode sair via navegação até que essa tarefa seja concluída ou cancelada.
Exibição de pop-ups
O Xamarin.Forms fornece dois elementos de interface do usuário semelhantes a pop-up: um alerta e uma folha de
ações. Esses elementos de interface podem ser usados para fazer perguntas simples a usuários e para orientar os
usuários por meio de tarefas.
Navegação hierárquica
12/04/2019 • 20 minutes to read • Edit Online
Baixar o exemplo
A classe NavigationPage oferece uma experiência de navegação hierárquica em que o usuário pode navegar
pelas páginas para frente e para trás, conforme desejado. A classe implementa a navegação como uma pilha
UEPS (último a entrar, primeiro a sair ) de objetos de Página. Este artigo demonstra como usar a classe
NavigationPage para executar a navegação em uma pilha de páginas.
Para ir de uma página para outra, um aplicativo enviará por push uma nova página para a pilha de navegação, na
qual ela se tornará a página ativa, conforme mostrado no diagrama a seguir:
Para retornar à página anterior, o aplicativo removerá a página atual da pilha de navegação e, em seguida, a nova
página de nível superior se tornará a página ativa, conforme mostrado no diagrama a seguir:
Os métodos de navegação são expostos pela propriedade Navigation em qualquer tipo derivado de Page . Esses
métodos possibilitam enviar páginas por push para a pilha de navegação, remover páginas da pilha de navegação
e executar a manipulação da pilha.
Executando a navegação
Na barra de navegação hierárquica, a classe NavigationPage é usada para navegar por meio de uma pilha de
objetos ContentPage . As capturas de tela a seguir mostram os principais componentes de NavigationPage em
cada plataforma:
NOTE
É recomendável que um NavigationPage seja preenchido somente com instâncias de ContentPage .
public App ()
{
MainPage = new NavigationPage (new Page1Xaml ());
}
Isso faz com que a instância ContentPage de Page1Xaml seja enviada por push para a pilha de navegação, em que
se torna a página ativa e a página raiz do aplicativo. Isso é mostrado nas capturas de tela a seguir:
NOTE
A propriedade RootPage de uma instância de NavigationPage fornece acesso à primeira página na pilha de navegação.
NOTE
Chamadas para as substituições OnDisappearing e OnAppearing não podem ser tratadas como indicações garantidas de
navegação de página. Por exemplo, no iOS, a substituição OnDisappearing é chamada na página ativa quando o aplicativo
é encerrado.
Isso faz com que a instância Page2Xaml seja removida da pilha de navegação, com a nova página de nível superior
tornando-se a página ativa. Quando o método PopAsync é invocado, os seguintes eventos ocorrem:
A página que chama PopAsync tem sua substituição OnDisappearing invocada.
A página para a qual o usuário está voltando tem sua substituição OnAppearing invocada.
A tarefa PopAsync é retornada.
No entanto, a ordem exata em que esses eventos ocorrem depende da plataforma. Para obter mais informações,
confira o Capítulo 24 do livro de Charles Petzold sobre Xamarin.Forms.
Assim como os métodos PushAsync e PopAsync , a propriedade Navigation de cada página também fornece um
método PopToRootAsync , que é mostrado no exemplo de código a seguir:
Esse método retira todas a páginas, exceto pela Page raiz, da pilha de navegação, tornando assim a página raiz do
aplicativo a página ativa.
Animando transições de página
A propriedade Navigation de cada página também fornece métodos de envio por push e remoção substituídos
que incluem um parâmetro boolean que controla se deve ser exibida uma animação de página durante a
navegação, conforme mostrado no código de exemplo a seguir:
Definir o parâmetro boolean como false desabilita a animação de transição de página, enquanto definir o
parâmetro como true habilita a animação de transição de página, desde que ela tenha suporte da plataforma
subjacente. No entanto, os métodos de envio por push e remoção que não têm esse parâmetro habilitam a
animação por padrão.
public App ()
{
MainPage = new NavigationPage (new MainPage (DateTime.Now.ToString ("u")));
}
Esse código cria uma instância de MainPage , transmitindo a data e a hora atuais no formato ISO8601, que é
encapsulada em uma instância de NavigationPage .
A instância de MainPage recebe os dados por meio de um parâmetro de construtor, conforme mostrado no
exemplo de código a seguir:
Os dados são exibidos na página definindo a propriedade Label.Text , conforme mostrado nas capturas de tela
seguir:
Esse código define o BindingContext da instância de SecondPage como a instância de Contact e, em seguida,
navega para o SecondPage .
O SecondPage , em seguida, usa a associação de dados para exibir os dados da instância de Contact , conforme
mostrado no exemplo de código XAML a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PassingData.SecondPage"
Title="Second Page">
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<StackLayout Orientation="Horizontal">
<Label Text="Name:" HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
</StackLayout>
...
<Button x:Name="navigateButton" Text="Previous Page" Clicked="OnNavigateButtonClicked" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O exemplo de código a seguir mostra como a associação de dados pode ser feita em C#:
Em seguida, os dados são exibidos na página por uma série de controles de Label , conforme mostrado nas
capturas de tela seguir:
Para obter mais informações sobre vinculação de dados, veja Noções básicas de vinculação de dados.
O método RemovePage remove a página especificada da pilha de navegação, conforme mostrado no diagrama a
seguir:
Esses métodos permitem criar uma experiência de navegação personalizada, como substituir uma página de
logon por uma nova página após um logon bem-sucedido. O código de exemplo a seguir demonstra esse cenário:
Desde que as credenciais do usuário estejam corretas, a instância MainPage será inserida na pilha de navegação
antes da página atual. Em seguida, o método PopAsync remove a página atual da pilha de navegação, com a
instância de MainPage se tornando a página ativa.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NavigationPageTitleView.TitleViewPage">
<NavigationPage.TitleView>
<Slider HeightRequest="44" WidthRequest="300" />
</NavigationPage.TitleView>
...
</ContentPage>
Isso faz com que um Slider seja exibido na barra de navegação na NavigationPage :
IMPORTANT
Muitos modos de exibição não aparecerão na barra de navegação a menos que o tamanho do modo de exibição seja
especificado com as propriedades WidthRequest e HeightRequest . Como alternativa, o modo de exibição pode ser
encapsulado em um StackLayout com as propriedades HorizontalOptions e VerticalOptions definidas como os
valores apropriados.
Observe que, como a classe Layout é derivada da classe View , a propriedade anexada TitleView pode ser
definida para exibir uma classe de layout que contém vários modos de exibição. No iOS e na UWP (Plataforma
Universal do Windows), não é possível alterar a altura da barra de navegação e, portanto, será feito um recorte se
o modo de exibição na barra de navegação for maior que o tamanho padrão da barra de navegação. No entanto,
no Android, a altura da barra de navegação pode ser alterada definindo a propriedade vinculável
NavigationPage.BarHeight como um double que representa a nova altura. Para obter mais informações, confira
Definindo a altura da barra de navegação em uma NavigationPage.
Como alternativa, é possível sugerir uma barra de navegação estendida colocando parte do conteúdo na barra de
navegação e parte em um modo de exibição na parte superior do conteúdo da página, cuja cor deve corresponder
à da barra de navegação. Além disso, no iOS, a linha separadora e sombra na parte inferior da barra de
navegação podem ser removidas definindo a propriedade associável NavigationPage.HideNavigationBarSeparator
como true . Para obter mais informações, confira Ocultando o separador da barra de navegação em uma
NavigationPage.
NOTE
As propriedades BackButtonTitle , Title , TitleIcon e TitleView podem definir valores que ocupam espaço na
barra de navegação. Embora o tamanho da barra de navegação varie de acordo com o tamanho da tela e a plataforma,
definir todas essas propriedades causará conflitos devido à limitação do espaço disponível. Em vez de tentar usar uma
combinação dessas propriedades, você provavelmente concluirá que é mais fácil obter o design desejado da barra de
navegação definindo apenas a propriedade TitleView .
Limitações
É necessário estar ciente de uma série de limitações ao exibir um View na barra de navegação de uma
NavigationPage :
Links relacionados
Navegação da página
Hierárquica (amostra)
PassingData (amostra)
LoginFlow (amostra)
TitleView (amostra)
Exemplo de como criar um fluxo de tela de entrada no Xamarin.Forms (vídeo do Xamarin University)
Como criar um fluxo de tela de entrada no Xamarin.Forms (vídeo do Xamarin University)
NavigationPage
Página com guias do Xamarin.Forms
12/04/2019 • 10 minutes to read • Edit Online
Baixar o exemplo
A TabbedPage do Xamarin.Forms consiste em uma lista de guias e uma área do detalhe maior, com cada guia
carregando conteúdo na área do detalhe. Este artigo demonstra como usar uma TabbedPage para navegar por
uma coleção de páginas.
Visão geral
As seguintes capturas de tela mostram uma TabbedPage em cada plataforma:
NOTE
Observe que o TabbedRenderer para iOS tem um método GetIcon substituível que pode ser usado para carregar
ícones de guia de uma origem especificada. Essa substituição possibilita o uso de imagens SVG como ícones em uma
TabbedPage . Além disso, versões selecionadas e não selecionadas de um ícone podem ser fornecidas.
No Android, a lista de guias é exibida na parte superior da tela por padrão e a área do detalhe fica abaixo
dela. No entanto, a lista de guias pode ser movida para a parte inferior da tela com um código específico da
plataforma. Para obter mais informações, confira Definindo o posicionamento e a cor da barra de
ferramentas da TabbedPage.
NOTE
Observe que, ao usar AppCompat no Android, cada guia também exibirá um ícone. Além disso, o
TabbedPageRenderer para Android AppCompat tem um método GetIconDrawable substituível que pode ser
usado para carregar ícones de guia de um Drawable personalizado. Essa substituição possibilita o uso de imagens
SVG como ícones em uma TabbedPage e funciona com barras de guia superior e inferior. Como alternativa, o
método SetTabIcon substituível pode ser usado para carregar ícones de guia de um Drawable personalizado
para barras de guia superior.
Em fatores forma de tablets Windows, as guias não ficam sempre visíveis e os usuários precisam passar o
dedo para baixo (ou clicar com o botão direito do mouse, caso tenham um mouse anexado) para exibir as
guias em uma TabbedPage (conforme mostrado abaixo).
NOTE
É recomendável popular uma TabbedPage somente com as instâncias NavigationPage e ContentPage . Isso ajudará a
garantir uma experiência do usuário consistente em todas as plataformas.
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TabbedPageWithNavigationPage;assembly=TabbedPageWithNavigationPage"
x:Class="TabbedPageWithNavigationPage.MainPage">
<local:TodayPage />
<NavigationPage Title="Schedule" Icon="schedule.png">
<x:Arguments>
<local:SchedulePage />
</x:Arguments>
</NavigationPage>
</TabbedPage>
A TabbedPage é populada com dois objetos Page filho. O primeiro filho é uma instância ContentPage e a segunda
guia é uma NavigationPage que contém uma instância ContentPage .
NOTE
A TabbedPage não dá suporte à virtualização de interface do usuário. Portanto, o desempenho poderá ser afetado se a
TabbedPage contiver muitos elementos filho.
As seguintes capturas de tela mostram a instância TodayPage ContentPage , que é mostrada na guia Hoje:
A seleção da guia Agendamento exibe a instância SchedulePage ContentPage , que é encapsulada em uma
instância NavigationPage , e é mostrada na seguinte captura de tela:
Para obter informações sobre o layout de uma NavigationPage , confira Executando a navegação.
NOTE
Embora seja aceitável colocar uma NavigationPage em uma TabbedPage , não é recomendável colocar uma TabbedPage
em uma NavigationPage . Isso ocorre porque, no iOS, um UITabBarController sempre funciona como um wrapper para
o UINavigationController . Para obter mais informações, confira Interfaces combinadas do controlador de exibição na
Biblioteca do Desenvolvedor do iOS.
Isso faz com que a instância UpcomingAppointmentsPage seja enviada por push para a pilha de navegação, em que
ele se torna a página ativa. Isso é mostrado nas seguintes capturas de tela:
Para obter mais informações sobre como executar a navegação usando a classe NavigationPage , confira
Navegação hierárquica.
Populando uma TabbedPage com um modelo
O exemplo de código XAML a seguir mostra uma TabbedPage construída pela atribuição de um DataTemplate à
propriedade ItemTemplate para retornar páginas para objetos na coleção:
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TabbedPageDemo;assembly=TabbedPageDemo"
x:Class="TabbedPageDemo.TabbedPageDemoPage">
<TabbedPage.Resources>
<ResourceDictionary>
<local:NonNullToBooleanConverter x:Key="booleanConverter" />
</ResourceDictionary>
</TabbedPage.Resources>
<TabbedPage.ItemTemplate>
<DataTemplate>
<ContentPage Title="{Binding Name}" Icon="monkeyicon.png">
<StackLayout Padding="5, 25">
<Label Text="{Binding Name}" Font="Bold,Large" HorizontalOptions="Center" />
<Image Source="{Binding PhotoUrl}" WidthRequest="200" HeightRequest="200" />
<StackLayout Padding="50, 10">
<StackLayout Orientation="Horizontal">
<Label Text="Family:" HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Family}" Font="Bold,Medium" />
</StackLayout>
...
</StackLayout>
</StackLayout>
</ContentPage>
</DataTemplate>
</TabbedPage.ItemTemplate>
</TabbedPage>
A TabbedPage é populada com os dados, definindo a propriedade ItemsSource no construtor para o arquivo code-
behind:
public TabbedPageDemoPage ()
{
...
ItemsSource = MonkeyDataModel.All;
}
Cada guia exibe uma ContentPage que usa uma série de instâncias StackLayout e Label para exibir os dados
para a guia. As seguintes capturas de tela mostram o conteúdo da guia Tamarin:
A seleção de outra guia exibe o conteúdo dessa guia.
NOTE
A TabbedPage não dá suporte à virtualização de interface do usuário. Portanto, o desempenho poderá ser afetado se a
TabbedPage contiver muitos elementos filho.
Para obter mais informações sobre a TabbedPage , confira o Capítulo 25 do livro sobre o Xamarin.Forms de
Charles Petzold.
Resumo
Este artigo demonstrou como usar uma TabbedPage para navegar por uma coleção de páginas. A TabbedPage do
Xamarin.Forms consiste em uma lista de guias e uma área do detalhe maior, com cada guia carregando conteúdo
na área do detalhe.
Links relacionados
Variedades de página
TabbedPageWithNavigationPage (amostra)
TabbedPage (amostra)
TabbedPage
Página de carrossel do Xamarin.Forms
12/04/2019 • 7 minutes to read • Edit Online
Baixar o exemplo
A CarouselPage do Xamarin.Forms é uma página em que os usuários podem passar o dedo de um lado ao outro
para navegar por páginas de conteúdo, como uma galeria. Este artigo demonstra como usar uma CarouselPage
para navegar por uma coleção de páginas.
Visão geral
As seguintes capturas de tela mostram uma CarouselPage em cada plataforma:
O layout de uma CarouselPage é idêntico em todas as plataformas. As páginas podem ser navegadas passando o
dedo da direita para a esquerda para navegar para frente na coleção e passando o dedo da esquerda para a direita
para navegar para trás. As capturas de tela a seguir mostram a primeira página em uma instância de uma
CarouselPage :
Passar o dedo da direita para a esquerda leva para a segunda página, conforme mostrado nas capturas de tela
seguir:
Passar o dedo da direita para a esquerda novamente leva para a terceira página, enquanto passar o dedo da
esquerda para a direita retorna à página anterior.
Com as duas abordagens, a CarouselPage exibirá uma página por vez, com uma interação de passar o dedo
levando para a próxima página a ser exibida.
NOTE
Uma CarouselPage pode ser populada apenas com instâncias de ContentPage ou derivados de ContentPage .
Children.Add (redContentPage);
Children.Add (greenContentPage);
Children.Add (blueContentPage);
}
}
Cada ContentPage simplesmente exibe um Label para uma cor específica e um BoxView dessa cor.
NOTE
A CarouselPage não dá suporte à virtualização de interface do usuário. Portanto, o desempenho poderá ser afetado se a
CarouselPage contiver muitos elementos filho.
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="CarouselPageNavigation.MainPage">
<CarouselPage.ItemTemplate>
<DataTemplate>
<ContentPage>
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS, Android" Value="0,40,0,0" />
</OnPlatform>
</ContentPage.Padding>
<StackLayout>
<Label Text="{Binding Name}" FontSize="Medium" HorizontalOptions="Center" />
<BoxView Color="{Binding Color}" WidthRequest="200" HeightRequest="200"
HorizontalOptions="Center" VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
</DataTemplate>
</CarouselPage.ItemTemplate>
</CarouselPage>
A CarouselPage é populada com os dados, definindo a propriedade ItemsSource no construtor para o arquivo
code-behind:
public MainPage ()
{
...
ItemsSource = ColorsDataModel.All;
}
ItemsSource = ColorsDataModel.All;
}
}
Cada ContentPage simplesmente exibe um Label para uma cor específica e um BoxView dessa cor.
NOTE
A CarouselPage não dá suporte à virtualização de interface do usuário. Portanto, o desempenho poderá ser afetado se a
CarouselPage contiver muitos elementos filho.
Resumo
Este artigo demonstrou como usar uma CarouselPage para navegar por uma coleção de páginas. A CarouselPage
é uma página em que os usuários podem passar o dedo de um lado ao outro para navegar por páginas de
conteúdo, assim como uma galeria.
Links relacionados
Variedades de página
CarouselPage (amostra)
CarouselPageTemplate (amostra)
CarouselPage
Página Mestre/Detalhes do Xamarin.Forms
12/04/2019 • 15 minutes to read • Edit Online
Baixar o exemplo
A MasterDetailPage do Xamarin.Forms é uma página que gerencia duas páginas relacionadas de informações –
uma página mestra que apresenta itens e uma página de detalhes que apresenta detalhes sobre os itens na
página mestra. Este artigo explica como usar uma MasterDetailPage e navegar entre suas páginas de
informações.
Visão geral
Uma página mestra normalmente exibe uma lista de itens, conforme mostrado nas capturas de tela seguir:
A localização da lista de itens é idêntico em cada plataforma e selecionar um dos itens navegará até a página de
detalhes correspondente. Além disso, a página mestra também apresenta uma barra de navegação que contém
um botão que pode ser usado para navegar até a página de detalhes ativa:
No iOS, a barra de navegação está presente na parte superior da página e tem um botão que navega até a
página de detalhes. Além disso, é possível navegar até a página de detalhes ativa passando o dedo na página
mestra para a esquerda.
No Android, a barra de navegação está presente na parte superior da página e exibe um título, um ícone e um
botão que navega até a página de detalhes. O ícone é definido no atributo [Activity] que decora a classe
MainActivity no projeto específico da plataforma Android. Além disso, é possível navegar até a página de
detalhes ativa passando o dedo na página mestra para a esquerda, tocando a página de detalhes na
extremidade direita da tela e tocando no botão Voltar na parte inferior da tela.
Na UWP (Plataforma Universal do Windows), a barra de navegação está presente na parte superior da página
e tem um botão que navega até a página de detalhes.
Uma página de detalhes exibe dados correspondentes ao item selecionado na página mestra e os principais
componentes da página de detalhes são mostrados nas capturas de tela a seguir:
A página de detalhes contém uma barra de navegação, cujo conteúdo dependem da plataforma:
No iOS, a barra de navegação está presente na parte superior da página, exibe um título e tem um botão que
retorna para a página mestra, contanto que a instância da página de detalhes seja encapsulada na instância
NavigationPage . Além disso, é possível retornar à página mestra passando o dedo na página de detalhes para a
direita.
No Android, uma barra de navegação está presente na parte superior da página e exibe um título, um ícone e
um botão que retorna à página mestra. O ícone é definido no atributo [Activity] que decora a classe
MainActivity no projeto específico da plataforma Android.
Na UWP, uma barra de navegação está presente na parte superior da página e exibe um título e tem botão que
retorna à página mestra.
Comportamento de navegação
O comportamento da experiência de navegação entre páginas mestras e de detalhes depende da plataforma:
No iOS, a página de detalhes desliza para a direita enquanto a página mestra desliza para a esquerda e a parte
esquerda da página de detalhes ainda está visível.
No Android, as páginas mestras e de detalhes são sobrepostas umas às outras.
Na UWP, a página mestra desliza da esquerda para parte da página de detalhes, desde que a propriedade
MasterBehavior esteja definida como Popover . Para obter mais informações, confira Controlando o
comportamento de exibição da página de detalhes.
Um comportamento semelhante será observado no modo paisagem, exceto que a página mestra no iOS e no
Android tem uma largura semelhante à da página mestra no modo retrato; portanto, mais coisas da página de
detalhes ficarão visíveis.
Para saber como controlar o comportamento de navegação, confira Controlling the Detail Page Display Behavior
(Controlando o comportamento de exibição da página de detalhes).
Criando um MasterDetailPage
Um MasterDetailPage contém as propriedades Master e Detail que são do tipo Page , usadas para obter e
definir as páginas mestras e de detalhes, respectivamente.
IMPORTANT
Um MasterDetailPage foi criado para ser uma página raiz e usá-la como uma página filho em outros tipos de página pode
resultar em comportamento inesperado e inconsistente. Além disso, é recomendável que a página mestra de um
MasterDetailPage sempre deva ser uma instância ContentPage , e que a página de detalhes só deva ser populada com as
instâncias TabbedPage , NavigationPage e ContentPage . Isso ajudará a garantir uma experiência do usuário consistente
em todas as plataformas.
O exemplo de código XAML a seguir mostra um MasterDetailPage que define as propriedades Master e Detail :
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MasterDetailPageNavigation;assembly=MasterDetailPageNavigation"
x:Class="MasterDetailPageNavigation.MainPage">
<MasterDetailPage.Master>
<local:MasterPage x:Name="masterPage" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage>
<x:Arguments>
<local:ContactsPage />
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
public MainPageCS ()
{
masterPage = new MasterPageCS ();
Master = masterPage;
Detail = new NavigationPage (new ContactsPageCS ());
...
}
...
}
A página consiste em uma ListView populada com os dados em XAML definindo sua propriedade ItemsSource
como uma matriz de instâncias MasterPageItem . Cada MasterPageItem define propriedades Title , IconSource e
TargetType .
NOTE
A página MasterDetailPage.Master deve ter a propriedade Title definida ou ocorrerá uma exceção.
ListView listView;
public MasterPageCS ()
{
var masterPageItems = new List<MasterPageItem> ();
masterPageItems.Add (new MasterPageItem {
Title = "Contacts",
IconSource = "contacts.png",
TargetType = typeof(ContactsPageCS)
});
masterPageItems.Add (new MasterPageItem {
Title = "TodoList",
IconSource = "todo.png",
TargetType = typeof(TodoListPageCS)
});
masterPageItems.Add (new MasterPageItem {
Title = "Reminders",
IconSource = "reminders.png",
TargetType = typeof(ReminderPageCS)
});
grid.Children.Add(image);
grid.Children.Add(label, 1, 0);
Icon = "hamburger.png";
Title = "Personal Organiser";
Content = new StackLayout
{
Children = { listView }
};
}
}
As capturas de tela a seguir mostram a página de detalhes ContactPage , mostrada depois que ela for selecionada
na página mestra:
public MainPageCS ()
{
MasterBehavior = MasterBehavior.Popover;
...
}
}
Contudo, o valor da propriedade MasterBehavior afeta apenas aplicativos em execução em tablets ou na área de
trabalho. Aplicativos em execução nos telefones sempre têm o comportamento Popover.
Resumo
Este artigo demonstrou como usar uma MasterDetailPage e navegar entre suas páginas de informações. O
MasterDetailPage do Xamarin.Forms é uma página que gerencia duas páginas de informações relacionadas – uma
página mestra que apresenta itens e uma página de detalhes que apresenta detalhes sobre os itens na página
mestra.
Links relacionados
Variedades de página
MasterDetailPage (exemplo)
MasterDetailPage
Páginas modais do Xamarin.Forms
12/04/2019 • 12 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms dá suporte a páginas modais. Uma página modal incentiva os usuários a concluir uma tarefa
independente da qual não se pode sair via navegação até que essa tarefa seja concluída ou cancelada. Este artigo
demonstra como navegar até as páginas modais.
Este artigo aborda os seguintes tópicos:
Executar a navegação – enviar páginas por push para a pilha modal, remover páginas da pilha modal,
desabilitar o botão Voltar e animar transições de página.
Passar dados ao navegar – passar dados por meio de um construtor de página e de um BindingContext .
Visão geral
Uma página restrita pode ser qualquer um dos tipos de Página para os quais o Xamarin.Forms dá suporte. Para
exibir uma página modal, o aplicativo a enviará por push para a pilha modal, na qual ela se tornará a página ativa,
conforme mostrado no diagrama a seguir:
Para retornar à página anterior, o aplicativo removerá a página atual da pilha modal e, em seguida, a nova página
de nível superior se tornará a página ativa, conforme mostrado no diagrama a seguir:
Executando a navegação
Os métodos de navegação modal são expostos pela propriedade Navigation em quaisquer tipos derivados de
Page . Esses métodos possibilitam enviar páginas modais por push para a pilha modal e remover páginas modais
da pilha modal.
A propriedade Navigation também expõe uma propriedade ModalStack da qual as páginas modais na pilha
modal podem ser obtidas. No entanto, não há nenhum conceito de realização de manipulação de pilha modal ou
remoção do item mais recente da pilha até a página raiz na navegação modal. Isso ocorre porque não há suporte
universal para essas operações pelas plataformas subjacentes.
NOTE
Uma instância de NavigationPage não é necessária para executar a navegação de página modal.
Isso faz com que a instância de ModalPage seja enviada por push para a pilha modal, na qual ela se torna a página
ativa, desde que um item tenha sido selecionado no ListView na instância de MainPage . A instância de ModalPage
é mostrada nas capturas de tela a seguir:
No entanto, a ordem exata em que esses eventos ocorrem depende da plataforma. Para obter mais informações,
confira o Capítulo 24 do livro de Charles Petzold sobre Xamarin.Forms.
NOTE
Chamadas para as substituições OnDisappearing e OnAppearing não podem ser tratadas como indicações garantidas de
navegação de página. Por exemplo, no iOS, a substituição OnDisappearing é chamada na página ativa quando o aplicativo
é encerrado.
Isso faz com que a instância ModalPage seja removida da pilha modal, com a nova página de nível superior
tornando-se a página ativa. Quando PopModalAsync é invocado, os seguintes eventos ocorrem:
A página que chama PopModalAsync tem sua substituição OnDisappearing invocada.
A página para a qual o usuário está voltando tem sua substituição de OnAppearing invocada, desde que a
plataforma subjacente não seja o Android.
A tarefa PopModalAsync é retornada.
No entanto, a ordem exata em que esses eventos ocorrem depende da plataforma. Para obter mais informações,
confira o Capítulo 24 do livro de Charles Petzold sobre Xamarin.Forms.
Desabilitando o botão Voltar
No Android, o usuário sempre pode retornar à página anterior pressionando o botão Voltar padrão no dispositivo.
Se a página modal exigir que o usuário conclua uma tarefa independente antes de sair da página, o aplicativo
deverá desabilitar o botão Voltar. Isso pode ser feito substituindo o método Page.OnBackButtonPressed na página
modal. Para obter mais informações, confira o Capítulo 24 do livro de Charles Petzold sobre Xamarin.Forms.
Animando transições de página
A propriedade Navigation de cada página também fornece métodos de envio por push e remoção substituídos
que incluem um parâmetro boolean que controla se deve ser exibida uma animação de página durante a
navegação, conforme mostrado no código de exemplo a seguir:
Definir o parâmetro boolean como false desabilita a animação de transição de página, enquanto definir o
parâmetro como true habilita a animação de transição de página, desde que ela tenha suporte da plataforma
subjacente. No entanto, os métodos de envio por push e remoção que não têm esse parâmetro habilitam a
animação por padrão.
Esse código cria uma instância de MainPage , transmitindo a data e a hora atuais no formato ISO8601.
A instância de MainPage recebe os dados por meio de um parâmetro de construtor, conforme mostrado no
exemplo de código a seguir:
Esse código define o BindingContext da instância de DetailPage como a instância de Contact e, em seguida,
navega para o DetailPage .
O DetailPage , em seguida, usa a associação de dados para exibir os dados da instância de Contact , conforme
mostrado no exemplo de código XAML a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ModalNavigation.DetailPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0,40,0,0" />
</OnPlatform>
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<StackLayout Orientation="Horizontal">
<Label Text="Name:" FontSize="Medium" HorizontalOptions="FillAndExpand" />
<Label Text="{Binding Name}" FontSize="Medium" FontAttributes="Bold" />
</StackLayout>
...
<Button x:Name="dismissButton" Text="Dismiss" Clicked="OnDismissButtonClicked" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O exemplo de código a seguir mostra como a associação de dados pode ser feita em C#:
public class DetailPageCS : ContentPage
{
public DetailPageCS ()
{
var nameLabel = new Label {
FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
FontAttributes = FontAttributes.Bold
};
nameLabel.SetBinding (Label.TextProperty, "Name");
...
var dismissButton = new Button { Text = "Dismiss" };
dismissButton.Clicked += OnDismissButtonClicked;
Thickness padding;
switch (Device.RuntimePlatform)
{
case Device.iOS:
padding = new Thickness(0, 40, 0, 0);
break;
default:
padding = new Thickness();
break;
}
Padding = padding;
Content = new StackLayout {
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.Center,
Children = {
new StackLayout {
Orientation = StackOrientation.Horizontal,
Children = {
new Label{ Text = "Name:", FontSize = Device.GetNamedSize (NamedSize.Medium, typeof(Label)),
HorizontalOptions = LayoutOptions.FillAndExpand },
nameLabel
}
},
...
dismissButton
}
};
}
Em seguida, os dados são exibidos na página por uma série de controles de Label .
Para obter mais informações sobre vinculação de dados, veja Noções básicas de vinculação de dados.
Resumo
Este artigo demonstrou como navegar até as páginas modais. Uma página modal incentiva os usuários a concluir
uma tarefa independente da qual não se pode sair via navegação até que essa tarefa seja concluída ou cancelada.
Links relacionados
Navegação da página
Modal (amostra)
PassingData (amostra)
Exibindo pop-ups
12/04/2019 • 4 minutes to read • Edit Online
Baixar o exemplo
O Xamarin.Forms fornece dois elementos de interface do usuário semelhantes a pop -up: um alerta e uma folha de
ações. Este artigo demonstra como usar as APIs de folha de alerta e de ação para fazer perguntas simples para os
usuários e orientá -los em suas tarefas.
Exibir um alerta ou pedir que um usuário faça uma escolha é uma tarefa comum da interface do usuário. O
Xamarin.Forms tem dois métodos na classe Page para interagir com o usuário por meio de um pop-up:
DisplayAlert e DisplayActionSheet . Eles são renderizados com os controles nativos apropriados em cada
plataforma.
Exibindo um alerta
Todas as plataformas com suporte do Xamarin.Forms têm um pop-up modal para alertar o usuário ou fazer
perguntas simples a ele. Para exibir esses alertas no Xamarin.Forms, use o método DisplayAlert em qualquer
Page . A linha de código a seguir mostra uma mensagem simples para o usuário:
Este exemplo não coleta informações do usuário. O alerta é exibido de forma modal e, após descartado, o usuário
continua interagindo com o aplicativo.
O método DisplayAlert também pode ser usado para capturar a resposta do usuário apresentando dois botões e
retornando um boolean . Para obter uma resposta a um alerta, forneça texto para os dois botões e para o método
await . Após o usuário selecionar uma das opções, a resposta será retornada ao seu código. Observe as palavras-
chave async e await no código de exemplo abaixo:
async void OnAlertYesNoClicked (object sender, EventArgs e)
{
bool answer = await DisplayAlert ("Question?", "Would you like to play a game", "Yes", "No");
Debug.WriteLine ("Answer: " + answer);
}
O botão destroy é renderizado de forma diferente dos outros e pode ser deixado como null ou ser especificado
como o terceiro parâmetro de cadeia de caracteres. O exemplo a seguir usa o botão destroy :
Links relacionados
PopupsSample
Shell do Xamarin.Forms
12/04/2019 • 16 minutes to read • Edit Online
Baixar o exemplo
O Shell do Xamarin.Forms é um contêiner para aplicativos, que fornece os recursos fundamentais da interface do
usuário que a maioria dos aplicativos exige, permitindo que você se concentre na carga de trabalho principal do
aplicativo. Os aplicativos do Shell são fornecidos com a seguinte funcionalidade:
Um único lugar para descrever a estrutura visual de um aplicativo.
Uma interface do usuário de navegação comum.
Um serviço de navegação com vinculação profunda.
Um manipulador de pesquisa integrado.
Essa funcionalidade reduz a complexidade dos aplicativos e aumenta a produtividade do desenvolvedor. Além
disso, o Shell é gravado considerando a renderização do consumo de memória e de velocidade.
IMPORTANT
Os aplicativos iOS e Android existentes podem adotar o Shell e beneficiar-se imediatamente das melhorias de navegação,
desempenho e extensibilidade.
O Shell fornece uma interface do usuário de navegação "pretensiosa", com base em guias e submenus. O nível
superior da navegação em um aplicativo do Shell é um submenu:
O próximo nível de navegação é a barra de guias inferior:
Quando o submenu não estiver aberto, a barra de guias inferior será considerada o nível superior do painel de
navegação
Em cada guia inferior, o próximo nível de navegação é a barra de guias superior, em que cada guia é uma
ContentPage :
Dentro de cada ContentPage , instâncias de ContentPage adicionais podem ser adicionadas e removidas da pilha de
navegação.
namespace TailwindTraders.Mobile
{
public partial class App : Application
{
public App()
{
InitializeComponent();
IMPORTANT
O Shell é experimental no momento e só pode ser usado com a adição de Forms.SetFlags("Shell_Experimental"); ao
projeto de plataforma, antes da invocação do método Forms.Init .
Android
iOS
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle savedInstanceState)
{
global::Xamarin.Forms.Forms.SetFlags("Shell_Experimental");
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
}
Nenhum desses elementos representa uma interface do usuário, mas sim a organização da estrutura visual do
aplicativo. O Shell usará esses elementos e produzirá a interface do usuário de navegação do conteúdo.
O XAML a seguir mostra um exemplo simples de um arquivo Shell:
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TailwindTraders.Mobile.Features.Shell"
x:Class="TailwindTraders.Mobile.Features.Shell.TheShell"
Title="TailwindTraders">
<ShellItem Title="Home">
<ShellSection>
<ShellContent>
<local:HomePage />
</ShellContent>
</ShellSection>
</ShellItem>
</Shell>
NOTE
Cada ShellItem também pode definir uma propriedade FlyoutIcon para um ImageSource , que será exibido à esquerda
do título.
Esse XAML exibe a HomePage , pois esse é o primeiro item de conteúdo declarado no arquivo do Shell:
Quando o botão de hambúrguer é pressionado, o menu suspenso é exibido:
O número de itens no submenu pode ser aumentado com a adição de mais instâncias de ShellItem ao arquivo do
Shell. No entanto, observe que HomePage é criado durante a inicialização do aplicativo, e a adição de mais
instâncias de ShellItem usando essa abordagem fará com que essas páginas também sejam criadas durante a
inicialização do aplicativo. Isso pode ser evitado definindo a propriedade ShellContent.ContentTemplate para um
DataTemplate :
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TailwindTraders.Mobile.Features.Shell"
x:Class="TailwindTraders.Mobile.Features.Shell.TheShell"
Title="TailwindTraders">
<ShellItem Title="Home">
<ShellSection>
<ShellContent>
<local:HomePage />
</ShellContent>
</ShellSection>
<ShellItem>
<ShellContent Title="Profile"
ContentTemplate="{DataTemplate local:ProfilePage}" />
</Shell>
Com essa abordagem, a ProfilePage é criada somente quando o usuário navega para ela e não na inicialização do
aplicativo. Além disso, observe que para a ProfilePage , os objetos ShellItem e ShellSection são omitidos, e a
propriedade Title é definida na instância de ShellContent . Essa abordagem concisa requer menos marcação
com o Shell fornecendo os wrappers lógicos necessários (sem introduzir exibições adicionais à árvore visual).
Além disso, a aparência de cada ShellItem pode ser personalizada definindo a propriedade Shell.ItemTemplate
para um DataTemplate :
<Shell.ItemTemplate>
<DataTemplate>
<ContentView HeightRequest="32">
<ContentView.Padding>
<Thickness Left="32"
Top="16" />
</ContentView.Padding>
<Label Text="{Binding Title}" />
</ContentView>
</DataTemplate>
</Shell.ItemTemplate>
Esse código simplesmente reposiciona o texto para cada ShellItem dentro do submenu. Observe que o Shell
fornece as propriedades Title (e Icon ) para o BindingContext do DataTemplate .
Submenu
O submenu é o menu raiz do aplicativo e consiste em um cabeçalho de submenu e em itens de menu:
Comportamento do submenu
O submenu por ser acessado pelo botão de hambúrguer ou passando o dedo na lateral tela. No entanto, esse
comportamento pode ser alterado definindo a propriedade Shell.FlyoutBehavior para um dos membros da
enumeração FlyoutBehavior :
<Shell ...
FlyoutBehavior="Disabled">
...
</Shell>
A definição da propriedade FlyoutBehavior para Disabled oculta o submenu, o que é útil quando há apenas um
ShellItem . Outros valores válidos de FlyoutBehavior são Flyout (padrão) e Locked .
Cabeçalho do submenu
O cabeçalho do submenu é o conteúdo que é exibido, opcionalmente, na parte superior do submenu, com sua
aparência definida por uma View que pode ser configurada por meio do valor da propriedade Shell.FlyoutHeader
:
<Shell.FlyoutHeader>
<local:FlyoutHeader />
</Shell.FlyoutHeader>
Como alternativa, a aparência do cabeçalho do submenu pode ser definida configurando a propriedade
Shell.FlyoutHeaderTemplate para um DataTemplate :
<Shell.FlyoutHeaderTemplate>
<DataTemplate>
<StackLayout HorizontalOptions="Fill"
VerticalOptions="Fill"
BackgroundColor="White"
Padding="16">
<Label FontSize="Medium"
Text="Smart Shopping">
<Label.Margin>
<Thickness Left="8" />
</Label.Margin>
</Label>
<Button Image="photo"
Text="By taking a photo">
<Button.Margin>
<Thickness Top="16" />
</Button.Margin>
</Button>
<Button Image="ia"
Text="By using AR">
<Button.Margin>
<Thickness Top="8" />
</Button.Margin>
</Button>
</StackLayout>
</DataTemplate>
</Shell.FlyoutHeaderTemplate>
Por padrão, o cabeçalho do submenu ficará fixo no submenu enquanto o conteúdo abaixo poderá ser rolado se
houver itens suficientes. No entanto, esse comportamento pode ser alterado definindo a propriedade
Shell.FlyoutHeaderBehavior para um dos membros da enumeração FlyoutHeaderBehavior :
<Shell ...
FlyoutHeaderBehavior="CollapseOnScroll">
...
</Shell>
Itens de menu
O número de itens no submenu pode ser aumentado adicionando mais instâncias de ShellItem . No entanto,
também é possível adicionar instâncias de MenuItem no menu suspenso. Isso permite cenários como a navegação
até uma página idêntica passando dados por meio da propriedade MenuItem.CommandParameter .
As instâncias de MenuItem devem ser adicionadas à coleção Shell.MenuItems :
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TailwindTraders.Views"
x:Class="TailwindTraders.Shell"
FlyoutHeaderBehavior="Fixed"
Title="Tailwind Traders"
...>
<Shell.MenuItems>
<MenuItem Command="{Binding ProductTypeCommand}"
CommandParameter="1"
Text="Holiday decorations" />
<MenuItem Command="{Binding ProductTypeCommand}"
CommandParameter="2"
Text="Appliances" />
<MenuItem Command="{Binding ProductTypeCommand}"
CommandParameter="3"
Text="Bathrooms" />
...
</Shell.MenuItems>
<ShellItem Title="Home">
<ShellSection>
<ShellContent>
<local:HomePage />
</ShellContent>
</ShellSection>
</ShellItem>
</Shell>
NOTE
Cada MenuItem também pode definir uma propriedade Icon para uma FileImageSource , que será exibida à esquerda
do texto.
<Shell.MenuItemTemplate>
<DataTemplate>
<ContentView HeightRequest="32">
<ContentView.Padding>
<Thickness Left="32"
Top="16" />
</ContentView.Padding>
<Label Text="{Binding Text}"
FontAttributes="Bold" />
</ContentView>
</DataTemplate>
</Shell.MenuItemTemplate>
Os itens serão renderizados como guias superiores, desde que haja várias instâncias de
ShellContent
ShellContent em uma única ShellSection :
<ShellItem Title="Store Home"
Shell.TitleView="Store Home"
Style="{StaticResource BaseStyle}">
<ShellSection Title="Browse Product">
<ShellContent Title="Featured"
ContentTemplate="{DataTemplate local:FeaturedPage}" />
<ShellContent Title="On Sale"
ContentTemplate="{DataTemplate local:SalePage}" />
</ShellSection>
</ShellItem>
As guias podem ser estilizadas usando estilos XAML ou fornecendo um renderizador personalizado. Por exemplo,
o exemplo a seguir mostra um estilo XAML que define a cor da guia:
<Style x:Key="BaseStyle"
TargetType="Element">
<Setter Property="Shell.ShellTabBarBackgroundColor"
Value="#3498DB" />
<Setter Property="Shell.ShellTabBarTitleColor"
Value="White" />
<Setter Property="Shell.ShellTabBarUnselectedColor"
Value="#B4FFFFFF" />
</Style>
Navegação
O Shell inclui uma experiência de navegação baseada em URI. Os URIs fornecem uma experiência de navegação
aprimorada que permite a navegação para qualquer página no aplicativo, sem precisar seguir uma hierarquia de
navegação definida. Além disso, eles também oferecem a capacidade de navegar para trás, sem precisar visitar
todas as páginas na pilha de navegação.
Essa navegação baseada em URI é realizada com rotas, que são segmentos de URI usados para navegar dentro do
aplicativo. O arquivo Shell deve declarar um esquema de rota, um host de rota e uma rota:
<Shell ...
Route="tailwindtraders"
RouteHost="www.microsoft.com"
RouteScheme="app">
...
</Shell>
Implementando a navegação
Os itens de menu expõem uma propriedade Command que pode ser usada para implementar a navegação:
Para invocar a navegação, é necessário obter uma referência ao aplicativo Shell por meio da propriedade
MainPage da classe Application . Em seguida, a navegação poderá ser invocada ao chamar o método GoToAsync
passando um URI válido como um argumento. O método GoToAsync navega usando um objeto
ShellNavigationState , que será construído usando uma string ou um Uri .
Passando dados
Os dados podem ser passados entre as páginas por meio de parâmetros de cadeia de consulta. O Shell definirá os
valores dos parâmetros de cadeia de consulta na ContentPage ou no ViewModel quando você adicionar atributos
de propriedade de consulta à classe:
[QueryProperty("TypeID", "id")]
public partial class ProductCategoryPage : ContentPage
{
private string _typeId;
public ProductCategoryPage()
{
InitializeComponent();
O atributo QueryProperty especifica que o TypeID receberá os dados passados no parâmetro de cadeia de
consulta id do URI na chamada de método GoToAsync .
Interceptando a navegação
O Shell fornece a capacidade de interceptar o roteamento de navegação antes que ele seja concluído e após sua
conclusão. Isso pode ser feito registrando manipuladores de eventos para os eventos Navigating e Navigated ,
respectivamente:
<Shell ...
Navigating="OnShellNavigating">
...
</Shell>
void OnShellNavigating(object sender, ShellNavigatingEventArgs e)
{
if (...)
{
e.Cancel(); // Cancel the navigation
}
}
Além disso, o Shell fornece um método OnBackButtonPressed substituível que pode ser usado para interceptar um
pressionamento do botão de retorno.
Links relacionados
Tailwind Traders (exemplo)
Modelos do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Modelos de controle
Os modelos de controle do Xamarin.Forms fornecem a capacidade de tematizar e tematizar novamente páginas de
aplicativo em tempo de execução.
Modelos de dados
Os modelos de dados do Xamarin.Forms fornecem a capacidade de definir a apresentação de dados em controles
compatíveis.
Modelos de Controle do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Modelos de controle fornecem uma separação clara entre a aparência de uma página e seu conteúdo,
permitindo a criação de páginas cujo tema pode ser definido facilmente.
Introdução
Os modelos de controle do Xamarin.Forms fornecem a capacidade de tematizar e tematizar novamente páginas
de aplicativo em tempo de execução. Este artigo fornece uma introdução a modelos de controle.
Criando um ControlTemplate
Modelos de controle podem ser definidos no nível do aplicativo ou no nível da página. Este artigo demonstra
como criar e consumir modelos de controle.
Associando de um ControlTemplate
Associações do modelo permitem que os controles em um modelo de controle associem dados a propriedades
públicas, permitindo que os valores de propriedade em controles no modelo de controle sejam alterados
facilmente. Este artigo demonstra como usar associações de modelo para realizar a associação de dados de um
modelo de controle.
Introdução aos modelos de controle do
Xamarin.Forms
12/04/2019 • 6 minutes to read • Edit Online
Criando um ControlTemplate
Um ControlTemplate especifica a aparência de uma página ou de uma exibição e contém um layout raiz e, dentro
do layout, os controles que implementam o modelo. Normalmente, um ControlTemplate utilizará um
ContentPresenter para marcar onde o conteúdo a ser exibido pela página ou pela exibição será exibido. A página
ou a exibição que consome o ControlTemplate definirá o conteúdo a ser exibido pelo ContentPresenter . O
diagrama a seguir ilustra um ControlTemplate para uma página que contém um número de controles, incluindo
um ContentPresenter marcado por um retângulo azul:
Um ControlTemplate pode ser aplicado aos seguintes tipos definindo suas propriedades ControlTemplate :
ContentPage
ContentView
TemplatedPage
TemplatedView
Quando um ControlTemplate é criado e atribuído a esses tipos, qualquer aparência existente é substituída pela
aparência definida no ControlTemplate . Ademais, além de definir a aparência usando a propriedade
ControlTemplate , os modelos de controle também podem ser aplicados usando estilos para expandir ainda mais a
capacidade do tema.
NOTE
O que são os tipos TemplatedPage e TemplatedView ? TemplatedPage é a classe base para ContentPage e é o tipo de
página mais básico fornecido pelo Xamarin.Forms. Diferentemente de ContentPage , TemplatedPage não tem uma
propriedade Content . Portanto, o conteúdo não pode ser diretamente adicionado a uma instância TemplatedPage . Em vez
disso, o conteúdo é adicionado, definindo o modelo de controle para a instância TemplatedPage . De maneira semelhante,
TemplatedView é a classe base para ContentView . Diferentemente de ContentView , TemplatedView não tem uma
propriedade Content . Portanto, o conteúdo não pode ser diretamente adicionado a uma instância TemplatedView . Em vez
disso, o conteúdo é adicionado, definindo o modelo de controle para a instância TemplatedView .
Links relacionados
Estilos
ControlTemplate
ContentPresenter
Criando um ControlTemplate
12/04/2019 • 7 minutes to read • Edit Online
Baixar o exemplo
Modelos de controle podem ser definidos no nível do aplicativo ou no nível da página. Este artigo demonstra
como criar e consumir modelos de controle.
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.App">
<Application.Resources>
<ResourceDictionary>
<ControlTemplate x:Key="TealTemplate">
<Grid>
...
<BoxView ... />
<Label Text="Control Template Demo App"
TextColor="White"
VerticalOptions="Center" ... />
<ContentPresenter ... />
<BoxView Color="Teal" ... />
<Label Text="(c) Xamarin 2016"
TextColor="White"
VerticalOptions="Center" ... />
</Grid>
</ControlTemplate>
<ControlTemplate x:Key="AquaTemplate">
...
</ControlTemplate>
</ResourceDictionary>
</Application.Resources>
</Application>
Cada instância de ControlTemplate é criada como um objeto reutilizável em um ResourceDictionary . Isso é feito
dando a cada declaração um atributo x:Key exclusivo, que fornece a ela uma chave descritiva no
ResourceDictionary .
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.HomePage">
<ContentView x:Name="contentView" Padding="0,20,0,0"
ControlTemplate="{StaticResource TealTemplate}">
<StackLayout VerticalOptions="CenterAndExpand">
<Label Text="Welcome to the app!" HorizontalOptions="Center" />
<Button Text="Change Theme" Clicked="OnButtonClicked" />
</StackLayout>
</ContentView>
</ContentPage>
Esse método substitui a instância ativa de ControlTemplate pela instância alternativa de ControlTemplate ,
resultando na seguinte captura de tela:
NOTE
Em um ContentPage , a propriedade Content pode ser atribuída e a propriedade ControlTemplate também pode ser
definida. Quando isso ocorre, se o ControlTemplate contiver uma instância de ContentPresenter , o conteúdo atribuído à
propriedade Content será apresentado pelo ContentPresenter dentro do ControlTemplate .
<Style TargetType="ContentView">
<Setter Property="ControlTemplate" Value="{StaticResource TealTemplate}" />
</Style>
Como a instância de Style é implícita, ela será aplicada a todas as instâncias de ContentView no aplicativo.
Portanto, não é mais necessário definir a propriedade ContentView.ControlTemplate , conforme demonstrado no
exemplo de código a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="SimpleTheme.HomePage">
<ContentView x:Name="contentView" Padding="0,20,0,0">
...
</ContentView>
</ContentPage>
Criando um ControlTemplate em C#
Para definir um ControlTemplate no nível do aplicativo, deve ser criado um class que representa o
ControlTemplate . A classe deve derivar do layout que está sendo usado para o modelo, conforme mostrado no
exemplo de código a seguir:
A classe AquaTemplate é idêntica à classe TealTemplate , exceto pelo fato de que cores diferentes são usadas para
as propriedades BoxView.Color e Label.TextColor .
O exemplo de código a seguir mostra um ContentPage aplicando um TealTemplate ao ContentView :
public class HomePageCS : ContentPage
{
...
ControlTemplate tealTemplate = new ControlTemplate (typeof(TealTemplate));
ControlTemplate aquaTemplate = new ControlTemplate (typeof(AquaTemplate));
public HomePageCS ()
{
var button = new Button { Text = "Change Theme" };
var contentView = new ContentView {
Padding = new Thickness (0, 20, 0, 0),
Content = new StackLayout {
VerticalOptions = LayoutOptions.CenterAndExpand,
Children = {
new Label { Text = "Welcome to the app!", HorizontalOptions = LayoutOptions.Center },
button
}
},
ControlTemplate = tealTemplate
};
...
Content = contentView;
}
}
As instâncias de ControlTemplate são criadas especificando o tipo das classes que definem os modelos de controle,
no construtor ControlTemplate .
A propriedade ContentView.Content é definida como um StackLayout que define o conteúdo a ser exibido no
ContentPage . Esse conteúdo será exibido pelo ContentPresenter contido no TealTemplate . O mesmo mecanismo
descrito anteriormente é usado para alterar o tema em tempo de execução para o AquaTheme .
Resumo
Este artigo demonstrou como criar e consumir modelos de controle. Modelos de controle podem ser definidos no
nível do aplicativo ou no nível da página.
Links relacionados
Estilos
Tema simples (amostra)
ControlTemplate
ContentPresenter
ContentView
ResourceDictionary
Associação de um ControlTemplate do
Xamarin.Forms
12/04/2019 • 8 minutes to read • Edit Online
Baixar o exemplo
Associações de modelo permitem que os controles em um modelo de controle associem dados a propriedades
públicas, permitindo que os valores de propriedade em controles no modelo de controle sejam alterados
facilmente. Este artigo demonstra como usar associações de modelo para realizar a associação de dados de um
modelo de controle.
Um TemplateBinding é usado para associar a propriedade de um controle em um modelo de controle a uma
propriedade associável no pai da exibição de destino é proprietária do modelo de controle. Por exemplo, em vez
de definir o texto exibido por instâncias de Label dentro do ControlTemplate , você poderia usar uma associação
de modelo para associar a propriedade Label.Text a propriedades vinculáveis que definem o texto a ser exibido.
Um TemplateBindingé semelhante a um Binding existente, exceto pelo fato de que a origem de um
TemplateBinding sempre é definida automaticamente como pai da exibição de destino que é proprietária do
modelo de controle. No entanto, observe que não há suporte para usar um TemplateBinding fora de um
ControlTemplate .
<ControlTemplate x:Key="TealTemplate">
<Grid>
...
<Label Text="{TemplateBinding Parent.HeaderText}" ... />
...
<Label Text="{TemplateBinding Parent.FooterText}" ... />
</Grid>
</ControlTemplate>
Em vez de definir as propriedades de Label.Text como texto estático, as propriedades podem usar associações de
modelo para associar a propriedades associáveis no pai da exibição de destino que é proprietária do
ControlTemplate . No entanto, observe que as associações de modelo se associam a Parent.HeaderText e
Parent.FooterText , em vez de HeaderText e FooterText . Isso ocorre porque, neste exemplo, as propriedades
associáveis são definidas no avô da exibição de destino, em vez do pai, conforme demonstrado no exemplo de
código a seguir:
<ContentPage ...>
<ContentView ... ControlTemplate="{StaticResource TealTemplate}">
...
</ContentView>
</ContentPage>
A origem da associação de modelo sempre é definida automaticamente como pai da exibição de destino que é
proprietária do modelo de controle, que aqui é a instância de ContentView . A associação de modelo usa a
propriedade Parent para retornar o elemento pai da instância de ContentView , que é a instância de ContentPage .
Portanto, usar um TemplateBinding no ControlTemplate para associar a Parent.HeaderText e Parent.FooterText
localiza as propriedades associáveis que estão definidas no ContentPage , conforme demonstrado no exemplo de
código a seguir:
Criando um TemplateBinding em C#
Em C#, um TemplateBinding é criado usando o construtor TemplateBinding , conforme demonstrado no exemplo
de código a seguir:
Em vez de definir as propriedades de Label.Text como texto estático, as propriedades podem usar associações de
modelo para associar a propriedades associáveis no pai da exibição de destino que é proprietária do
ControlTemplate . A associação de modelo é criada usando o método SetBinding , especificando uma instância de
TemplateBinding como o segundo parâmetro. Observe que as associações de modelo se associam a
Parent.HeaderText e Parent.FooterText , porque as propriedades associáveis são definidas no avô da exibição de
destino, em vez do pai, conforme demonstrado no exemplo de código a seguir:
<ContentPage xmlns:local="clr-namespace:SimpleTheme;assembly=SimpleTheme"
HeaderText="{Binding HeaderText}" FooterText="{Binding FooterText}" ...>
<ContentPage.BindingContext>
<local:HomePageViewModel />
</ContentPage.BindingContext>
<ContentView ControlTemplate="{StaticResource TealTemplate}" ...>
...
</ContentView>
</ContentPage>
Você também pode estabelecer a associação com as propriedades do modelo de exibição diretamente, para que
não seja necessário declarar BindableProperty s para HeaderText e FooterText no ContentPage , associando o
modelo de controle a Parent.BindingContext.PropertyName, por exemplo:
<ControlTemplate x:Key="TealTemplate">
<Grid>
...
<Label Text="{TemplateBinding Parent.BindingContext.HeaderText}" ... />
...
<Label Text="{TemplateBinding Parent.BindingContext.FooterText}" ... />
</Grid>
</ControlTemplate>
Para obter mais informações sobre a associação de dados para ViewModels, confira De associações de dados a
MVVM.
Resumo
Este artigo demonstrou como usar associações de modelo para realizar a associação de dados de um modelo de
controle. Associações de modelo permitem que os controles em um modelo de controle associem dados a
propriedades públicas, permitindo que os valores de propriedade em controles no modelo de controle sejam
alterados facilmente.
Links relacionados
Conceitos básicos da associação de dados
De associações de dados a MVVM
Tema simples com associação de modelo (amostra)
Tema simples com associação de modelo e ViewModel (amostra)
TemplateBinding
ControlTemplate
ContentView
Modelos de dados do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Baixar o exemplo
Um DataTemplate é usado para especificar a aparência dos dados em controles compatíveis e geralmente é
associado aos dados a serem exibidos.
Introdução
Os modelos de dados do Xamarin.Forms fornecem a capacidade de definir a apresentação de dados em
controles compatíveis. Este artigo fornece uma introdução aos modelos de dados, examinando o motivo pelo
qual eles são necessários.
Criando um DataTemplate
Modelos de dados podem ser criados embutidos, em um ResourceDictionary ou de um tipo personalizado ou
um tipo de célula apropriado do Xamarin.Forms. Um modelo embutido deve ser usado se não há nenhuma
necessidade de reutilizar o modelo de dados em outro lugar. Como alternativa, um modelo de dados pode ser
reutilizado, definindo-o como um tipo personalizado ou como um recurso de aplicativo de nível de controle, de
página ou de aplicativo.
Criando um DataTemplateSelector
Um DataTemplateSelector pode ser usado para escolher um DataTemplate em tempo de execução com base no
valor de uma propriedade associada a dados. Isso permite que várias instâncias de DataTemplate sejam aplicadas
ao mesmo tipo de objeto, para personalizar a aparência de objetos específicos. Este artigo demonstra como criar
e consumir um DataTemplateSelector .
Links relacionados
Modelos de dados (amostra)
Introdução a modelos de dados do Xamarin.Forms
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Os modelos de dados do Xamarin.Forms fornecem a capacidade de definir a apresentação de dados em controles
compatíveis. Este artigo fornece uma introdução aos modelos de dados, examinando o motivo pelo qual eles são
necessários.
Considere uma ListView que exibe uma coleção de objetos Person . O exemplo de código a seguir mostra a
definição da classe Person :
A classe Persondefine as propriedades Name , Age e Location , que podem ser definidas quando um objeto
Person é criado. O ListView é usado para exibir a coleção de objetos Person , conforme mostrado no exemplo de
código XAML a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DataTemplates"
...>
<StackLayout Margin="20">
...
<ListView Margin="0,20,0,0">
<ListView.ItemsSource>
<x:Array Type="{x:Type local:Person}">
<local:Person Name="Steve" Age="21" Location="USA" />
<local:Person Name="John" Age="37" Location="USA" />
<local:Person Name="Tom" Age="42" Location="UK" />
<local:Person Name="Lucas" Age="29" Location="Germany" />
<local:Person Name="Tariq" Age="39" Location="UK" />
<local:Person Name="Jane" Age="30" Location="USA" />
</x:Array>
</ListView.ItemsSource>
</ListView>
</StackLayout>
</ContentPage>
Itens são adicionados ao ListView no XAML inicializando a propriedade ItemsSource de uma matriz de instâncias
de Person .
NOTE
Observe que o elemento x:Array requer um atributo Type que indica o tipo dos itens na matriz.
A página em C# equivalente é mostrada no exemplo de código a seguir, que inicializa a propriedade ItemsSource
para um List de instâncias de Person :
public WithoutDataTemplatePageCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
new Person { Name = "John", Age = 37, Location = "USA" },
new Person { Name = "Tom", Age = 42, Location = "UK" },
new Person { Name = "Lucas", Age = 29, Location = "Germany" },
new Person { Name = "Tariq", Age = 39, Location = "UK" },
new Person { Name = "Jane", Age = 30, Location = "USA" }
};
O ListView chama ToString ao exibir os objetos na coleção. Como não há uma substituição de Person.ToString ,
ToString retorna o nome do tipo de cada objeto, conforme mostrado nas capturas de tela seguir:
O objeto Person pode substituir o método ToString para exibir dados significativos, conforme mostrado no
exemplo de código a seguir:
Isso faz com que ListView exiba o valor da propriedade Person.Name para cada objeto na coleção, conforme
mostrado nas capturas de tela seguir:
A substituição Person.ToString poderia retornar uma cadeia de caracteres formatada composta pelas
propriedades Name , Age e Location . No entanto, essa abordagem oferece apenas controle limitado sobre a
aparência de cada item de dados. Para ter mais flexibilidade, é possível criar um DataTemplate que define a
aparência dos dados.
Criando um DataTemplate
Um DataTemplate é usado para especificar a aparência dos dados e normalmente usa a associação de dados para
exibir dados. Um cenário de uso comum é exibir dados de uma coleção de objetos em um ListView . Por exemplo,
quando um ListView está associado a uma coleção de objetos Person , a propriedade ListView.ItemTemplate é
definida como um DataTemplate que define a aparência de cada objeto Person no ListView . O DataTemplate
conterá elementos que associam aos valores de propriedade de cada objeto Person . Para obter mais informações
sobre vinculação de dados, veja Noções básicas de vinculação de dados.
Um DataTemplate pode ser usado como um valor para as seguintes propriedades:
ListView.HeaderTemplate
ListView.FooterTemplate
ListView.GroupHeaderTemplate
ItemsView.ItemTemplate , que é herdado por ListView .
MultiPage.ItemTemplate , que é herdado por CarouselPage , MasterDetailPage e TabbedPage .
NOTE
Observe que, embora o TableView use objetos Cell , ele não usa um DataTemplate . Isso acontece porque as
associações de dados sempre são definidas diretamente em objetos Cell .
Um DataTemplate que é colocado como filho direto das propriedades listadas acima é conhecido como um
modelo embutido. Como alternativa, é possível definir um DataTemplate como um recurso de nível de controle,
nível de página ou nível de aplicativo. Escolher onde definir um DataTemplate afeta onde ele pode ser usado:
Um DataTemplate definido no nível do controle só pode ser aplicado ao controle.
Um DataTemplate definido no nível da página só pode ser aplicado a vários controles válidos na página.
Um DataTemplate definido no nível do aplicativo pode ser aos controles válidos em todo o aplicativo.
Modelos de dados posicionados mais baixo na hierarquia de exibição têm precedência sobre os definidos mais
acima quando eles compartilham atributos de x:Key . Por exemplo, um modelo de dados no nível do aplicativo
será substituído por um modelo de dados no nível da página e um modelo de dados no nível da página será
substituído por um modelo de dados no nível de controle ou por um modelo de dados embutido.
Links relacionados
Aparência de célula
Modelos de dados (amostra)
DataTemplate
Criando um DataTemplate do Xamarin.Forms
12/04/2019 • 8 minutes to read • Edit Online
Baixar o exemplo
Os modelos de dados podem ser criados embutidos, em um ResourceDictionary ou de um tipo personalizado ou
um tipo de célula apropriado do Xamarin.Forms. Este artigo explora cada técnica.
Um cenário de uso comum para um DataTemplate é exibir dados de uma coleção de objetos em um ListView . A
aparência dos dados para cada célula no ListView pode ser gerenciada definindo a propriedade
ListView.ItemTemplate como um DataTemplate . Há várias técnicas que podem ser usadas para fazer isso:
O filho de um DataTemplate embutido deve ser do tipo Cell ou derivado dele. Este exemplo usa um ViewCell ,
que deriva de Cell . O layout dentro do ViewCell é gerenciado aqui por um Grid . O Grid contém três
instâncias Label que associam suas propriedades Text às propriedades adequadas de cada objeto Person na
coleção.
O código C# equivalente é mostrado no exemplo de código a seguir:
public class WithDataTemplatePageCS : ContentPage
{
public WithDataTemplatePageCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
Em C#, o DataTemplate embutido é criado usando uma sobrecarga de construtor que especifica um argumento
Func .
Aqui, a propriedade ListView.ItemTemplate é definida como um DataTemplate criado com base em um tipo
personalizado que define a aparência da célula. O tipo personalizado deve ser derivado do tipo ViewCell ,
conforme mostrado no exemplo de código a seguir:
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DataTemplates.PersonCell">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*" />
<ColumnDefinition Width="0.2*" />
<ColumnDefinition Width="0.3*" />
</Grid.ColumnDefinitions>
<Label Text="{Binding Name}" FontAttributes="Bold" />
<Label Grid.Column="1" Text="{Binding Age}" />
<Label Grid.Column="2" Text="{Binding Location}" HorizontalTextAlignment="End" />
</Grid>
</ViewCell>
Dentro do ViewCell , o layout é gerenciado aqui por um Grid . O Grid contém três instâncias Label que
associam suas propriedades Text às propriedades adequadas de cada objeto Person na coleção.
O código C# equivalente é mostrado no exemplo a seguir:
public class WithDataTemplatePageFromTypeCS : ContentPage
{
public WithDataTemplatePageFromTypeCS()
{
...
var people = new List<Person>
{
new Person { Name = "Steve", Age = 21, Location = "USA" },
...
};
Em C#, o DataTemplate é criado usando uma sobrecarga de construtor que especifica o tipo de célula como um
argumento. O tipo de célula deve ser derivado do tipo ViewCell , conforme mostrado no exemplo de código a
seguir:
nameLabel.SetBinding(Label.TextProperty, "Name");
ageLabel.SetBinding(Label.TextProperty, "Age");
locationLabel.SetBinding(Label.TextProperty, "Location");
grid.Children.Add(nameLabel);
grid.Children.Add(ageLabel, 1, 0);
grid.Children.Add(locationLabel, 2, 0);
View = grid;
}
}
NOTE
Observe que o Xamarin.Forms também inclui tipos de células que podem ser usados para exibir dados simples em células
ListView . Para saber mais, confira Cell Appearance (Aparência da célula).
O DataTemplate é adicionado ao ResourceDictionary usando o método Add , que especifica uma cadeia de
caracteres Key usada para referenciar o DataTemplate ao recuperá-la.
Resumo
Este artigo explicou como criar modelos de dados, embutidos, com base em um tipo personalizado ou em um
ResourceDictionary . Um modelo embutido deve ser usado caso não haja necessidade de reutilizar o modelo de
dados em outro lugar. Como alternativa, um modelo de dados pode ser reutilizado, definindo-o como um tipo
personalizado ou como um recurso de aplicativo de nível de controle, de página ou de aplicativo.
Links relacionados
Aparência de célula
Modelos de dados (amostra)
DataTemplate
Criando um DataTemplateSelector do Xamarin.Forms
12/04/2019 • 6 minutes to read • Edit Online
Baixar o exemplo
Um DataTemplateSelector pode ser usado para escolher um DataTemplate em tempo de execução com base no
valor de uma propriedade associada a dados. Isso permite que várias instâncias de DataTemplates sejam
aplicadas ao mesmo tipo de objeto, para personalizar a aparência de objetos específicos. Este artigo demonstra
como criar e consumir um DataTemplateSelector.
Um seletor de modelo de dados permite cenários como uma associação do ListView a uma coleção de objetos,
em que a aparência de cada objeto no ListView pode ser escolhida em tempo de execução pelo seletor de
modelo de dados que retorna um DataTemplate específico.
Criando um DataTemplateSelector
Um seletor de modelo de dados é implementado criando uma classe herdada de DataTemplateSelector . O método
OnSelectTemplate é substituído para retornar um determinado DataTemplate , conforme mostrado no exemplo de
código a seguir:
O método OnSelectTemplate retorna o modelo apropriado com base no valor da propriedade DateOfBirth . O
modelo a ser retornado é o valor da propriedade ValidTemplate ou da propriedade InvalidTemplate , que são
definidas ao consumir o PersonDataTemplateSelector .
Uma instância da classe de seletor de modelo de dados pode ser atribuída às propriedades de controle do
Xamarin.Forms, como ListView.ItemTemplate . Para obter uma lista de propriedades válidas, confira Criando um
DataTemplate.
Limitações
As instâncias DataTemplateSelector têm as seguintes limitações:
A subclasse DataTemplateSelector deve sempre retornar o mesmo modelo para os mesmos dados se
consultada várias vezes.
A subclasse DataTemplateSelector não deve retornar outra subclasse DataTemplateSelector .
A subclasse DataTemplateSelector não deve retornar novas instâncias de um DataTemplate em cada chamada.
Em vez disso, a mesma instância deve ser retornada. Não fazer isso criará uma perda de memória e
desabilitará a virtualização.
No Android, não pode haver mais de 20 modelos de dados diferentes por ListView .
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Selector;assembly=Selector"
x:Class="Selector.HomePage">
<ContentPage.Resources>
<ResourceDictionary>
<DataTemplate x:Key="validPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<DataTemplate x:Key="invalidPersonTemplate">
<ViewCell>
...
</ViewCell>
</DataTemplate>
<local:PersonDataTemplateSelector x:Key="personDataTemplateSelector"
ValidTemplate="{StaticResource validPersonTemplate}"
InvalidTemplate="{StaticResource invalidPersonTemplate}" />
</ResourceDictionary>
</ContentPage.Resources>
...
</ContentPage>
Consumindo um DataTemplateSelector em C#
Em C#, o PersonDataTemplateSelector pode ser instanciado e atribuído à propriedade ListView.ItemTemplate ,
conforme mostrado no exemplo de código a seguir:
public HomePageCS ()
{
...
SetupDataTemplates ();
var listView = new ListView {
ItemsSource = people,
ItemTemplate = new PersonDataTemplateSelector {
ValidTemplate = validTemplate,
InvalidTemplate = invalidTemplate }
};
Links relacionados
Seletor de Modelo de Dados (exemplo)
DataTemplateSelector
Gatilhos do Xamarin.Forms
12/04/2019 • 12 minutes to read • Edit Online
Baixar o exemplo
Os gatilhos permitem expressar ações declarativamente em XAML que alteram a aparência dos controles com
base em eventos ou alterações de propriedade.
Você pode atribuir um gatilho diretamente a um controle ou adicioná-lo a um dicionário de recursos na página ou
aplicativo a ser aplicado a vários controles.
Há quatro tipos de gatilho:
Gatilho de propriedade – ocorre quando uma propriedade em um controle é definida como um valor
específico.
Gatilho de dados – usa associação de dados para disparar com base nas propriedades de outro controle.
Gatilho de evento – ocorre quando acontece um evento no controle.
Gatilho múltiplo – permite que várias condições de gatilho sejam definidas antes que uma ação ocorra.
Gatilhos de propriedade
Um gatilho simples pode ser expresso puramente em XAML, adicionando um elemento Trigger a uma coleção
de gatilhos do controle. Este exemplo mostra um gatilho que altera uma cor da tela de fundo Entry quando
recebe o foco:
Gatilhos de dados
Os gatilhos de dados usam a associação de dados para monitorar outro controle para fazer com que Setter s
sejam chamados. Em vez do atributo Property em um gatilho de propriedade, defina o atributo Binding para
monitorar o valor especificado.
O exemplo a seguir usa a sintaxe de associação de dados {Binding Source={x:Reference entry}, Path=Text.Length}
que é como nos referimos a outras propriedades do controle. Quando o tamanho do entry for zero, o gatilho
será ativado. Neste exemplo, o gatilho desabilita o botão quando a entrada está vazia.
Dica: ao avaliar Path=Text.Length , sempre forneça um valor padrão para a propriedade de destino (por exemplo,
Text="" ), pois, caso contrário, ele será null e o gatilho não funcionará como esperado.
Gatilhos de evento
O elemento EventTrigger requer apenas uma propriedade Event , como "Clicked" no exemplo a seguir.
<EventTrigger Event="Clicked">
<local:NumericValidationTriggerAction />
</EventTrigger>
Observe que não há elementos , mas, em vez disso, uma referência a uma classe definida por
Setter
local:NumericValidationTriggerAction , que requer que o xmlns:local seja declarado no XAML da página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:WorkingWithTriggers;assembly=WorkingWithTriggers"
A classe em si implementa TriggerAction , o que significa que ela deve fornecer uma substituição para o método
Invoke que é chamado sempre que ocorre o evento de gatilho.
Substituir o método Invoke – isso é chamado sempre que os critérios do gatilho forem atendidos.
Outra opção é expor propriedades que podem ser definidas no XAML quando o gatilho é declarado (como
Anchor , Scale e Length neste exemplo).
As propriedades expostas pela ação de gatilho podem ser definidas na declaração de XAML da seguinte maneira:
<EventTrigger Event="TextChanged">
<local:NumericValidationTriggerAction />
</EventTrigger>
Tenha cuidado ao compartilhar gatilhos em um ResourceDictionary , pois uma instância será compartilhada entre
os controles para que qualquer estado que está configurado uma vez se aplique a todos.
Observe que os gatilhos de evento não dão suporte a EnterActions nem a ExitActions descrito abaixo.
Múltiplos gatilhos
Um MultiTrigger é semelhante a um Trigger ou DataTrigger , exceto que pode haver mais de uma condição.
Todas as condições devem ser verdadeiras antes de Setter s serem disparados.
Aqui está um exemplo de um gatilho para um botão que é associado a duas entradas diferentes ( email e phone ):
<MultiTrigger TargetType="Button">
<MultiTrigger.Conditions>
<BindingCondition Binding="{Binding Source={x:Reference email},
Path=Text.Length}"
Value="0" />
<BindingCondition Binding="{Binding Source={x:Reference phone},
Path=Text.Length}"
Value="0" />
</MultiTrigger.Conditions>
Para usar esse conversor em um gatilho múltiplo, primeiro adicione-o ao dicionário de recursos da página (junto
com uma definição de namespace xmlns:local personalizada):
<ResourceDictionary>
<local:MultiTriggerConverter x:Key="dataHasBeenEntered" />
</ResourceDictionary>
O XAML é mostrado abaixo. Observe as seguintes diferenças do primeiro exemplo de gatilho múltiplo:
O botão tem IsEnabled="false" definido por padrão.
As condições de gatilho múltiplo usam o conversor para transformar o valor Text.Length em um boolean .
Quando todas as condições forem true , o setter transformará o IsEnabled do botão na propriedade true .
<Entry x:Name="user" Text="" Placeholder="user name" />
Essas capturas de tela mostram a diferença entre os dois exemplos de gatilho múltiplo acima. Na parte superior
das telas, a entrada de texto em apenas um Entry é suficiente para habilitar o botão Salvar. Na parte inferior das
telas, o botão Logon permanece inativo até que ambos os campos contenham dados.
EnterActions e ExitActions
Outra maneira de implementar alterações quando ocorre um gatilho é adicionando as coleções EnterActions e
ExitActions e especificando as implementações TriggerAction<T> .
Você pode fornecer ambos EnterActions e ExitActions , bem como Setter s em um gatilho, mas lembre-se de
que Setter s são chamados imediatamente (eles não aguardam o EnterAction ou o ExitAction ser concluído).
Como alternativa, você pode executar tudo no código e não usar Setter s.
<Trigger.ExitActions>
<local:FadeTriggerAction StartsFrom="1" />
</Trigger.ExitActions>
<!-- You can use both Enter/Exit and Setter together if required -->
</Trigger>
</Entry.Triggers>
</Entry>
Como sempre, quando uma classe é referenciada no XAML você deve declarar um namespace como xmlns:local
, conforme mostrado aqui:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:WorkingWithTriggers;assembly=WorkingWithTriggers"
}),
length:1000, // milliseconds
easing: Easing.Linear);
}
}
Links relacionados
Exemplo de gatilhos
Documentação da API do Xamarin.Forms
Exibições de Interface do usuário do xamarin. Forms
12/04/2019 • 6 minutes to read
baixar o exemplo
Como usar os modos de exibição fornecidos pelo xamarin. Forms
Animação
Xamarin. Forms inclui sua própria infraestrutura de animação que é muito simples para a criação de animações
simples, embora também seja suficientemente versátil para criar animações complexas.
BoxView
O BoxView é apenas um retângulo colorido simple, mas ele pode ser usado para itens decorativos, gráficos
rudimentares e para a obtenção de entrada por toque interativa.
Button
O Button responde a um toque ou clique que direciona um aplicativo para executar uma tarefa específica.
CollectionView
O CollectionView é uma exibição flexível e de alto desempenho para apresentações de listas de dados usando as
especificações de layout diferente.
Cores
Definindo e usando cores entre plataformas podem ser complicados quando cada plataforma tem seus próprios
padrões e os padrões.
Referência de controles
Este documento é uma referência rápida para os modos de exibição da interface do usuário que compõem a
estrutura do xamarin. Forms, tal como páginas, Layouts, modos de exibição e células.
DataPages
DataSourceControl fornece uma API para rápida e facilmente vincular uma fonte de dados para exibições
predefinidas. Itens de lista e páginas de detalhes renderização automaticamente os dados e ser personalizadas
usando temas.
DatePicker
O DatePicker permite que um usuário selecione uma data dentro do intervalo especificado. Ele é implementado
usando o seletor de datas com suporte na plataforma específica que o aplicativo é executado.
ImageButton
O ImageButton exibe uma imagem e responde a um toque ou clique que direciona um aplicativo para executar
uma tarefa específica.
Layouts
Xamarin. Forms tem vários layouts para organizar conteúdos na tela. StackLayout , Grid , FlexLayout ,
AbsoluteLayout , ScrollView , e RelativeLayout cada um pode ser usada para criar interfaces do usuário atraentes
e dinâmicos.
ListView
Xamarin. Forms fornece um controle de exibição de lista para exibir a rolagem de linhas de dados. O controle inclui
ações contextuais, HasUnevenRows o dimensionamento automático, personalização de separador, puxar para
atualizar e cabeçalhos e rodapés.
Mapas
Adicionar mapas requer um download adicional de pacote do NuGet e algumas configurações específicas da
plataforma. Mapas e marcadores de pin que podem ser adicionados em apenas algumas linhas de código depois
que a configuração é feita.
Seletor
O Picker exibição é um controle para selecionar um item de texto em uma lista de dados.
Slider
O Slider permite que um usuário selecione um valor numérico de um intervalo contínuo.
Passador
O Stepper permite que um usuário selecione um valor numérico de um intervalo de valores. Ele consiste em dois
botões rotulados com sinais de adição e de subtração. Manipular os dois botões altera o valor selecionado
incrementalmente.
Estilos
Fonte, cor e outros atributos podem ser agrupados em estilos que podem ser compartilhados entre os controles,
layouts ou todo o aplicativo usando ResourceDictionaries.
TableView
O modo de exibição de tabela é semelhante a uma exibição de lista, mas em vez de que está sendo criado para
listas longas de dados destina-se para telas de estilo de entrada de dados de rolagem controles ou menus simples
de rolagem.
Texto
Xamarin. Forms tem vários modos de exibição para apresentar e receber texto. Modos de exibição de texto podem
ser formatados e personalizados para as plataformas. Configurações de fonte específico podem habilitar a
compatibilidade com os recursos de acessibilidade.
Temas
Temas do xamarin. Forms definem uma aparência visual específica para os controles padrão. Depois que você
adiciona um tema para o dicionário de recursos do aplicativo, a aparência dos controles padrão será alterado.
TimePicker
O TimePicker permite que um usuário selecione uma hora. Ele é implementado usando o seletor de tempo com
suporte na plataforma específica que o aplicativo é executado.
Visual
Material do xamarin. Forms Visual pode ser usado para criar aplicativos xamarin. Forms que se parecem idênticos
ou praticamente idênticas, no iOS e Android.
WebView
Xamarin. Forms usa o controle de navegador da web nativos em cada plataforma e pode exibir cadeias de
caracteres Html geradas, recursos locais e sites.
Links relacionados
Galeria do Xamarin.Forms (amostra)
Animação no xamarin. Forms
12/04/2019 • 2 minutes to read
Xamarin. Forms inclui sua própria infraestrutura de animação que é muito simples para a criação de animações
simples, embora também seja suficientemente versátil para criar animações complexas.
As classes de animação do xamarin. Forms diferentes propriedades de elementos visuais, de destino com uma
animação típica progressivamente alterar uma propriedade de um valor para outro durante um período de tempo.
Observe que não há nenhuma interface XAML para as classes de animação do xamarin. Forms. No entanto, as
animações podem ser encapsuladas em comportamentos e, em seguida, referenciado do XAML.
Animações simples
O ViewExtensions classe fornece métodos de extensão que podem ser usados para construir animações simples
que giram, dimensionarem, traduzam e fade VisualElement instâncias. Este artigo demonstra como criar e
cancelar as animações usando o ViewExtensions classe.
Funções de easing
Xamarin. Forms inclui um Easing classe que permite que você especifique uma função de transferência que
controla como as animações acelerar ou diminuir como elas estão em execução. Este artigo demonstra como
utilizar as funções de easing predefinidas e como criar funções de easing personalizadas.
Animações personalizadas
O Animation classe é o bloco de construção de todas as animações de xamarin. Forms, com os métodos de
extensão no ViewExtensions classe criando um ou mais Animation objetos. Este artigo demonstra como usar o
Animation classe para criar e Cancelar animações, sincronizar várias animações e criar animações personalizadas
que animar propriedades que não estão animadas pelos métodos de animação existentes.
Animações simples no xamarin. Forms
12/04/2019 • 18 minutes to read
baixar o exemplo
A classe ViewExtensions fornece métodos de extensão que podem ser usados para construir animações simples.
Este artigo demonstra como criar e cancelar as animações usando a classe ViewExtensions.
O ViewExtensions classe fornece os seguintes métodos de extensão que podem ser usados para criar animações
simples:
TranslateTo Anima o TranslationX e TranslationY propriedades de um VisualElement .
ScaleTo Anima o Scale propriedade de uma VisualElement .
RelScaleTo aplica-se um aumento incremental animado ou diminuirá para o Scale propriedade de uma
VisualElement .
RotateTo Anima o Rotation propriedade de uma VisualElement .
RelRotateTo aplica-se um aumento incremental animado ou diminuirá para o Rotation propriedade de uma
VisualElement .
RotateXTo Anima o RotationX propriedade de uma VisualElement .
RotateYTo Anima o RotationY propriedade de uma VisualElement .
FadeTo Anima o Opacity propriedade de uma VisualElement .
Por padrão, cada animação levará 250 milissegundos. No entanto, uma duração para cada animação pode ser
especificada ao criar a animação.
O ViewExtensions classe também inclui um CancelAnimations método que pode ser usado para cancelar todas as
animações.
NOTE
O ViewExtensions classe fornece um LayoutTo método de extensão. No entanto, esse método se destina a ser usado
pelo layouts para animar as transições entre estados de layout que contêm o tamanho e posição alterações. Portanto, ele só
deve ser usado pelo Layout subclasses.
Os métodos de extensão de animação na ViewExtensions classe são assíncronas e retorno um Task<bool> objeto.
O valor retornado será false se a animação for concluída, e true se a animação for cancelada. Portanto, os
métodos de animação normalmente devem ser usados com o await operador, que torna possível determinar
facilmente quando uma animação for concluída. Além disso, em seguida, torna possível criar animações
sequenciais com métodos de animação subsequente executados depois que o método anterior foi concluída. Para
obter mais informações, consulte composta animações.
Se houver um requisito para permitir que uma animação completa em segundo plano, em seguida, a await
operador pode ser omitido. Nesse cenário, os métodos de extensão de animação retornará rapidamente após
iniciar a animação, com a animação que ocorrem em segundo plano. Essa operação pode ser aproveitada durante
a criação de animações de composição. Para obter mais informações, consulte animações de composição.
Para obter mais informações sobre o await operador, consulte visão geral do suporte assíncrono.
Animações únicas
Cada método de extensão na ViewExtensions implementa uma operação única animação progressivamente altera
uma propriedade de um valor para outro valor por um período de tempo. Essa seção explora cada operação de
animação.
Rotação
O exemplo de código a seguir demonstra como usar o RotateTo método animar o Rotation propriedade de um
Image :
Esse código é animado a Image instância, girando até 360 graus em 2 segundos (2000 milissegundos). O
RotateTo método obtém atual Rotation propriedade de valor para o início da animação e, em seguida, gira desse
valor para o seu primeiro argumento (360). Depois que a animação for concluída, a imagem Rotation
propriedade é redefinida como 0. Isso garante que o Rotation propriedade não permaneça em 360 depois que a
animação termina, o que impediria rotações adicionais.
As capturas de tela a seguir mostram a rotação em andamento em cada plataforma:
Rotação relativa
O exemplo de código a seguir demonstra como usar o RelRotateTo método para aumentar ou diminuir de forma
incremental o Rotation propriedade de um Image :
Esse código é animado a Image instância por mais de 2 segundos (2000 milissegundos) de rotação de 360 graus
de sua posição inicial. O RelRotateTo método obtém atual Rotation propriedade de valor para o início da
animação e, em seguida, gira desse valor para o valor mais seu primeiro argumento (360). Isso garante que cada
animação sempre será uma rotação de 360 graus a partir da posição inicial. Portanto, se uma nova animação será
invocada, enquanto uma animação já está em andamento, ele será iniciada a partir da posição atual e pode
terminar em uma posição que não é um incremento de 360 graus.
As capturas de tela a seguir mostram a rotação relativa em andamento em cada plataforma:
Dimensionamento
O exemplo de código a seguir demonstra como usar o ScaleTo método animar o Scale propriedade de um
Image :
Esse código é animado a Image instância pelo escalar verticalmente para duas vezes o tamanho mais de 2
segundos (2000 milissegundos). O ScaleTo método obtém atual Scale valor da propriedade (valor padrão de 1)
para o início da animação e, em seguida, escalas desse valor para o seu primeiro argumento (2). Isso tem o efeito
de expansão do tamanho da imagem para duas vezes seu tamanho.
As capturas de tela a seguir mostram o dimensionamento em andamento em cada plataforma:
NOTE
O VisualElement classe define também ScaleX e ScaleY propriedades, que podem dimensionar o VisualElement
forma diferente no direções horizontal e vertical. Essas propriedades podem ser animadas com o Animation classe. Para
obter mais informações, consulte animações personalizadas no xamarin. Forms.
Relativo ao dimensionamento
O exemplo de código a seguir demonstra como usar o RelScaleTo método animar o Scale propriedade de um
Image :
Esse código é animado a Image instância pelo escalar verticalmente para duas vezes o tamanho mais de 2
segundos (2000 milissegundos). O RelScaleTo método obtém atual Scale valor da propriedade para o início da
animação e, em seguida, escalas desse valor para o valor mais seu primeiro argumento (2). Isso garante que cada
animação sempre será uma escala de 2 a partir da posição inicial.
Escala e rotação com âncoras
O AnchorX e AnchorY propriedades define o centro da escala ou rotação para a Rotation e Scale propriedades.
Portanto, seus valores também afetam a RotateTo e ScaleTo métodos.
Considerando um Image que foi colocado no Centro de um layout, o exemplo de código a seguir demonstra a
rotação a imagem em torno do centro do layout, definindo seu AnchorY propriedade:
Conversão
O exemplo de código a seguir demonstra como usar o TranslateTo método animar o TranslationX e
TranslationY propriedades de um Image :
Esse código é animado a Image instância, convertendo-lo horizontalmente e verticalmente mais de 1 segundo
(1000 milissegundos). O TranslateTo método simultaneamente traduz os pixels da imagem 100 para a esquerda
e para cima de 100 pixels. Isso ocorre porque o primeiro e segundo argumentos são os dois números negativos.
Fornecer números positivos convertem a imagem à direita e para baixo.
As capturas de tela a seguir mostram a tradução em andamento em cada plataforma:
NOTE
Se um elemento é inicialmente disposto fora da tela e, em seguida, convertido para a tela, após a tradução de entrada o
layout do elemento permanece fora da tela e o usuário não pode interagir com ele. Portanto, é recomendável que um modo
de exibição deve ser disposto em sua posição final e, em seguida, todas as exigidas traduções executadas.
Esmaecimento
O exemplo de código a seguir demonstra como usar o FadeTo método animar o Opacity propriedade de um
Image :
image.Opacity = 0;
await image.FadeTo (1, 4000);
Esse código é animado a Image instância pelo esmaecimento-lo em mais de 4 segundos (4000 milissegundos). O
FadeTo método obtém atual Opacity valor da propriedade para o início da animação e, em seguida, esmaece
desse valor para o seu primeiro argumento (1).
As capturas de tela a seguir mostram o esmaecimento em andamento em cada plataforma:
Animações compostas
Uma animação composta é uma combinação sequencial de animações e podem ser criada com o await operador,
conforme demonstrado no exemplo de código a seguir:
Neste exemplo, o Image é convertido em 6 segundos (6000 milissegundos). A conversão do Image usa cinco
animações, com o await operador que indica que cada animação é executada sequencialmente. Portanto,
métodos de animação subsequente executadas depois que o método anterior foi concluída.
Animações de composição
Uma animação de composição é uma combinação de animações em que dois ou mais animações executados
simultaneamente. Animações de composição podem ser criadas pela mistura animações esperadas e não é
aguardada, conforme demonstrado no exemplo de código a seguir:
Neste exemplo, o Image é dimensionado e girado simultaneamente mais de 4 segundos (4000 milissegundos). O
dimensionamento do Image usa duas animações sequenciais que ocorrem ao mesmo tempo que a rotação. O
RotateTo método é executado sem um await operador e retorna imediatamente, com o primeiro ScaleTo , em
seguida, a partir de animação. O await operador na primeira ScaleTo chamada de método atrasa a segunda
ScaleTo chamada de método até que a primeira ScaleTo chamada de método foi concluída. Neste momento a
RotateTo animação é metade forma concluída e o Image será girada 180 graus. Durante os últimos 2 segundos
(2000 milissegundos), a segunda ScaleTo animação e o RotateTo animação ambos concluir.
A execução simultânea de vários métodos assíncronos
O static Task.WhenAny e Task.WhenAll métodos são usados para executar vários métodos assíncronos
simultaneamente e, portanto, pode ser usados para criar animações de composição. Ambos os métodos retornam
um Task do objeto e aceitar uma coleção de métodos de retorno que cada um Task objeto. O Task.WhenAny
método é concluído quando qualquer método em sua coleção conclui a execução, conforme demonstrado no
exemplo de código a seguir:
await Task.WhenAny<bool>
(
image.RotateTo (360, 4000),
image.ScaleTo (2, 2000)
);
await image.ScaleTo (1, 2000);
Neste exemplo, o Task.WhenAny chamada de método contém duas tarefas. A primeira tarefa gira a imagem mais
de 4 segundos (4000 milissegundos), e a segunda tarefa redimensiona a imagem mais de 2 segundos (2000
milissegundos). Quando a segunda tarefa é concluída, o Task.WhenAny chamada de método é concluída. No
entanto, mesmo que o RotateTo método ainda está em execução, a segunda ScaleTo método pode começar.
O Task.WhenAll método é concluído quando tem concluído todos os métodos em sua coleção, conforme
demonstrado no exemplo de código a seguir:
// 10 minute animation
uint duration = 10 * 60 * 1000;
await Task.WhenAll (
image.RotateTo (307 * 360, duration),
image.RotateXTo (251 * 360, duration),
image.RotateYTo (199 * 360, duration)
);
Neste exemplo, o Task.WhenAll chamada de método contém três tarefas, cada uma delas executa mais de 10
minutos. Cada Task faz com que um número diferente de rotações de 360 graus – 307 rotações para RotateTo ,
251 rotações para RotateXTo e as 199 rotações para RotateYTo . Esses valores são números primos, portanto,
garantindo que as rotações não estão sincronizadas e, portanto, não resultará em padrões repetitivos.
As capturas de tela a seguir mostram as rotações vários em andamento em cada plataforma:
Cancelando a animações
Um aplicativo pode cancelar uma ou mais animações com uma chamada para o static
ViewExtensions.CancelAnimations método, conforme demonstrado no exemplo de código a seguir:
ViewExtensions.CancelAnimations (image);
Isso cancelará todas as animações que estão sendo executados no imediatamente a Image instância.
Resumo
Este artigo demonstrou criando e Cancelando animações usando o ViewExtensions classe. Essa classe fornece
métodos de extensão que podem ser usados para construir animações simples que giram, dimensionarem,
traduzam e fade VisualElement instâncias.
Links relacionados
Visão geral do suporte assíncrono
Animação básica (amostra)
ViewExtensions
Funções de easing no xamarin. Forms
12/04/2019 • 7 minutes to read
baixar o exemplo
Xamarin. Forms inclui uma classe de atenuação que permite que você especifique uma função de transferência
que controla como as animações aceleram ou diminuir como elas estão em execução. Este artigo demonstra
como utilizar as funções de easing predefinidas e como criar funções de easing personalizadas.
O Easing classe define um número de funções de easing que podem ser consumidos por animações:
O BounceIn função de easing bounces a animação no início.
O BounceOut função de easing bounces a animação no final.
O CubicIn função de easing lentamente acelera a animação.
O CubicInOut função de easing acelera a animação no início e desacelerada a animação no final.
O CubicOut função de easing rapidamente desacelerada a animação.
O Linear função de easing usa uma velocidade constante e é o padrão a função de easing.
O SinIn função de easing suavemente acelera a animação.
O SinInOut função de easing suavemente acelera a animação no início e desacelerada suavemente a animação
no final.
O SinOut função de easing suavemente desacelerada a animação.
O SpringIn função de easing faz com que a animação acelerar rapidamente até o final.
O SpringOut função de easing faz com que a animação de desacelerar rapidamente até o final.
O In e Out sufixos que indicam se o efeito fornecido pela função de easing é perceptível no início da animação,
no final, ou ambos.
Além disso, as funções de easing personalizadas podem ser criadas. Para obter mais informações, consulte
funções de Easing personalizada.
Especificando uma função de easing para uma animação, a velocidade da animação se torna não lineares e produz
o efeito fornecido pela função de easing. A omissão de uma função de easing durante a criação de uma animação
faz com que a animação usar o padrão Linear facilitando a função, que produz uma velocidade linear.
Para obter mais informações sobre como usar os métodos de extensão de animação na ViewExtensions da classe,
consulte animações simples. Funções de easing também podem ser consumidas pela Animation classe. Para obter
mais informações, consulte animações personalizadas.
Funções de Easing personalizado
Há três abordagens principais para a criação de uma função de easing personalizada:
1. Criar um método que usa um double argumento e retorna um double resultado.
2. Criará um Func<double, double> .
3. Especifica a função de easing como o argumento para o Easing construtor.
Em todos os três casos, a função de easing personalizada deve retornar 0 para um argumento de 0 e 1 para um
argumento de 1. No entanto, qualquer valor pode ser retornado entre os valores de argumento de 0 e 1. Cada
abordagem agora será discutida detalhadamente.
Método de Easing personalizado
Uma função de easing personalizada pode ser definida como um método que usa um double argumento e
retorna um double resultar, conforme demonstrado no exemplo de código a seguir:
O CustomEase método truncará o valor de entrada para os valores 0, 0.2, 0,4, 0,6, 0,8 e 1. Portanto, o Image
instância é convertida em pequenos saltos, em vez de sem problemas.
Easing Func personalizado
Uma função de easing personalizada também pode ser definida como um Func<double, double> , conforme
demonstrado no exemplo de código a seguir:
O CustomEase Func representa uma função de easing começa rápidos e mais lento e inverte o curso e, em
seguida, reverte curso novamente para acelerar rapidamente até o final. Portanto, embora a movimentação geral
do Image instância é para baixo, ele também temporariamente inverte o curso no meio da animação.
Construtor de Easing personalizado
Uma função de easing personalizada também pode ser definida como o argumento para o Easing construtor,
conforme demonstrado no exemplo de código a seguir:
await image.TranslateTo (0, 200, 2000, new Easing (t => 1 - Math.Cos (10 * Math.PI * t) * Math.Exp (-5 * t)));
A função de easing personalizada é especificada como um argumento de função lambda para o Easing construtor
e usa o Math.Cos método para criar um efeito de soltar lento é amortecido pelo Math.Exp método. Portanto, o
Image instância é convertida para que ele apareça descartar ao seu local de repouso final.
Resumo
Este artigo demonstrou como utilizar as funções de easing predefinidas e como criar funções de easing
personalizadas. Xamarin. Forms inclui um Easing classe que permite que você especifique uma função de
transferência que controla como as animações acelerar ou diminuir como elas estão em execução.
Links relacionados
Visão geral do suporte assíncrono
Funções de easing (amostra)
Atenuação
ViewExtensions
Animações personalizadas no xamarin. Forms
12/04/2019 • 19 minutes to read
baixar o exemplo
A classe de animação é o bloco de construção de todas as animações de xamarin. Forms, com os métodos de
extensão na classe ViewExtensions criando um ou mais objetos de animação. Este artigo demonstra como usar a
classe de animação para criar e Cancelar animações, sincronizar várias animações e criar animações
personalizadas que animar propriedades que não estão animadas pelos métodos de animação existentes.
Um número de parâmetros deve ser especificado durante a criação de um Animation objeto, incluindo os valores
inicial e final da propriedade sendo animada e um retorno de chamada que altera o valor da propriedade. Um
Animation objeto também pode manter uma coleção de animações filho que podem ser executados e
sincronizadas. Para obter mais informações, consulte animações filho.
Executar uma animação criada com o Animation classe, que pode ou não incluir animações filho, é obtida
chamando o Commit método. Esse método Especifica a duração da animação e, entre outros itens, um retorno de
chamada que controla se deve repetir a animação.
Esse código define uma animação do Scale propriedade de uma Image instância de um valor de 1 para um
valor de 2. O valor animado, o que é derivado por xamarin. Forms, é passado ao retorno de chamada especificado
como o primeiro argumento, em que ele é usado para alterar o valor da Scale propriedade.
A animação é iniciada com uma chamada para o Commit método, conforme demonstrado no exemplo de código
a seguir:
animation.Commit (this, "SimpleAnimation", 16, 2000, Easing.Linear, (v, c) => image.Scale = 1, () => true);
Observe que o Commit método não retorna um Task objeto. Em vez disso, as notificações são fornecidas por
meio de métodos de retorno de chamada.
Os argumentos a seguir são especificados no Commit método:
O primeiro argumento (proprietário) identifica o proprietário da animação. Isso pode ser o elemento visual na
qual a animação é aplicada, ou outro elemento visual, como a página.
O segundo argumento (nome) identifica a animação com um nome. O nome é combinado com o proprietário
para identificar exclusivamente a animação. Essa identificação exclusiva, em seguida, pode ser usada para
determinar se a animação está em execução ( AnimationIsRunning ), ou para cancelá-la ( AbortAnimation ).
O terceiro argumento (taxa) indica o número de milissegundos entre cada chamada para o método de retorno
de chamada definido na Animation construtor
O quarto argumento ( comprimento) indica a duração da animação, em milissegundos.
O quinto argumento (atenuação) define a função de easing a ser usado na animação. Como alternativa, a
função de easing pode ser especificada como um argumento para o Animation construtor. Para obter mais
informações sobre funções de easing, consulte funções de Easing.
O sexto argumento (concluído) é um retorno de chamada que será executado quando a animação for
concluída. Esse retorno de chamada usa dois argumentos, com o primeiro argumento que indica um valor
final e o segundo argumento que está sendo uma bool que é definido como true se a animação foi
cancelada. Como alternativa, o concluída retorno de chamada pode ser especificado como um argumento para
o Animation construtor. No entanto, com uma única animação, se concluída retornos de chamada
especificados em ambos o Animation construtor e o Commit método, apenas o retorno de chamada
especificado no Commit método será executado.
O sétimo argumento (Repita) é um retorno de chamada que permite que a animação ser repetida. Ele é
chamado no final da animação e retornando true indica que a animação deve ser repetida.
O efeito geral é criar uma animação que aumenta a Scale propriedade de uma Image de 1 a 2, mais de 2
segundos (2000 milissegundos), usando o Linear função de easing. Cada vez que a animação for concluída, seu
Scale propriedade é redefinida como 1 e a animação se repete.
NOTE
Animações simultâneas, que são executados independentemente uns dos outros podem ser construídas com a criação de
um Animation do objeto para cada animação e, em seguida, chamar o Commit método em cada animação.
Animações filho
O Animation classe também dá suporte a animações filho, que envolve a criação de uma Animation objeto para
os quais outros Animation objetos são adicionados. Isso permite que uma série de animações a ser executado e
sincronizadas. O exemplo de código a seguir demonstra como criar e executar animações filho:
parentAnimation.Commit (this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState (true,
false));
Como alternativa, o exemplo de código pode ser gravado mais concisa, conforme demonstrado no exemplo de
código a seguir:
new Animation {
{ 0, 0.5, new Animation (v => image.Scale = v, 1, 2) },
{ 0, 1, new Animation (v => image.Rotation = v, 0, 360) },
{ 0.5, 1, new Animation (v => image.Scale = v, 2, 1) }
}.Commit (this, "ChildAnimations", 16, 4000, null, (v, c) => SetIsEnabledButtonState (true, false));
Nos dois exemplos de código, um pai Animation objeto é criado, no qual adicionais Animation objetos são
adicionados. Os dois primeiros argumentos para o Add método especifique quando deve começar e terminar a
animação de filho. Os valores de argumento devem ser entre 0 e 1 e representar o período relativo dentro da
animação pai que a animação filho especificado estará ativa. Portanto, no exemplo o scaleUpAnimation ficará ativo
para a primeira metade da animação, o scaleDownAnimation ficará ativo para a segunda metade da animação e o
rotateAnimation estará ativo durante todo o período.
O efeito geral é que a animação ocorre mais de 4 segundos (4000 milissegundos). O scaleUpAnimation anima a
Scale propriedade de 1 a 2, mais de 2 segundos. O scaleDownAnimation , em seguida, anima a Scale
propriedade de 2 para 1, mais de 2 segundos. Embora ambas as animações de escala estão ocorrendo, o
rotateAnimation anima a Rotation propriedade de 0 a 360, mais de 4 segundos. Observe que as animações de
escala também usam funções de easing. O SpringIn função de easing faz com que o Image reduzir inicialmente
antes de obter maior e o SpringOut função de easing faz com que o Image se torne menor do que seu tamanho
real até o final da animação completa.
Há várias diferenças entre um Animation objeto que usa animações filho e outro que não:
Ao usar animações filho, o concluída retorno de chamada em uma animação de filho indica quando o filho for
concluída e o concluída retorno de chamada passada para o Commit método indica quando o toda animação
foi concluída.
Ao usar animações filho, retornando true do Repita retorno de chamada a Commit método não fará com que
a animação ser repetida, mas a animação será continuarão sendo executados sem novos valores.
Ao incluir uma função de easing a Commit método e a função de easing retorna um valor maior que 1, a
animação será encerrada. Se a função de easing retorna um valor menor que 0, o valor será fixado como 0.
Para usar uma função de easing que retorna um valor menor que 0 ou maior que 1, ele deve ser especificado
em uma das animações filho, em vez de no Commit método.
O Animation classe também inclui WithConcurrent métodos que podem ser usados para adicionar animações
filho a um pai Animation objeto. No entanto, suas começar e concluir valores de argumento não são restritos
para 0 para 1, mas apenas essa parte da animação filho que corresponde a um intervalo de 0 a 1 estará ativa. Por
exemplo, se um WithConcurrent chamada de método define uma animação de filho que tem como alvo um
Scale propriedade de 1 a 6, mas com começar e concluir valores de -2 e 3, o começar valor de -2 corresponde a
um Scale valor de 1 e o concluir valor 3 corresponde a um Scale valor de 6. Porque valores fora do intervalo
de 0 e 1 não reproduzir nenhuma parte em uma animação, o Scale propriedade apenas será ser animada de 3 a
6.
this.AbortAnimation ("SimpleAnimation");
Observe que as animações são identificadas exclusivamente por uma combinação do proprietário de animação e
o nome da animação. Portanto, o proprietário e o nome especificado ao executar a animação deve ser
especificado para cancelar a animação. Portanto, o exemplo de código imediatamente cancelará a animação
chamada SimpleAnimation que pertence a página.
A animação resultante fornece a aparência de aprimorando o plano de fundo da página por meio das cores do
arco-íris.
Para obter mais exemplos de criação de animações complexas, incluindo uma animação de curva de Bézier,
consulte capítulo 22 dos criação de aplicativos móveis com xamarin. Forms.
await Task.WhenAll(
label.ColorTo(Color.Red, Color.Blue, c => label.TextColor = c, 5000),
label.ColorTo(Color.Blue, Color.Red, c => label.BackgroundColor = c, 5000));
await this.ColorTo(Color.FromRgb(0, 0, 0), Color.FromRgb(255, 255, 255), c => BackgroundColor = c, 5000);
await boxView.ColorTo(Color.Blue, Color.Red, c => boxView.Color = c, 4000);
Neste exemplo de código, o ColorTo método anima a TextColor e BackgroundColor propriedades de um Label ,
a BackgroundColor propriedade de uma página e o Color propriedade de um BoxView .
Resumo
Este artigo demonstrou como usar o Animation classe para criar e Cancelar animações, sincronizar várias
animações e criar animações personalizadas que animar propriedades que não estão animadas pela animação
existente métodos. O Animation classe é o bloco de construção de todas as animações de xamarin. Forms.
Links relacionados
Animações personalizadas (amostra)
Animação
AnimationExtensions
Xamarin. Forms BoxView
12/04/2019 • 28 minutes to read
baixar o exemplo
BoxView renderiza um retângulo simples de uma largura especificada, altura e cor. Você pode usar BoxView para
decoração, gráficos rudimentares e para interação com o usuário por meio de toque.
Porque o xamarin. Forms não tem um sistema de elementos gráficos de vetor internos, o BoxView ajuda a
compensar. Alguns dos programas de exemplo descritos neste artigo usam BoxView para processamento de
gráficos. O BoxView podem ser dimensionados para se parecer com uma linha de uma largura específica e a
espessura e, em seguida, girado usando qualquer ângulo a Rotation propriedade.
Embora BoxView pode imitar o elementos gráficos simples, talvez você queira investigar usar SkiaSharp em
xamarin. Forms para requisitos de elementos gráficos mais sofisticados.
Este artigo discute os seguintes tópicos:
Definindo BoxView cor e tamanho – definir o BoxView propriedades.
Decorações de texto de renderização – usar um BoxView para linhas de renderização.
A listagem de cores com BoxView – exibir todas as cores do sistema em um ListView .
Reproduzir o jogo da vida útil pela criação de subclasses BoxView – implementar um mecanismo de
celular famoso.
Criação de um relógio Digital – simular uma exibição de matriz de pontos.
Criação de um relógio analógico – transformar e animar BoxView elementos.
O Color propriedade é do tipo Color ; a propriedade pode ser definida para qualquer Color valor, incluindo os
141 campos estáticos de somente leitura de chamado colors desde em ordem alfabética AliceBlue para
YellowGreen .
O CornerRadius propriedade é do tipo CornerRadius ; a propriedade pode ser definida como um único double
uniforme por valor de raio de canto, ou um CornerRadius estrutura definida por quatro double valores que são
aplicados a a parte superior esquerda, superior direita, parte inferior esquerda e inferior direita do BoxView .
O WidthRequest e HeightRequest propriedades desempenham uma função somente se o BoxView é irrestrita no
layout. Esse é o caso quando o contêiner de layout precisa saber o filho do tamanho, por exemplo, quando o
BoxView é um filho de uma célula de dimensionamento automático no Grid layout. Um BoxView também é
irrestrita quando seus HorizontalOptions e VerticalOptions propriedades são definidas como valores diferentes
de LayoutOptions.Fill . Se o BoxView irrestrita, mas o WidthRequest e HeightRequest não são definidas e, em
seguida, a largura ou altura são definidos como valores padrão de 40 unidades ou cerca de 1/4 polegadas em
dispositivos móveis.
O WidthRequest e HeightRequest propriedades são ignoradas se o BoxView é restrita no layout, nesse caso, o
contêiner de layout impõe seu próprio tamanho no BoxView .
Um BoxView pode ser restrito em uma dimensão e sem restrições no outro. Por exemplo, se o BoxView é um filho
de um vertical StackLayout , a dimensão vertical do BoxView é irrestrita e sua dimensão horizontal geralmente é
restrito. Mas há exceções para a dimensão horizontal: se o BoxView tem sua HorizontalOptions propriedade
definida como algo diferente de LayoutOptions.Fill , em seguida, a dimensão horizontal também é irrestrita.
Também é possível que o StackLayout em si para ter uma dimensão horizontal irrestrita, caso em que o BoxView
também será horizontalmente irrestrita.
O BasicBoxView exemplo exibe um one-polegadas-quadrado irrestrita BoxView no centro da sua página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BasicBoxView"
x:Class="BasicBoxView.MainPage">
<BoxView Color="CornflowerBlue"
CornerRadius="10"
WidthRequest="160"
HeightRequest="160"
VerticalOptions="Center"
HorizontalOptions="Center" />
</ContentPage>
Se o VerticalOptions e HorizontalOptions propriedades são removidas do BoxView marca ou são definidas com
Fill , em seguida, a BoxView fica restrito pelo tamanho da página e se expande para preencher a página.
Um BoxView também pode ser um filho de um AbsoluteLayout . Nesse caso, o local e o tamanho da BoxView são
definidos usando o LayoutBounds propriedade associável anexada. O AbsoluteLayout é discutida no artigo
AbsoluteLayout.
Você verá exemplos de todos esses casos nos programas de exemplo a seguir.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:TextDecoration"
x:Class="TextDecoration.MainPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 20, 0, 0" />
</OnPlatform>
</ContentPage.Padding>
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="BoxView">
<Setter Property="Color" Value="Black" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ScrollView Margin="15">
<StackLayout>
···
</StackLayout>
</ScrollView>
</ContentPage>
A marcação que segue todas são filhos do StackLayout . Essa marcação consiste em vários tipos de decorativos
BoxView elementos usados com o Label elemento:
O cabeçalho com estilo na parte superior da página é obtido com um AbsoluteLayout cujos filhos são os quatro
BoxView elementos e um Label , todos os de quais são atribuídas a locais específicos e tamanhos:
<AbsoluteLayout>
<BoxView AbsoluteLayout.LayoutBounds="0, 10, 200, 5" />
<BoxView AbsoluteLayout.LayoutBounds="0, 20, 200, 5" />
<BoxView AbsoluteLayout.LayoutBounds="10, 0, 5, 65" />
<BoxView AbsoluteLayout.LayoutBounds="20, 0, 5, 65" />
<Label Text="Stylish Header"
FontSize="24"
AbsoluteLayout.LayoutBounds="30, 25, AutoSize, AutoSize"/>
</AbsoluteLayout>
No arquivo XAML, o AbsoluteLayout é seguido por um Label com o texto formatado que descreve o
AbsoluteLayout .
Uma cadeia de caracteres de texto pode ser sublinhar colocando ambos os Label e BoxView em um StackLayout
que tem seu HorizontalOptions valor definido como algo diferente de Fill . A largura do StackLayout , em
seguida, é governada pela largura do Label , que então impõe essa largura no BoxView . O BoxView é atribuído
uma explícita de altura:
<StackLayout HorizontalOptions="Center">
<Label Text="Underlined Text"
FontSize="24" />
<BoxView HeightRequest="2" />
</StackLayout>
Você não pode usar essa técnica para sublinhar palavras individuais em mais cadeias de caracteres de texto ou um
parágrafo.
Também é possível usar um BoxView se pareça com uma marca HTML hr elemento (régua horizontal).
Simplesmente permitir que a largura do BoxView ser determinado por seu contêiner pai, que nesse caso é o
StackLayout :
Por fim, você pode desenhar uma linha vertical em um dos lados de um parágrafo de texto, colocando ambos os
BoxView e o Label na horizontal StackLayout . Nesse caso, a altura do BoxView é o mesmo que a altura da
StackLayout , que é controlado pela altura do Label :
<StackLayout Orientation="Horizontal">
<BoxView WidthRequest="4"
Margin="0, 0, 10, 0" />
<Label>
···
</Label>
</StackLayout>
// Static members.
static NamedColor()
{
List<NamedColor> all = new List<NamedColor>();
StringBuilder stringBuilder = new StringBuilder();
Os visuais do programa são descritos no arquivo XAML. O ItemsSource propriedade do ListView é definido
como estático NamedColor.All propriedade, o que significa que o ListView exibe todos os individuais NamedColor
objetos:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ListViewColors"
x:Class="ListViewColors.MainPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="10, 20, 10, 0" />
<On Platform="Android, UWP" Value="10, 0" />
</OnPlatform>
</ContentPage.Padding>
<ListView SeparatorVisibility="None"
ItemsSource="{x:Static local:NamedColor.All}">
<ListView.RowHeight>
<OnPlatform x:TypeArguments="x:Int32">
<On Platform="iOS, Android" Value="80" />
<On Platform="UWP" Value="90" />
</OnPlatform>
</ListView.RowHeight>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ContentView Padding="5">
<Frame OutlineColor="Accent"
Padding="10">
<StackLayout Orientation="Horizontal">
<BoxView Color="{Binding Color}"
WidthRequest="50"
HeightRequest="50" />
<StackLayout>
<Label Text="{Binding FriendlyName}"
FontSize="22"
VerticalOptions="StartAndExpand" />
<Label Text="{Binding RgbDisplay, StringFormat='RGB = {0}'}"
FontSize="16"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</StackLayout>
</Frame>
</ContentView>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage>
O NamedColor objetos são formatados pelo ViewCell objeto que é definido como o modelo de dados do
ListView . Esse modelo inclui uma BoxView cujos Color propriedade está associada a Color propriedade do
NamedColor objeto.
public LifeCell()
{
BackgroundColor = Color.White;
LifeCell adiciona três propriedades para BoxView : o Col e Row propriedades armazenam a posição da célula
dentro da grade e o IsAlive propriedade indica seu estado. O IsAlive também define uma propriedade de
Color propriedade do BoxView para preto, se a célula estiver ativo e em branco se a célula não está ativa.
LifeCell também instala um TapGestureRecognizer para permitir que o usuário alterne o estado de células
tocando-los. A classe converte a Tapped o reconhecedor de gestos em seu próprio evento Tapped evento.
O GameOfLife programa também inclui um LifeGrid classe que encapsula a maior parte da lógica do jogo, e
um MainPage classe que manipula os visuais do programa. Esses incluem uma sobreposição que descreve as
regras do jogo. Este é o programa em ação mostrando umas centenas LifeCell objetos na página:
Criação de um relógio Digital
O DotMatrixClock programa cria 210 BoxView elementos para simular os pontos de uma exibição de 5 por 7
matricial antigo. Você pode ler a hora no modo retrato ou paisagem, mas maior no cenário:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:DotMatrixClock"
x:Class="DotMatrixClock.MainPage"
Padding="10"
SizeChanged="OnPageSizeChanged">
<AbsoluteLayout x:Name="absoluteLayout"
VerticalOptions="Center" />
</ContentPage>
Todo o resto ocorre no arquivo code-behind. A lógica de exibição de matriz de pontos é bastante simplificada com
a definição de várias matrizes que descrevem os pontos correspondentes a cada um dos 10 dígitos e dois-pontos:
public partial class MainPage : ContentPage
{
// Total dots horizontally and vertically.
const int horzDots = 41;
const int vertDots = 7;
···
}
Esses campos terminam com uma matriz tridimensional do BoxView elementos para armazenar os padrões de
ponto para os seis dígitos.
O construtor cria todos os as BoxView elementos para os dígitos e dois-pontos e também inicializa a Color
propriedade do BoxView elementos para os dois-pontos:
···
public MainPage()
{
InitializeComponent();
···
···
···
A largura do AbsoluteLayout é definido automaticamente porque ele se estende até a largura total da página.
O código final no MainPage cores nos pontos de cada dígito e processa o retorno de chamada do temporizador de
classe. A definição das matrizes multidimensionais no início do arquivo code-behind ajuda a tornar essa lógica a
parte mais simples do programa:
public partial class MainPage : ContentPage
{
···
bool OnTimer()
{
DateTime dateTime = DateTime.Now;
Todos os visuais nos BoxViewClock programa são filhos de um AbsoluteLayout . Esses elementos são
dimensionados usando o LayoutBounds propriedade anexada e girado usando o Rotation propriedade.
Os três BoxView elementos para os ponteiros do relógio são instanciados no arquivo XAML, mas não
posicionados ou em tamanho:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:BoxViewClock"
x:Class="BoxViewClock.MainPage">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness">
<On Platform="iOS" Value="0, 20, 0, 0" />
</OnPlatform>
</ContentPage.Padding>
<AbsoluteLayout x:Name="absoluteLayout"
SizeChanged="OnAbsoluteLayoutSizeChanged">
<BoxView x:Name="hourHand"
Color="Black" />
<BoxView x:Name="minuteHand"
Color="Black" />
<BoxView x:Name="secondHand"
Color="Black" />
</AbsoluteLayout>
</ContentPage>
O construtor do arquivo code-behind instancia a 60 BoxView elementos para as marcas de escala em torno da
circunferência do relógio:
···
public MainPage()
{
InitializeComponent();
···
···
···
AbsoluteLayout.SetLayoutBounds(boxView,
new Rectangle(center.X - 0.5 * width,
center.Y - offset * height,
width, height));
···
O LayoutHand método posições e os tamanhos cada mão para apontar diretamente até a posição de 12:00. No
final do método, o AnchorY estiver definida como uma posição correspondente para o centro do relógio. Isso
indica que o Centro de rotação.
Os ponteiros são girados na função de retorno de chamada de temporizador:
public partial class MainPage : ContentPage
{
···
bool OnTimerTick()
{
// Set rotation angles for hour and minute hands.
DateTime dateTime = DateTime.Now;
hourHand.Rotation = 30 * (dateTime.Hour % 12) + 0.5 * dateTime.Minute;
minuteHand.Rotation = 6 * dateTime.Minute + 0.1 * dateTime.Second;
if (t < 0.5)
{
t = 0.5 * Easing.SpringIn.Ease(t / 0.5);
}
else
{
t = 0.5 * (1 + Easing.SpringOut.Ease((t - 0.5) / 0.5));
}
A mão de segundo é tratada de maneira um pouco diferente: uma função de easing de animação é aplicada para
fazer com que o movimento pareça ser mecânico, em vez de suave. Em todas as marcas, a mão segundo efetua
pull de voltar um pouco e, em seguida, overshoots seu destino. Esse pequeno trecho de código adiciona muito o
realismo do movimento.
Conclusão
O BoxView pode parecer simples em primeiro lugar, mas como você viu, ele pode ser bastante versáteis e podem
quase reproduzir visuais que são normalmente possíveis somente com gráficos vetoriais. Para gráficos mais
sofisticados, consulte usar SkiaSharp em xamarin. Forms.
Links relacionados
BoxView básica (exemplo)
Decoração de texto (exemplo)
Caixa de listagem de cor (amostra)
Jogo da vida útil (amostra)
Matriz de pontos de relógio (amostra)
Relógio de BoxView (amostra)
BoxView
Botão de xamarin. Forms
12/04/2019 • 33 minutes to read
baixar o exemplo
O botão responde a um toque ou clique que direciona um aplicativo para executar uma tarefa específica.
O Button é o controle interativo mais fundamental em todas as do xamarin. Forms. O Button normalmente
exibe uma cadeia de caracteres de texto curto indicando um comando, mas também pode exibe uma imagem de
bitmap, ou uma combinação de texto e uma imagem. O usuário pressiona o Button com um dedo ou clica nele
com o mouse para iniciar esse comando.
A maioria dos tópicos discutidos a seguir corresponde às páginas na ButtonDemos exemplo.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.BasicButtonClickPage"
Title="Basic Button Click">
<StackLayout>
<Label x:Name="label"
Text="Click the Button below"
FontSize="Large"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
O Button tende a ocupar todo o espaço permitido para ele. Por exemplo, se você não definir a
HorizontalOptions propriedade de Button para algo diferente de Fill , o Button ocupa a largura total do seu
pai.
Por padrão, o Button é retangular, mas você pode atribuir os cantos arredondado de it, usando o CornerRadius
propriedade, conforme descrito abaixo na seção botão aparência .
O Text propriedade especifica o texto que aparece no Button . O Clicked evento é definido como um
manipulador de eventos chamado OnButtonClicked . Esse manipulador está localizado no arquivo code-behind,
BasicButtonClickPage.xaml.cs:
public partial class BasicButtonClickPage : ContentPage
{
public BasicButtonClickPage ()
{
InitializeComponent ();
}
Quando o Button é tocado, o OnButtonClicked método é executado. O sender argumento é o Button objeto
responsável por esse evento. Você pode usar isso para acessar o Button objeto, ou para distinguir entre vários
Button objetos que compartilham o mesmo Clicked eventos.
Essa determinada Clicked manipulador chama uma função de animação que gira o Label 360 graus em 1000
milissegundos. Aqui está o programa em execução em dispositivos iOS e Android e como um aplicativo da
plataforma Universal do Windows (UWP ) na área de trabalho do Windows 10:
Observe que o OnButtonClicked método inclui o async modificador porque await é usado dentro do
manipulador de eventos. Um Clicked manipulador de eventos exige as async modificador somente se o corpo
do manipulador usa await .
Cada plataforma renderiza o Button em sua própria maneira específica. No botão aparência seção, você verá
como definir cores e fazer o Button borda visível para aparências mais personalizadas. Button implementa o
IFontElement interface, portanto, ela inclui FontFamily , FontSize , e FontAttributes propriedades.
Tudo o que é feito no construtor da classe. Porque o Clicked manipulador é apenas uma instrução longa, ele
pode ser anexado ao evento muito simples:
É claro, você também pode definir o manipulador de eventos como um método separado (assim como o
OnButtonClick método no básico de clique do botão) e anexar esse método para o evento:
button.Clicked += OnButtonClicked;
Desabilitação do botão
Às vezes, um aplicativo está em um estado específico em que um determinado Button clique não é uma
operação válida. Nesses casos, o Button deve ser desabilitado definindo seu IsEnabled propriedade false . O
exemplo clássico é um Entry controle de um nome de arquivo acompanhado por uma abertura de arquivo
Button : O Button deve ser habilitada apenas se algum texto foi digitado para o Entry . Você pode usar um
DataTrigger para essa tarefa, conforme mostrado na gatilhos de dados artigo.
Essa abordagem é especialmente adequada em conexão com a vinculação de dados e especialmente quando a
implementação da arquitetura do Model-View -ViewModel (MVVM ). Esses tópicos são discutidos nos artigos
associação de dados, de associações de dados a MVVM, e MVVM.
Em um aplicativo MVVM, o ViewModel define propriedades do tipo ICommand conectados, em seguida, o XAML
Button elementos com associações de dados. Xamarin. Forms também define Command e Command<T> as classes
que implementam o ICommand de interface e auxiliar o ViewModel na definição de propriedades de tipo
ICommand .
Comandos é descrito mais detalhadamente no artigo a Interface de comando , mas o básica de botão de
comando página o ButtonDemos exemplo mostra a abordagem básica.
O CommandDemoViewModel classe é um ViewModel muito simple que define uma propriedade do tipo double
denominado Number e duas propriedades do tipo ICommand denominada MultiplyBy2Command e DivideBy2Command
:
public CommandDemoViewModel()
{
MultiplyBy2Command = new Command(() => Number *= 2);
Os dois as propriedades são inicializadas no construtor da classe com dois objetos do tipo Command . O
ICommand
Command construtores incluem uma pequena função (chamado de execute argumento do construtor ) que dobra
ou reduz pela metade o Number propriedade.
O BasicButtonCommand.xaml arquivo define seu BindingContext a uma instância do CommandDemoViewModel .
O Label elemento e dois Button elementos contenham associações para as três propriedades em
CommandDemoViewModel :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonDemos"
x:Class="ButtonDemos.BasicButtonCommandPage"
Title="Basic Button Command">
<ContentPage.BindingContext>
<local:CommandDemoViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="{Binding Number, StringFormat='Value is now {0}'}"
FontSize="Large"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center" />
Como os dois Button tocados elementos, os comandos são executados, e o número de alterações de valor:
A vantagem dessa abordagem em relação Clicked manipuladores é que toda a lógica que envolvem a
funcionalidade dessa página está localizada no ViewModel em vez de um arquivo code-behind, obtendo uma
melhor separação da interface do usuário da lógica de negócios.
Também é possível que o Command objetos para controlar a habilitação e desabilitação do Button elementos. Por
exemplo, suponha que você deseja limitar o intervalo de valores numéricos entre 210 e 2–10. Você pode adicionar
outra função para o construtor (chamado de canExecute argumento) que retorna true se o Button deve ser
habilitado. Aqui está a modificação para o CommandDemoViewModel construtor:
class CommandDemoViewModel : INotifyPropertyChanged
{
···
public CommandDemoViewModel()
{
MultiplyBy2Command = new Command(
execute: () =>
{
Number *= 2;
((Command)MultiplyBy2Command).ChangeCanExecute();
((Command)DivideBy2Command).ChangeCanExecute();
},
canExecute: () => Number < Math.Pow(2, 10));
As chamadas para o ChangeCanExecute método de Command são necessárias para que o Command método pode
chamar o canExecute método e determinar se o Button deve ser desabilitado ou não. Com essa alteração de
código, como o número de atingir o limite, o Button está desabilitado:
É possível que duas ou mais Button elementos a ser associado ao mesmo ICommand propriedade. O Button
elementos podem ser diferenciados com o CommandParameter propriedade do Button . Nesse caso, você desejará
usar o genérico Command<T> classe. O CommandParameter objeto é então passado como um argumento para o
execute e canExecute métodos. Essa técnica é mostrada em detalhes na comandos básicos seção os Interface
de comando artigo.
O ButtonDemos exemplo também usa essa técnica em seu MainPage classe. O MainPage. XAML arquivo
contém um Button para cada página de exemplo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonDemos"
x:Class="ButtonDemos.MainPage"
Title="Button Demos">
<ScrollView>
<FlexLayout Direction="Column"
JustifyContent="SpaceEvenly"
AlignItems="Center">
</FlexLayout>
</ScrollView>
</ContentPage>
Cada Buttontem sua Command propriedade associada a uma propriedade denominada NavigateCommand e o
CommandParameter é definido como um Type objeto correspondente a uma das classes de página no projeto.
BindingContext = this;
}
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.PressAndReleaseButtonPage"
Title="Press and Release Button">
<StackLayout>
<Label x:Name="label"
Text="Press and hold the Button below"
FontSize="Large"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
O arquivo code-behind anima a Label quando um Pressed evento ocorre, mas suspende a rotação quando um
Released evento ocorre:
public partial class PressAndReleaseButtonPage : ContentPage
{
bool animationInProgress = false;
Stopwatch stopwatch = new Stopwatch();
public PressAndReleaseButtonPage ()
{
InitializeComponent ();
}
Device.StartTimer(TimeSpan.FromMilliseconds(16), () =>
{
label.Rotation = 360 * (stopwatch.Elapsed.TotalSeconds % 1);
return animationInProgress;
});
}
O resultado é que o Label apenas gira enquanto é de um dedo em contato com o Button e é interrompido
quando o dedo é liberado:
Esse tipo de comportamento tem aplicativos de jogos: Um dedo mantido um Button pode fazer um objeto de
tela em Mover em uma direção específica.
Aparência do botão
O Button herda ou define várias propriedades que afetam sua aparência:
TextColor é a cor do Button texto
BackgroundColor é a cor do plano de fundo para que o texto
BorderColor é a cor de uma área ao redor do Button
FontFamily a família de fontes para o texto é usada
FontSize é o tamanho do texto
FontAttributes Indica se o texto em negrito ou itálico
BorderWidth é a largura da borda
CornerRadius é o raio do canto das Button
NOTE
O Button classe também tem Margin e Padding propriedades que controlam o comportamento de layout a Button .
Para obter mais informações, consulte margem e preenchimento.
Os efeitos de seis dessas propriedades (exceto FontFamily e FontAttributes ) são demonstradas a aparência
botão página. Outra propriedade, Image , é discutida na seção usar bitmaps com o botão.
Todas as associações de dados e modos de exibição na aparência botão página são definidos no arquivo XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonDemos"
x:Class="ButtonDemos.ButtonAppearancePage"
Title="Button Appearance">
<StackLayout>
<Button x:Name="button"
Text="Button"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
TextColor="{Binding Source={x:Reference textColorPicker},
Path=SelectedItem.Color}"
BackgroundColor="{Binding Source={x:Reference backgroundColorPicker},
Path=SelectedItem.Color}"
BorderColor="{Binding Source={x:Reference borderColorPicker},
Path=SelectedItem.Color}" />
<Slider x:Name="fontSizeSlider"
Maximum="48"
Minimum="1"
Value="{Binding FontSize}" />
<Slider x:Name="borderWidthSlider"
Minimum="-1"
Maximum="12"
Value="{Binding BorderWidth}" />
<Slider x:Name="cornerRadiusSlider"
Minimum="-1"
Maximum="24"
Value="{Binding CornerRadius}" />
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.Resources>
<Style TargetType="Label">
<Setter Property="VerticalOptions" Value="Center" />
</Style>
</Grid.Resources>
<Picker x:Name="textColorPicker"
ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
ItemDisplayBinding="{Binding FriendlyName}"
SelectedIndex="0"
Grid.Row="0" Grid.Column="1" />
<Picker x:Name="backgroundColorPicker"
ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
ItemDisplayBinding="{Binding FriendlyName}"
SelectedIndex="0"
Grid.Row="1" Grid.Column="1" />
<Picker x:Name="borderColorPicker"
ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
ItemDisplayBinding="{Binding FriendlyName}"
SelectedIndex="0"
Grid.Row="2" Grid.Column="1" />
</Grid>
</StackLayout>
</StackLayout>
</ContentPage>
O Button na parte superior da página tem suas três Color propriedades associadas a Picker elementos na
parte inferior da página. Os itens a Picker elementos são as cores do NamedColor incluído no projeto de classe.
Três Slider elementos contêm as vinculações bidirecionais para o FontSize , BorderWidth , e CornerRadius
propriedades do Button .
Esse programa permite que você experimente combinações de todas essas propriedades:
Para ver os borda, você precisará definir um
Button BorderColor para algo diferente de Default eo
BorderWidth como um valor positivo.
No iOS, você observará que as larguras de borda grande atrapalham a para o interior do Button e interferir com
a exibição do texto. Se você optar por usar um border com um iOS Button , você provavelmente vai querer
começar e terminar o Text propriedade com espaços para manter sua visibilidade.
Na UWP, selecionando uma CornerRadius que excede a metade da altura do Button gera uma exceção.
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Property="Scale"
Value="0.8" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
O Pressed VisualState Especifica que, quando o Button for pressionado, seu Scale propriedade será alterada
de seu valor padrão de 1 para 0,8. O Normal VisualState Especifica que, quando o Button está em um estado
normal, seu Scale propriedade será definida como 1. Portanto, o efeito geral é que quando o Button é
pressionado, ele será escalada novamente para ser um pouco menores e quando o Button é lançado, ele será
escalada novamente ao seu tamanho padrão.
Para obter mais informações sobre estados visuais, consulte o Gerenciador de estado Visual xamarin. Forms.
public ToggleButton()
{
Clicked += (sender, args) => IsToggled ^= true;
}
// Fire event
toggleButton.Toggled?.Invoke(toggleButton, new ToggledEventArgs(isToggled));
O ToggleButton construtor anexa um manipulador para o Clicked evento para que ele possa alterar o valor da
IsToggled propriedade. O OnIsToggledChanged método dispara o Toggled eventos.
A última linha do OnIsToggledChanged chamadas de método estático VisualStateManager.GoToState método com
o texto de duas cadeias de caracteres "ToggledOn" e "ToggledOff". Você pode ler sobre esse método e como seu
aplicativo pode responder a estados visuais no artigo o Gerenciador de estado Visual xamarin. Forms.
Porque ToggleButton faz a chamada para VisualStateManager.GoToState , a classe em si não precisa incluir
quaisquer instalações adicionais para alterar a aparência do botão com base em seu IsToggled estado. Ou seja, a
responsabilidade do XAML que hospeda o ToggleButton .
O demonstração do botão de alternância página contém duas instâncias do ToggleButton , inclusive a
marcação de Gerenciador de estado Visual que define os Text , BackgroundColor , e TextColor do botão de
acordo com o estado visual:
<ContentPage.Resources>
<Style TargetType="local:ToggleButton">
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="HorizontalOptions" Value="Center" />
</Style>
</ContentPage.Resources>
<VisualState Name="ToggledOn">
<VisualState.Setters>
<Setter Property="Text" Value=" Italic On " />
<Setter Property="BackgroundColor" Value="#404040" />
<Setter Property="TextColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:ToggleButton>
<local:ToggleButton Toggled="OnBoldButtonToggled">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ToggleStates">
<VisualState Name="ToggledOff">
<VisualState.Setters>
<Setter Property="Text" Value="Bold Off" />
<Setter Property="BackgroundColor" Value="#C0C0C0" />
<Setter Property="TextColor" Value="Black" />
</VisualState.Setters>
</VisualState>
<VisualState Name="ToggledOn">
<VisualState.Setters>
<Setter Property="Text" Value=" Bold On " />
<Setter Property="BackgroundColor" Value="#404040" />
<Setter Property="TextColor" Value="White" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</local:ToggleButton>
<Label x:Name="label"
Text="Just a little passage of some sample text that can be formatted in italic or boldface by
toggling the two buttons."
FontSize="Large"
HorizontalTextAlignment="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Toggledmanipuladores de eventos estão no arquivo code-behind. Eles são responsáveis por configuração o
FontAttributes propriedade do Label com base no estado dos botões:
Os padrões são Left e 10 unidades. Duas propriedades somente leitura do ButtonContentLayout nomeado
Position e Spacing forneça os valores dessas propriedades.
No código, você pode criar uma Button e defina o ContentLayout propriedade como este:
Button button = new Button
{
Text = "button text",
Image = new FileImageSource
{
File = "image filename"
},
ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};
O imagem Button Demo página usa OnPlatform para especificar nomes de arquivo diferente para o iOS,
Android e UWP arquivos de bitmap. Se você quiser usar o mesmo nome de arquivo para cada plataforma e evite
o uso de OnPlatform , você precisa para armazenar os bitmaps UWP no diretório raiz do projeto.
A primeira Button no imagem Button Demo página conjuntos a Image propriedade, mas não o Text
propriedade:
<Button>
<Button.Image>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS, Android" Value="MonkeyFace.png" />
<On Platform="UWP" Value="Assets/MonkeyFace.png" />
</OnPlatform>
</Button.Image>
</Button>
Se os bitmaps UWP são armazenados no diretório raiz do projeto, essa marcação pode ser consideravelmente
simplificada:
Para evitar muita marcação repetitivas na ImageButtonDemo.xaml arquivo implícito Style também é
definido para configurar o Image propriedade. Isso Style é aplicada automaticamente a outros cinco Button
elementos. Aqui está o arquivo XAML completo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.ImageButtonDemoPage">
<FlexLayout Direction="Column"
JustifyContent="SpaceEvenly"
AlignItems="Center">
<FlexLayout.Resources>
<Style TargetType="Button">
<Setter Property="Image">
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS, Android" Value="MonkeyFace.png" />
<On Platform="UWP" Value="Assets/MonkeyFace.png" />
</OnPlatform>
</Setter>
</Style>
</FlexLayout.Resources>
<Button>
<Button.Image>
<OnPlatform x:TypeArguments="FileImageSource">
<On Platform="iOS, Android" Value="MonkeyFace.png" />
<On Platform="UWP" Value="Assets/MonkeyFace.png" />
</OnPlatform>
</Button.Image>
</Button>
Os quatro final Button elementos fazem uso do ContentLayout propriedade para especificar uma posição e o
espaçamento entre o texto e o bitmap:
Agora você já viu as várias maneiras que você pode manipular Button eventos e altere o Button aparência.
Links relacionados
Exemplo de ButtonDemos
Botão de API
Xamarin. Forms CollectionView
12/04/2019 • 3 minutes to read
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a
API pode mudar conforme a implementação for concluída.
CollectionView é um modo de exibição para apresentar as listas de dados usando as especificações de layout
diferente. Tem como objetivo fornecer uma mais flexível e alternativa de alto desempenho para o ListView .
Enquanto o CollectionView e ListView APIs são semelhantes, existem algumas diferenças importantes:
CollectionView tem um modelo de layout flexível que permite que os dados a ser apresentado verticalmente
ou horizontalmente, em uma lista ou uma grade.
CollectionView não tem nenhum conceito de células. Em vez disso, um modelo de dados é usado para definir
a aparência de cada item de dados na lista.
CollectionView utiliza automaticamente a virtualização fornecida pelos controles nativos subjacentes.
CollectionView reduz a superfície de API do ListView . Muitas propriedades e eventos do ListView não
estão presentes no CollectionView .
CollectionView não inclui separadores internos.
CollectionView está disponível nas versões de pré-lançamento de 4.0 do xamarin. Forms. No entanto, ele é
atualmente experimental e só pode ser usado, adicionando a seguinte linha de código para seus AppDelegate
classe no iOS, ou para seus MainActivity classe no Android, antes de chamar Forms.Init :
Forms.SetFlags("CollectionView_Experimental");
NOTE
CollectionView só está disponível no iOS e Android.
Baixar o exemplo
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a API
pode mudar conforme a implementação for concluída.
CollectionView Define as seguintes propriedades que definem os dados a ser exibido e sua aparência:
ItemsSource , do tipo IEnumerable , especifica a coleção de itens a serem exibidos, e tem um valor padrão de
null .
ItemTemplate, do tipo DataTemplate , especifica o modelo a ser aplicado a cada item na coleção de itens a
serem exibidos.
Essas propriedades têm o respaldo BindableProperty objetos, o que significa que as propriedades podem ser alvos
de vinculações de dados.
<CollectionView>
<CollectionView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</CollectionView.ItemsSource>
</CollectionView>
NOTE
Observe que o elemento x:Array requer um atributo Type que indica o tipo dos itens na matriz.
O código C# equivalente é:
IMPORTANT
Se o CollectionView é necessária para atualizada à medida que itens são adicionados, removidos ou alterados na coleção
subjacente, a coleção subjacente deve ser um IEnumerable coleção que envia a propriedade notificações de alteração, como
ObservableCollection .
Por padrão, CollectionView exibe itens em uma lista vertical, conforme mostrado nas capturas de tela seguir:
Para obter informações sobre como alterar o CollectionView layout, consulte especificar um Layout. Para obter
informações sobre como definir a aparência de cada item na CollectionView , consulte definem a aparência do
item.
Associação de dados
CollectionView pode ser preenchido com dados usando associação de dados para associar seu ItemsSource
propriedade para um IEnumerable coleção. No XAML, isso é feito com o Binding extensão de marcação:
O código C# equivalente é:
Neste exemplo, o ItemsSource associa dados de propriedade para o Monkeys propriedade do modelo de exibição
conectado.
NOTE
Associações compiladas podem ser habilitadas para melhorar o desempenho de associação de dados em aplicativos xamarin.
Forms. Para obter mais informações, consulte compilado associações.
Para obter mais informações sobre associação de dados, confira Associação de Dados do Xamarin.Forms.
O código C# equivalente é:
CollectionView collectionView = new CollectionView();
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
Grid.SetRowSpan(image, 2);
grid.Children.Add(image);
grid.Children.Add(nameLabel, 1, 0);
grid.Children.Add(locationLabel, 1, 1);
return grid;
});
Os elementos especificados na DataTemplate definem a aparência de cada item na lista. No exemplo, o layout do
DataTemplate é gerenciada por um Grid . O Grid contém uma Image objeto e duas Label objetos, que todos se
associar a propriedades do Monkey classe:
Links relacionados
CollectionView (amostra)
Associação de dados do xamarin. Forms
Modelos de dados do xamarin. Forms
Especifique o Layout do xamarin. Forms
CollectionView
12/04/2019 • 11 minutes to read
Baixar o exemplo
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a
API pode mudar conforme a implementação for concluída.
Essas propriedades têm o respaldo BindableProperty objetos, o que significa que as propriedades podem ser
alvos de vinculações de dados.
Por padrão, um CollectionView exibirá seus itens em uma lista vertical. No entanto, qualquer um dos seguintes
layouts podem ser usados:
Lista vertical – uma lista de coluna única que cresce verticalmente conforme novos itens são adicionados.
Lista horizontal – uma lista de única linha cresce horizontalmente conforme novos itens são adicionados.
Grade vertical – uma grade de várias coluna que cresce verticalmente conforme novos itens são adicionados.
Grade horizontal – uma grade de várias linhas cresce horizontalmente conforme novos itens são adicionados.
Esses layouts podem ser especificados definindo a ItemsLayout propriedade para a classe que deriva de
ItemsLayout classe. Essa classe define as propriedades a seguir:
NOTE
CollectionView usa os mecanismos de layout nativo para executar o layout.
Lista vertical
Por padrão, CollectionViewexibirá seus itens em um layout da lista vertical. Portanto, não é necessário definir o
ItemsLayout propriedade para usar este layout:
No entanto, para fins de integridade, uma CollectionView pode ser definido para exibir seus itens em uma lista
vertical definindo seu ItemsLayout a um estático ListItemsLayout.VerticalList membro:
Como alternativa, isso também pode ser feito definindo a ItemsLayout propriedade para um objeto do
ListItemsLayout classe, especificando as Vertical ItemsLayoutOrientation membro de enumeração como um
argumento:
O código C# equivalente é:
Isso resulta em uma lista de coluna única que cresce verticalmente conforme novos itens são adicionados:
Lista horizontal
CollectionView pode exibir seus itens em uma lista horizontal, definindo sua ItemsLayout propriedade para
estático ListItemsLayout.HorizontalList membro:
<CollectionView ItemsSource="{Binding Monkeys}"
ItemsLayout="{x:Static ListItemsLayout.HorizontalList}">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="35" />
<RowDefinition Height="35" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="70" />
<ColumnDefinition Width="140" />
</Grid.ColumnDefinitions>
<Image Grid.RowSpan="2"
Source="{Binding ImageUrl}"
Aspect="AspectFill"
HeightRequest="60"
WidthRequest="60" />
<Label Grid.Column="1"
Text="{Binding Name}"
FontAttributes="Bold"
LineBreakMode="TailTruncation" />
<Label Grid.Row="1"
Grid.Column="1"
Text="{Binding Location}"
LineBreakMode="TailTruncation"
FontAttributes="Italic"
VerticalOptions="End" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
Como alternativa, isso também pode ser feito definindo a ItemsLayout propriedade para um ListItemsLayout do
objeto, especificando as Horizontal ItemsLayoutOrientation membro de enumeração como um argumento:
O código C# equivalente é:
Isso resulta em uma lista de única linha, que cresce horizontalmente conforme novos itens são adicionados:
Grade vertical
CollectionView pode exibir seus itens em uma grade vertical, definindo sua ItemsLayout propriedade para um
GridItemsLayout do objeto cuja Orientation estiver definida como Vertical :
O código C# equivalente é:
Por padrão, um vertical GridItemsLayout exibirá itens em uma única coluna. No entanto, este exemplo define o
GridItemsLayout.Span propriedade como 2. Isso resulta em uma grade de duas colunas, cresce verticalmente
conforme novos itens são adicionados:
Grade horizontal
CollectionView pode exibir seus itens em uma grade horizontal, definindo sua ItemsLayout propriedade para um
GridItemsLayout do objeto cuja Orientation estiver definida como Horizontal :
O código C# equivalente é:
CollectionView collectionView = new CollectionView
{
...
ItemsLayout = new GridItemsLayout(4, ItemsLayoutOrientation.Horizontal)
};
Por padrão, um horizontal GridItemsLayout exibirá itens em uma única linha. No entanto, este exemplo define o
GridItemsLayout.Span propriedade para 4. Isso resulta em uma grade de quatro linhas, que cresce
horizontalmente conforme novos itens são adicionados:
O padrão FlowDirection para um elemento com um pai é MatchParent . Portanto, o CollectionView herda a
FlowDirection valor da propriedade a StackLayout , que por sua vez herda o FlowDirection valor da propriedade
do ContentPage . Isso resulta no layout da direita para esquerda mostrado nas capturas de tela seguir:
Para obter mais informações sobre a direção do fluxo, consulte localização da direita para esquerda.
Dimensionamento do item
Por padrão, cada item em uma CollectionView é individualmente medido e dimensionado, desde que os
elementos de interface do usuário na DataTemplate não especificar tamanhos fixos. Esse comportamento, que
pode ser alterado, é especificado pelo CollectionView.ItemSizingStrategy valor da propriedade. Esse valor de
propriedade pode ser definido como um do ItemSizingStrategy membros de enumeração:
MeasureAllItems – cada item é medida individualmente. Este é o valor padrão.
MeasureFirstItem – somente o primeiro item é medido, com todos os itens subsequentes que está sendo
fornecidos do mesmo tamanho que o primeiro item.
IMPORTANT
O MeasureFirstItem estratégia de dimensionamento deve ser usado em situações em que o tamanho do item se destina
a ser uniforme em todos os itens e resultará em um melhor desempenho.
<CollectionView ...
ItemSizingStrategy="MeasureFirstItem">
...
</CollectionView>
O código C# equivalente é:
Links relacionados
CollectionView (amostra)
Localização da direita para esquerda
Rolar um Item na exibição
Definir o modo de seleção CollectionView
12/04/2019 • 8 minutes to read
Baixar o exemplo
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a API
pode mudar conforme a implementação for concluída.
Todas essas propriedades têm o respaldo BindableProperty objetos, o que significa que as propriedades podem
ser alvos de vinculações de dados.
Por padrão, CollectionView seleção está desabilitada. No entanto, esse comportamento pode ser alterado
definindo a SelectionMode valor de propriedade a um do SelectionMode membros de enumeração:
None – indica que os itens não podem ser selecionados. Este é o valor padrão.
Single – indica que um único item pode ser selecionado, com o item selecionado que está sendo realçado.
Multiple – indica que vários itens podem ser selecionados, com os itens selecionados que está sendo
realçados.
CollectionView define uma SelectionChanged evento que é disparado quando o SelectedItem propriedade é
alterada, seja porque o usuário selecionar um item da lista, ou quando um aplicativo define a propriedade. O
SelectionChangedEventArgs objeto que acompanha o SelectionChanged evento tem duas propriedades, ambos do
tipo IReadOnlyList<object> :
PreviousSelection – a lista de itens que foram selecionados, antes que a seleção é alterada.
CurrentSelection – a lista de itens selecionados, após a alteração da seleção.
Seleção única
Quando o SelectionMode estiver definida como Single , um único item no CollectionView podem ser
selecionados. Quando um item é selecionado, o SelectedItem propriedade será definida como o valor do item
selecionado. Quando essa propriedade é alterada, o SelectionChangedCommand é executada (com o valor da
SelectionChangedCommandParameter que está sendo passado para o ICommand ) e o SelectionChanged evento é
acionado.
A exemplo XAML a seguir mostra um CollectionView que pode responder a seleção de item único:
O código C# equivalente é:
IMPORTANT
O SelectionChanged eventos podem ser acionados por alterações que ocorrem como resultado da alteração de
SelectionMode propriedade.
Pré-seleção
Quando o SelectionMode estiver definida como Single , um único item na CollectionView previamente
selecionadas, definindo o SelectedItem propriedade para o item. A exemplo XAML a seguir mostra um
CollectionView que pré-seleciona um único item:
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single"
SelectedItem="{Binding SelectedMonkey, Mode=TwoWay}">
...
</CollectionView>
O código C# equivalente é:
Monkey selectedMonkey;
public Monkey SelectedMonkey
{
get
{
return selectedMonkey;
}
set
{
if (selectedMonkey != value)
{
selectedMonkey = value;
}
}
}
public MonkeysViewModel()
{
...
selectedMonkey = Monkeys.Skip(3).FirstOrDefault();
}
...
}
<ContentPage ...>
<ContentPage.Resources>
<Style TargetType="Grid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="LightSkyBlue" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>
<StackLayout Margin="20">
<CollectionView ItemsSource="{Binding Monkeys}"
SelectionMode="Single">
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid Padding="10">
...
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
IMPORTANT
O Style que contém o Selected VisualState deve ter uma TargetType valor da propriedade que é o tipo de
elemento raiz do DataTemplate , que é definido como o ItemTemplate valor da propriedade.
Neste exemplo, o Style.TargetType o valor da propriedade é definido como Grid porque o elemento raiz do
ItemTemplate é um Grid . O Selected VisualState Especifica que quando um item no CollectionView estiver
selecionada, o BackgroundColor do item será definido como LightSkyBlue :
[ ] (selection-images/single-selection-color-
large.png#lightbox " Lista vertical de CollectionView com uma cor personalizada de seleção única")
Para obter mais informações sobre estados visuais, consulte Gerenciador de estado Visual do xamarin. Forms.
Desabilitar seleção
CollectionView seleção é desabilitada por padrão. No entanto, se um CollectionView tem seleção habilitada, ele
pode ser desabilitado definindo o SelectionMode propriedade para None :
<CollectionView ...
SelectionMode="None" />
O código C# equivalente é:
Quando o SelectionMode estiver definida como None , os itens na CollectionView não pode ser selecionado, o
SelectedItem propriedade permanecerá null e o SelectionChanged evento não será disparado.
NOTE
Quando um item foi selecionado e o SelectionMode propriedade é alterada de Single ao None , o SelectedItem
propriedade será definida como null e o SelectionChanged evento será acionado com um vazio CurrentSelection
propriedade.
Links relacionados
CollectionView (amostra)
Xamarin. Forms Visual State Manager
Exibir um EmptyView quando dados não estão
disponível
12/04/2019 • 9 minutes to read
Baixar o exemplo
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a API
pode mudar conforme a implementação for concluída.
CollectionView Define as propriedades a seguir que podem ser usadas para fornecer comentários do usuário
quando não há nenhum dado para exibir:
EmptyView , do tipo , a cadeia de caracteres, a associação ou o modo de exibição que será exibido
object
quando o ItemsSource é de propriedade null , ou quando a coleção especificada pelo ItemsSource é de
propriedade null ou está vazio. O valor padrão é null .
EmptyViewTemplate , do tipo DataTemplate , o modelo a ser usado para formatar especificado EmptyView . O
valor padrão é null .
Essas propriedades têm o respaldo BindableProperty objetos, o que significa que as propriedades podem ser alvos
de vinculações de dados.
Os cenários de uso principal para a configuração de EmptyView propriedade estiver exibindo comentários do
usuário quando uma operação de filtragem em um CollectionView produz sem dados e exibir comentários do
usuário, enquanto os dados estão sendo recuperados de um serviço web.
NOTE
O EmptyView propriedade pode ser definida como uma exibição que inclui conteúdo interativo, se necessário.
Para obter mais informações sobre modelos de dados, confira Modelos de dados do Xamarin.Forms.
O código C# equivalente é:
CollectionView collectionView = new CollectionView
{
EmptyView = "No items to display"
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "EmptyMonkeys");
O resultado é que, como os dados associados a coleção é null , a cadeia de caracteres é definido como o
EmptyView valor da propriedade é exibido:
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
<CollectionView.EmptyView>
<StackLayout>
<Label Text="No results matched your filter."
Margin="10,25,10,10"
FontAttributes="Bold"
FontSize="18"
HorizontalOptions="Fill"
HorizontalTextAlignment="Center" />
<Label Text="Try a broader filter?"
FontAttributes="Italic"
FontSize="12"
HorizontalOptions="Fill"
HorizontalTextAlignment="Center" />
</StackLayout>
</CollectionView.EmptyView>
</CollectionView>
</StackLayout>
O código C# equivalente é:
SearchBar searchBar = new SearchBar { ... };
CollectionView collectionView = new CollectionView
{
EmptyView = new StackLayout
{
Children =
{
new Label { Text = "No results matched your filter.", ... },
new Label { Text = "Try a broader filter?", ... }
}
}
};
collectionView.SetBinding(ItemsView.ItemsSourceProperty, "Monkeys");
Quando o SearchBar executa o FilterCommand , a coleção exibida pelo CollectionView é filtrado para o termo de
pesquisa são armazenados no SearchBar.Text propriedade. Se a operação de filtragem não produz nenhum dado,
o StackLayout definido como o EmptyView valor da propriedade é exibido:
O código C# equivalente é:
O EmptyView estiver definida como uma FilterData objeto e o Filter associa dados de propriedade para o
SearchBar.Text propriedade. Quando o SearchBar executa o FilterCommand , a coleção exibida pelo
CollectionView é filtrado para o termo de pesquisa são armazenados no Filter propriedade. Se a operação de
filtragem não produz nenhum dado, o Label definidos no DataTemplate , que é definido como o
EmptyViewTemplate valor da propriedade, é exibida:
NOTE
Ao exibir um tipo de modelo personalizado quando dados não estiverem disponíveis, o EmptyViewTemplate propriedade
pode ser definida como uma exibição que contém vários modos de exibição filho.
<StackLayout Margin="20">
<SearchBar x:Name="searchBar"
SearchCommand="{Binding FilterCommand}"
SearchCommandParameter="{Binding Source={x:Reference searchBar}, Path=Text}"
Placeholder="Filter" />
<StackLayout Orientation="Horizontal">
<Label Text="Toggle EmptyViews" />
<Switch Toggled="OnEmptyViewSwitchToggled" />
</StackLayout>
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</ContentPage>
Esse XAML define dois ContentView objetos no nível da página ResourceDictionary , com o Switch objeto
controlando quais ContentView objeto será definido como o EmptyView valor da propriedade. Quando o Switch é
alternado, o OnEmptyViewSwitchToggled manipulador de eventos executa o ToggleEmptyView método:
O ToggleEmptyView método define o EmptyView propriedade da collectionView objeto para um dos dois
ContentView objetos armazenados no ResourceDictionary , com base no valor da Switch.IsToggled propriedade.
Quando o SearchBar executa o FilterCommand , a coleção exibida pelo CollectionView é filtrado para o termo de
pesquisa são armazenados no SearchBar.Text propriedade. Se a operação de filtragem não produz nenhum dado,
o ContentView objeto definido como o EmptyView propriedade é exibida:
Para obter mais informações sobre dicionários de recursos, consulte dicionários de recursos do xamarin. Forms.
Links relacionados
CollectionView (amostra)
Modelos de dados do xamarin. Forms
Dicionários de recursos do xamarin. Forms
Rolar um Item na exibição
12/04/2019 • 9 minutes to read
Baixar o exemplo
IMPORTANT
O CollectionView atualmente é uma visualização e não tem algumas das suas funcionalidades planejada. Além disso, a
API pode mudar conforme a implementação for concluída.
CollectionView define dois ScrollTo métodos, que rolagem os itens na exibição. Uma das sobrecargas rola o
item no índice especificado na exibição, enquanto o outro rola o item especificado na exibição. Ambas as
sobrecargas têm argumentos adicionais que podem ser especificados para indicar a posição exata do item depois
que a rolagem for concluída e se deseja animar a rolagem.
CollectionView define uma ScrollToRequestedevento que é disparado quando uma da ScrollTo métodos é
invocado. O ScrollToRequestedEventArgs objeto que acompanha o ScrollToRequested evento tem muitas
propriedades, incluindo IsAnimated , Index , Item , e ScrollToPosition . Essas propriedades são definidas a partir
dos argumentos especificados no ScrollTo chamadas de método.
Quando um dedo do usuário para iniciar uma rolagem, a posição final da rolagem pode ser controlada para que
os itens são totalmente exibidas. Esse recurso é conhecido como encaixe, como itens de ajuste para posicionar
durante a rolagem é interrompido. Para obter mais informações, consulte ajustar pontos.
collectionView.ScrollTo(12);
Esse código de exemplo resulta na rolagem mínima necessária para rolar o item na exibição:
NOTE
O ScrollToPosition.MakeVisible membro é usado por padrão, se o position argumento não for especificado ao
chamar o ScrollTo método.
Início
O ScrollToPosition.Start membro indica que o item deve ser rolado para o início do modo de exibição:
Esse código de exemplo resulta no item que está sendo rolado para o início da exibição:
Centralizado
O ScrollToPosition.Center membro indica que o item deve ser rolado para o centro do modo de exibição:
Esse código de exemplo resulta no item que está sendo rolado para o centro da exibição:
End
O ScrollToPosition.End membro indica que o item deve ser rolado até o final do modo de exibição:
Esse código de exemplo resulta no item que está sendo rolado até o final do modo de exibição:
Desativar a animação de rolagem
Uma animação de rolagem é exibida quando um item de rolagem no modo de exibição. No entanto, essa
animação pode ser desabilitada definindo a animate argumento do ScrollTo método false :
Pontas de encaixe
Quando um dedo do usuário para iniciar uma rolagem, a posição final da rolagem pode ser controlada para que
os itens são totalmente exibidas. Esse recurso é conhecido como encaixe, como itens de ajustar-se à posição
quando rolagem for interrompido e é controlada pelas seguintes propriedades do ItemsLayout classe:
SnapPointsType , do tipo SnapPointsType , especifica o comportamento de pontos de alinhamento durante a
rolagem.
SnapPointsAlignment , do tipo SnapPointsAlignment , especifica como os pontos de alinhamento são alinhados
com os itens.
Essas propriedades têm o respaldo BindableProperty objetos, o que significa que as propriedades podem ser
alvos de vinculações de dados.
NOTE
Quando o ajuste ocorre, ele ocorrerá na direção que produz a menor quantidade de movimento.
Por padrão, o SnapPointsType estiver definida como SnapPointsType.None , que garante que a rolagem não se
ajusta itens, conforme mostrado nas capturas de tela seguir:
Ajustar-se pontos de alinhamento
O SnapPointsAlignment enumeração define Start , Center ,e End membros.
IMPORTANT
O valor da SnapPointsAlignment propriedade só é respeitada quando o SnapPointsType estiver definida como
Mandatory , ou MandatorySingle .
Início
O SnapPointsAlignment.Start membro indica que pontos de alinhamento são alinhados com a borda à esquerda
de itens.
Por padrão, o SnapPointsAlignment estiver definida como SnapPointsAlignment.Start . No entanto, para fins de
integridade, o exemplo XAML a seguir mostra como definir este membro de enumeração:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout SnapPointsType="MandatorySingle"
SnapPointsAlignment="Start">
<x:Arguments>
<ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
O código C# equivalente é:
CollectionView collectionView = new CollectionView
{
ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Vertical)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Start
},
ItemTemplate = new DataTemplate(() =>
{
return null;
})
};
Quando um dedo do usuário para iniciar uma rolagem, o item superior será alinhado à parte superior do modo
de exibição:
Centralizado
O SnapPointsAlignment.Center membro indica que pontos de alinhamento são alinhados com a Central de itens.
O exemplo XAML a seguir mostra como definir este membro de enumeração:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout SnapPointsType="MandatorySingle"
SnapPointsAlignment="Center">
<x:Arguments>
<ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
O código C# equivalente é:
CollectionView collectionView = new CollectionView
{
ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Vertical)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.Center
},
ItemTemplate = new DataTemplate(() =>
{
return null;
})
};
Quando um dedo do usuário para iniciar uma rolagem, o item superior será centralizado na parte superior do
modo de exibição:
End
O SnapPointsAlignment.End membro indica que os pontos de alinhamento são alinhados com a borda direita de
itens. O exemplo XAML a seguir mostra como definir este membro de enumeração:
<CollectionView x:Name="collectionView"
ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout SnapPointsType="MandatorySingle"
SnapPointsAlignment="End">
<x:Arguments>
<ItemsLayoutOrientation>Vertical</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
...
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
O código C# equivalente é:
CollectionView collectionView = new CollectionView
{
ItemsLayout = new ListItemsLayout(ItemsLayoutOrientation.Vertical)
{
SnapPointsType = SnapPointsType.MandatorySingle,
SnapPointsAlignment = SnapPointsAlignment.End
},
ItemTemplate = new DataTemplate(() =>
{
return null;
})
};
Quando um dedo do usuário para iniciar uma rolagem, o item na parte inferior será alinhado à parte inferior do
modo de exibição:
Links relacionados
CollectionView (amostra)
Cores no xamarin. Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Xamarin. Forms fornece uma classe flexível de cor de plataforma cruzada.
Este artigo apresenta as várias maneiras do Color classe pode ser usada no xamarin. Forms.
O Color classe fornece vários métodos para criar uma instância de cor
Chamado Colors -uma coleção de comuns cores nomeadas, incluindo Red , Green , e Blue .
FromHex -valor semelhante à sintaxe usada em HTML, por exemplo, "00FF00" cadeia de caracteres. Alfa é
opcionalmente pode ser especificado como o primeiro par de caracteres ("CC00FF00").
FromHsla -matiz, saturação e luminosidade double valores, com valor de alfa opcional (0.0-1.0).
FromRgb -vermelho, verde e azul int valores (0 a 255).
FromRgba -vermelho, verde, azul e alfa int valores (0 a 255).
FromUint -definir uma única double valor que representa argb.
Eis aqui algumas cores de exemplo, atribuídos para o BackgroundColor de alguns rótulos usando diferentes
variações da sintaxe permitido:
Essas cores são mostrados em cada plataforma abaixo. Observe a cor final - Accent -é uma cor blue-ish para iOS
e Android; esse valor é definido pelo xamarin. Forms.
Color.Default
Use o Default para definir um valor de cor para o padrão de plataforma (Noções básicas sobre que isso
representa uma cor subjacente diferente em cada plataforma para cada propriedade) (ou defina novamente uma).
Os desenvolvedores podem usar esse valor para definir um Color propriedade, mas deve não consultar essa
instância para obter seus valores RGB do componente (eles são todos definidos como -1).
Color.Transparent
Defina a cor para limpar.
Color.Accent
No iOS e Android desta instância é definida como uma cor contrastante que está visível na tela de fundo padrão,
mas não é o mesmo que a cor do texto padrão.
Métodos adicionais
Color instâncias incluem métodos adicionais que podem ser usados para criar novas cores:
AddLuminosity -retorna uma nova cor, modificando a luminosidade pelo delta fornecido.
WithHue -retorna uma nova cor, substituindo o hue com o valor fornecido.
WithLuminosity -retorna uma nova cor, substituindo a luminosidade com o valor fornecido.
WithSaturation -retorna uma nova cor, substituindo a saturação com o valor fornecido.
MultiplyAlpha -retorna uma nova cor, modificando o alfa, multiplicá-lo pelo valor alfa fornecido.
Conversões implícitas
Conversão implícita entre o Xamarin.Forms.Color e System.Drawing.Color tipos podem ser executados:
Device.RuntimePlatform
Este trecho de código usa o Device.RuntimePlatform propriedade para definir seletivamente a cor de um
ActivityIndicator :
Usando do XAML
Cores também podem ser facilmente referenciadas em XAML usando os nomes de cor definidos ou as
representações hexa mostradas aqui:
<Label Text="Sea color" BackgroundColor="Aqua" />
<Label Text="RGB" BackgroundColor="#00FF00" />
<Label Text="Alpha plus RGB" BackgroundColor="#CC00FF00" />
<Label Text="Tiny RGB" BackgroundColor="#0F0" />
<Label Text="Tiny Alpha plus RGB" BackgroundColor="#C0F0" />
NOTE
Ao usar a compilação de XAML, nomes de cores diferenciam maiusculas de minúsculas e, portanto, podem ser escritos em
letras minúsculas. Para obter mais informações sobre a compilação de XAML, consulte compilação XAML.
Resumo
O xamarin. Forms Color classe é usada para criar referências de cores de reconhecimento de plataforma. Ele
pode ser usado no código compartilhado e XAML.
Links relacionados
ColorsSample
Seletor de associável (amostra)
Referência de Controles
12/04/2019 • 2 minutes to read
baixar o exemplo
Uma descrição de todos os elementos visuais usados para construir um aplicativo xamarin. Forms.
A interface visual de um aplicativo xamarin. Forms é construída de objetos que são mapeados para controles
nativos de cada plataforma de destino. Isso permite que aplicativos específicos da plataforma para iOS, Android e
plataforma Universal do Windows usar código xamarin. Forms contido em um .NET Standard library ou um
projeto compartilhado.
Os quatro grupos de controle principal usados para criar a interface do usuário de um aplicativo xamarin. Forms
são mostrados nesses quatro artigos:
Páginas
Layouts
Modos de exibição
Células
Geralmente, uma página do xamarin. Forms ocupa a tela inteira. A página normalmente contém um layout, que
contém exibições e possivelmente outros layouts. As células são componentes especializados usados na conexão
com TableView e ListView .
Nos quatro artigos sobre páginas, Layouts, exibições , e células, cada tipo de controle é descrito com links
para documentação da API, um artigo que descreve seu uso (se houver) e um ou mais programas de exemplo (se
existirem). Cada tipo de controle também é acompanhado de uma captura de tela mostrando uma página a partir
de FormsGallery exemplo dispositivos em execução no iOS, Android e UWP. Cada captura de tela abaixo estão
os links para o código-fonte para a página em C#, a página XAML equivalente e (quando apropriado) o arquivo
de code-behind do C# para a página XAML.
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Documentação da API
Páginas do xamarin. Forms
12/04/2019 • 4 minutes to read
baixar o exemplo
Páginas do xamarin. Forms representam telas de aplicativos móveis de plataforma cruzada.
Todos os tipos de página que são descritos abaixo derivam da classe Page do Xamarin.Forms. Esses elementos
visuais ocupam toda a tela ou a maior parte dela. Um objeto Page representa um ViewController no iOS e um
Page na Plataforma Universal do Windows. No Android, cada página ocupa a tela como Activity , mas as
páginas Xamarin.Forms não são objetos Activity .
Pages (Páginas)
Xamarin. Forms dá suporte aos seguintes tipos de página:
ContentPage
Documentação da API
MasterDetailPage
Um MasterDetailPage gerencia dois painéis de
informações. Defina as Master propriedade a uma página
em geral, mostrando uma lista ou menu. Defina as Detail
propriedade para uma página mostrando um item
selecionado da página mestra. O IsPresented propriedade
controla se a página mestra ou de detalhes está visível.
NavigationPage
TabbedPage
CarouselPage
CarouselPage deriva de abstrata MultiPage de classe e
permite a navegação entre filho páginas por meio de passar
o dedo dedo. Defina a Children propriedade a uma
coleção de ContentPage objetos ou conjunto o
ItemsSource propriedade a uma coleção de objetos de
dados e o ItemTemplate propriedade como um
DataTemplate que descreve como cada objeto deve ser
visualmente representado.
TemplatedPage
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Amostras do Xamarin.Forms
Documentação da API do Xamarin.Forms
Layouts do xamarin. Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Layouts do xamarin. Forms são usados para compor controles de interface do usuário em estruturas de visual.
O Layout e Layout<T> classes no xamarin. Forms são subtipos especializados de exibições que atuam como
contêineres para outros layouts e exibições. O Layout deriva de classe em si View . Um Layout derivativo
normalmente contém lógica para definir a posição e tamanho dos elementos filho em aplicativos xamarin.
Forms.
Documentação da API
Documentação da API
ScrollView
TemplatedView
ContentPresenter
ContentPresenter é um Gerenciador de layout para
exibições com modelo, usado em uma ControlTemplate
para marcar onde o conteúdo que deve ser apresentada
aparece.
Grade
AbsoluteLayout
AbsoluteLayout Posiciona os elementos filho em locais
específicos em relação ao seu pai. Posição de um filho é
indicada usando o propriedades anexadas LayoutBounds e
LayoutFlags . Um AbsoluteLayout é útil para animar as
posições dos modos de exibição.
RelativeLayout
FlexLayout
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Amostras do Xamarin.Forms
Documentação da API do Xamarin.Forms
Modos de exibição do xamarin. Forms
16/04/2019 • 13 minutes to read
baixar o exemplo
Modos de exibição do xamarin. Forms são os blocos de construção de interfaces de usuário móvel de
plataforma cruzada.
Modos de exibição são objetos de interface do usuário, como rótulos, botões e controles deslizantes que são
normalmente conhecidos como controles ou widgets em outros ambientes de programação gráficas. As
exibições compatíveis com o xamarin. Forms todos derivam de View classe. Eles podem ser divididos em várias
categorias:
Image
BoxView
BoxView Exibe um retângulo sólido colorido pela Color
propriedade. BoxView tem uma solicitação de tamanho
padrão de 40 x 40. Para outros tamanhos, atribuir a
WidthRequest e HeightRequest propriedades.
WebView
OpenGLView
Documentação da API
Mapa
Map Exibe um mapa. O Xamarin.Forms.Maps pacote do
Nuget deve ser instalado. Android e plataforma Universal do
Windows exigem uma chave de autorização do mapa.
ImageButton
Guia / exemplo
SearchBar
SearchBar Exibe uma área para o usuário digite uma
cadeia de caracteres de texto e um botão (ou uma tecla do
teclado) que sinaliza o aplicativo para realizar uma pesquisa.
O Text propriedade fornece acesso ao texto e o
SearchButtonPressed evento indica que o botão foi
pressionado.
Documentação da API
Escalonador
Alternar
Switch assume a forma de uma chave liga/desliga para
permitir que o usuário selecione um valor booliano. O
IsToggled propriedade é o estado do comutador e o
Toggled evento é acionado quando o estado é alterado.
Documentação da API
DatePicker
TimePicker
Editor
Documentação da API
ProgressBar
ProgressBar usa uma animação para mostrar que o
aplicativo está em andamento através de uma atividade
demorada. Defina as Progress propriedade para valores
entre 0 e 1 para indicar o progresso.
Documentação da API
Guia / exemplo
O código C# para esta página / página XAML
ListView
Seletor
Picker Exibe um item selecionado em uma lista de cadeias
de caracteres de texto e permite selecionar esse item quando
o modo de exibição é tocado. Defina a Items propriedade
a uma lista de cadeias de caracteres ou o ItemsSource
propriedade a uma coleção de objetos. O
SelectedIndexChanged evento é disparado quando um
item é selecionado.
Documentação da API / guia / exemplo O código C# para esta página / página XAML com de lógica
Modo de tabela
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Amostras do Xamarin.Forms
Documentação da API do Xamarin.Forms
Células do xamarin. Forms
12/04/2019 • 2 minutes to read
baixar o exemplo
As células do xamarin. Forms podem ser adicionadas a ListViews e TableViews.
Um célula é um elemento especializado usado para itens em uma tabela e descreve como cada item em uma lista
deve ser renderizado. O Cell classe deriva Element , do qual VisualElement também deriva. Uma célula não é
propriamente um elemento visual. em vez disso, ele é um modelo para a criação de um elemento visual.
Cell é usado exclusivamente com ListView e TableView controles. Para saber como usar e personalizar
células, consulte o ListView e TableView documentação.
Células
Xamarin. Forms dá suporte aos seguintes tipos de célula:
TextCell
ImageCell
EntryCell
Links relacionados
Exemplo de xamarin. Forms FormsGallery
Amostras do Xamarin.Forms
Documentação da API do Xamarin.Forms
Xamarin. Forms DataSourceControl
12/04/2019 • 3 minutes to read
IMPORTANT
DataSourceControl requer uma xamarin. Forms tema referência ao renderizar.
Xamarin. Forms DataSourceControl foram lançados no Evolve 2016 e estão disponível como uma visualização
para que os clientes experimentar e fornecer comentários.
DataSourceControl fornece uma API para rápida e facilmente vincular uma fonte de dados para exibições
predefinidas. Itens de lista e páginas de detalhes renderização automaticamente os dados e podem ser
personalizadas usando temas.
Para ver como funciona a palestra de demonstração evoluem, confira a guia de Introdução.
Introdução
Fontes de dados e as páginas de dados associadas permitem que os desenvolvedores rapidamente e facilmente
consumir uma fonte de dados com suporte e renderizá-lo usando interno que o scaffolding de interface do usuário
pode ser personalizado com temas.
DataSourceControl é adicionados a um aplicativo xamarin. Forms, incluindo o Xamarin.Forms.Pages pacote do
Nuget.
Data Sources
A visualização tem algumas fontes de dados predefinidos disponíveis para uso:
JsonDataSource
AzureDataSource (separe Nuget)
AzureEasyTableDataSource (separe Nuget)
Consulte a guia de Introdução para obter um exemplo usando um JsonDataSource .
Páginas e controles
As seguintes páginas e controles estão incluídos para permitir a fácil associação às fontes de dados fornecido:
ListDataPage – consulte a Introdução ao exemplo.
DirectoryPage – uma lista com o agrupamento habilitado.
PersonDetailPage – um modo de exibição personalizado para um tipo de objeto específico (uma entrada de
contato) de item de dados únicos.
DataView – um modo de exibição para expor os dados da origem de uma forma genérica.
Widgets CardView – um com o estilo de exibição que contém uma imagem, o texto do título e o texto de
descrição.
HeroImage – um modo de exibição de renderização de imagem.
ListItem – um pré-criados em modo de exibição com um layout semelhante ao iOS nativo e itens de lista para
Android.
Consulte a referência de controles DataSourceControl para obter exemplos.
Nos bastidores
Uma fonte de dados do xamarin. Forms segue o IDataSource interface.
A infraestrutura do xamarin. Forms interage com uma fonte de dados por meio das seguintes propriedades:
Data – uma lista somente leitura de itens de dados que podem ser exibidos.
IsLoading – um valor booliano que indica se os dados são carregados e estão disponíveis para renderização.
[key] – um indexador para recuperar elementos.
Há dois métodos MaskKey e UnmaskKey que pode ser usado para ocultar (ou Mostrar) propriedades do item de
dados (ie. impedi que está sendo processado). A chave corresponde à uma propriedade nomeada no objeto de
item de dados.
Guia de Introdução DataSourceControl
18/04/2019 • 7 minutes to read
baixar o exemplo
IMPORTANT
DataSourceControl requer uma xamarin. Forms tema referência ao renderizar.
Para começar a criação de uma página simple controlado por dados usando a visualização DataSourceControl,
siga as etapas abaixo. Este usa demonstração um estilo de embutidos em código ("eventos") na visualização
compilações que só funciona com o formato JSON específico no código.
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mytheme="clr-namespace:Xamarin.Forms.Themes;assembly=Xamarin.Forms.Theme.Light"
x:Class="DataPagesDemo.App">
<Application.Resources>
<ResourceDictionary MergedWith="mytheme:LightThemeResources" />
</Application.Resources>
</Application>
IMPORTANTE: Você também deve seguir as etapas a serem carregar assemblies de tema (abaixo) adicionando
um código clichê para o iOS AppDelegate e Android MainActivity . Isso será melhorado em uma versão de
visualização futura.
Arquivo XAML
Além de alterar o elemento raiz ser <p:ListDataPage> o espaço para nome personalizado xmlns:p também deve
ser adicionado:
<ContentPage.Content></ContentPage.Content>
</p:ListDataPage>
Subclasse de aplicativo
Alterar o App construtor de classe, de modo que o MainPage é definido como um NavigationPage que contém o
novo SessionDataPage . Uma página da navegação deve ser usado.
<p:ListDataPage.DataSource>
<p:JsonDataSource Source="http://demo3143189.mockable.io/sessions" />
</p:ListDataPage.DataSource>
</p:ListDataPage>
Dados JSON
Um exemplo dos dados JSON com o fonte de demonstração é mostrado abaixo:
[{
"end": "2016-04-27T18:00:00Z",
"start": "2016-04-27T17:15:00Z",
"abstract": "The new Apple TV has been released, and YOU can be one of the first developers to write apps
for it. To make things even better, you can build these apps in C#! This session will introduce the basics of
how to create a tvOS app with Xamarin, including: differences between tvOS and iOS APIs, TV user interface
best practices, responding to user input, as well as the capabilities and limitations of building apps for a
television. Grab some popcorn—this is going to be good!",
"title": "As Seen On TV … Bringing C# to the Living Room",
"presenter": "Matthew Soucoup",
"biography": "Matthew is a Xamarin MVP and Certified Xamarin Developer from Madison, WI. He founded his
company Code Mill Technologies and started the Madison Mobile .Net Developers Group. Matt regularly speaks
on .Net and Xamarin development at user groups, code camps and conferences throughout the Midwest. Matt
gardens hot peppers, rides bikes, and loves Wisconsin micro-brews and cheese.",
"image": "http://i.imgur.com/ASj60DP.jpg",
"avatar": "http://i.imgur.com/ASj60DP.jpg",
"room": "Crick"
}]
4. Executar!
As etapas acima devem resultar em uma página de dados de trabalho:
Isso funciona porque o estilo pré-criados "Eventos" existe no pacote Nuget de tema de luz e tem os estilos
definidos que correspondem à fonte de dados (por exemplo. "title", "imagem", "apresentador").
"Eventos" StyleClass é criado para exibir o ListDataPage controle com um personalizado CardView controle
que é definido em Xamarin.Forms.Pages. O CardView controle tem três propriedades: ImageSource , Text , e
Detail . O tema está codificado para associar três campos os dados da fonte (do arquivo JSON ) para essas
propriedades para exibição.
5. Personalizar
O estilo herdado pode ser substituído especificando um modelo e usando associações de código-fonte de dados.
O XAML a seguir declara um modelo personalizado para cada linha usando o novo ListItemControl e
{p:DataSourceBinding} sintaxe que está incluído na Xamarin.Forms.Pages Nuget:
<p:ListDataPage.DefaultItemTemplate>
<DataTemplate>
<ViewCell>
<p:ListItemControl
Title="{p:DataSourceBinding title}"
Detail="{p:DataSourceBinding room}"
ImageSource="{p:DataSourceBinding image}"
DataSource="{Binding Value}"
HeightRequest="90"
>
</p:ListItemControl>
</ViewCell>
</DataTemplate>
</p:ListDataPage.DefaultItemTemplate>
Fornecendo uma DataTemplate esse código substitui o StyleClass e, em vez disso, usa o layout padrão para um
ListItemControl .
Os desenvolvedores que preferem o c# para o XAML pode criar dados de associações de origem muito (Lembre-
se de incluir um using Xamarin.Forms.Pages; instrução):
É um pouco mais trabalho para criar temas do zero (consulte a guia de temas), mas versões prévias futuras
tornará isso mais fácil de fazer.
Solução de problemas
Não foi possível carregar arquivo ou assembly
'Xamarin.Forms.Theme.Light' ou uma de suas dependências
Na versão de visualização, temas podem não ser capazes de carregar no tempo de execução. Adicione o código
mostrado abaixo nos projetos relevantes para corrigir esse erro.
iOS
No AppDelegate.cs adicione as seguintes linhas depois de LoadApplication
var x = typeof(Xamarin.Forms.Themes.DarkThemeResources);
x = typeof(Xamarin.Forms.Themes.LightThemeResources);
x = typeof(Xamarin.Forms.Themes.iOS.UnderlineEffect);
Android
No MainActivity.cs adicione as seguintes linhas depois de LoadApplication
var x = typeof(Xamarin.Forms.Themes.DarkThemeResources);
x = typeof(Xamarin.Forms.Themes.LightThemeResources);
x = typeof(Xamarin.Forms.Themes.Android.UnderlineEffect);
Links relacionados
Exemplo de DataPagesDemo
Referência de controles DataSourceControl
12/04/2019 • 7 minutes to read
IMPORTANT
DataSourceControl requer uma xamarin. Forms tema referência ao renderizar.
O xamarin. Forms DataSourceControl Nuget inclui uma série de controles que podem tirar proveito da ligação de
fonte de dados.
Para usar esses controles no XAML, verifique se o namespace foi incluído, por exemplo consulte o xmlns:pages
declaração abaixo:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:pages="clr-namespace:Xamarin.Forms.Pages;assembly=Xamarin.Forms.Pages"
x:Class="DataPagesDemo.Detail">
Os exemplos a seguir incluem DynamicResource referências que seriam preciso existir no dicionário de recursos do
projeto para trabalhar. Também é um exemplo de como criar um controle personalizado
Controles internos
HeroImage
ListItem
HeroImage
O HeroImage controle tem quatro propriedades:
Texto
Detalhe
ImageSource
Aspecto
<pages:HeroImage
ImageSource="{ DynamicResource HeroImageImage }"
Text="Keith Ballinger"
Detail="Xamarin"
/>
Android
iOS
ListItem
O ListItem o layout do controle é semelhante ao nativos de iOS e Android lista ou tabela de linhas, no entanto
ele também pode ser usado como um modo de exibição normal. No exemplo de código abaixo dele é mostrado
hospedado dentro de um StackLayout , mas também pode ser usado em controles de lista associado a dados
scolling.
Há cinco propriedades:
Título
Detalhe
ImageSource
PlaceholdImageSource
Aspecto
<StackLayout Spacing="0">
<pages:ListItemControl
Detail="Xamarin"
ImageSource="{ DynamicResource UserImage }"
Title="Miguel de Icaza"
PlaceholdImageSource="{ DynamicResource IconImage }"
/>
Essas capturas de tela mostram o ListItem em plataformas iOS e Android usando tanto a luz e escuridão temas:
Android
iOS
<local:CardView
ImageSource="{ DynamicResource CardViewImage }"
Text="CardView Text"
Detail="CardView Detail"
/>
Deve se parecer com as capturas de tela abaixo usando cores correspondente a temas claro e escuro internos:
Android
iOS
public CardView()
{
}
}
</StackLayout>
</ControlTemplate>
5. Adicione os recursos específicos do tema
Como esse é um controle personalizado, adicione os recursos que correspondem o tema que você estiver usando
o dicionário de recursos:
Co r es de t em a c l ar o
<Color x:Key="iOSCardViewBackgroundColor">#FFFFFF</Color>
<Color x:Key="AndroidCardViewBackgroundColor">#FFFFFF</Color>
<Color x:Key="AndroidCardViewTextTextColor">#030303</Color>
<Color x:Key="iOSCardViewTextTextColor">#030303</Color>
<Color x:Key="AndroidCardViewDetailTextColor">#8F8E94</Color>
<Color x:Key="iOSCardViewDetailTextColor">#8F8E94</Color>
C o r e s d e t e m a e sc u r o
<Color x:Key="AndroidCardViewTextTextColor">#FFFFFF</Color>
<Color x:Key="iOSCardViewTextTextColor">#FFFFFF</Color>
<Color x:Key="AndroidCardViewDetailTextColor">#B5B4B9</Color>
<Color x:Key="iOSCardViewDetailTextColor">#B5B4B9</Color>
<Style TargetType="local:CardView">
<Setter Property="ControlTemplate" Value="{ StaticResource CardViewControlControlTemplate }" />
... some custom styling omitted
<Setter Property="BackgroundColor" Value="{ StaticResource CardViewBackgroundColor }" />
</Style>
<StackLayout Spacing="0">
<local:CardView
Margin="12,6"
ImageSource="{ DynamicResource CardViewImage }"
Text="CardView Text"
Detail="CardView Detail"
/>
</StackLayout>
DatePicker do xamarin. Forms
12/04/2019 • 9 minutes to read
baixar o exemplo
Uma exibição do xamarin. Forms que permite que o usuário selecione uma data.
O xamarin. Forms DatePicker invoca o controle de seletor de data da plataforma e permite que o usuário
selecione uma data. DatePicker define oito propriedades:
MinimumDate do tipo DateTime , cujo padrão é o primeiro dia do ano de 1900.
MaximumDate do tipo DateTime , qual o padrão é o último dia do ano 2100.
Date do tipo DateTime , a data selecionada, cujo padrão é o valor DateTime.Today .
Format do tipo string , um padrão ou personalizado .NET formatação de cadeia de caracteres, que assume
como padrão "D", de longa data padrão.
TextColor do tipo Color , a cor usada para exibir a data selecionada, cujo padrão é Color.Default .
FontAttributes do tipo FontAttributes , cujo padrão é FontAtributes.None .
FontFamily do tipo string , cujo padrão é null .
FontSize do tipo double , cujo padrão é de -1,0.
O DatePicker dispara uma DateSelected evento quando o usuário seleciona uma data.
WARNING
Ao definir MinimumDate e MaximumDate , verifique se MinimumDate sempre é menor que ou igual a MaximumDate . Caso
contrário, DatePicker gerarão uma exceção.
Internamente, o DatePicker garante que Date entre MinimumDate e MaximumDate , inclusive. Se MinimumDate ou
MaximumDate é definido para que Date não está entre eles, DatePicker ajustará o valor de Date .
Todos os oito propriedades têm o respaldo BindableProperty objetos, o que significa que eles podem ser
estilizados e as propriedades podem ser alvos de vinculações de dados. O Date propriedade tem um modo de
associação padrão de BindingMode.TwoWay , que significa que ele pode ser um destino de associação de dados em
um aplicativo que usa o Model-View -ViewModel (MVVM ) arquitetura.
Quando um valor é especificado no XAML, o analisador XAML usa a DateTime.Parse método com um
DateTime
CultureInfo.InvariantCulture argumento para converter a cadeia de caracteres para um DateTime valor. As datas
devem ser especificadas em um formato exato: dois dígitos meses, dias de dois dígitos e anos de quatro dígitos
separados por barras "/":
<DatePicker MinimumDate="01/01/2018"
MaximumDate="12/31/2018"
Date="06/21/2018" />
Se o BindingContext propriedade de DatePicker é definido como uma instância de um ViewModel que contém
as propriedades do tipo DateTime denominada MinDate , MaxDate , e SelectedDate (por exemplo), você pode
instanciar o DatePicker semelhante a esta :
Neste exemplo, todas as três propriedades são inicializadas para as propriedades correspondentes no ViewModel.
Porque o Date propriedade tem um modo de associação de TwoWay , qualquer nova data em que o usuário
selecionar é refletida automaticamente no ViewModel.
Se o DatePicker não contém uma associação em seu Date propriedade, um aplicativo deve anexar um
manipulador para o DateSelected evento a ser informado quando o usuário seleciona uma nova data.
Para obter informações sobre como definir propriedades de fonte, consulte fontes.
Layout e DatePicker
É possível usar uma opção de layout horizontal irrestrito, como Center , Start , ou End com DatePicker :
<DatePicker ···
HorizontalOptions="Center"
··· />
No entanto, isso não é recomendado. Dependendo da configuração de Format propriedade, selecionada datas
podem exigir que as larguras de exibição diferentes. Por exemplo, faz com que a cadeia de caracteres de formato
"D" DateTime exibir datas em um formato longo e "Quarta-feira, 12 de setembro de 2018" requer uma largura de
exibição maior que "Sexta-feira, 4 de maio de 2018". Dependendo da plataforma, essa diferença pode causar a
DateTime exibição para alterar a largura de layout, ou para a exibição a ser truncado.
TIP
É melhor usar o padrão HorizontalOptions configuração do Fill com DatePicker e não deve usar uma largura de
Auto ao colocar DatePicker em um Grid célula.
<StackLayout Margin="10">
<Label Text="Days Between Dates"
Style="{DynamicResource TitleStyle}"
Margin="0, 20"
HorizontalTextAlignment="Center" />
<DatePicker x:Name="startDatePicker"
Format="D"
Margin="30, 0, 0, 30"
DateSelected="OnDateSelected" />
<DatePicker x:Name="endDatePicker"
MinimumDate="{Binding Source={x:Reference startDatePicker},
Path=Date}"
Format="D"
Margin="30, 0, 0, 30"
DateSelected="OnDateSelected" />
<StackLayout Orientation="Horizontal"
Margin="0, 0, 0, 30">
<Label Text="Include both days in total: "
VerticalOptions="Center" />
<Switch x:Name="includeSwitch"
Toggled="OnSwitchToggled" />
</StackLayout>
<Label x:Name="resultLabel"
FontAttributes="Bold"
HorizontalTextAlignment="Center" />
</StackLayout>
</ContentPage>
Cada DatePicker é atribuído um Format propriedade de "D" para um formato de data por extenso. Observe
também que o endDatePicker objeto possui uma associação que tem como alvo seus MinimumDate propriedade.
A origem da associação é selecionado Date propriedade do startDatePicker objeto. Isso garante que a data de
término é sempre posterior ou igual à data de início. Além dos dois DatePicker objetos, um Switch é rotulado
como "Incluir ambos os dias no total".
Os dois DatePicker modos de exibição têm manipuladores anexados para o DateSelected evento e o Switch
tem um manipulador anexado seu Toggled eventos. Esses manipuladores de eventos estão no arquivo code-
behind e disparam um novo cálculo dos dias entre as duas datas:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
void Recalculate()
{
TimeSpan timeSpan = endDatePicker.Date - startDatePicker.Date +
(includeSwitch.IsToggled ? TimeSpan.FromDays(1) : TimeSpan.Zero);
Quando o exemplo é primeiro executado, ambos DatePicker modos de exibição são inicializados a data de hoje.
Captura de tela a seguir mostra o programa em execução no iOS, Android e plataforma Universal do Windows:
Tocando em qualquer uma da DatePicker exibe invoca o selecionador de data de plataforma. As plataformas de
implementam esse seletor de data em duas maneiras diferentes, mas cada abordagem é familiar aos usuários da
plataforma:
TIP
No Android, o DatePicker caixa de diálogo pode ser personalizada substituindo o CreateDatePickerDialog método em
um renderizador personalizado. Isso permite, por exemplo, botões adicionais a serem adicionados à caixa de diálogo.
Depois de duas datas forem selecionadas, o aplicativo exibe o número de dias entre essas datas:
Links relacionados
Exemplo de DaysBetweenDates
API de DatePicker
Elementos gráficos de SkiaSharp em Xamarin.Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Usar SkiaSharp para gráficos 2D em seus aplicativos xamarin. Forms
SkiaSharp é um sistema de gráficos em 2D para .NET e c# com o engine gráficos Skia de código-fonte aberto que
é amplamente usado em produtos do Google. Você pode usar SkiaSharp em seus aplicativos xamarin. Forms para
desenhar o texto, bitmaps e gráficos vetoriais 2D. Consulte a desenho 2D guia para obter mais informações gerais
sobre a biblioteca de SkiaSharp e alguns outros tutoriais.
Este guia pressupõe que você esteja familiarizado com a programação do xamarin. Forms.
IMPORTANT
O SkiaSharp.Views.Forms namespace também contém um SKGLView classe que deriva de View mas utiliza o OpenGL
para renderização de gráficos. Para fins de simplicidade, este guia restringe-se ao SKCanvasView , mas o uso SKGLView em
vez disso, é bastante semelhante.
Transformações de SkiaSharp
As transformações permitem que os objetos gráficos ser uniformemente traduzido, dimensionado, girados ou
inclinados. Este artigo também mostra como você pode usar uma matriz de transformação de 3 por 3 padrão para
criar transformações não afins e aplicar transformações aos caminhos.
Bitmaps do SkiaSharp
Os bitmaps são matrizes retangulares de bits que correspondem aos pixels de um dispositivo de vídeo. Esta série
de artigos mostra como carregar, salvar, exibir, criar, desenhar em, animar e acessar os bits de SkiaSharp bitmaps.
Efeitos de SkiaSharp
Os efeitos são propriedades que alteram a exibição normal de elementos gráficos, incluindo gradientes linear e
circulares, lado a lado de bitmap, misturar modos de desfoque e outras pessoas.
Links relacionados
APIs de SkiaSharp
SkiaSharpFormsDemos (amostra)
SkiaSharp com xamarin. Forms Webinar (vídeo)
Imagens no xamarin. Forms
12/04/2019 • 23 minutes to read
baixar o exemplo
Imagens podem ser compartilhadas entre plataformas com o xamarin. Forms, podem ser carregados
especificamente para cada plataforma ou podem ser baixados para exibição.
Imagens são uma parte crucial da navegação do aplicativo, a usabilidade e a identidade visual. Aplicativos
xamarin. Forms precisam ser capaz de compartilhar imagens entre todas as plataformas, mas também pode
exibir imagens diferentes em cada plataforma.
Imagens específicas da plataforma também são necessárias para os ícones e telas de abertura; eles precisam ser
configurados em uma base por plataforma.
Exibindo imagens
Xamarin. Forms usa o Image modo de exibição para exibir imagens em uma página. Ele tem duas propriedades
importantes:
Source -An ImageSource instância, arquivo, Uri ou recurso, que define a imagem a ser exibida.
Aspect -Como dimensionar a imagem dentro dos limites que está sendo exibido dentro de (seja para
stretch, cortar ou letterbox).
ImageSource instâncias podem ser obtidas usando métodos estáticos para cada tipo de origem da imagem:
FromFile -Requer um nome de arquivo ou caminho do arquivo que pode ser resolvido em cada plataforma.
FromUri -Requer um objeto de Uri, por exemplo. new Uri("http://server.com/image.jpg") .
FromResource -Requer um identificador de recurso para um arquivo de imagem inserido no aplicativo ou
projeto de biblioteca .NET Standard, com um ação de Build: EmbeddedResource.
FromStream -Requer um fluxo que fornece dados de imagem.
O Aspect propriedade determina como a imagem será dimensionada para caber na área de exibição:
Fill -Alonga a imagem para a área de exibição de preencher completamente e exatamente. Isso pode
resultar na imagem que está sendo distorcida.
AspectFill -Recorta a imagem de modo que ele preencha a área de exibição, preservando o aspecto (ie.
nenhuma distorção).
AspectFit -E Letterbox a imagem (se necessário) para que a imagem inteira se adapta a área de exibição,
com espaço em branco adicionado para o de cima para baixo ou os lados, dependendo se a imagem é altas
ou largas.
Imagens podem ser carregadas de um arquivo local, um recurso incorporado, ou baixado. Além disso, os ícones
de fonte podem ser exibidos pela Image exibição, especificando os dados do ícone de fonte em um
FontImageSource objeto. Para obter mais informações, consulte exibir ícones de fonte na fontes guia.
Imagens locais
Arquivos de imagem podem ser adicionados a cada projeto de aplicativo e referenciados no código do xamarin.
Forms compartilhado. Esse método de distribuição de imagens é necessário quando as imagens são específicas
da plataforma, como ao usar resoluções diferentes em diferentes plataformas ou designs ligeiramente
diferentes.
Para usar uma única imagem em todos os aplicativos, o mesmo nome de arquivo deve ser usado em todas as
plataformas, e ele deve ser um nome de recurso válido do Android (ie. são permitidos apenas letras minúsculas,
números, sublinhado e o período de).
iOS – o preferencial a maneira de gerenciar e dar suporte a imagens desde que o iOS 9 é usar conjuntos de
imagem do catálogo de ativos, que deve conter todas as versões de uma imagem que são necessárias
para dar suporte a vários dispositivos e fatores de escala um aplicativo. Para obter mais informações,
consulte adicionar imagens a um conjunto de imagem de catálogo ativo.
Android -colocar imagens em de recursos/drawable diretório com ação de compilação:
AndroidResource. Versões de DPI alto e baixo de uma imagem também podem ser fornecidas
(adequadamente chamado recursos subdiretórios, como desenháveis ldpi, drawable-hdpie desenháveis
xhdpi).
Plataforma universal do Windows (UWP ) -Insira imagens no diretório de raiz do aplicativo com ação de
compilação: Content.
IMPORTANT
Antes do iOS 9, imagens normalmente foram colocadas na recursos pasta com ação de compilação: BundleResource.
No entanto, esse método de trabalhar com imagens em um aplicativo iOS foi substituído pela Apple. Para obter mais
informações, consulte tamanhos de imagem e nomes de arquivo.
Aderir a essas regras de nomenclatura de arquivo e o posicionamento permite que o XAML a seguir carregar e
exibir a imagem em todas as plataformas:
As capturas de tela a seguir mostram o resultado de exibição de uma imagem local em cada plataforma:
Para obter mais flexibilidade a Device.RuntimePlatform propriedade pode ser usada para selecionar um arquivo
de imagem diferente ou o caminho para algumas ou todas as plataformas, conforme mostrado neste exemplo
de código:
image.Source = Device.RuntimePlatform == Device.Android ? ImageSource.FromFile("waterfront.jpg") :
ImageSource.FromFile("Images/waterfront.jpg");
IMPORTANT
Para usar o mesmo nome de arquivo de imagem em todas as plataformas, o nome deve ser válido em todas as
plataformas. Desenháveis Android têm restrições de nomenclatura – são permitidos apenas letras minúsculas, números,
sublinhado e período – e para compatibilidade de plataforma cruzada isso deve ser seguido em todas as outras
plataformas também. O nome do arquivo de exemplo waterfront.png segue as regras, mas os exemplos de nomes de
arquivo inválidos incluem "água front.png", "WaterFront.png", "água front.png" e "wåterfront.png".
Nomes de arquivo de imagem UWP pode ser com o sufixo .scale-xxx antes da extensão de arquivo, onde
xxx é a porcentagem de dimensionamento aplicado ao ativo, por exemplo, myimage.scale 200.png. Imagens,
em seguida, podem ser chamadas para no código ou XAML sem o modificador de escala, por exemplo, apenas
myimage.png. A plataforma selecionará a escala mais próxima do ativo apropriado com base em DPI de atual
da tela.
Controles adicionais que exibem imagens
Alguns controles têm propriedades que exibem uma imagem, como:
Page -Qualquer tipo que deriva de página Page tem Icon e BackgroundImage propriedades, que podem
ser atribuídas a uma referência de arquivo local. Em determinadas circunstâncias, como quando um
NavigationPage está exibindo um ContentPage , o ícone será exibido se houver suporte pela plataforma.
IMPORTANT
No iOS, o Page.Icon não é possível popular a propriedade de uma imagem em um conjunto de imagens de
catálogo ativo. Em vez disso, carregar imagens de ícone para o Page.Icon propriedade a partir de recursos
pasta no projeto do iOS.
ToolbarItem – Tem um Icon propriedade que pode ser definida como uma referência de arquivo local.
ImageCell– Tem um ImageSource recuperados de propriedade que pode ser definida como uma
imagem de um arquivo local, um recurso inserido ou um URI.
Imagens inseridas
Imagens inseridas também são fornecidas com um aplicativo (como imagens locais), mas em vez de ter uma
cópia da imagem na estrutura de arquivos de cada aplicativo a imagem do arquivo é inserido no assembly como
um recurso. Esse método de distribuição de imagens é recomendado quando imagens idênticas são usadas em
cada plataforma e é especialmente adequado para a criação de componentes, como a imagem é fornecida com
o código.
Para inserir uma imagem em um projeto, clique com botão direito para adicionar novos itens e selecione a
imagem/s que você deseja adicionar. Por padrão a imagem terá ação de compilação: None; isso deve ser
definido como ação de compilação: EmbeddedResource.
Visual Studio
Visual Studio para Mac
O ação de compilação podem ser exibidos e alterados na propriedades janela para um arquivo.
Neste exemplo é a ID de recurso WorkingWithImages.beach.jpg. O IDE gerou esse padrão por meio da
concatenação de Namespace padrão para este projeto com o nome do arquivo, usando um ponto (.) entre
cada valor.
Se você colocar imagens inseridas em pastas dentro de seu projeto, os nomes das pastas também são
separados por pontos (.) na ID do recurso. Movendo o beach.jpg imagem em uma pasta chamada MyImages
resultaria em uma ID de recurso de WorkingWithImages.MyImages.beach.jpg
O código para carregar uma imagem inserida simplesmente passa o ID do recurso para o
ImageSource.FromResource método conforme mostrado abaixo:
NOTE
Para dar suporte à exibição de imagens inseridas no modo de versão na plataforma Universal do Windows, é necessário
usar a sobrecarga do ImageSource.FromResource que especifica o assembly de origem no qual pesquisar a imagem.
Atualmente não há nenhuma conversão implícita para identificadores de recurso. Em vez disso, você deve usar
ImageSource.FromResource ou new ResourceImageSource() para carregar imagens inseridas.
As capturas de tela a seguir mostram o resultado de exibição de uma imagem inserida em cada plataforma:
Usando XAML
Porque não há nenhum conversor de tipo interno do string para ResourceImageSource , esses tipos de imagens
de modo nativo não podem ser carregados pelo XAML. Em vez disso, uma extensão de marcação XAML
personalizada simple pode ser escrita para carregar imagens usando um ID do recurso especificado no XAML:
[ContentProperty (nameof(Source))]
public class ImageResourceExtension : IMarkupExtension
{
public string Source { get; set; }
return imageSource;
}
}
NOTE
Para dar suporte à exibição de imagens inseridas no modo de versão na plataforma Universal do Windows, é necessário
usar a sobrecarga do ImageSource.FromResource que especifica o assembly de origem no qual pesquisar a imagem.
Para usar essa extensão de adicionar personalizado xmlns para XAML, usando os valores corretos de
namespace e assembly para o projeto. A origem da imagem, em seguida, pode ser definida usando esta sintaxe:
{local:ImageResource WorkingWithImages.beach.jpg} . Um exemplo XAML completo é mostrado 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"
xmlns:local="clr-namespace:WorkingWithImages;assembly=WorkingWithImages"
x:Class="WorkingWithImages.EmbeddedImagesXaml">
<StackLayout VerticalOptions="Center" HorizontalOptions="Center">
<!-- use a custom Markup Extension -->
<Image Source="{local:ImageResource WorkingWithImages.beach.jpg}" />
</StackLayout>
</ContentPage>
using System.Reflection;
// ...
// NOTE: use for debugging, not in released app code!
var assembly = typeof(EmbeddedImages).GetTypeInfo().Assembly;
foreach (var res in assembly.GetManifestResourceNames())
{
System.Diagnostics.Debug.WriteLine("found resource: " + res);
}
Download de imagens
Imagens podem ser baixadas automaticamente para a exibição, como mostra o XAML a seguir:
O ImageSource.FromUri método exige um Uri do objeto e retorna um novo UriImageSource que lê do Uri .
Também há uma conversão implícita de cadeias de caracteres do URI, portanto, o exemplo a seguir também
funcionará:
webImage.Source = "https://xamarin.com/content/images/pages/forms/example-app.png";
As capturas de tela a seguir mostram o resultado de exibição de uma imagem remota em cada plataforma:
Armazenamento em cache é habilitado por padrão e armazenará a imagem localmente para 24 horas. Para
desabilitar o cache de uma imagem específica, instanciar a origem da imagem da seguinte maneira:
Para definir um período de cache específica (por exemplo, 5 dias) instanciar a origem da imagem da seguinte
maneira:
Armazenamento em cache interno facilita muito dar suporte a cenários, como listas de imagens, onde você
pode definir (ou associar) uma imagem de rolagem em cada célula e permitir que o cache interno cuidar de
carregar novamente a imagem quando a célula é rolada novamente no modo de exibição.
Ícones
Consulte a iOS trabalhando com imagens, Google iconografia, e diretrizes para ativos de bloco e ícone para
obter mais informações sobre como criar esses recursos de aplicativo.
Além disso, os ícones de fonte podem ser exibidos pela Image exibição, especificando os dados do ícone de
fonte em um FontImageSource objeto. Para obter mais informações, consulte exibir ícones de fonte na fontes
guia.
Telas de abertura
Somente aplicativos iOS e UWP exigem uma tela inicial (também chamada de uma imagem de tela ou padrão
de inicialização).
Consulte a documentação para iOS trabalhando com imagens e telas de abertura no Centro de
desenvolvimento do Windows.
Resumo
Xamarin. Forms oferece um número de diferentes maneiras de incluir imagens em um aplicativo de plataforma
cruzada, permitindo que para a mesma imagem a ser usado em plataformas ou para imagens específicas da
plataforma seja especificado. Imagens baixadas são automaticamente armazenadas em cache, automatizando
um cenário comum de codificação.
Imagens de tela de abertura e de ícone de aplicativo são a configuração e configurado como para aplicativos
não xamarin. Forms - sigam as mesmas orientações usada para aplicativos específicos da plataforma.
Links relacionados
WorkingWithImages (amostra)
iOS trabalhando com imagens
Iconografia Android
Diretrizes para ativos de bloco e ícone
Xamarin. Forms ImageButton
12/04/2019 • 11 minutes to read
baixar o exemplo
O ImageButton exibe uma imagem e responde a um toque ou clique que direciona um aplicativo para executar
uma tarefa específica.
O ImageButton exibir combina o Button modo de exibição e Image modo de exibição para criar um botão cujo
conteúdo é uma imagem. O usuário pressiona o ImageButton com um dedo ou clica nele com o mouse para
direcionar o aplicativo para executar uma tarefa específica. No entanto, ao contrário do Button modo de exibição,
o ImageButton exibição não tem nenhum conceito de texto e a aparência do texto.
NOTE
Enquanto o Button view define uma Image propriedade, que lhe permite exibir uma imagem no Button , esta
propriedade destina-se a ser usado ao exibir um ícone pequeno ao lado de Button texto.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FormsGallery.XamlExamples.ImageButtonDemoPage"
Title="ImageButton Demo">
<StackLayout>
<Label Text="ImageButton"
FontSize="50"
FontAttributes="Bold"
HorizontalOptions="Center" />
<ImageButton Source="XamarinLogo.png"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Source propriedade especifica a imagem que aparece no ImageButton . Neste exemplo, ele é definido como um
arquivo local que será carregado a partir de cada projeto da plataforma, resultando em capturas de tela as seguir:
Por padrão, o ImageButton é retangular, mas você pode atribuir os cantos arredondado de it, usando o
CornerRadius propriedade. Para obter mais informações sobre ImageButton aparência, consulte ImageButton
aparência.
O exemplo a seguir mostra como criar uma página que é funcionalmente equivalente ao exemplo XAML anterior,
mas inteiramente no C#:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FormsGallery.XamlExamples.ImageButtonDemoPage"
Title="ImageButton Demo">
<StackLayout>
<Label Text="ImageButton"
FontSize="50"
FontAttributes="Bold"
HorizontalOptions="Center" />
<ImageButton Source="XamarinLogo.png"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
Clicked="OnImageButtonClicked" />
<Label x:Name="label"
Text="0 ImageButton clicks"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Clicked evento é definido como um manipulador de eventos chamado OnImageButtonClicked que está
localizado no arquivo code-behind:
public ImageButtonDemoPage()
{
InitializeComponent();
}
public ImageButtonDemoPage()
{
Label header = new Label
{
Text = "ImageButton",
FontSize = 50,
FontAttributes = FontAttributes.Bold,
HorizontalOptions = LayoutOptions.Center
};
Desabilitando o ImageButton
Às vezes, um aplicativo está em um estado específico em que um determinado ImageButton clique não é uma
operação válida. Nesses casos, o ImageButton deve ser desabilitado definindo seu IsEnabled propriedade false .
Aparência ImageButton
Além das propriedades que ImageButton herda a View classe, ImageButton também define várias propriedades
que afetam sua aparência:
Aspect é como a imagem será dimensionada para caber na área de exibição.
BorderColor é a cor de uma área ao redor de ImageButton .
BorderWidth é a largura da borda.
CornerRadius é o raio do canto do ImageButton .
O Aspect propriedade pode ser definida para um dos membros de Aspect enumeração:
Fill -Alonga a imagem para preencher completamente e exatamente o ImageButton . Isso pode resultar na
imagem que está sendo distorcida.
AspectFill -Corta a imagem de modo que ele preencha o ImageButton , preservando a taxa de proporção.
AspectFit -e Letterbox a imagem (se necessário) para que a imagem inteira se adapta a ImageButton , com
espaço em branco adicionado para o de cima para baixo ou lados dependendo se a imagem é altas ou largas.
Isso é o valor padrão de Aspect enumeração.
NOTE
O ImageButton classe também tem Margin e Padding as propriedades que controlam o comportamento de layout a
ImageButton . Para obter mais informações, consulte margem e preenchimento.
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Property="Scale"
Value="0.8" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ImageButton>
O Pressed VisualState Especifica que, quando o ImageButton é pressionado, seu Scale propriedade será
alterada do valor padrão de 1 para 0,8. O Normal VisualState Especifica que, quando o ImageButton está em um
estado normal, seu Scale propriedade será definida como 1. Portanto, o efeito geral é que quando o
ImageButton é pressionado, ele será escalada novamente para ser um pouco menores e quando o ImageButton é
lançado, ele será escalada novamente ao seu tamanho padrão.
Para obter mais informações sobre estados visuais, consulte o Gerenciador de estado Visual xamarin. Forms.
Links relacionados
Exemplo de FormsGallery
Layouts no Xamarin.Forms
12/04/2019 • 16 minutes to read
baixar o exemplo
Xamarin.Forms tem vários layouts e recursos para organizar o conteúdo na tela.
<StackLayout Orientation="Horizontal">
<Label HorizontalOptions="StartAndExpand" Text="Label" />
<Button HorizontalOptions="End" Text="Button" />
</StackLayout>
FlexLayout
O FlexLayout é semelhante ao StackLayout em que ele exibe os modos de exibição filho horizontal ou
verticalmente:
<FlexLayout Direction="Column"
AlignItems="Center"
JustifyContent="SpaceEvenly">
No entanto, se houver muitos filhos para caber em uma única linha ou coluna, FlexLayout também é capaz de
encapsular essas exibições. FlexLayout se baseia no módulo de Layout de caixa flexível CSS e tem muitas das
mesmas opções internas para posicionar e alinhar seus filhos.
AbsoluteLayout
O AbsoluteLayout é usado para exibir os modos de exibição, com tamanho e posição que está sendo especificado
como valores explícitos ou relativo ao tamanho do layout. Diferentemente StackLayout e Grid , AbsoluteLayout
permite que o filho exibições se sobrepõem. Diferentemente RelativeLayout , AbsoluteLayout não permite que
você colocar elementos fora da tela.
Para obter um exemplo de quando AbsoluteLayout seria uma boa opção, considere um aplicativo que precisa para
apresentar as coleções de objetos como pilhas. Isso é geralmente visto ao apresentar álbuns de fotos ou músicas.
O código a seguir fornece a aparência de uma pilha, com elementos girados para dica sobre o conteúdo da pilha:
No XAML:
<AbsoluteLayout Padding="15">
<Image AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
Rotation="30"
Source="bottom.png" />
<Image AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
Rotation="60"
Source="middle.png" />
<Image AbsoluteLayout.LayoutFlags="PositionProportional" AbsoluteLayout.LayoutBounds="0.5, 0, 100, 100"
Source="cover.png" />
</AbsoluteLayout>
RelativeLayout
O RelativeLayout é usado para exibir os modos de exibição, com tamanho e posição especificada como valores
relativos aos valores de layout ou de outro modo de exibição. Não é necessário correspondê-lo corresponde o
valor no modo de exibição relacionado valores relativos. Por exemplo, é possível definir um modo de exibição
Width propriedade seja proporcional para outra exibição X propriedade.
RelativeLayout pode ser usado para criar interfaces do usuário que são dimensionados proporcionalmente de
tamanhos de dispositivo. O XAML a seguir implementa um design com as caixas nos cantos mais altas, com um
flagpole com sinalizador no Centro de:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="1" Grid.Row="0" Grid.Column="0" />
<Button Text="2" Grid.Row="0" Grid.Column="1" />
<Button Text="3" Grid.Row="0" Grid.Column="2" />
<Button Text="4" Grid.Row="1" Grid.Column="0" />
<Button Text="5" Grid.Row="1" Grid.Column="1" />
<Button Text="6" Grid.Row="1" Grid.Column="2" />
<Button Text="7" Grid.Row="2" Grid.Column="0" />
<Button Text="8" Grid.Row="2" Grid.Column="1" />
<Button Text="9" Grid.Row="2" Grid.Column="2" />
<Button Text="0" Grid.Row="3" Grid.Column="1" />
<Button Text="<-" Grid.Row="3" Grid.Column="2" />
</Grid>
Links relacionados
Diretrizes de Interface humana da Apple
Site de Design do Android
Layout (amostra)
Exemplo de BusinessTumble (amostra)
StackLayout do xamarin. Forms
12/04/2019 • 7 minutes to read
baixar o exemplo
StackLayout Organiza os modos de exibição em uma linha unidimensional ("pilha"), horizontal ou verticalmente.
Exibições em um StackLayout pode ser dimensionado com base no espaço no layout usando as opções de
layout. Posicionamento é determinada pela ordem de modos de exibição foram adicionados para o layout e as
opções de layout dos modos de exibição.
Finalidade
StackLayout é menos complexo do que outros modos de exibição. Interfaces de lineares simples podem ser
criadas simplesmente adicionando modos de exibição para um StackLayout e mais complexas interfaces criadas,
aninhando-los.
Uso e comportamento
Espaçamento
Por padrão, StackLayout será adicionada uma margem de 6px entre modos de exibição. Isso pode ser controlado
ou definido como não ter nenhuma margem, definindo o Spacing propriedade StackLayout. O exemplo a seguir
demonstra como definir o espaçamento e o efeito de opções de espaçamento diferentes:
No XAML:
No C#:
public class StackLayoutCode : ContentPage
{
public StackLayoutCode ()
{
var layout = new StackLayout ();
var button = new Button { Text = "StackLayout", VerticalOptions = LayoutOptions.Start,
HorizontalOptions = LayoutOptions.FillAndExpand };
var yellowBox = new BoxView { Color = Color.Yellow, VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand };
var greenBox = new BoxView { Color = Color.Green, VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand };
var blueBox = new BoxView { Color = Color.Blue, VerticalOptions = LayoutOptions.FillAndExpand,
HorizontalOptions = LayoutOptions.FillAndExpand, HeightRequest = 75 };
layout.Children.Add(button);
layout.Children.Add(yellowBox);
layout.Children.Add(greenBox);
layout.Children.Add(blueBox);
layout.Spacing = 10;
Content = layout;
}
}
Espaçamento = 0:
Espaçamento de dez:
Dimensionamento
O tamanho de uma exibição em um StackLayout depende das solicitações de altura e largura e as opções de
layout. StackLayout irá impor o preenchimento. O seguinte LayoutOption s fará com que os modos de exibição
ocupar o espaço disponível do layout:
CenterAndExpand – centraliza a exibição no layout e expande para ocupar tanto espaço quanto o layout será
dê a ele.
EndAndExpand – coloca o modo de exibição no final do layout (inferior ou limite à direita) e se expande para
ocupar tanto espaço quanto o layout será dê a ele.
FillAndExpand – coloca o modo de exibição para que ele não tem nenhum preenchimento e ocupa espaço
quanto o layout será dê a ele.
StartAndExpand – coloca o modo de exibição no início do layout e ocupa tanto espaço quanto fornecerá o
pai.
Para obter mais informações, consulte expansão.
Posicionamento
Modos de exibição em um StackLayout podem ser posicionados e dimensionados usando LayoutOptions . Cada
modo de exibição pode ser dada VerticalOptions e HorizontalOptions , definindo como os modos de exibição irá
se posicionar em relação ao layout. O seguinte predefinidos LayoutOptions estão disponíveis:
Centro – centraliza a exibição no layout.
Término – coloca o modo de exibição no final do layout (inferior ou limite à direita).
Preencher – coloca o modo de exibição para que ele não tem nenhum preenchimento.
Inicie – coloca o modo de exibição no início do layout.
O código a seguir demonstra as opções de layout de configuração:
No XAML:
No C#:
layout.Children.Add(button);
layout.Children.Add(oneBox);
layout.Children.Add(twoBox);
layout.Children.Add(threeBox);
Content = layout;
}
}
Links relacionados
LayoutOptions
Layout (amostra)
Exemplo de BusinessTumble (amostra)
Xamarin. Forms AbsoluteLayout
12/04/2019 • 12 minutes to read
baixar o exemplo
AbsoluteLayout posiciona e dimensiona proporcional ao seu próprio tamanho e posição ou por valores
absolutos de elementos filho. Modos de exibição filho podem ser posicionado e dimensionados usando
proporcionais valores ou valores estáticos e proporcional e valores estáticos podem ser combinados.
Finalidade
Por causa do modelo de posicionamento de AbsoluteLayout , o layout torna relativamente fácil para posicionar
elementos para que fiquem com qualquer lado do layout ou centralizado. Com proporcionais tamanhos e
posições, elementos em um AbsoluteLayout pode ser dimensionado automaticamente para qualquer tamanho
de exibição. Para itens em que apenas a posição, mas não o tamanho deve ser dimensionado, os valores
absolutos e proporcionais podem ser combinados.
AbsoluteLayout pode ser usado em qualquer lugar em que precisa ser posicionado em uma exibição de
elementos e é especialmente útil ao alinhar os elementos para bordas.
Uso
Layouts proporcionais
AbsoluteLayout tem um modelo de âncora exclusivo, no qual a âncora do elemento é posicionada em relação ao
seu elemento como o elemento é posicionado em relação ao layout quando posicionamento proporcional é
usado. Quando o posicionamento absoluto é usado, a âncora é em (0,0) dentro da exibição. Isso tem duas
consequências importantes:
Elementos não podem ser posicionados fora da tela usando valores proporcionais.
Elementos podem ser posicionados de forma confiável ao longo de qualquer lado do layout ou no centro,
independentemente do tamanho do layout ou dispositivo.
AbsoluteLayout , como RelativeLayout , é capaz de posicionar elementos para que eles se sobrepõem.
Observe, na captura de tela abaixo, a âncora da caixa é um ponto branco. Observe a relação entre a âncora e a
caixa enquanto se movimentam pelo layout:
Especificando valores
Modos de exibição dentro de um AbsoluteLayout são posicionados usando quatro valores:
X – a posição de x (horizontal) da âncora da exibição
Y – a posição y (vertical) da âncora da exibição
Largura – a largura da exibição
Altura – a altura da exibição
Cada um desses valores pode ser definida como uma proporcional valor ou uma absoluto valor.
Valores são especificados como uma combinação de limites e um sinalizador. LayoutBounds é um Rectangle
consiste em quatro valores: x , y , width , height .
AbsoluteLayoutFlags
AbsoluteLayoutFlags Especifica como os valores serão interpretados e tem as seguintes opções predefinidas:
None – interpreta todos os valores como absolutos. Isso é o valor padrão se nenhum sinalizador de layout
forem especificados.
Todos os – interpreta todos os valores como proporcional.
WidthProportional – interpreta o Width valor como proporcional e todos os outros valores como
absolutos.
HeightProportional – interpreta apenas o valor altura como proporcional com todos os outros valores
absolutos.
XProportional – interpreta o X valor como proporcional, ao tratar todos os outros valores como absolutos.
YProportional – interpreta o Y valor como proporcional, ao tratar todos os outros valores como absolutos.
PositionProportional – interpreta o X e Y valores conforme proporcional, enquanto os valores de
tamanho são interpretados como absolutos.
SizeProportional – interpreta o Width e Height valores conforme proporcional, enquanto os valores de
posição são absolutos.
No XAML, limites e os sinalizadores são definidos como parte da definição de modos de exibição no layout,
usando o AbsoluteLayout.LayoutBounds propriedade. Limites são definidos como uma lista separada por vírgulas
de valores, X , Y , Width , e Height , nessa ordem. Sinalizadores também são especificados na declaração de
modos de exibição no layout usando o AbsoluteLayout.LayoutFlags propriedade. Observe que os sinalizadores
podem ser combinados em XAML usando uma lista separada por vírgulas. Considere o exemplo a seguir:
Observe o seguinte:
No centro do rótulo é posicionado usando valores de tamanho e posição absolutas. Por causa disso,
aparentemente centralizada no iPhone 4S e inferior, mas não centralizado em dispositivos maiores.
O texto na parte inferior do layout é posicionado usando valores de tamanho e posição proporcionais. Ele
sempre será exibido na parte inferior central do layout, mas seu tamanho aumentará com tamanhos maiores
de layout.
Três coloridas BoxView s são posicionados nas bordas superior, esquerdas e direita da tela usando a posição
proporcional e o tamanho absoluto.
O exemplo a seguir alcança o mesmo layout em c#:
var bottomLabel = new Label { Text = "I'm bottom center on every device.", LineBreakMode =
LineBreakMode.WordWrap };
AbsoluteLayout.SetLayoutBounds (bottomLabel, new Rectangle (.5, 1, .5, .1));
AbsoluteLayout.SetLayoutFlags (bottomLabel, AbsoluteLayoutFlags.All);
layout.Children.Add (bottomLabel);
layout.Children.Add (centerLabel);
layout.Children.Add (rightBox);
layout.Children.Add (leftBox);
layout.Children.Add (topBox);
Content = layout;
}
}
Valores proporcionais
Valores proporcionais definem uma relação entre um layout e um modo de exibição. Essa relação define a
posição de um modo de exibição de filho ou valor de escala como uma proporção do valor correspondente do
layout pai. Esses valores são expressos como double s com valores entre 0 e 1.
Proporcionais valores são usados para exibições de tamanho no layout e posição. Portanto, quando a largura do
modo de exibição é definida como uma proporção, o valor de largura resultante é a proporção multiplicada pela
AbsoluteLayout da largura. Por exemplo, com um AbsoluteLayout da largura 500 e uma exibição definida para
ter uma largura proporcional de.5, a largura renderizada da exibição serão 250 (500 x.5 n
Para usar valores proporcionais, defina LayoutBounds usando (x, y) proporções e tamanhos proporcionais, em
seguida, defina LayoutFlags para All .
No XAML:
No C#:
var label = new Label {Text = "I'm bottom center on every device."};
AbsoluteLayout.SetLayoutBounds(label, new Rectangle(.5,1,.5,.1));
AbsoluteLayout.SetLayoutFlags(label, AbsoluteLayoutFlags.All);
Valores absolutos
Valores absolutos definir explicitamente onde os modos de exibição devem ser posicionados no layout. Ao
contrário de valores proporcionais, os valores absolutos são capazes de posicionar e dimensionar uma exibição
que não se ajustar dentro dos limites do layout.
Usando os valores absolutos para posicionamento pode ser perigoso quando o tamanho do layout não é
conhecido. Ao usar posições absolutas, um elemento no centro da tela em um tamanho poderia ser deslocado
em qualquer outro tamanho. É importante testar seu aplicativo em vários tamanhos de tela de seus dispositivos
com suporte.
Para usar valores de layout absoluto, defina LayoutBounds usando (x, y) as coordenadas e tamanhos explícitos,
em seguida, defina LayoutFlags para None .
No XAML:
No C#:
var label = new Label {Text = "I'm centered on iPhone 4 but no other device."};
AbsoluteLayout.SetLayoutBounds(label, new Rectangle(115,150,100,100));
Observe que AbsoluteLayout s forem aninhadas, pois em alguns casos layouts de aninhamento pode ser mais
fácil do que apresentar todos os elementos do layout do mesmo.
Links relacionados
Criação de aplicativos móveis com xamarin. Forms, capítulo 14
AbsoluteLayout
Layout (amostra)
Exemplo de BusinessTumble (amostra)
Xamarin. Forms RelativeLayout
12/04/2019 • 8 minutes to read
baixar o exemplo
RelativeLayout é usado para a posição e modos de exibição de tamanho em relação a propriedades das
exibições de layout ou irmão. Diferentemente AbsoluteLayout , RelativeLayout não tem o conceito da âncora de
movimentação e não tem recursos para posicionar elementos em relação a margem inferior ou direita do layout.
RelativeLayout oferece suporte a elementos de posicionamento fora de seus próprios limites.
Finalidade
RelativeLayoutpode ser usado para posicionar os modos de exibição na tela em relação ao layout geral ou a
outros modos de exibição.
Uso
Noções básicas sobre restrições
Posicionar e dimensionar um modo de exibição dentro de um RelativeLayout é feito com restrições. Uma
expressão de restrição pode incluir as seguintes informações:
Tipo de – se a restrição é relativo ao pai ou para outro modo.
Propriedade – qual propriedade a ser usado como base para a restrição.
Fator – o fator a ser aplicado ao valor da propriedade.
Constante – o valor a ser usado como um deslocamento do valor.
ElementName – o nome da exibição que a restrição é relativo.
No XAML, as restrições são expressos como ConstraintExpression s. Considere o exemplo a seguir:
No C#, as restrições são expressas de forma diferente, usando funções em vez de expressões na exibição.
Restrições são especificadas como argumentos para o layout Add método:
NOTE
Por causa da maneira que as restrições são definidas, é possível fazer os layouts mais complexos no C# que podem ser
especificados com XAML.
Os dois exemplos acima definem restrições como RelativeToParent – ou seja, seus valores são em relação ao
elemento pai. Também é possível definir restrições como relativos a outra exibição. Isso permite que os layouts
mais intuitivos (para o desenvolvedor) e pode deixar a intenção do seu código de layout mais aparente.
Considere um layout em que um elemento deve ser menor do que o outro de 20 pixels. Se ambos os elementos
são definidos com valores constantes, menor poderia ter seus Y restrição definida como uma constante que é
maior que 20 pixels, o Y restrição do maior elemento. Essa abordagem deixa a desejar se o elemento superior é
posicionado usando uma proporção, para que o tamanho de pixel não é conhecido. Nesse caso, restringir o
elemento com base na posição do elemento para outro é mais robusta:
<RelativeLayout>
<BoxView Color="Red" x:Name="redBox"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent,
Property=Height,Factor=.15,Constant=0}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=1,Constant=0}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=.8,Constant=0}" />
<BoxView Color="Blue"
RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToView,
ElementName=redBox,Property=Y,Factor=1,Constant=20}"
RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToView,
ElementName=redBox,Property=X,Factor=1,Constant=20}"
RelativeLayout.WidthConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Width,Factor=.5,Constant=0}"
RelativeLayout.HeightConstraint="{ConstraintExpression
Type=RelativeToParent,Property=Height,Factor=.5,Constant=0}" />
</RelativeLayout>
Isso produz a seguinte saída, com a posição da caixa azul determinada relativo para a posição da caixa vermelha:
Dimensionamento
Modos de exibição apresentados pelo RelativeLayout tem duas opções para especificar seu tamanho:
HeightRequest & WidthRequest
RelativeLayout.WidthConstraint & RelativeLayout.HeightConstraint
HeightRequest e WidthRequest especificam a altura desejada e a largura da exibição, mas pode ser substituída
pelos layouts conforme necessário. WidthConstraint e HeightConstraint dá suporte à definição a altura e largura
como um valor em relação a propriedades de layout ou outra exibição, ou como um valor constante.
Links relacionados
Layout (amostra)
Exemplo de BusinessTumble (amostra)
Grade de xamarin. Forms
12/04/2019 • 15 minutes to read
baixar o exemplo
Grid dá suporte à organização exibições em linhas e colunas. Linhas e colunas podem ser definidas para ter
tamanhos proporcionais ou tamanhos absolutos. O Grid layout não deve ser confundido com tabelas
tradicionais e não se destina a apresentar dados tabulares. Grid não tem o conceito de linha, coluna ou célula de
formatação. Ao contrário das tabelas HTML, Grid destina-se puramente para dispor o conteúdo.
Uso
Ao contrário das tabelas tradicionais, Grid não deduz o número e os tamanhos de linhas e colunas do conteúdo.
Em vez disso, Grid tem RowDefinitions e ColumnDefinitions coleções. Eles mantêm as definições de quantas
linhas e colunas serão dispostas. As exibições são adicionadas à Grid com a linha especificada e os índices de
coluna, que identificam quais linhas e colunas de um modo de exibição deve ser colocado em.
Linhas e colunas
Informações de linha e coluna são armazenadas no Grid do RowDefinitions & ColumnDefinitions propriedades,
que são coleções de cada de RowDefinition e ColumnDefinition objetos, respectivamente. RowDefinition tem
uma única propriedade, Height , e ColumnDefinition tem uma propriedade única, Width . As opções para altura e
largura são da seguinte maneira:
Auto – automaticamente os tamanhos para ajustar o conteúdo da linha ou coluna. Especificado como
GridUnitType.Auto em C# ou como Auto em XAML.
Proportional(*) – dimensiona as colunas e linhas como uma proporção de espaço restante. Especificado
como um valor e GridUnitType.Star em C# e como #* em XAML, com # sendo o valor desejado.
Especificando uma linha/coluna com * fará com que ela preencher o espaço disponível.
Absoluto – dimensiona as colunas e linhas com valores de altura e largura fixas, específicos. Especificado
como um valor e GridUnitType.Absolute em C# e como # em XAML, com # sendo o valor desejado.
NOTE
Os valores de largura de colunas são definidos como * por padrão no xamarin. Forms, que garante que a coluna
preencherá o espaço disponível. Os valores de altura para linhas também são definidos como * por padrão.
Considere um aplicativo que precisa de três linhas e duas colunas. A linha inferior precisa ser exatamente 200px
altura e a linha superior precisa ser duas vezes com a altura da linha intermediária. A coluna à esquerda deve ser
grande o suficiente para caber o conteúdo e a coluna à direita precisa preencher o espaço restante.
No XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="*" />
<RowDefinition Height="200" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
</Grid>
No C#:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Top Left" Grid.Row="0" Grid.Column="0" />
<Label Text="Top Right" Grid.Row="0" Grid.Column="1" />
<Label Text="Bottom Left" Grid.Row="1" Grid.Column="0" />
<Label Text="Bottom Right" Grid.Row="1" Grid.Column="1" />
</Grid>
No C#:
var grid = new Grid();
grid.Children.Add(topLeft, 0, 0);
grid.Children.Add(topRight, 1, 0);
grid.Children.Add(bottomLeft, 0, 1);
grid.Children.Add(bottomRight, 1, 1);
O código acima cria a grade com quatro rótulos, duas colunas e duas linhas. Observe que cada rótulo terá o
mesmo tamanho e que as linhas se expandem para usar todo o espaço disponível.
No exemplo acima, as exibições são adicionadas para o Grid.Children coleção usando o Add sobrecarga que
especifica os argumentos left e top. Ao usar o Add durante a sobrecarga que especifica para a esquerda, direita,
superior e argumentos de parte inferior, esquerda e argumentos superior sempre fará referência às células dentro
a Grid , à direita e argumentos de parte inferior podem aparecer para se referir às células que estão fora de
Grid . Isso ocorre porque o argumento à direita sempre deve ser maior que o argumento esquerdo e o
argumento inferior sempre deve ser maior que o argumento superior. O exemplo a seguir mostra o código
equivalente usando os dois Add sobrecargas:
// left, top
grid.Children.Add(topLeft, 0, 0);
grid.Children.Add(topRight, 1, 0);
grid.Children.Add(bottomLeft, 0, 1);
grid.Children.Add(bottomRight, 1, 1);
Espaçamento
Grid tem propriedades para controlar o espaçamento entre linhas e colunas. As seguintes propriedades estão
disponíveis para personalizar o Grid :
ColumnSpacing – a quantidade de espaço entre colunas. O valor padrão dessa propriedade é 6.
RowSpacing – a quantidade de espaço entre as linhas. O valor padrão dessa propriedade é 6.
O XAML a seguir especifica um Grid com duas colunas, uma linha e 5 px de espaçamento entre colunas:
<Grid ColumnSpacing="5">
<Grid.ColumnDefinitions>
<ColumnDefinitions Width="*" />
<ColumnDefinitions Width="*" />
</Grid.ColumnDefinitions>
</Grid>
No C#:
var grid = new Grid { ColumnSpacing = 5 };
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star)});
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength (1, GridUnitType.Star)});
Intervalos
Geralmente, ao trabalhar com uma grade, há um elemento que deve ocupar mais de uma linha ou coluna.
Considere um aplicativo de calculadora simples:
Observe que o botão 0 abrange duas colunas, assim como em que as calculadoras internos para cada plataforma.
Isso é feito usando o ColumnSpan propriedade, que especifica quantas colunas um elemento deve ocupar. O
XAML para esse botão:
E, em C#:
Observe que no código, métodos estáticos do Grid classe são usados para executar alterações de
posicionamento, incluindo as alterações ColumnSpan e RowSpan . Também Observe que, ao contrário de outras
propriedades que podem ser definidas a qualquer momento, as propriedades definidas usando os métodos
estáticos já devem estar na grade antes que sejam alteradas.
O XAML completo para o aplicativo Calculadora acima é da seguinte maneira:
<?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="LayoutSamples.CalculatorGridXAML"
Title = "Calculator - XAML"
BackgroundColor="#404040">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="plainButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="#eee"/>
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderRadius" Value="0"/>
<Setter Property="FontSize" Value="40" />
</Style>
<Style x:Key="darkerButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="#ddd"/>
<Setter Property="TextColor" Value="Black" />
<Setter Property="BorderRadius" Value="0"/>
<Setter Property="FontSize" Value="40" />
</Style>
<Style x:Key="orangeButton" TargetType="Button">
<Setter Property="BackgroundColor" Value="#E8AD00"/>
<Setter Property="TextColor" Value="White" />
<Setter Property="BorderRadius" Value="0"/>
<Setter Property="FontSize" Value="40" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<Grid x:Name="controlGrid" RowSpacing="1" ColumnSpacing="1">
<Grid.RowDefinitions>
<RowDefinition Height="150" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="0" Grid.Row="0" HorizontalTextAlignment="End" VerticalTextAlignment="End"
TextColor="White"
FontSize="60" Grid.ColumnSpan="4" />
<Button Text = "C" Grid.Row="1" Grid.Column="0"
Style="{StaticResource darkerButton}" />
<Button Text = "+/-" Grid.Row="1" Grid.Column="1"
Style="{StaticResource darkerButton}" />
<Button Text = "%" Grid.Row="1" Grid.Column="2"
Style="{StaticResource darkerButton}" />
<Button Text = "div" Grid.Row="1" Grid.Column="3"
Style="{StaticResource orangeButton}" />
<Button Text = "7" Grid.Row="2" Grid.Column="0"
Style="{StaticResource plainButton}" />
<Button Text = "8" Grid.Row="2" Grid.Column="1"
Style="{StaticResource plainButton}" />
<Button Text = "9" Grid.Row="2" Grid.Column="2"
Style="{StaticResource plainButton}" />
<Button Text = "X" Grid.Row="2" Grid.Column="3"
Style="{StaticResource orangeButton}" />
<Button Text = "4" Grid.Row="3" Grid.Column="0"
Style="{StaticResource plainButton}" />
<Button Text = "5" Grid.Row="3" Grid.Column="1"
Style="{StaticResource plainButton}" />
<Button Text = "6" Grid.Row="3" Grid.Column="2"
Style="{StaticResource plainButton}" />
Style="{StaticResource plainButton}" />
<Button Text = "-" Grid.Row="3" Grid.Column="3"
Style="{StaticResource orangeButton}" />
<Button Text = "1" Grid.Row="4" Grid.Column="0"
Style="{StaticResource plainButton}" />
<Button Text = "2" Grid.Row="4" Grid.Column="1"
Style="{StaticResource plainButton}" />
<Button Text = "3" Grid.Row="4" Grid.Column="2"
Style="{StaticResource plainButton}" />
<Button Text = "+" Grid.Row="4" Grid.Column="3"
Style="{StaticResource orangeButton}" />
<Button Text = "0" Grid.ColumnSpan="2"
Grid.Row="5" Grid.Column="0" Style="{StaticResource plainButton}" />
<Button Text = "." Grid.Row="5" Grid.Column="2"
Style="{StaticResource plainButton}" />
<Button Text = "=" Grid.Row="5" Grid.Column="3"
Style="{StaticResource orangeButton}" />
</Grid>
</ContentPage.Content>
</ContentPage>
Observe que tanto o rótulo na parte superior da grade e o botão zero são occuping mais de uma coluna. Embora
um layout semelhante pode ser obtido usando grades aninhadas, a ColumnSpan & RowSpan abordagem é mais
simples.
A implementação do C#:
public CalculatorGridCode ()
{
Title = "Calculator - C#";
BackgroundColor = Color.FromHex ("#404040");
Content = controlGrid;
}
Links relacionados
Criação de aplicativos móveis com xamarin. Forms, capítulo 17
Grade
Layout (amostra)
Exemplo de BusinessTumble (amostra)
O xamarin. Forms FlexLayout
12/04/2019 • 42 minutes to read
baixar o exemplo
Use FlexLayout para empilhamento ou encapsulando uma coleção de exibições filho.
O xamarin. Forms FlexLayout há de novo no xamarin. Forms versão 3.0. Ele se baseia na folha de estilos módulo
de Layout de caixa flexível, comumente conhecido como flex layout ou flex caixa, assim chamada porque ele inclui
muitas opções flexíveis para organizar filhos no layout.
FlexLayout é semelhante ao xamarin. Forms StackLayout em que ele pode organizar seus filhos horizontalmente
e verticalmente em uma pilha. No entanto, o FlexLayout também é capaz de quebra automática de seus filhos se
houver muitas para caber em uma única linha ou coluna, e também tem muitas opções para a orientação,
alinhamento e adaptar-se a vários tamanhos de tela.
FlexLayout deriva Layout<View> e herda um Children propriedade do tipo IList<View> .
FlexLayout define seis propriedades vinculáveis públicas e cinco propriedades vinculáveis anexadas que afetam o
tamanho, orientação e o alinhamento dos elementos filho. (Se você não estiver familiarizado com as propriedades
vinculáveis anexadas, consulte o artigo propriedades anexadas.) Essas propriedades são descritas
detalhadamente nas seções a seguir as propriedades vinculáveis detalhadamente e as propriedades
anexadas associáveis detalhadamente. No entanto, este artigo começa com uma seção em algumas cenários
comuns de uso de FlexLayout que descreve muitas dessas propriedades de modo mais informal. Até o final do
artigo, você verá como combinar FlexLayout com folhas de estilos CSS.
<FlexLayout Direction="Column"
AlignItems="Center"
JustifyContent="SpaceEvenly">
Com essa alteração, essa Label é posicionado na borda esquerda do FlexLayout quando a ordem de
leitura é esquerda para a direita.
O JustifyContent propriedade é do tipo FlexJustify e especifica como os itens são organizados no eixo
principal. O SpaceEvenly opção aloca todos os espaço vertical abandonado igualmente entre todos os
itens e acima do primeiro item e abaixo do último item.
Se você estivesse usando um StackLayout , você precisará atribuir a VerticalOptions propriedade de cada
item para CenterAndExpand para conseguir um efeito semelhante. Mas o CenterAndExpand opção alocará
duas vezes mais espaço entre cada item que antes do primeiro item e depois do último item. Você pode
imitar a CenterAndExpand opção de VerticalOptions definindo o JustifyContent propriedade do
FlexLayout para SpaceAround .
Eles FlexLayout propriedades são discutidas mais detalhadamente na seção as propriedades vinculáveis
detalhadamente abaixo.
Usando FlexLayout para quebra automática de itens
O foto encapsulamento página do FlexLayoutDemos exemplo demonstra como FlexLayout pode encapsular
a seus filhos para linhas ou colunas adicionais. O arquivo XAML instancia o FlexLayout e atribui as duas
propriedades:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="FlexLayoutDemos.PhotoWrappingPage"
Title="Photo Wrapping">
<Grid>
<ScrollView>
<FlexLayout x:Name="flexLayout"
Wrap="Wrap"
JustifyContent="SpaceAround" />
</ScrollView>
<ActivityIndicator x:Name="activityIndicator"
IsRunning="True"
VerticalOptions="Center" />
</Grid>
</ContentPage>
O Direction propriedade deste FlexLayout não for definido, para que ele tenha a configuração padrão de Row ,
que significa que os filhos são organizados em linhas e o eixo principal é horizontal.
O Wrap é de propriedade de um tipo de enumeração FlexWrap . Se houver itens demais para caber em uma
linha, a configuração dessa propriedade faz com que os itens quebre para a próxima linha.
Observe que o FlexLayout é um filho de um ScrollView . Se houver muitas linhas para caber na página, em
seguida, a ScrollView tem um padrão Orientation propriedade de Vertical e permite a rolagem vertical.
O JustifyContent propriedade aloca espaço remanescente no eixo principal (o eixo horizontal), de modo que
cada item fica entre a mesma quantidade de espaço em branco.
O arquivo code-behind acessa uma coleção de fotos de exemplo e adicioná-los para o Children coleção do
FlexLayout :
public partial class PhotoWrappingPage : ContentPage
{
// Class for deserializing JSON list of sample bitmaps
[DataContract]
class ImageList
{
[DataMember(Name = "photos")]
public List<string> Photos = null;
}
public PhotoWrappingPage ()
{
InitializeComponent ();
LoadBitmapCollection();
}
activityIndicator.IsRunning = false;
activityIndicator.IsVisible = false;
}
}
<FlexLayout Direction="Column">
</FlexLayout>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:FlexLayoutDemos"
x:Class="FlexLayoutDemos.CatalogItemsPage"
Title="Catalog Items">
<ContentPage.Resources>
<Style TargetType="Frame">
<Setter Property="BackgroundColor" Value="LightYellow" />
<Setter Property="BorderColor" Value="Blue" />
<Setter Property="Margin" Value="10" />
<Setter Property="CornerRadius" Value="15" />
</Style>
<Style TargetType="Label">
<Setter Property="Margin" Value="0, 4" />
</Style>
<Style TargetType="Image">
<Setter Property="FlexLayout.Order" Value="-1" />
<Setter Property="FlexLayout.AlignSelf" Value="Center" />
</Style>
<Style TargetType="Button">
<Setter Property="Text" Value="LEARN MORE" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="White" />
<Setter Property="BackgroundColor" Value="Green" />
<Setter Property="BorderRadius" Value="20" />
</Style>
</ContentPage.Resources>
<ScrollView Orientation="Both">
<FlexLayout>
<Frame WidthRequest="300"
HeightRequest="480">
<FlexLayout Direction="Column">
<Label Text="Seated Monkey"
Style="{StaticResource headerLabel}" />
<Label Text="This monkey is laid back and relaxed, and likes to watch the world go by."
/>
<Label Text=" • Doesn't make a lot of noise" />
<Label Text=" • Often smiles mysteriously" />
<Label Text=" • Sleeps sitting up" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.SeatedMonkey.jpg}"
WidthRequest="180"
HeightRequest="180" />
<Label FlexLayout.Grow="1" />
<Button />
</FlexLayout>
</Frame>
<Frame WidthRequest="300"
HeightRequest="480">
<FlexLayout Direction="Column">
<Label Text="Banana Monkey"
Style="{StaticResource headerLabel}" />
<Label Text="Watch this monkey eat a giant banana." />
<Label Text=" • More fun than a barrel of monkeys" />
<Label Text=" • Banana not included" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.Banana.jpg}"
WidthRequest="240"
HeightRequest="180" />
<Label FlexLayout.Grow="1" />
<Button />
</FlexLayout>
</Frame>
<Frame WidthRequest="300"
HeightRequest="480">
<FlexLayout Direction="Column">
<Label Text="Face-Palm Monkey"
Style="{StaticResource headerLabel}" />
<Label Text="This monkey reacts appropriately to ridiculous assertions and actions." />
<Label Text=" • Cynical but not unfriendly" />
<Label Text=" • Seven varieties of grimaces" />
<Label Text=" • Doesn't laugh at your jokes" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.FacePalm.jpg}"
WidthRequest="180"
HeightRequest="180" />
<Label FlexLayout.Grow="1" />
<Button />
</FlexLayout>
</Frame>
</FlexLayout>
</ScrollView>
</ContentPage>
O estilo implícito para o Image inclui as configurações de duas propriedades vinculáveis anexadas de Flexlayout
:
<Style TargetType="Image">
<Setter Property="FlexLayout.Order" Value="-1" />
<Setter Property="FlexLayout.AlignSelf" Value="Center" />
</Style>
O Order configuração do –1 faz com que o Image elemento a ser exibido pela primeira vez em cada uma das
aninhada FlexLayout modos de exibição, independentemente de sua posição dentro da coleção de filhos. O
AlignSelf propriedade de Center faz com que o Image centralizado dentro de FlexLayout . Isso substitui a
configuração do AlignItems propriedade, que tem um valor padrão de Stretch , o que significa que o Label e
Button filhos são ampliados para a largura total do FlexLayout .
Dentro de cada um dos três FlexLayout modos de exibição, um espaço em branco Label precede a Button , mas
tem um Grow configuração de 1. Isso significa que todo o espaço vertical extra é alocado para isso em branco
Label , que efetivamente envia a Button na parte inferior.
Cada um dos Label modos de exibição tem um plano de fundo cinza que mostra o espaço alocado para que
Label dentro de FlexLayout . Plano de fundo do FlexLayout em si é azul-bebê. Ele ocupa a área inteira inferior
da página, exceto para uma pequena margem à esquerda e direita.
A propriedade de direção
O Direction propriedade é do tipo FlexDirection , uma enumeração com quatro membros:
Column
ColumnReverse (ou "reversão de coluna" em XAML )
Row , o padrão
RowReverse (ou "reversão de linha" em XAML )
No XAML, você pode especificar o valor dessa propriedade usando os nomes de membro de enumeração em
letras minúsculas, letras maiusculas, ou maiusculas e minúsculas, ou você pode usar duas cadeias de caracteres
adicionais entre parênteses são os mesmos que os indicadores CSS. (As cadeias de caracteres "coluna inverso" e
"linha reversão" são definidas na FlexDirectionTypeConverter classe usada pelo analisador XAML.)
Aqui está o experimento página mostrando (da esquerda para a direita), o Row direção, Column direção, e
ColumnReverse direção:
Observe que para o Reverse opções, os itens iniciam na parte direita ou inferior.
A propriedade de quebra automática de linha
O Wrap propriedade é do tipo FlexWrap , uma enumeração com três membros:
NoWrap , o padrão
Wrap
Reverse (ou "reversão de quebra automática de linha" em XAML )
Da esquerda para direita, essas telas mostram a NoWrap , Wrap e Reverse opções para os filhos de 12:
Quando o Wrap estiver definida como NoWrap eixo principal é restrito (como esse programa) e o eixo principal
não está altas ou largas o suficiente para se ajustar todos os filhos, o FlexLayout faz com que os itens de menor,
como a captura de tela do iOS Demonstra. Você pode controlar o shrinkness dos itens com o Shrink
propriedade associável anexada.
A propriedade JustifyContent
O JustifyContent propriedade é do tipo FlexJustify , uma enumeração com seis membros:
Start (ou "flex-start" em XAML ), o padrão
Center
End (ou "flex-end" em XAML )
SpaceBetween (ou "espaço-entre" em XAML )
SpaceAround (ou "espaço-around" em XAML )
SpaceEvenly
Esta propriedade especifica como os itens são espaçados no eixo principal, que é o eixo horizontal neste exemplo:
Em todos os três capturas de tela, o Wrap estiver definida como Wrap . O Start padrão é mostrado na captura
de tela Android anterior. Mostra a captura de tela do iOS aqui o Center opção: todos os itens são movidos para o
centro. As três outras opções começando com a palavra Space alocar o espaço extra não ocupado pelos itens.
SpaceBetween aloca o espaço igualmente entre os itens; SpaceAround puts igual espaço ao redor de cada item,
enquanto SpaceEvenly puts igual espaço entre cada item e antes do primeiro item e depois do último item na
linha.
A propriedade AlignItems
O AlignItems propriedade é do tipo FlexAlignItems , uma enumeração com quatro membros:
Stretch , o padrão
Center
Start (ou "flex-start" em XAML )
End (ou "flex-end" em XAML )
Essa é uma das duas propriedades (o outro sendo AlignContent ) que indica como os filhos são alinhados no eixo
transversal. Em cada linha, os filhos são alongados (conforme mostrado na captura de tela anterior) ou alinhados
no início, centro ou final de cada item, conforme mostrado nas capturas de três tela seguintes:
A captura de tela do iOS, as partes superiores de todos os filhos são alinhadas. No Android capturas de tela, os
itens são centralizados verticalmente com base no filho mais alto. A captura de tela de UWP, a parte inferior de
todos os itens é alinhados.
Para qualquer item individual, o AlignItems configuração pode ser substituída com o AlignSelf propriedade
associável anexada.
A propriedade AlignContent
O AlignContent propriedade é do tipo FlexAlignContent , uma enumeração com sete membros:
Stretch , o padrão
Center
Start (ou "flex-start" em XAML )
End (ou "flex-end" em XAML )
SpaceBetween (ou "espaço-entre" em XAML )
SpaceAround (ou "espaço-around" em XAML )
SpaceEvenly
Como o AlignItems , o AlignContent propriedade também alinha filhos no eixo transversal, mas afeta linhas ou
colunas inteiras:
A captura de tela do iOS, ambas as linhas estão na parte superior; na captura de tela Android está no Centro de; e
a captura de tela de UWP que eles estão na parte inferior. As linhas também podem ser espaçadas de várias
maneiras:
O AlignContent não tem nenhum efeito quando há apenas uma linha ou coluna.
Para qualquer filho individual do FlexLayout , essa propriedade substituirá o AlignItems propriedade definida no
FlexLayout em si. A configuração padrão de Auto significa usar o AlignItems configuração.
Para um Label elemento denominado label (ou exemplo), você pode definir o AlignSelf propriedade no
código como este:
FlexLayout.SetAlignSelf(label, FlexAlignSelf.Center);
Observe que não há nenhuma referência para o FlexLayout pai do Label . No XAML, você definir a propriedade
como este:
A propriedade de ordem
O Order propriedade é do tipo int . O valor padrão é 0.
O Order propriedade permite que você altere a ordem que os filhos do FlexLayout são organizados.
Normalmente, os filhos de um FlexLayout são organizados é a mesma ordem que aparecem no Children
coleção. Você pode substituir essa ordem, definindo o Order propriedade associável anexada a um valor inteiro
diferente de zero em uma ou mais filhos. O FlexLayout , em seguida, organiza seus filhos com base na
configuração do Order propriedade em cada filho, mas filhos com o mesmo Order configuração são
organizados na ordem em que aparecem no Children coleção.
A propriedade de base
O Basis anexados a propriedade associável indica a quantidade de espaço é alocado para um filho do
FlexLayout no eixo principal. O tamanho especificado o Basis propriedade é o tamanho ao longo do eixo
principal do pai FlexLayout . Portanto, Basis indica a largura de um filho quando os filhos são organizados em
linhas ou a altura, quando os filhos são organizados em colunas.
O Basis propriedade é do tipo FlexBasis , uma estrutura. O tamanho pode ser especificado em qualquer um
dos unidades independentes de dispositivo ou como uma porcentagem do tamanho do FlexLayout . O valor
padrão de Basis é a propriedade estática FlexBasis.Auto , o que significa que o filho solicitado pelo largura ou
altura é usada.
No código, você pode definir as Basis propriedade para um Label denominado label para 40 unidades
independentes de dispositivo como este:
O segundo argumento para o FlexBasis construtor é chamado isRelative e indica se o tamanho é relativo (
true ) ou absoluto ( false ). O argumento tem um valor padrão de false , portanto, você também pode usar o
código a seguir:
Uma conversão implícita da float para FlexBasis for definida, portanto, você pode simplificar ainda mais:
FlexLayout.SetBasis(label, 40);
Você pode definir o tamanho para 25% do FlexLayout pai como este:
O base experiências página do FlexLayoutDemos amostra permite que você experimentar o Basis
propriedade. A página exibe uma coluna encapsulada de cinco Label elementos com alternando as cores de
primeiro plano e plano de fundo. Duas Slider elementos permitem que você especifique Basis valores para o
segundo e quarto Label :
A captura de tela do iOS à esquerda mostra os dois Label elementos que estão sendo fornecidos alturas em
unidades independentes de dispositivo. A tela Android mostra-las sendo dada alturas menos da metade da altura
total do FlexLayout . Se o Basis é definida em 100%, em seguida, o filho é a altura do FlexLayout e passe para a
próxima coluna e ocupa toda a altura da coluna, como demonstra a captura de tela UWP: Ele aparece como se os
filhos de cinco são organizados em uma linha, mas, na verdade, são dispostos em cinco colunas.
A propriedade de crescimento
O Grow anexados a propriedade associável é do tipo int . O valor padrão é 0 e o valor deve ser maior que ou
igual a 0.
O Grow propriedade desempenha um papel quando o Wrap estiver definida como NoWrap e a linha de filhos
tem uma largura total menor que a largura do FlexLayout , ou a coluna de filhos tem uma altura menor que o
FlexLayout . O Grow propriedade indica como distribuir o espaço entre os filhos.
No experimento crescer página cinco Label elementos de cores alternadas são organizados em uma coluna e
dois Slider elementos permitem que você ajuste a Grow propriedade do segundo e quarto Label . A captura de
tela do iOS na extremidade esquerda mostra o padrão Grow propriedades 0:
Se qualquer um filho é fornecido um positivo Grow de valor, em seguida, esse filho ocupa todo o espaço restante,
como demonstra a captura de tela do Android. Esse espaço também pode ser alocado entre dois ou mais filhos. A
captura de tela de UWP, o Grow propriedade da segunda Label é definido como 0,5, enquanto o Grow
propriedade do quarto Label é 1.5, que fornece a quarta Label três vezes mais do espaço de sobra como o
segundo Label .
Como o modo de exibição filho usa esse espaço depende do tipo específico de filho. Para um Label , o texto pode
ser posicionado dentro do espaço total do Label usando as propriedades HorizontalTextAlignment e
VerticalTextAlignment .
A propriedade de redução
O Shrink anexados a propriedade associável é do tipo int . O valor padrão é 1, e o valor deve ser maior que ou
igual a 0.
O Shrink propriedade desempenha um papel quando o Wrap estiver definida como NoWrap e a largura de
agregação de uma linha de filhos é maior que a largura do FlexLayout , ou a altura de agregação de uma única
coluna de filhos é maior que o altura do FlexLayout . Normalmente o FlexLayout exibirá esses filhos por
constricting seus tamanhos. O Shrink propriedade pode indicar quais filhas recebem prioridade em que estão
sendo exibidos com seus tamanhos completos.
O reduzir experimento página cria uma FlexLayout com uma única linha de cinco Label filhos que exigem
mais espaço do que o FlexLayout largura. A captura de tela do iOS à esquerda mostra todos os Label
elementos com os valores padrão de 1:
Na captura de tela Android, o Shrink valor para a segunda Label é definido como 0 e que Label é exibido na
sua largura completa. Além disso, o quarto Label recebe um Shrink valor maior do que um e, em seguida, ele
foi reduzido. Mostra a captura de tela UWP Label elementos que estão sendo fornecidos um Shrink valor de 0
para permitir que sejam exibidos em seu tamanho completo, se isso for possível.
Você pode definir ambos os Grow e Shrink valores para adaptar a situações em que os tamanhos de agregação
filho, às vezes, podem ser menor que ou às vezes maior que o tamanho do FlexLayout .
<Style TargetType="Frame">
<Setter Property="BorderColor" Value="Blue" />
<Setter Property="CornerRadius" Value="15" />
</Style>
<Style TargetType="Button">
<Setter Property="Text" Value="LEARN MORE" />
<Setter Property="BorderRadius" Value="20" />
</Style>
</ContentPage.Resources>
<ScrollView Orientation="Both">
<FlexLayout>
<Frame>
<FlexLayout Direction="Column">
<Label Text="Seated Monkey" StyleClass="header" />
<Label Text="This monkey is laid back and relaxed, and likes to watch the world go by."
/>
<Label Text=" • Doesn't make a lot of noise" />
<Label Text=" • Often smiles mysteriously" />
<Label Text=" • Sleeps sitting up" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.SeatedMonkey.jpg}" />
<Label StyleClass="empty" />
<Button />
</FlexLayout>
</Frame>
<Frame>
<FlexLayout Direction="Column">
<Label Text="Banana Monkey" StyleClass="header" />
<Label Text="Watch this monkey eat a giant banana." />
<Label Text=" • More fun than a barrel of monkeys" />
<Label Text=" • Banana not included" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.Banana.jpg}" />
<Label StyleClass="empty" />
<Button />
</FlexLayout>
</Frame>
<Frame>
<FlexLayout Direction="Column">
<Label Text="Face-Palm Monkey" StyleClass="header" />
<Label Text="This monkey reacts appropriately to ridiculous assertions and actions." />
<Label Text=" • Cynical but not unfriendly" />
<Label Text=" • Seven varieties of grimaces" />
<Label Text=" • Doesn't laugh at your jokes" />
<Image Source="{local:ImageResource FlexLayoutDemos.Images.FacePalm.jpg}" />
<Label StyleClass="empty" />
<Button />
</FlexLayout>
</Frame>
</FlexLayout>
</ScrollView>
</ContentPage>
Observe também que dois elementos em cada um dos três itens a incluem StyleClass configurações:
frame {
width: 300;
height: 480;
background-color: lightyellow;
margin: 10;
}
label {
margin: 4 0;
}
label.header {
margin: 8 0;
font-size: large;
color: blue;
}
label.empty {
flex-grow: 1;
}
image {
height: 180;
order: -1;
align-self: center;
}
button {
font-size: large;
color: white;
background-color: green;
}
Vários FlexLayout propriedades vinculáveis anexadas são referenciadas aqui. No label.empty seletor, você verá
o flex-grow atributo, que define o estilo vazio Label para fornecer um espaço em branco acima a Button . O
image seletor contém um order atributo e um align-self atributo, que correspondem aos FlexLayout
associáveis propriedades anexadas.
Você já viu que você pode definir propriedades diretamente na FlexLayout e você pode definir propriedades
vinculáveis anexadas nos filhos de um FlexLayout . Ou, você pode definir essas propriedades indiretamente
usando estilos tradicionais baseado em XAML ou estilos CSS. O importante é saber e compreender essas
propriedades. Essas propriedades são o que torna o FlexLayout realmente flexível.
baixar o exemplo
ScrollView contém layouts e permite que eles para fora da tela de rolagem. ScrollView também é usado para
permitir que os modos de exibição mover automaticamente para a parte visível da tela quando o teclado está
mostrando.
Finalidade
ScrollView pode ser usado para garantir que os modos de exibição maiores exibem bem em telefones menores.
Por exemplo, um layout que funciona em um iPhone 6s poderão ser cortado em um iPhone 4s. Usando um
ScrollView permitiria que as partes recortadas do layout a ser exibido na tela menor.
Uso
NOTE
ScrollView s não devem ser aninhados. Além disso, ScrollView s não devem ser aninhados com outros controles que
fornecem a rolagem, como ListView e WebView .
ScrollView expõe um Content propriedade que pode ser definida como um único modo de exibição ou layout.
Considere este exemplo de um layout com um boxView muito grande, seguido por um Entry :
<ContentPage.Content>
<ScrollView>
<StackLayout>
<BoxView BackgroundColor="Red" HeightRequest="600" WidthRequest="150" />
<Entry />
</StackLayout>
</ScrollView>
</ContentPage.Content>
No C#:
Observe que, quando o usuário começa a inserir texto no Entry , o modo de exibição rola para mantê-lo visível na
tela:
Propriedades
ScrollView Define as propriedades a seguir:
ContentSize Obtém uma Size valor que representa o tamanho do conteúdo.
Orientation Obtém ou define um ScrollOrientation valor de enumeração que representa a direção de
rolagem do ScrollView .
ScrollX Obtém um double que representa a atual posição de rolagem X.
ScrollY Obtém um double que representa a atual posição de rolagem de Y.
HorizontalScrollBarVisibility Obtém ou define um ScrollBarVisibility valor que representa quando a
barra de rolagem horizontal está visível.
VerticalScrollBarVisibility Obtém ou define um ScrollBarVisibility valor que representa quando a barra
de rolagem vertical está visível.
Métodos
ScrollView Fornece um ScrollToAsync método, que pode ser usado para rolar a exibição usando coordenadas
ou ao especificar um modo de exibição específico que deve ficar visível.
Ao usar coordenadas, especifique o x e y coordenadas, juntamente com um valor booliano que indica se a
rolagem deve ser animada:
scroll.ScrollToAsync(0, 150, true); //scrolls so that the position at 150px from the top is visible
scroll.ScrollToAsync(label, ScrollToPosition.Start, true); //scrolls so that the label is at the start of the
list
Durante a rolagem para um elemento específico, o ScrollToPosition Especifica enumeração onde no modo de
exibição do elemento será exibido:
Centro – rola o elemento para o centro da parte visível da exibição.
Término – rola o elemento ao final da parte visível da exibição.
MakeVisible – rola o elemento para que ele fique visível dentro da exibição.
Inicie – rola o elemento ao início da parte visível da exibição.
O IsAnimated propriedade especifica como o modo de exibição será rolado. Quando definido como true, uma
animação suave será usado, em vez de instantaneamente movendo o conteúdo no modo de exibição.
Eventos
ScrollView define apenas um evento, Scrolled . Scrolled é gerado quando o modo de exibição terminou de
rolagem. Manipulador de eventos do Scrolled leva ScrolledEventArgs , que tem o ScrollX e ScrollY
propriedades. A seguir demonstra como atualizar um rótulo com a atual posição de rolagem de um ScrollView :
Observe que as posições de rolagem podem ser negativas, devido ao efeito de devolução durante a rolagem no
final de uma lista.
Links relacionados
Layout (amostra)
Exemplo de BusinessTumble (amostra)
Opções de layout no xamarin. Forms
12/04/2019 • 10 minutes to read
baixar o exemplo
Cada modo de exibição do xamarin. Forms tem as propriedades HorizontalOptions e propriedades
VerticalOptions, do tipo LayoutOptions. Este artigo explica o efeito que cada valor LayoutOptions tem sobre o
alinhamento e a expansão de um modo de exibição.
Visão geral
O LayoutOptions estrutura encapsula duas as preferências de layout:
Alinhamento – o modo de exibição preferencial do alinhamento, que determina sua posição e tamanho
dentro do seu layout pai.
Expansão – usada somente por um StackLayout e indica se o modo de exibição deve usar o espaço extra, se
ele estiver disponível.
Essas preferências de layout podem ser aplicadas a um View , em relação a seu pai, definindo o
HorizontalOptions ou VerticalOptions propriedade das View dentre os campos públicos do LayoutOptions
estrutura. Os campos públicos são da seguinte maneira:
Start
Center
End
Fill
StartAndExpand
CenterAndExpand
EndAndExpand
FillAndExpand
O Start , Center , End ,e Fill campos são usados para definir o alinhamento do modo de exibição do layout do
pai:
Para alinhamento horizontal, Start posições a View no lado esquerdo do layout pai e o alinhamento vertical,
ela posiciona o View na parte superior das layout pai.
Para o alinhamento horizontal e vertical, Center horizontal ou verticalmente centraliza as View .
Para o alinhamento horizontal, End posições a View no lado direito do layout pai e o alinhamento vertical, ela
posiciona o View na parte inferior do layout pai.
Para o alinhamento horizontal, Fill garante que o View preenche a largura do layout pai e o alinhamento
vertical, garante que o View preenche o altura do layout pai.
O StartAndExpand , CenterAndExpand , EndAndExpand , e FillAndExpand valores são usados para definir a preferência
de alinhamento, e se o modo de exibição será ocupam mais espaço, se disponível dentro do pai StackLayout .
NOTE
O valor padrão de um modo de exibição HorizontalOptions e VerticalOptions propriedades é LayoutOptions.Fill .
Alinhamento
Alinhamento de controles como um modo de exibição é posicionado dentro de seu layout pai quando o layout pai
contém espaço não utilizado (ou seja, o layout do pai é maior do que o tamanho combinado de todos os seus
filhos).
Um StackLayout somente respeita o Start , Center , End , e Fill LayoutOptions campos em modos de exibição
filho que estão na direção oposta para o StackLayout orientação. Portanto, o filho exibições dentro de uma
orientação vertical StackLayout pode definir seus HorizontalOptions as propriedades para um dos Start ,
Center , End , ou Fill campos. Da mesma forma, o filho exibições dentro de uma orientação horizontal
StackLayout pode definir seus VerticalOptions as propriedades para um dos Start , Center , End , ou Fill
campos.
Um StackLayout não respeita a Start , Center , End , e Fill LayoutOptions campos em modos de exibição filho
que estão na mesma direção o StackLayout orientação. Portanto, uma orientação vertical StackLayout ignora os
Start , Center , End , ou Fill campos se eles são definidos na VerticalOptions propriedades de exibições filho.
Da mesma forma, um orientado horizontalmente StackLayout ignora os Start , Center , End , ou Fill campos
se elas são definidas no HorizontalOptions propriedades de exibições filho.
NOTE
LayoutOptions.Fill geralmente substituições dimensionar solicitações especificadas usando o HeightRequest e
WidthRequest propriedades.
O exemplo de código XAML a seguir demonstra uma orientação vertical StackLayout onde cada filho Label
define seu HorizontalOptions propriedade para um dos campos de alinhamento de quatro a LayoutOptions
estrutura:
<StackLayout Margin="0,20,0,0">
...
<Label Text="Start" BackgroundColor="Gray" HorizontalOptions="Start" />
<Label Text="Center" BackgroundColor="Gray" HorizontalOptions="Center" />
<Label Text="End" BackgroundColor="Gray" HorizontalOptions="End" />
<Label Text="Fill" BackgroundColor="Gray" HorizontalOptions="Fill" />
</StackLayout>
Um StackLayout não é possível expandir os modos de exibição filho na direção oposta à sua orientação. Portanto,
na orientação vertical StackLayout , definindo o HorizontalOptions propriedade em um modo de exibição filho
StartAndExpand tem o mesmo efeito que definir a propriedade como Start .
NOTE
Observe que habilitar a expansão não altera o tamanho de um modo de exibição, a menos que ele usa
LayoutOptions.FillAndExpand .
O exemplo de código XAML a seguir demonstra uma orientação vertical StackLayout onde cada filho Label
define seu VerticalOptions propriedade para um dos campos de expansão de quatro a LayoutOptions estrutura:
<StackLayout Margin="0,20,0,0">
...
<BoxView BackgroundColor="Red" HeightRequest="1" />
<Label Text="Start" BackgroundColor="Gray" VerticalOptions="StartAndExpand" />
<BoxView BackgroundColor="Red" HeightRequest="1" />
<Label Text="Center" BackgroundColor="Gray" VerticalOptions="CenterAndExpand" />
<BoxView BackgroundColor="Red" HeightRequest="1" />
<Label Text="End" BackgroundColor="Gray" VerticalOptions="EndAndExpand" />
<BoxView BackgroundColor="Red" HeightRequest="1" />
<Label Text="Fill" BackgroundColor="Gray" VerticalOptions="FillAndExpand" />
<BoxView BackgroundColor="Red" HeightRequest="1" />
</StackLayout>
Resumo
Este artigo explicou o efeito que cada LayoutOptions valor estrutura tem sobre o alinhamento e a expansão de
uma exibição, relativo ao seu pai. O Start , Center , End , e Fill campos são usados para definir o alinhamento
do modo de exibição do layout do pai e o StartAndExpand , CenterAndExpand , EndAndExpand , e FillAndExpand
campos são usados para definir a preferência de alinhamento e para determinar se o modo de exibição ocupará
mais espaço, se disponível, dentro de um StackLayout .
Links relacionados
LayoutOptions (amostra)
LayoutOptions
Margem e preenchimento
12/04/2019 • 3 minutes to read
Visão geral
Margem e preenchimento são conceitos relacionados de layout:
O Margin propriedade representa a distância entre um elemento e seus elementos adjacentes e é usada para
controlar a posição de renderização do elemento e a posição de renderização de seus vizinhos. Margin
valores podem ser especificados em layout e exibição classes.
O Padding propriedade representa a distância entre um elemento e seus elementos filho e é usada para
separar o controle de seu próprio conteúdo. Padding valores podem ser especificados em layout classes.
Observe que Margin valores são aditivas. Portanto, se dois elementos adjacentes especificam uma margem de
20 pixels, a distância entre os elementos será 40 pixels. Além disso, margem e preenchimento são aditivos,
quando ambos são aplicadas, em que a distância entre um elemento e qualquer conteúdo será a margem e
preenchimento.
Especifica uma espessura
O Margin e Padding propriedades forem do tipo Thickness . Existem três possibilidades durante a criação de
um Thickness estrutura:
Criar uma Thickness estrutura definida por um único valor uniforme. O valor único é aplicado para a
esquerda, superior, direita e lados da parte inferior do elemento.
Criar uma Thickness estrutura definida pelos valores horizontais e verticais. O valor horizontal é aplicado
simetricamente para os lados esquerdo e direito do elemento, com o valor vertical que está sendo aplicado
simetricamente para os lados superior e inferior do elemento.
Criar uma Thickness estrutura definida por quatro valores distintos que são aplicados para a esquerda,
superior, direita e lados da parte inferior do elemento.
O exemplo de código XAML a seguir mostra todas as três possibilidades:
<StackLayout Padding="0,20,0,0">
<Label Text="Xamarin.Forms" Margin="20" />
<Label Text="Xamarin.iOS" Margin="10, 15" />
<Label Text="Xamarin.Android" Margin="0, 20, 15, 5" />
</StackLayout>
NOTE
Thickness valores podem ser negativos, que normalmente recorta ou overdraws o conteúdo.
Resumo
Este artigo demonstrou a diferença entre o Margin e Padding propriedades e como defini-las. As propriedades
controlam o comportamento de layout quando um elemento é renderizado na interface do usuário.
Links relacionados
Margem
Preenchimento
Espessura
Orientação do dispositivo
12/04/2019 • 18 minutes to read
baixar o exemplo
É importante considerar como seu aplicativo será usado e como orientação paisagem pode ser incorporada para
melhorar a experiência do usuário. Layouts individuais podem ser projetados para acomodar várias orientações e
melhor usa o espaço disponível. No nível do aplicativo, rotação pode ser desabilitada ou habilitada.
Controlando a orientação
Ao usar o xamarin. Forms, o método com suporte de controlar a orientação do dispositivo é usar as configurações
para cada projeto individual.
iOS
No iOS, a orientação do dispositivo está configurada para aplicativos que usam o Info. plist arquivo. Esse arquivo
incluirá as configurações de orientação para iPhone e iPod, bem como configurações para iPad, se o aplicativo
inclui-lo como um destino. A seguir estão as instruções específicas para seu IDE. Use as opções de IDE na parte
superior deste documento para selecionar quais instruções que você gostaria de ver:
Visual Studio
Visual Studio para Mac
No Visual Studio, abra o projeto do iOS e abra Info. plist. O arquivo será aberto em um painel de configuração,
começando com o guia de informações de implantação do iPhone:
Para configurar a orientação do iPad, selecione a informações de implantação do iPad guia na parte superior
esquerda do painel, em seguida, selecione das orientações disponíveis:
Android
Para controlar a orientação no Android, abra MainActivity.cs e defina a orientação usando o atributo decorar o
MainActivity classe:
namespace MyRotatingApp.Droid
{
[Activity (Label = "MyRotatingApp.Droid", Icon = "@drawable/icon", Theme = "@style/MainTheme",
MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation,
ScreenOrientation = ScreenOrientation.Landscape)] //This is what controls orientation
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate (Bundle bundle)
...
NOTE
Há um pacote de NuGet existente e gratuito para receber notificações de alterações de orientação no código compartilhado.
Consulte a repositório GitHub para obter mais informações.
Como alternativa, é possível substituir a OnSizeAllocated método em um Page , inserindo qualquer layout alterar
lógica nele. O OnSizeAllocated método é chamado sempre que um Page é alocado um novo tamanho, o que
ocorre sempre que o dispositivo seja girado. Observe que a implementação base de OnSizeAllocated executa
funções importantes de layout, portanto, é importante chamar a implementação base na substituição:
Falha ao executar essa etapa resulta em uma página não está funcionando.
Observe que o OnSizeAllocated método pode ser chamado várias vezes quando um dispositivo é girado.
Alterando o layout de cada vez que é um desperdício de recursos e pode levar a cintilação. Considere o uso de
uma variável de instância dentro de sua página para controlar se a orientação é em paisagem ou retrato e
redesenhar somente quando há uma alteração:
e o cenário:
Observe que os aplicativos aproveitam o espaço disponível com a adição de mais funcionalidades em paisagem.
Layout dinâmico
É possível para interfaces de design usando os layouts internos para que eles normalmente a transição quando o
dispositivo é girado. Durante a criação de interfaces que continuarão a ser atraente ao responder a alterações na
orientação, considere as seguintes regras gerais:
Preste atenção às taxas – alterações na orientação podem causar problemas quando determinadas
suposições são feitas com relação a taxas. Por exemplo, uma exibição que teria bastante espaço em 1/3, o
espaço vertical de uma tela em Retrato não caber em 1/3 do espaço vertical em paisagem.
Tenha cuidado com os valores absolutos – valores absolutos (pixel) que fazem sentido em Retrato talvez
não faça sentido em paisagem. Quando valores absolutos forem necessárias, use layouts aninhados para isolar
seu impacto. Por exemplo, seria razoável usar valores absolutos em um TableView ItemTemplate quando o
modelo de item tem uma altura uniforme garantida.
As regras acima também se aplicam ao implementar interfaces para vários tamanhos de tela e são geralmente
considerados práticas recomendadas. O restante deste guia explicará exemplos específicos de layouts responsivos
usando cada um dos layouts primários no xamarin. Forms.
NOTE
Para maior clareza, as seções a seguir demonstram como implementar layouts responsivos usando apenas um tipo de
Layout por vez. Na prática, geralmente é mais simples de misturar Layout s para obter um layout desejado usando o
mais simples ou mais intuitiva Layout para cada componente.
StackLayout
Considere o aplicativo a seguir, exibido em Retrato:
e o cenário:
Que pode ser feito com o XAML a seguir:
<?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="ResponsiveLayout.StackLayoutPageXaml"
Title="Stack Photo Editor - XAML">
<ContentPage.Content>
<StackLayout Spacing="10" Padding="5" Orientation="Vertical"
x:Name="outerStack"> <!-- can change orientation to make responsive -->
<ScrollView>
<StackLayout Spacing="5" HorizontalOptions="FillAndExpand"
WidthRequest="1000">
<StackLayout Orientation="Horizontal">
<Label Text="Name: " WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="deer.jpg"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Date: " WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="07/05/2015"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Tags:" WidthRequest="75"
HorizontalOptions="Start" />
<Entry Text="deer, tiger"
HorizontalOptions="FillAndExpand" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Button Text="Save" HorizontalOptions="FillAndExpand" />
</StackLayout>
</StackLayout>
</ScrollView>
<Image Source="deer.jpg" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Alguns C# é usado para alterar a orientação do outerStack com base na orientação do dispositivo:
Observe o seguinte:
é ajustado para apresentar os controles e a imagem como uma pilha horizontal ou vertical,
outerStack
dependendo da orientação, para aproveitar melhor o espaço disponível.
AbsoluteLayout
Considere o aplicativo a seguir, exibido em Retrato:
e o cenário:
Que pode ser feito com o XAML a seguir:
<?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="ResponsiveLayout.AbsoluteLayoutPageXaml"
Title="AbsoluteLayout - XAML" BackgroundImage="deer.jpg">
<ContentPage.Content>
<AbsoluteLayout>
<ScrollView AbsoluteLayout.LayoutBounds="0,0,1,1"
AbsoluteLayout.LayoutFlags="PositionProportional,SizeProportional">
<AbsoluteLayout>
<Image Source="deer.jpg"
AbsoluteLayout.LayoutBounds=".5,0,300,300"
AbsoluteLayout.LayoutFlags="PositionProportional" />
<BoxView Color="#CC1A7019" AbsoluteLayout.LayoutBounds=".5
300,.7,50" AbsoluteLayout.LayoutFlags="XProportional
WidthProportional" />
<Label Text="deer.jpg" AbsoluteLayout.LayoutBounds = ".5
310,1, 50" AbsoluteLayout.LayoutFlags="XProportional
WidthProportional" HorizontalTextAlignment="Center" TextColor="White" />
</AbsoluteLayout>
</ScrollView>
<Button Text="Previous" AbsoluteLayout.LayoutBounds="0,1,.5,60"
AbsoluteLayout.LayoutFlags="PositionProportional
WidthProportional"
BackgroundColor="White" TextColor="Green" BorderRadius="0" />
<Button Text="Next" AbsoluteLayout.LayoutBounds="1,1,.5,60"
AbsoluteLayout.LayoutFlags="PositionProportional
WidthProportional" BackgroundColor="White"
TextColor="Green" BorderRadius="0" />
</AbsoluteLayout>
</ContentPage.Content>
</ContentPage>
Observe o seguinte:
Por causa da maneira que a página foi disposta, não é necessário para o código procedural introduzir a
capacidade de resposta.
O ScrollView está sendo usado para permitir que o rótulo fique visível, mesmo quando a altura da tela é
menor que a soma das alturas dos botões e a imagem fixas.
RelativeLayout
Considere o aplicativo a seguir, exibido em Retrato:
e o cenário:
Que pode ser feito com o XAML a seguir:
</ScrollView>
Observe o seguinte:
Por causa da maneira que a página foi disposta, não é necessário para o código procedural introduzir a
capacidade de resposta.
O ScrollView está sendo usado para permitir que o rótulo fique visível, mesmo quando a altura da tela é
menor que a soma das alturas dos botões e a imagem fixas.
Grade
Considere o aplicativo a seguir, exibido em Retrato:
e o cenário:
Que pode ser feito com o XAML a seguir:
<?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="ResponsiveLayout.GridPageXaml"
Title="Grid - XAML">
<ContentPage.Content>
<Grid x:Name="outerGrid">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="60" />
</Grid.RowDefinitions>
<Grid x:Name="innerGrid" Grid.Row="0" Padding="10">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Source="deer.jpg" Grid.Row="0" Grid.Column="0" HeightRequest="300" WidthRequest="300"
/>
<Grid x:Name="controlsGrid" Grid.Row="0" Grid.Column="1" >
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label Text="Name:" Grid.Row="0" Grid.Column="0" />
<Label Text="Date:" Grid.Row="1" Grid.Column="0" />
<Label Text="Tags:" Grid.Row="2" Grid.Column="0" />
<Entry Grid.Row="0" Grid.Column="1" />
<Entry Grid.Row="1" Grid.Column="1" />
<Entry Grid.Row="2" Grid.Column="1" />
</Grid>
</Grid>
<Grid x:Name="buttonsGrid" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Text="Previous" Grid.Column="0" />
<Button Text="Save" Grid.Column="1" />
<Button Text="Next" Grid.Column="2" />
</Grid>
</Grid>
</ContentPage.Content>
</ContentPage>
Observe o seguinte:
Por causa da maneira que a página foi disposta, há um método para alterar o posicionamento de grade dos
controles.
Links relacionados
Layout (amostra)
Exemplo de BusinessTumble (amostra)
Layout dinâmico (exemplo)
Exibir uma imagem com base na orientação da tela
Layout para aplicativos de Tablet e área de trabalho
12/04/2019 • 5 minutes to read
Xamarin. Forms oferece suporte a todos os tipos de dispositivo disponíveis em plataformas com suporte, além de
telefones, os aplicativos também podem executar em:
iPads,
Tablets Android,
Tablets Windows e computadores desktop (executando o Windows 10).
Esta página aborda resumidamente:
com suporte tipos de dispositivo, e
como otimizar layouts para tablets e telefones.
Tipos de dispositivo
Dispositivos de tela maiores estão disponíveis para todas as plataformas com suporte pelo xamarin. Forms.
iPads (iOS )
O modelo do xamarin. Forms inclui automaticamente suporte a iPad, configurando o Info. plist > dispositivos
definir como Universal (o que significa que há suporte para iPhone e iPad).
Para fornecer uma experiência de inicialização agradável e verifique se a resolução de tela inteira é usada em
todos os dispositivos, você deve verificar se um tela de inicialização específicas do iPad (usando um storyboard) é
fornecido. Isso garante que o aplicativo é renderizado corretamente em dispositivos de iPad mini, iPad e iPad Pro.
Antes do iOS 9 todos os aplicativos ocupou toda a tela no dispositivo, mas agora pode executar alguns iPads
dividir a tela multitarefa. Isso significa que seu aplicativo pode levar apenas uma coluna slim na lateral da tela,
50% da largura da tela, ou a tela inteira.
O Split screen funcionalidade significa que você deve projetar seu aplicativo funcione bem com até 320 pixels de
largura ou de 1366 tanto quanto pixels de largura.
Tablets Android
O ecossistema do Android tem uma grande variedade de tamanhos de tela com suporte, de telefones pequeno
até grandes tablets. Xamarin. Forms pode dar suporte a todos os tamanhos de tela, mas como com outras
plataformas você talvez queira ajustar sua interface do usuário para dispositivos maiores.
Ao dar suporte a muitos diferentes resoluções de tela, você pode fornecer os recursos de imagem nativa em
tamanhos diferentes para otimizar a experiência do usuário. Examine os recursos do Android documentação (e,
em particular criar recursos para abranger diferentes tamanhos de tela) para obter mais informações sobre como
estruturar as pastas e os nomes de arquivo em seu aplicativo Android projeto para incluir recursos de imagem
otimizada em seu aplicativo.
Desktops e Tablets Windows
Para dar suporte a tablets e computadores desktop que executam o Windows, você precisará usar suporte do
Windows UWP, que compila aplicativos universais que são executados no Windows 10.
Aplicativos que são executados em desktops e tablets Windows podem ser redimensionados para dimensões
arbitrárias além para tela inteira em execução.
Otimizando para Tablet e área de trabalho
Você pode ajustar sua interface do usuário do xamarin. Forms, dependendo se um telefone ou dispositivo de
tablet/área de trabalho está sendo usado. Isso significa que você pode otimizar a experiência do usuário para
dispositivos de tela grande, como tablets e computadores desktop.
Device.Idiom
Você pode usar o Device classe para alterar o comportamento da interface do usuário ou aplicativo. Usando o
Device.Idiom enumeração, você pode
if (Device.Idiom == TargetIdiom.Phone)
{
HeroImage.Source = ImageSource.FromFile("hero.jpg");
} else {
HeroImage.Source = ImageSource.FromFile("herotablet.jpg");
}
Essa abordagem pode ser expandida para fazer alterações significativas aos layouts de página individual, ou até
mesmo para renderizar páginas inteiramente diferentes em telas maiores.
Aproveitando MasterDetailPage
O MasterDetailPage é ideal para telas maiores, especialmente no iPad em que ele usa o UISplitViewController
para fornecer uma experiência do iOS nativo.
Revisão esta postagem de blog do Xamarin para ver como você pode adaptar sua interface do usuário para que os
telefones usam um layout e telas maiores podem usar outro (com o MasterDetailPage ).
Links relacionados
Blog do Xamarin
Exemplo de MyShoppe
Associáveis Layouts no xamarin. Forms
12/04/2019 • 6 minutes to read
Baixar o exemplo
Layouts associáveis habilitam qualquer classe de layout que deriva de Layout<T> classe para gerar seu conteúdo
por associação a uma coleção de itens, com a opção de definir a aparência de cada item com um DataTemplate .
Layouts associáveis são fornecidos pelo BindableLayout classe, que expõe as propriedades anexadas a seguir:
ItemsSource – Especifica a coleção de IEnumerable itens a serem exibidos no layout.
ItemTemplate – Especifica o DataTemplate para aplicar a cada item na coleção de itens exibidos pelo layout.
ItemTemplateSelector – Especifica o DataTemplateSelector que será usado para escolher um DataTemplate
para um item em tempo de execução.
Essas propriedades podem ser anexadas à AbsoluteLayout , FlexLayout , Grid , RelativeLayout ,e StackLayout
classes, que derivam de Layout<T> classe.
NOTE
O ItemTemplate propriedade terá precedência quando tanto o ItemTemplate e ItemTemplateSelector são definidas.
O Layout<T> classe expõe um Children coleta, à qual os elementos filho de um layout são adicionados. Quando
o BinableLayout.ItemsSource propriedade é definida como uma coleção de itens e anexada a uma Layout<T> -
classe derivada, cada item na coleção é adicionado ao Layout<T>.Children coleção para exibição pelo layout. O
Layout<T> -classe derivada, em seguida, atualize suas exibições filha quando a coleção subjacente é alterado. Para
obter mais informações sobre o ciclo de layout do xamarin. Forms, consulte criação de um Layout personalizado.
IMPORTANT
Layouts associáveis só devem ser usados quando a coleção de itens a serem exibidos é pequena e de rolagem e a seleção
não é necessária. Enquanto a rolagem pode ser fornecida, encapsulando um layout associável em uma ScrollView , isso
não é recomendado como associáveis layouts não têm a virtualização de interface do usuário. Quando a rolagem é
necessária, uma exibição rolável que inclui a virtualização de interface do usuário, como ListView ou CollectionView ,
deve ser usado. Para observar essa recomendação pode levar a problemas de desempenho.
O código C# equivalente é:
O código C# equivalente é:
Neste exemplo, todos os itens a TopFollowers coleção será exibida por um CircleImage exibição definida na
DataTemplate :
Para obter mais informações sobre modelos de dados, consulte modelos de dados do xamarin. Forms.
O código C# equivalente é:
DataTemplateSelector dataTemplateSelector = new TechItemTemplateSelector { ... };
var flexLayout = new FlexLayout();
BindableLayout.SetItemsSource(flexLayout, viewModel.User.FavoriteTech);
BindableLayout.SetItemTemplateSelector(flexLayout, dataTemplateSelector);
Para obter mais informações sobre os seletores de modelo de dados, consulte criando um xamarin. Forms
DataTemplateSelector.
Links relacionados
Demonstração de Layout associável (amostra)
Criar um layout personalizado
Modelos de dados do xamarin. Forms
Criando um DataTemplateSelector xamarin. Forms
Criar um Layout personalizado
12/04/2019 • 27 minutes to read
baixar o exemplo
Xamarin. Forms define quatro classes de layout – StackLayout, AbsoluteLayout, RelativeLayout e grade, e cada
organiza seus filhos de uma maneira diferente. No entanto, às vezes, é necessário para organizar o conteúdo da
página usando um layout que não são fornecido pelo xamarin. Forms. Este artigo explica como escrever uma
classe de layout personalizado e demonstra uma classe de WrapLayout sensíveis à orientação que organiza seus
filhos horizontalmente pela página e, em seguida, ajusta a exibição dos filhos subsequentes em linhas adicionais.
Visão geral
No xamarin. Forms, todas as classes de layout derivam de Layout<T> classe e restringir o tipo genérico para
View e seus tipos derivados. Por sua vez, o Layout<T> classe deriva de Layout classe, que fornece o mecanismo
para posicionamento e o filho de dimensionamento elementos.
Cada elemento visual é responsável por determinar seu próprio tamanho preferencial, o que é conhecido como
o solicitado tamanho. Page , Layout , e Layout<View> tipos derivados são responsáveis por determinar o local e
o tamanho do seu filho ou filhos, em relação a mesmos. Portanto, o layout envolve uma relação pai-filho, no qual
o pai determina qual deve ser o tamanho de seus filhos, mas tentará acomodar o tamanho solicitado do filho.
Uma compreensão detalhada dos ciclos de layout e a invalidação da xamarin. Forms é necessária para criar um
layout personalizado. Esses ciclos agora serão discutidos.
Layout
Layout começa na parte superior da árvore visual com uma página, e ele passa todas as ramificações da árvore
visual para abranger todos os elementos visuais em uma página. Elementos que são pais de outros elementos
são responsáveis por redimensionar e posicionar seus filhos em relação a mesmos.
O VisualElement classe define um Measure o método que mede um elemento para operações de layout, e um
Layout método Especifica a área retangular que o elemento será renderizado no. Quando um aplicativo é
iniciado e a primeira página for exibida, um ciclo de layout primeiro consistindo de Measure chamadas e, em
seguida Layout chama, inicia no Page objeto:
1. Durante o ciclo de layout, cada elemento pai é responsável por chamar o Measure método em seus filhos.
2. Após os filhos terem sido medidos, todos os elementos pai é responsável por chamar o Layout método em
seus filhos.
Esse ciclo garante que cada elemento visual na página recebe chamadas para o Measure e Layout métodos. O
processo é mostrado no diagrama a seguir:
NOTE
Observe que os ciclos de layout também podem ocorrer em um subconjunto da árvore visual se algo for alterado para
afetar o layout. Isso inclui itens que estão sendo adicionados ou removidos da coleção como em uma StackLayout , uma
alteração no IsVisible propriedade de um elemento ou uma alteração no tamanho de um elemento.
Cada classe de xamarin. Forms que tem um Content ou um Children propriedade tem um substituível
LayoutChildren método. Classes de layout personalizados que derivam de Layout<View> deve substituir esse
método e certifique-se de que o Measure e Layout são métodos chamado em todos os filhos do elemento, para
fornecer o layout personalizado desejado.
Além disso, cada classe que deriva de Layout ou Layout<View> deve substituir o OnMeasure método, que é
sempre que uma classe de layout Determina o tamanho que ele precisa estar fazendo chamadas para o Measure
métodos de seus filhos.
NOTE
Elementos determinam seu tamanho com base no restrições, que indicam a quantidade de espaço está disponível para um
elemento dentro do pai do elemento. Restrições passada para o Measure e OnMeasure métodos podem variar de 0 a
Double.PositiveInfinity . É um elemento restrita, ou totalmente restrita, quando ele recebe uma chamada para seu
Measure método com argumentos não infinita - o elemento é restrita para um tamanho específico. É um elemento
irrestrita, ou parcialmente restrita, quando ele recebe uma chamada para seu Measure método com pelo menos um
argumento igual a Double.PositiveInfinity – a restrição de infinita pode ser pensada como indicando o
dimensionamento automático.
Invalidação
Invalidação de é o processo pelo qual uma alteração em um elemento em uma página dispara um novo ciclo de
layout. Elementos são considerados inválidos quando eles não terão mais o tamanho correto ou a posição. Por
exemplo, se o FontSize propriedade de uma Button alterações, o Button será considerada inválida porque ela
não terá mais o tamanho correto. Redimensionando o Button , em seguida, pode ter um efeito dominó das
alterações no layout através do restante de uma página.
Elementos invalidam a mesmos, invocando o InvalidateMeasure método, geralmente quando uma propriedade
do elemento é alterada que pode resultar em um novo tamanho do elemento. Este método aciona o
MeasureInvalidated evento, que lida com o pai do elemento para disparar um novo ciclo de layout.
O Layout classe define um manipulador para o MeasureInvalidated evento em todos os filhos adicionados ao
seu Content propriedade ou Children coleção e desanexa o manipulador quando o filho é removido. Portanto,
todos os elementos na árvore visual que tem filhos é alertado sempre que um de seus filhos altera o tamanho. O
diagrama a seguir ilustra como uma alteração no tamanho de um elemento na árvore visual pode causar
alterações ripple acima na árvore:
No entanto, o Layout classe tenta restringir o impacto de uma alteração no tamanho de um filho no layout de
uma página. Se o layout é restringido de tamanho, em seguida, uma alteração de tamanho de filho não afeta
nada maior do que o layout do pai na árvore visual. No entanto, geralmente uma alteração no tamanho de um
layout afeta como o layout organiza seus filhos. Portanto, qualquer alteração no tamanho de um layout iniciará
um ciclo de layout para o layout e o layout receberá chamadas para seus OnMeasure e LayoutChildren métodos.
O Layout classe define também uma InvalidateLayout método que tem uma finalidade similar do
InvalidateMeasure método. O InvalidateLayout método deve ser chamado sempre que for feita uma alteração
que afeta como o layout posiciona e dimensiona seus filhos. Por exemplo, o Layout classe invoca o
InvalidateLayout método sempre que um filho é adicionado ou removido de um layout.
O InvalidateLayoutpode ser substituído para implementar um cache para minimizar repetitivas invocações da
Measure métodos de filhos do layout. Substituindo o InvalidateLayout método fornecerá uma notificação de
quando os filhos são adicionados ou removidos do layout. Da mesma forma, o OnChildMeasureInvalidated
método pode ser substituído para fornecer uma notificação quando um dos filhos do layout muda de tamanho.
Para ambas as substituições de método, um layout personalizado deve responder ao limpar o cache. Para obter
mais informações, consulte Calculando e armazenando dados.
NOTE
Ao enumerar os filhos na OnMeasure e LayoutChildren substituições, ignore qualquer filho cujo IsVisible estiver
definida como false . Isso garantirá que o layout personalizado não deixar espaço para os filhos invisíveis.
1. [opcional] substituir a InvalidateLayout método a ser notificado quando os filhos são adicionados ou
removidos do layout. Para obter mais informações, consulte substituindo o método InvalidateLayout.
2. [opcional] substituir a OnChildMeasureInvalidated método a ser notificado quando um dos filhos do layout
muda de tamanho. Para obter mais informações, consulte substituindo o método
OnChildMeasureInvalidated.
NOTE
Observe que o OnMeasure substituição não será invocada se o tamanho do layout é controlado pelo seu pai, em vez de
seus filhos. No entanto, a substituição será chamada se uma ou ambas as restrições são infinitas ou se a classe de layout
tem não padrão HorizontalOptions ou VerticalOptions valores de propriedade. Por esse motivo, o
LayoutChildren substituição não pode contar com tamanhos de filho obtidos durante a OnMeasure chamada de
método. Em vez disso, LayoutChildren deve invocar o Measure método nos filhos do layout, antes de invocar o
Layout método. Como alternativa, o tamanho dos filhos obtido na OnMeasure substituição pode ser armazenados em
cache para evitar mais tarde Measure invocações no LayoutChildren substituição, mas a classe de layout será preciso
saber quando os tamanhos precisam ser obtido novamente. Para obter mais informações, consulte Calculando e
armazenando dados de Layout.
A classe de layout, em seguida, pode ser consumida por adicioná-lo para um Page e pela adição de filhos no
layout. Para obter mais informações, consulte consumindo o WrapLayout.
Criando um WrapLayout
O aplicativo de exemplo demonstra uma orientação diferencia WrapLayout classe que organiza seus filhos
horizontalmente pela página e, em seguida, ajusta a exibição dos filhos subsequentes em linhas adicionais.
O WrapLayout classe aloca a mesma quantidade de espaço para cada filho, conhecido como o tamanho de
célula, com base no tamanho máximo dos filhos. Menor do que o tamanho da célula pode ser posicionado
dentro da célula de filhos com base em suas HorizontalOptions e VerticalOptions valores de propriedade.
O WrapLayout definição de classe é mostrada no exemplo de código a seguir:
O layoutDataCache campo é usado para armazenar vários LayoutData valores. Quando o aplicativo for iniciado,
dois LayoutData objetos serão armazenados em cache para o layoutDataCache dicionário para a orientação
atual – uma para os argumentos de restrição para o OnMeasure substituição e outro para o width e height
argumentos para o LayoutChildren substituir. Para girar o dispositivo em orientação paisagem, o OnMeasure
substituir e o LayoutChildren substituição será novamente invocada, que resulta em dois outro LayoutData
objetos a serem armazenados em cache no dicionário. No entanto, ao retornar o dispositivo para a orientação
retrato, não há cálculos adicionais são necessários porque o layoutDataCache já tem os dados necessários.
O seguinte exemplo de código mostra a GetLayoutData método, que calcula as propriedades do LayoutData
estruturados com base em um determinado tamanho:
int visibleChildCount = 0;
Size maxChildSize = new Size();
int rows = 0;
int columns = 0;
LayoutData layoutData = new LayoutData();
if (visibleChildCount != 0)
{
// Calculate the number of rows and columns.
if (Double.IsPositiveInfinity(width))
{
columns = visibleChildCount;
rows = 1;
}
else
{
columns = (int)((width + ColumnSpacing) / (maxChildSize.Width + ColumnSpacing));
columns = Math.Max(1, columns);
rows = (visibleChildCount + columns - 1) / columns;
}
if (Double.IsPositiveInfinity(width))
cellSize.Width = maxChildSize.Width;
else
cellSize.Width = (width - ColumnSpacing * (columns - 1)) / columns;
cellSize.Width = (width - ColumnSpacing * (columns - 1)) / columns;
if (Double.IsPositiveInfinity(height))
cellSize.Height = maxChildSize.Height;
else
cellSize.Height = (height - RowSpacing * (rows - 1)) / rows;
layoutDataCache.Add(size, layoutData);
return layoutData;
}
Invoca a substituição de GetLayoutData método e construções de um SizeRequest objeto dos dados retornados,
levando em consideração também a RowSpacing e ColumnSpacing valores de propriedade. Para obter mais
informações sobre o GetLayoutData método, consulte Calculando e armazenando dados.
IMPORTANT
O Measure e OnMeasure métodos nunca devem solicitar uma dimensão de infinita, retornando um SizeRequest valor
com uma propriedade definida como Double.PositiveInfinity . No entanto, pelo menos um dos argumentos de
restrição OnMeasure pode ser Double.PositiveInfinity .
if (layoutData.VisibleChildCount == 0)
{
return;
}
double xChild = x;
double yChild = y;
int row = 0;
int column = 0;
A substituição começa com uma chamada para o GetLayoutData método e, em seguida, enumera todos os filhos
para dimensionar e posicioná-los dentro da célula de cada filho. Isso é feito invocando o
LayoutChildIntoBoundingRegion método, que é usado para posicionar um filho dentro de um retângulo com base
em seu HorizontalOptions e VerticalOptions valores de propriedade. Isso é equivalente a fazer uma chamada
para o filho Layout método.
NOTE
Observe que o retângulo transmitido para o LayoutChildIntoBoundingRegion método inclui toda a área em que o filho
pode residir.
Para obter mais informações sobre o GetLayoutData método, consulte Calculando e armazenando dados.
Substituindo o método InvalidateLayout
O InvalidateLayout substituição é invocada quando filhos são adicionados ou removidos do layout, ou quando
um do WrapLayout alterações de propriedades de valor, conforme mostrado no exemplo de código a seguir:
public ImageWrapLayoutPageCS()
{
wrapLayout = new WrapLayout();
Filhos, em seguida, podem ser adicionados para o WrapLayout conforme necessário. O seguinte exemplo de
código mostra Image elementos que estão sendo adicionados ao WrapLayout :
protected override async void OnAppearing()
{
base.OnAppearing();
Quando a página que contém o WrapLayout aparecer, de forma assíncrona, o aplicativo de exemplo acessa um
arquivo JSON remoto que contém uma lista de fotos, cria um Image elemento para cada foto e adiciona-o para
o WrapLayout . Isso resulta na exibição mostrada nas capturas de tela seguir:
As capturas de tela a seguir mostram o WrapLayout depois é girada para a orientação paisagem:
O número de colunas em cada linha depende do tamanho da foto, a largura da tela e o número de pixels por
unidade independente de dispositivo. O Image elementos de forma assíncrona carregar as fotos e, portanto, o
WrapLayout classe receberá chamadas frequentes para seus LayoutChildren método conforme cada Image
elemento recebe um novo tamanho com base na foto carregada.
Resumo
Este artigo explica como escrever uma classe de layout personalizado e demonstramos uma orientação
diferencia WrapLayout classe que organiza seus filhos horizontalmente pela página e, em seguida, ajusta a
exibição dos filhos subsequentes em linhas adicionais.
Links relacionados
WrapLayout (amostra)
Layouts personalizados
Criar Layouts personalizados no xamarin. Forms (vídeo)
Layout
Layout
VisualElement
Compactação de Layout
12/04/2019 • 8 minutes to read
baixar o exemplo
Compactação de layout remove os layouts especificados da árvore visual em uma tentativa de melhorar o
desempenho de renderização da página. Este artigo explica como habilitar a compactação de layout e os
benefícios que ele pode trazer.
Visão geral
Xamarin. Forms executa usando duas séries de chamadas de método recursiva de layout:
Layout começa na parte superior da árvore visual com uma página, e ele passa todas as ramificações da
árvore visual para abranger todos os elementos visuais em uma página. Elementos que são pais de outros
elementos são responsáveis por redimensionar e posicionar seus filhos em relação a mesmos.
Invalidação de é o processo pelo qual uma alteração em um elemento em uma página dispara um novo ciclo
de layout. Elementos são considerados inválidos quando eles não terão mais o tamanho correto ou a posição.
Todos os elementos na árvore visual que tem filhos é alertado sempre que um de seus filhos altera tamanhos.
Portanto, uma alteração no tamanho de um elemento na árvore visual pode causar alterações ripple acima na
árvore.
Para obter mais informações sobre como o xamarin. Forms executa o layout, consulte criação de um Layout
personalizado.
O resultado do processo de layout é uma hierarquia de controles nativos. No entanto, essa hierarquia inclui os
renderizadores de contêiner adicional e wrappers para renderizadores de plataforma, aumentando ainda mais a
hierarquia de exibição de aninhamento. O maior o nível de aninhamento, maior a quantidade de trabalho que o
xamarin. Forms deve executar para exibir uma página. Para layouts complexos, a hierarquia de exibição pode ser
profundo e abrangente, com vários níveis de aninhamento.
Por exemplo, considere o seguinte botão do aplicativo de exemplo para fazer logon no Facebook:
Esse botão é especificado como um controle personalizado com a hierarquia de exibição XAML a seguir:
<ContentView ...>
<StackLayout>
<StackLayout ...>
<AbsoluteLayout ...>
<Button ... />
<Image ... />
<Image ... />
<BoxView ... />
<Label ... />
<Button ... />
</AbsoluteLayout>
</StackLayout>
<Label ... />
</StackLayout>
</ContentView>
A hierarquia de exibição aninhada resultante poderá ser examinada com Xamarin Inspector. No Android, a
hierarquia de exibição aninhada contém exibições de 17:
Compactação de layout, que está disponível para aplicativos xamarin. Forms nas plataformas Android e iOS, tem
como objetivo para mesclar a exibição de aninhamento, removendo os layouts especificados da árvore visual, que
pode melhorar o desempenho de renderização da página. O benefício de desempenho que é fornecido varia
dependendo da complexidade de uma página, a versão do sistema operacional que está sendo usado e o
dispositivo no qual o aplicativo está em execução. No entanto, os maiores ganhos de desempenho serão
observados em versões mais antigas.
NOTE
Embora este artigo se concentra nos resultados da aplicação de compactação de layout no Android, é igualmente aplicável
para iOS.
Compactação de Layout
No XAML, a compactação de layout pode ser habilitada definindo o CompressedLayout.IsHeadless anexado à
propriedade true em uma classe de layout:
<StackLayout CompressedLayout.IsHeadless="true">
...
</StackLayout>
Como alternativa, ele pode ser habilitado em c#, especificando a instância de layout como o primeiro argumento
para o CompressedLayout.SetIsHeadless método:
CompressedLayout.SetIsHeadless(stackLayout, true);
IMPORTANT
Uma vez que a compactação de layout remove um layout da árvore visual, não é adequado para layouts que têm uma
aparência visual, ou que obtêm entrada por toque. Portanto, layouts que defina VisualElement propriedades (como
BackgroundColor , IsVisible , Rotation , Scale , TranslationX e TranslationY ou que aceitar gestos, não são
candidatos para o layout compactação. No entanto, a habilitação da compactação de layout em um layout que define as
propriedades de aparência visual, ou que aceita a gestos, não resultará em um erro de compilação ou tempo de execução.
Em vez disso, compactação de layout será aplicada e as propriedades de aparência visual e reconhecimento de gesto,
falharão silenciosamente.
Para o botão do Facebook, compactação de layout pode ser habilitada nas classes de layout de três:
<StackLayout CompressedLayout.IsHeadless="true">
<StackLayout CompressedLayout.IsHeadless="true" ...>
<AbsoluteLayout CompressedLayout.IsHeadless="true" ...>
...
</AbsoluteLayout>
</StackLayout>
...
</StackLayout>
Em comparação com a hierarquia de exibição aninhada original das exibições de 17, isso representa uma redução
no número de modos de exibição de 17%. Embora essa redução pode aparecer insignificante, a redução de modo
de exibição ao longo de uma página inteira pode ser mais significativa.
Renderizadores Rápidos
Renderizadores rápidos reduzem os custos de renderização de controles do xamarin. Forms no Android e inflação
nivelando a hierarquia resultante de modo nativo. Isso aprimora o desempenho criando menos objetos, que por
sua vez, resulta em uma árvore visual menos complexa e menos uso de memória. Para obter mais informações
sobre renderizadores rápidos, consulte os renderizadores rápidos.
Para o botão do Facebook no aplicativo de exemplo, a combinação de compactação de layout e os renderizadores
rápidos produz uma hierarquia de exibição aninhada de exibições de 8:
Em comparação com a hierarquia de exibição aninhada original das exibições de 17, isso representa uma redução
de 52%.
O aplicativo de exemplo contém uma página extraída de um aplicativo real. Sem compactação de layout e os
renderizadores rápidos, a página produz uma hierarquia de exibição aninhada de 130 exibições no Android.
Habilitando os renderizadores rápidos e compactação de layout em classes de layout adequado reduz a hierarquia
de exibição aninhada a 70 modos de exibição, uma redução de 46%.
Resumo
Compactação de layout remove os layouts especificados da árvore visual em uma tentativa de melhorar o
desempenho de renderização da página. O benefício de desempenho que isso oferece varia dependendo da
complexidade de uma página, da versão do sistema operacional que está sendo usado e do dispositivo no qual o
aplicativo está sendo executado. No entanto, os maiores ganhos de desempenho serão observados em versões
mais antigas.
Links relacionados
Criar um layout personalizado
Renderizadores Rápidos
LayoutCompression (amostra)
Xamarin. Forms ListView
12/04/2019 • 5 minutes to read
Baixar o exemplo
ListView é uma exibição para apresentar as listas de dados, especialmente listas longas que exigem rolagem.
IMPORTANT
CollectionView é um modo de exibição para apresentar as listas de dados usando as especificações de layout diferente.
Tem como objetivo fornecer uma mais flexível e alternativa de alto desempenho para o ListView . Para obter mais
informações, consulte xamarin. Forms CollectionView.
Casos de uso
Certifique-se de que ListView é o controle certo para suas necessidades. ListView pode ser usado em qualquer
situação em que você está exibindo a lista rolável de dados. ListViews dão suporte a ações de contexto e
associação de dados.
Não deve ser confundido com o ListView modo de tabela. O controle de modo de tabela é uma opção melhor,
sempre que você tem uma lista não associadas de opções ou de dados. Por exemplo, o aplicativo de
configurações do iOS, que tem um conjunto predefinido de principalmente de opções, é mais adequado usar o
modo de tabela que ListView.
Também Observe que um ListView é melhor adequada para dados homogêneos – ou seja, todos os dados
devem ser do mesmo tipo. Isso ocorre porque apenas um tipo de célula pode ser usado para cada linha na lista.
TableViews pode dar suporte a vários tipos de célula, portanto, eles são uma opção melhor quando você
precisar combinar modos de exibição.
Componentes
ListView tem um número de componentes disponíveis para praticar a funcionalidade nativa de cada
plataforma. Cada um desses componentes é descrita abaixo:
Cabeçalhos e rodapés – separar de texto ou modo de exibição para exibir no início e no final de uma lista
de dados da lista. Cabeçalhos e rodapés de páginas podem ser associados a uma fonte de dados
independentemente da fonte de dados do ListView.
Grupos – dados em um ListView que podem ser agrupados para facilitar a navegação. Normalmente, os
grupos são associados a dados:
Células – dados em um ListView são apresentados nas células. Cada célula corresponde a uma linha de
dados. Houver células internas à sua escolha, ou você pode definir sua própria célula personalizado. Células
de internas e personalizadas podem ser usadas/definido em XAML ou código.
Interna – criados nas células, especialmente TextCell e ImageCell, pode ser ótimo para o
desempenho, já que eles correspondem aos controles nativos em cada plataforma.
TextCell – exibe uma cadeia de caracteres de texto, opcionalmente, com o texto detalhado.
Texto de detalhe é renderizado como uma segunda linha em uma fonte menor com uma cor de
ênfase.
ImageCell – exibe uma imagem com texto. Aparece como um TextCell com uma imagem à
esquerda.
Células personalizadas – células personalizadas são ótimos quando você precisa apresentar dados
complexos. Por exemplo, uma exibição personalizada poderia ser usada para apresentar uma lista de
músicas, incluindo o álbum e o artista:
Para saber mais sobre como personalizar células em um ListView, consulte personalizando aparência de célula
do ListView.
Funcionalidade
ListView oferece suporte a um número de estilos de interação, incluindo:
Atualização de pull – ListView oferece suporte a pull para atualizar em cada plataforma.
Ações de contexto – ListView oferece suporte a executar ações em itens individuais em uma lista. Por
exemplo, você pode implementar a ação para passar o dedo no iOS, ou toque ações no Android.
Seleção – você pode escutar seleções e contíguas para agir quando uma linha é tocada.
Para saber mais sobre os recursos de interatividade do ListView, consulte ações & interatividade com ListView.
Links relacionados
Trabalhando com ListView (amostra)
Associação bidirecional (amostra)
Criado em células (amostra)
Células personalizadas (amostra)
Agrupamento (amostra)
Exibição de renderizador personalizado (amostra)
Interatividade do ListView (amostra)
Fontes de dados de ListView
12/04/2019 • 5 minutes to read
baixar o exemplo
Um ListView é usado para exibir listas de dados. Aprenderemos sobre preenchendo um ListView com dados e
como podemos fazer a ligação para o item selecionado.
ItemsSource
Um ListView é preenchida com dados usando o ItemsSource propriedade, que pode aceitar qualquer coleção que
implementa IEnumerable . A maneira mais simples para preencher um ListView envolve o uso de uma matriz de
cadeias de caracteres:
<ListView>
<ListView.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>mono</x:String>
<x:String>monodroid</x:String>
<x:String>monotouch</x:String>
<x:String>monorail</x:String>
<x:String>monodevelop</x:String>
<x:String>monotone</x:String>
<x:String>monopoly</x:String>
<x:String>monomodal</x:String>
<x:String>mononucleosis</x:String>
</x:Array>
</ListView.ItemsSource>
</ListView>
O código c# equivalente é:
Associação de dados
Associação de dados é a "cola" que associa as propriedades de um objeto de interface do usuário para as
propriedades de um objeto do CLR, como uma classe em seu ViewModel. Associação de dados é útil porque ele
simplifica o desenvolvimento de interfaces do usuário, substituindo muito código clichê que sem graça.
Associação de dados funciona mantendo os objetos sincronizados como alteram seus valores associados. Em vez
de precisar escrever manipuladores de eventos para sempre que um valor de controle é alterada, você estabelecer
a associação e habilitar a associação em seu ViewModel.
Para obter mais informações sobre associação de dados, consulte Noções básicas de vinculação de dados que é a
parte quatro da série de artigos de Noções básicas de XAML do xamarin. Forms.
Células de associação
Propriedades de células (e seus filhos de células) podem ser associadas às propriedades de objetos no
ItemsSource . Por exemplo, um ListView pode ser usado para apresentar uma lista de funcionários.
A classe do funcionário:
public EmployeeListPage()
{
...
employees.Add(new Employee{ DisplayName="Rob Finnerty"});
employees.Add(new Employee{ DisplayName="Bill Wrestler"});
employees.Add(new Employee{ DisplayName="Dr. Geri-Beth Hooper"});
employees.Add(new Employee{ DisplayName="Dr. Keith Joyce-Purdy"});
employees.Add(new Employee{ DisplayName="Sheri Spruce"});
employees.Add(new Employee{ DisplayName="Burt Indybrick"});
}
Observe que a associação foi configurada no código para manter a simplicidade, embora ele foi vinculado em
XAML.
O bit anterior de XAML define uma ContentPage que contém um ListView . Fonte de dados das ListView é
definido por meio de ItemsSource atributo. O layout de cada linha na ItemsSource é definido dentro de
ListView.ItemTemplate elemento.
Esse é o resultado:
Associação SelectedItem
Muitas vezes você desejará ligar para o item selecionado de um ListView , em vez de usar um manipulador de
eventos para responder a alterações. Para fazer isso no XAML, associar a SelectedItem propriedade:
<ListView x:Name="listView"
SelectedItem="{Binding Source={x:Reference SomeLabel},
Path=Text}">
…
</ListView>
Supondo listView do ItemsSource é uma lista de cadeias de caracteres SomeLabel terão sua propriedade de texto
associada ao SelectedItem .
Links relacionados
Associação bidirecional (amostra)
Personalizando a aparência de célula do ListView
12/04/2019 • 10 minutes to read
Baixar o exemplo
ListView apresenta listas roláveis, o que podem ser personalizadas por meio do uso de ViewCell s. ViewCells
pode ser usado para exibir texto e imagens, que indica um estado de verdadeiro/falso e receber entrada do
usuário.
Criado em células
Xamarin. Forms vem com células internos que funcionam para muitos aplicativos simples:
TextCell – para exibir o texto
ImageCell – para exibir uma imagem com texto.
Duas células adicionais, SwitchCell e EntryCell estão disponíveis, no entanto, eles não são comumente usados
com ListView . Ver TableView para obter mais informações sobre essas células.
TextCell
TextCell é uma célula para exibir o texto, opcionalmente com uma segunda linha como texto de detalhes.
TextCells são renderizados como controles nativos em tempo de execução, portanto, o desempenho é muito
bom em comparação com um personalizado ViewCell . TextCells são personalizáveis, permitindo que você
defina:
Text – o texto que é mostrado na primeira linha, em fonte grande.
Detail – o texto que é mostrado abaixo da primeira linha, em uma fonte menor.
TextColor – a cor do texto.
DetailColor – a cor do texto de detalhes
ImageCell
ImageCell , como TextCell , pode ser usado para exibir texto e texto secundário detalhes e oferece excelente
desempenho usando controles nativos de cada plataforma. ImageCell é diferente do TextCell em que ele
exibe uma imagem à esquerda do texto.
ImageCell é útil quando você precisa exibir uma lista de dados com um aspecto visual, como uma lista de
contatos ou filmes. ImageCells são personalizáveis, permitindo que você defina:
Text – o texto que é mostrado na primeira linha, em fontes grandes
Detail – o texto que é mostrado abaixo da primeira linha, em uma fonte menor
TextColor – a cor do texto
DetailColor – a cor do texto de detalhes
ImageSource – a imagem a ser exibida ao lado do texto
Células personalizadas
Quando as células internas não fornecerem o layout necessário, células personalizadas implementado o layout
necessário. Por exemplo, você talvez queira apresentar uma célula com dois rótulos que têm o mesmo peso. Um
TextCell seria insuficiente porque o TextCell tem um rótulo que for menor. A maioria das personalizações de
célula adicionar dados somente leitura adicionais (como rótulos adicionais, imagens ou outras informações de
exibição).
Todas as células personalizadas devem derivar de ViewCell , a mesma classe base que todos os internos célula
tipos de uso.
Xamarin. Forms 2 introduziu um novo comportamento de cache sobre o ListView controle que pode ser
definida para melhorar o desempenho de rolagem para alguns tipos de células personalizadas.
Este é um exemplo de uma célula personalizada:
XAML
O XAML para criar o layout acima está abaixo:
//set bindings
left.SetBinding (Label.TextProperty, "title");
right.SetBinding (Label.TextProperty, "subtitle");
image.SetBinding (Image.SourceProperty, "image");
Em seu construtor para a página com o ListView , defina o ListView ItemTemplate propriedade para um novo
DataTemplate :
Observe que o construtor para DataTemplate usa um tipo. O operador typeof obtém o tipo CLR para
CustomCell .
Alterações de contexto de associação
Ao associar a um tipo de célula personalizado BindableProperty instâncias, os controles de interface do usuário
exibindo as BindableProperty valores devem usar o OnBindingContextChanged substituição para definir os dados
a serem exibidos no cada célula, em vez do construtor de célula, conforme demonstrado no exemplo de código a
seguir:
if (BindingContext != null) {
nameLabel.Text = Name;
ageLabel.Text = Age.ToString ();
locationLabel.Text = Location;
}
}
}
NOTE
Ao substituir OnBindingContextChanged , certifique-se de que a classe base OnBindingContextChanged método é
chamado para que os representantes registrados recebam o BindingContextChanged eventos.
No XAML, associando o tipo de célula personalizado a dados pode ser obtida conforme mostrado no exemplo
de código a seguir:
<ListView x:Name="listView">
<ListView.ItemTemplate>
<DataTemplate>
<local:CustomCell Name="{Binding Name}" Age="{Binding Age}" Location="{Binding Location}" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Isso vincula o Name , Age , e Location propriedades vinculáveis no CustomCell da instância, como o Name ,
Age , e Location propriedades de cada objeto na coleção subjacente.
Links relacionados
Criado em células (amostra)
Células personalizadas (amostra)
Associação de contexto alterado (amostra)
Personalizando a aparência de ListView
12/04/2019 • 10 minutes to read
Baixar o exemplo
ListView tem a capacidade de controlar a apresentação da lista, além de ViewCell instâncias para cada linha na
lista.
Agrupamento
Muitas vezes, grandes conjuntos de dados podem se tornar complicados quando apresentadas em uma lista de
rolagem contínua. Habilitação de agrupamento pode melhorar a experiência do usuário nesses casos, organizar
melhor o conteúdo e ativar os controles específicos da plataforma que facilitam a navegação de dados.
Quando o agrupamento é ativado para um ListView , uma linha de cabeçalho é adicionada para cada grupo.
Para habilitar o agrupamento:
Crie uma lista de listas (uma lista de grupos, cada grupo que está sendo uma lista de elementos).
Defina as ListView do ItemsSource à lista.
Definir IsGroupingEnabled como true.
Definir GroupDisplayBinding para associar a propriedade dos grupos que está sendo usada como o título do
grupo.
[Opcional] Definir GroupShortNameBinding para associar à propriedade que está sendo usada como o nome
curto para o grupo dos grupos. O nome curto é usado para as listas de salto (coluna direita no iOS ).
Comece criando uma classe para os grupos:
No código acima, All é a lista será dado ao nosso ListView como a origem da associação. Title e ShortName são
as propriedades que serão usadas para títulos de grupo.
Nesse estágio, All é uma lista vazia. Adicione um construtor estático para que a lista será preenchida no início do
programa:
static PageTypeGroup()
{
List<PageTypeGroup> Groups = new List<PageTypeGroup> {
new PageTypeGroup ("Alfa", "A"){
new PageModel("Amelia", "Cedar", new switchCellPage(),""),
new PageModel("Alfie", "Spruce", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Ava", "Pine", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Archie", "Maple", new switchCellPage(), "grapefruit.jpg")
},
new PageTypeGroup ("Bravo", "B"){
new PageModel("Brooke", "Lumia", new switchCellPage(),""),
new PageModel("Bobby", "Xperia", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Bella", "Desire", new switchCellPage(), "grapefruit.jpg"),
new PageModel("Ben", "Chocolate", new switchCellPage(), "grapefruit.jpg")
}
}
All = Groups; //set the publicly accessible list
}
No código acima, também podemos chamar Add nos elementos de groups , que são instâncias do tipo
PageTypeGroup . Isso é possível porque PageTypeGroup herda de List<PageModel> . Este é um exemplo da lista de
padrão de listas observado acima.
Aqui está o XAML para exibir a lista agrupada:
O resultado é o seguinte:
Observe que temos:
Definir GroupShortNameBinding para o ShortName propriedade definida em nossa classe de grupo
Definir GroupDisplayBinding para o Title propriedade definida em nossa classe de grupo
Definir IsGroupingEnabled como true
Alterado o ListView do ItemsSource à lista agrupada
Personalizar agrupamento
Se o agrupamento tiver sido habilitado na lista, o cabeçalho de grupo também pode ser personalizado.
Assim como o ListView tem um ItemTemplate para definir como as linhas são exibidas, ListView tem um
GroupHeaderTemplate .
Um exemplo de como personalizar o cabeçalho de grupo em XAML é mostrado aqui:
<?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="DemoListView.GroupingViewPage">
<ContentPage.Content>
<ListView x:Name="GroupedView"
GroupDisplayBinding="{Binding Title}"
GroupShortNameBinding="{Binding ShortName}"
IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding Subtitle}"
TextColor="#f35e20"
DetailColor="#503026" />
</DataTemplate>
</ListView.ItemTemplate>
<!-- Group Header Customization-->
<ListView.GroupHeaderTemplate>
<DataTemplate>
<TextCell Text="{Binding Title}"
Detail="{Binding ShortName}"
TextColor="#f35e20"
DetailColor="#503026" />
</DataTemplate>
</ListView.GroupHeaderTemplate>
<!-- End Group Header Customization -->
</ListView>
</ContentPage.Content>
</ContentPage>
Cabeçalhos e rodapés
É possível para um ListView apresentar um cabeçalho e rodapé que rolam com os elementos da lista. O cabeçalho
e rodapé podem ser cadeias de caracteres de texto ou um layout mais complicado. Observe que isso é separado do
seção grupos.
Você pode definir as Header e/ou Footer para uma cadeia de caracteres simple valor, ou você pode defini-las para
um layout mais complexo. Também há HeaderTemplate e FooterTemplate propriedades que permitem criam
layouts mais complexos para o cabeçalho e rodapé que suportam associação de dados.
Para criar um cabeçalho/rodapé simple, basta defina as propriedades de cabeçalho ou rodapé para o texto que
você deseja exibir. No código:
No XAML:
<ListView.Header>
<StackLayout Orientation="Horizontal">
<Label Text="Header"
TextColor="Olive"
BackgroundColor="Red" />
</StackLayout>
</ListView.Header>
<ListView.Footer>
<StackLayout Orientation="Horizontal">
<Label Text="Footer"
TextColor="Gray"
BackgroundColor="Blue" />
</StackLayout>
</ListView.Footer>
Visibilidade da barra de rolagem
ListView tem e VerticalScrollBarVisibility propriedades, o qual obtém ou
HorizontalScrollBarVisibility
definir um ScrollBarVisibility valor que representa quando a barra de rolagem horizontal ou vertical, está visível.
Ambas as propriedades podem ser definidas com os seguintes valores:
Defaultindica o comportamento padrão de barra de rolagem para a plataforma e é o valor padrão para o
HorizontalScrollBarVisibilitye VerticalScrollBarVisibility propriedades.
Always indica que as barras de rolagem será visíveis, mesmo quando o conteúdo se ajusta no modo de
exibição.
Never indica que as barras de rolagem não será visíveis, mesmo se o conteúdo não se encaixa no modo de
exibição.
Separadores de linha
As linhas do separador são exibidas entre ListView elementos por padrão no iOS e Android. Se você desejar
ocultar as linhas de separador no iOS e Android, defina o SeparatorVisibility propriedade em sua ListView. As
opções para SeparatorVisibility são:
Padrão -mostra uma linha separadora no iOS e Android.
Nenhum -oculta o separador em todas as plataformas.
Visibilidade do padrão:
C#:
SepratorDemoListView.SeparatorVisibility = SeparatorVisibility.Default;
XAML:
Nenhum:
C#:
SepratorDemoListView.SeparatorVisibility = SeparatorVisibility.None;
XAML:
SepratorDemoListView.SeparatorColor = Color.Green;
XAML:
Você pode definir a altura de todas as linhas, definindo o RowHeight propriedade no ListView .
Altura de linha fixa personalizada
C#:
RowHeightDemoListView.RowHeight = 100;
XAML:
RowHeightDemoListView.HasUnevenRows = true;
XAML:
O OnImageTapped manipulador de eventos é executado em resposta a uma Image em uma célula que está sendo
tocado e aumenta o tamanho do Image exibido na célula para que ela é exibida com facilidade.
Observe que há uma grande possibilidade de degradação do desempenho se esse recurso está sendo usado em
excesso.
Links relacionados
Agrupamento (amostra)
Exibição de renderizador personalizado (amostra)
Redimensionamento de linhas dinâmicas (amostra)
Notas de versão 1.4
Notas de versão 1.3
Interatividade do ListView
12/04/2019 • 9 minutes to read
Baixar o exemplo
ListView dá suporte a interagir com os dados que ele apresenta.
Single indica que um único item pode ser selecionado, com o item selecionado que está sendo realçado. Este
é o valor padrão.
None indica que os itens não podem ser selecionados.
NOTE
O ItemTappedEventArgs classe, que contém os argumentos de evento para o ItemTapped , o evento tem Group e
Item propriedades e uma ItemIndex propriedade cujo valor representa o índice no ListView do item tocado. Da
mesma forma, o SelectedItemChangedEventArgs classe, que contém os argumentos de evento para o ItemSelected
evento, tem um SelectedItem propriedade e um SelectedItemIndex propriedade cujo valor representa o índice no
ListView do item selecionado.
Quando o estiver definida como Single , os itens no ListView pode ser selecionado, a
SelectionMode
ItemSelected e ItemTapped eventos serão disparados e o SelectedItem propriedade será definida como o valor
do item selecionado.
Quando o estiver definida como None , os itens no ListView não pode ser selecionado, a
SelectionMode
ItemSelected evento não será disparado e o SelectedItem propriedade permanecerá null . No entanto,
ItemTapped eventos ainda serão acionados e o item tocado será realçado brevemente durante o toque.
Quando um item foi selecionado e o SelectionMode propriedade é alterada de Single para None , o
SelectedItem propriedade será definida como null e o ItemSelected evento será acionado com um null item.
As capturas de tela a seguir mostram uma ListView com o modo de seleção padrão:
Desabilitar seleção
Para desabilitar ListView conjunto de seleção a SelectionMode propriedade None :
Ações de contexto
Muitas vezes, os usuários desejarão agir em um item em um ListView . Por exemplo, considere uma lista de
emails no aplicativo Mail. No iOS, você pode passar para excluir uma mensagem::
Ações de contexto podem ser implementadas em c# e XAML. Abaixo você encontrará guias específicos para
ambos, mas primeiro vamos dar uma olhada em alguns detalhes de implementação fundamentais para ambos.
Ações de contexto são criadas usando MenuItem s. Eventos de toque para MenuItems são acionados por
MenuItem em si, não o ListView. Isso é diferente de como os eventos de toque são tratados para células, onde o
ListView gera o evento em vez da célula. Porque o ListView está gerando o evento, seu manipulador de eventos
recebe informações de chave, como o qual o item foi selecionado ou tocado.
Por padrão, um MenuItem não tem nenhuma maneira de saber qual célula pertence. CommandParameter está
disponível em MenuItem para armazenar objetos, como o objeto por trás ViewCell de MenuItem.
CommandParameter pode ser definido em XAML e c#.
C#
Ações de contexto podem ser implementadas em qualquer Cell subclasse (contanto que ele não está sendo
usado como um cabeçalho de grupo), criando MenuItem s e adicioná-los para o ContextActions coleção para a
célula. Você tem as seguintes propriedades podem ser configuradas para a ação de contexto:
Texto – a cadeia de caracteres que aparece no item de menu.
Clicado – o evento quando o item é clicado.
IsDestructive – (opcional) quando for verdadeiro o item será renderizado da maneira diferente, no iOS.
Várias ações de contexto podem ser adicionadas a uma célula, no entanto, somente um deve ter IsDestructive
definido como true . O código a seguir demonstra como as ações de contexto seriam adicionadas a um ViewCell :
var deleteAction = new MenuItem { Text = "Delete", IsDestructive = true }; // red background
deleteAction.SetBinding (MenuItem.CommandParameterProperty, new Binding ("."));
deleteAction.Clicked += async (sender, e) => {
var mi = ((MenuItem)sender);
Debug.WriteLine("Delete Context Action clicked: " + mi.CommandParameter);
};
// add to the ViewCell's ContextActions property
ContextActions.Add (moreAction);
ContextActions.Add (deleteAction);
XAML
MenuItem s também pode ser criado declarativamente em uma coleção de XAML. O XAML a seguir demonstra
uma célula personalizada com duas ações de contexto implementadas:
<ListView x:Name="ContextDemoList">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem Clicked="OnMore" CommandParameter="{Binding .}"
Text="More" />
<MenuItem Clicked="OnDelete" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="{Binding title}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
NOTE
O NavigationPageRenderer para Android tem uma substituível UpdateMenuItemIcon método que pode ser usado para
carregar ícones de personalizado Drawable . Essa substituição torna possível usar as imagens de SVG como ícones em
MenuItem instâncias no Android.
<ListView ...
IsPullToRefreshEnabled="true" />
O código c# equivalente é:
listView.IsPullToRefreshEnabled = true;
Um controle giratório aparece durante a atualização, o que é preta por padrão. No entanto, a cor do controle
giratório pode ser alterada no iOS e Android, definindo o RefreshControlColor propriedade para um Color :
<ListView ...
IsPullToRefreshEnabled="true"
RefreshControlColor="Red" />
O código c# equivalente é:
listView.RefreshControlColor = Color.Red;
As capturas de tela a seguir mostram puxar para atualizar como o usuário está obtendo:
As capturas de tela a seguir mostram puxar para atualizar, depois que o usuário lançou o pull com o controle
giratório que está sendo mostrado enquanto o ListView está atualizando:
ListView é acionado o Refreshing evento para iniciar a atualização e o IsRefreshing propriedade será definida
como true . O código que é necessário para atualizar o conteúdo do ListView , em seguida, deve ser executado
após o manipulador de eventos para o Refreshing evento, ou pelo método executado pelo RefreshCommand . Uma
vez a ListView é atualizado, o IsRefreshing propriedade deve ser definida como false , ou o EndRefresh
método deve ser chamado, para indicar que a atualização for concluída.
NOTE
Ao definir uma RefreshCommand ,o CanExecute método do comando pode ser especificado para habilitar ou desabilitar o
comando.
Links relacionados
Interatividade do ListView (amostra)
Desempenho de ListView
12/04/2019 • 14 minutes to read
baixar o exemplo
Ao escrever aplicativos móveis, o desempenho é importante. Os usuários já conhecem rolagem suave e tempos
de carregamento rápido. Com falha atender às expectativas dos usuários custam avaliações na loja de aplicativos
ou no caso de um aplicativo de linha de negócios, custo organização tempo e dinheiro.
Embora ListView é um modo eficiente para exibir os dados, ele tem algumas limitações. Desempenho de
rolagem pode ser afetado ao usar células personalizadas, especialmente quando eles contenham hierarquias de
exibição profundamente aninhadas ou usam determinados layouts que exigem muita de medição. Felizmente,
existem técnicas que você pode usar para evitar um desempenho ruim.
Estratégia de cache
ListViews geralmente são usados para exibir dados muito mais do que pode caber na tela. Considere um
aplicativo de música, por exemplo. Uma biblioteca de músicas pode ter milhares de entradas. A abordagem
simple, o que seria criar uma linha para cada música, teria um desempenho ruim. Essa abordagem desperdiça
memória valiosa e pode reduzir a rolagem para um rastreamento. Outra abordagem é criar e destruir linhas como
dados são colocados na exibição. Isso exige a instanciação de constante e a limpeza de objetos de exibição, que
pode ser muito lento.
Para conservar memória, nativo ListView equivalentes para cada plataforma tem recursos internos para
reutilização de linhas. Apenas as células visíveis na tela são carregadas na memória e o conteúdo é carregado em
células existentes. Isso impede que o aplicativo precisar criar uma instância de milhares de objetos, economizando
tempo e memória.
Xamarin. Forms permite ListView célula usar novamente por meio de ListViewCachingStrategy enumeração, que
tem os seguintes valores:
NOTE
A Universal Windows Platform (UWP) ignora a RetainElement estratégia, de cache porque ele sempre usa o cache para
melhorar o desempenho. Portanto, por padrão se comporta como se o RecycleElement estratégia de cache é aplicada.
RetainElement
O RetainElement estratégia de cache Especifica que o ListView gerará uma célula para cada item na lista, e é o
padrão ListView comportamento. Geralmente, ele deve ser usado nas seguintes circunstâncias:
Quando cada célula tem um grande número de associações (20-30 ou mais).
Quando o modelo de célula é alterado com frequência.
Quando testar revela que o RecycleElement armazenar em cache os resultados de estratégia em uma
velocidade de execução reduzida.
É importante reconhecer as consequências do RetainElement estratégia de cache ao trabalhar com células
personalizadas. Qualquer código de inicialização de célula precisará executar para a criação de cada célula, que
pode ser várias vezes por segundo. Nessa circunstância, técnicas de layout que eram um problemas em uma
página, como uso de vários aninhados StackLayout instâncias, se tornar afunilamentos de desempenho quando
elas são configuradas e destruída em tempo real conforme o usuário rolar.
RecycleElement
O RecycleElement estratégia de cache Especifica que o ListView tenta minimizar sua velocidade de execução e o
volume de memória por meio da reciclagem de células da lista. Esse modo não oferece sempre uma melhoria de
desempenho e teste deve ser executado para determinar todos os aprimoramentos. No entanto, ele geralmente é
a opção preferencial e deve ser usado nas seguintes circunstâncias:
Quando cada célula tem um pequeno número moderado de associações.
Quando cada célula BindingContext define todos os dados da célula.
Quando cada célula é basicamente semelhante, com o modelo de célula inalterável.
Durante a virtualização, a célula terá seu contexto de associação atualizado e, portanto, se um aplicativo usa esse
modo deve garantir que as atualizações de contexto de associação são manipuladas corretamente. Todos os dados
sobre a célula devem ser provenientes do contexto de associação ou poderão ocorrer erros de consistência. Isso
pode ser feito usando vinculação de dados para exibir dados da célula. Como alternativa, os dados da célula
devem ser definidos no OnBindingContextChanged substituir, em vez de no construtor da célula personalizada,
conforme demonstrado no exemplo de código a seguir:
public CustomCell ()
{
image = new Image();
View = image;
}
RecycleElementAndDataTemplate
O RecycleElementAndDataTemplate estratégia de cache baseia-se a RecycleElement estratégia de cache, além disso,
garantindo que, quando um ListView usa um DataTemplateSelector para selecionar um DataTemplate ,
DataTemplate s são armazenados em cache pelo tipo de item na lista. Portanto, DataTemplate s são selecionados de
uma vez por tipo de item, em vez de uma vez por instância do item.
NOTE
O RecycleElementAndDataTemplate estratégia de cache tem um pré-requisito que o DataTemplate s retornado pelo
DataTemplateSelector deve usar o DataTemplate construtor que usa um Type .
<ListView CachingStrategy="RecycleElement">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
...
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Isso tem o mesmo efeito que definir o argumento de estratégia de cache do construtor no C#; Observe que não há
nenhuma CachingStrategy propriedade ListView .
Definir a estratégia de cache em uma subclasse ListView
Definindo o CachingStrategy atributo do XAML em uma subclasse ListView não produzirá o comportamento
desejado, porque não há nenhum CachingStrategy propriedade ListView . Além disso, se XAMLC é habilitada, a
seguinte mensagem de erro será produzida: nenhuma propriedade, a propriedade associável ou evento
encontrado para 'CachingStrategy'
A solução para esse problema é para especificar um construtor na subclasse ListView que aceita um
ListViewCachingStrategy parâmetro e o passa para a classe base:
public class CustomListView : ListView
{
public CustomListView (ListViewCachingStrategy strategy) : base (strategy)
{
}
...
}
<local:CustomListView>
<x:Arguments>
<ListViewCachingStrategy>RecycleElement</ListViewCachingStrategy>
</x:Arguments>
</local:CustomListView>
Links relacionados
Exibição de renderizador personalizado (amostra)
ViewCell de renderizador personalizado (amostra)
ListViewCachingStrategy
Mapa do xamarin. Forms
12/04/2019 • 12 minutes to read
baixar o exemplo
Xamarin. Forms usa o mapa nativo APIs em cada plataforma.
Xamarin.Forms.Maps usa as APIs de mapa nativa em cada plataforma. Isso fornece uma experiência de mapas
rápido e familiar para os usuários, mas significa que algumas etapas de configuração são necessários para
atender aos requisitos de API cada plataformas. Uma vez configurado, o Map controlar funciona exatamente
como qualquer outro elemento de xamarin. Forms em código comum.
O controle de mapa tenha sido usado na MapsSample sample, que é mostrado abaixo.
Funcionalidade de mapa pode ser aprimorada ainda mais com a criação de um mapear um renderizador
personalizado.
Inicialização de mapas
Ao adicionar mapas a um aplicativo xamarin. Forms, Xamarin.Forms.Maps é um pacote do NuGet separado
que você deve adicionar a todos os projetos na solução. No Android, isso também tem uma dependência no
GooglePlayServices (NuGet outro), que é baixada automaticamente quando você adiciona
Xamarin.Forms.Maps.
Depois de instalar o pacote do NuGet, um código de inicialização é necessária em cada projeto de aplicativo
após o Xamarin.Forms.Forms.Init chamada de método. Para iOS, use o seguinte código:
Xamarin.FormsMaps.Init();
Xamarin.FormsMaps.Init(this, bundle);
Xamarin.FormsMaps.Init("INSERT_AUTHENTICATION_TOKEN_HERE");
Adicione esta chamada nos seguintes arquivos para cada plataforma:
iOS -arquivo AppDelegate.cs, além de FinishedLaunching método.
Android -MainActivity.cs de arquivos, além de OnCreate método.
UWP -arquivo MainPage.xaml.cs, além de MainPage construtor.
Depois que o pacote do NuGet foi adicionado e o método de inicialização é chamado dentro de cada aplicativo,
Xamarin.Forms.Maps APIs podem ser usadas no código do projeto compartilhado ou projeto de biblioteca .NET
Standard comum.
Configuração de plataforma
Etapas de configuração adicionais são necessários em algumas plataformas antes do mapa será exibido.
iOS
Para acessar os serviços de localização no iOS, você deve definir as seguintes chaves Info. plist:
iOS 11
NSLocationWhenInUseUsageDescription – Para usar os serviços de localização quando o aplicativo está
em uso
NSLocationAlwaysAndWhenInUseUsageDescription – Para usar os serviços de localização em todos os
momentos
iOS 10 e versões anteriores
NSLocationWhenInUseUsageDescription – Para usar os serviços de localização quando o aplicativo está
em uso
NSLocationAlwaysUsageDescription – Para usar os serviços de localização em todos os momentos
Para dar suporte a iOS 11 e versões anteriores, você pode incluir todos os três chaves:
NSLocationWhenInUseUsageDescription , NSLocationAlwaysAndWhenInUseUsageDescription , e
NSLocationAlwaysUsageDescription .
A representação XML para essas chaves na Info. plist é mostrado abaixo. Você deve atualizar o string
valores para refletir como seu aplicativo está usando as informações de local:
<key>NSLocationAlwaysUsageDescription</key>
<string>Can we use your location at all times?</string>
<key>NSLocationWhenInUseUsageDescription</key>
<string>Can we use your location when your app is being used?</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Can we use your location at all times?</string>
O Info. plist entradas também podem ser adicionadas no fonte exibição ao editar o Info. plist arquivo:
Android
Para usar o API do Google Maps v2 no Android, você deve gerar uma chave de API e adicioná-lo ao seu
projeto Android. Siga as instruções no documento Xamarin na obtendo uma chave de API do Google Maps v2.
Depois de seguir essas instruções, cole a chave de API na androidmanifest arquivo (Exibir código-fonte e
localizar/atualizar o seguinte elemento):
<application ...>
<meta-data android:name="com.google.android.maps.v2.API_KEY" android:value="YOUR_API_KEY" />
</application>
Sem uma chave de API válida no controle maps será exibido como uma caixa cinza no Android.
NOTE
Observe que, na ordem de seu APK acessar o Google Maps, você deve incluir as impressões digitais de SHA-1 e nomes
para cada repositório de chaves (depuração e versão) que você usa para assinar o APK do pacote. Por exemplo, se você
usar um computador para outro computador para gerar a versão APK e de depuração, você deve incluir a impressão
digital SHA-1 do certificado do repositório de chaves de depuração do primeiro computador e a impressão digital do
certificado SHA-1 do repositório de chaves de versão o segundo computador. Lembre-se também ao editar as
credenciais de chave, se o aplicativo nome do pacote alterações. Ver obtendo uma chave de API do Google Maps v2.
Você também precisará habilitar as permissões apropriadas pelo botão direito do mouse no projeto do
Android e selecionando opções > Build > aplicativo Android e tique o seguinte:
AccessCoarseLocation
AccessFineLocation
AccessLocationExtraCommands
AccessMockLocation
AccessNetworkState
AccessWifiState
Internet
As duas últimas são necessárias porque os aplicativos exigem uma conexão de rede para baixar os dados de
mapa. Leia sobre o Android permissões para saber mais.
Plataforma Universal do Windows
Para usar mapas na plataforma Universal do Windows, você deve gerar um token de autorização. Para obter
mais informações, consulte solicitar uma chave de autenticação de mapas no MSDN.
O token de autenticação deve ser especificado, em seguida, no FormsMaps.Init("AUTHORIZATION_TOKEN")
chamada de método, para autenticar o aplicativo com o Bing Maps.
Uso de mapas
Consulte a MapPage.cs na amostra MobileCRM para obter um exemplo de como o controle de mapa pode ser
usado no código. Um simples MapPage classe pode parecer com este - aviso de que um novo MapSpan é criado
para posicionar a exibição do mapa:
public class MapPage : ContentPage {
public MapPage() {
var map = new Map(
MapSpan.FromCenterAndRadius(
new Position(37,-122), Distance.FromMiles(0.3))) {
IsShowingUser = true,
HeightRequest = 100,
WidthRequest = 960,
VerticalOptions = LayoutOptions.FillAndExpand
};
var stack = new StackLayout { Spacing = 0 };
stack.Children.Add(map);
Content = stack;
}
}
Tipo de mapa
O conteúdo do mapa também pode ser alterado definindo o MapType propriedade, para mostrar um mapa
rodoviário regular (o padrão), imagens de satélite ou uma combinação de ambos.
map.MapType == MapType.Street;
Para alterar o nível de zoom do mapa sem alterar o local, crie um novo MapSpan usando o local atual do
VisibleRegion.Center propriedade do controle de mapa. Um Slider poderia ser usado para controle de zoom
do mapa como este (no entanto, aumentar o zoom diretamente no controle de mapa, atualmente não é
possível atualizar o valor do controle deslizante):
PinType pode ser definido como um dos valores a seguir, que podem afetar a maneira que o pin é renderizado
(dependendo da plataforma):
Genérico
Local
SavedPin
SearchResult
Usando XAML
Mapas também podem ser posicionados em layouts XAML, conforme mostrado neste trecho de código.
NOTE
Adicional xmlns definição de namespace é necessário para referenciar os controles Xamarin.Forms.Maps.
O MapRegion e Pins pode ser definido no código usando o MyMap referência (ou o mapa de tudo o que é
chamado).
MyMap.MoveToRegion(
MapSpan.FromCenterAndRadius(
new Position(37,-122), Distance.FromMiles(1)));
Portanto, uma Map podem ser populados com dados por meio de associação de dados para associar seu
ItemsSource propriedade para um IEnumerable coleção:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
x:Class="WorkingWithMaps.PinItemsSourcePage">
<Grid>
...
<maps:Map x:Name="map"
ItemsSource="{Binding Locations}">
<maps:Map.ItemTemplate>
<DataTemplate>
<maps:Pin Position="{Binding Position}"
Address="{Binding Address}"
Label="{Binding Description}" />
</DataTemplate>
</maps:Map.ItemTemplate>
</maps:Map>
...
</Grid>
</ContentPage>
O modo de exibição do seletor é um controle para selecionar um item de texto de uma lista de dados.
O xamarin. Forms Picker exibe uma lista curta de itens, do qual o usuário pode selecionar um item. Picker
Define as propriedades a seguir:
Title do tipo string , cujo padrão é null .
TitleColor do tipo Color , a cor usada para exibir o Title texto.
ItemsSource do tipo IList , a lista de origem de itens a serem exibidos, cujo padrão é null .
SelectedIndex do tipo int , o índice do item selecionado, cujo padrão é -1.
SelectedItem do tipo object , o item selecionado, cujo padrão é null .
TextColor do tipo Color , a cor usada para exibir o texto, cujo padrão é Color.Default .
FontAttributes do tipo FontAttributes , cujo padrão é FontAtributes.None .
FontFamily do tipo string , cujo padrão é null .
FontSize do tipo double , cujo padrão é de -1,0.
Todas as propriedades têm o respaldo BindableProperty objetos, o que significa que eles podem ser estilizados e
as propriedades podem ser alvos de vinculações de dados. O SelectedIndex e SelectedItem propriedades têm
um modo de associação padrão do BindingMode.TwoWay , que significa que elas possam ser destinos de
vinculações de dados em um aplicativo que usa o Model-View -ViewModel (MVVM ) arquitetura. Para obter
informações sobre como definir propriedades de fonte, consulte fontes.
Um Picker não mostra todos os dados quando ele é exibido pela primeira vez. Em vez disso, o valor de sua
Title propriedade é mostrada como um espaço reservado nas plataformas Android e iOS:
Quando o Picker ganhos foco, seus dados é exibido e o usuário pode selecionar um item:
O Picker dispara uma SelectedIndexChanged evento quando o usuário seleciona um item. Após a seleção, o item
selecionado é exibido pelo Picker :
Links relacionados
Seletor
Definindo a propriedade ItemsSource de um seletor
12/04/2019 • 7 minutes to read
baixar o exemplo
O modo de exibição do seletor é um controle para selecionar um item de texto de uma lista de dados. Este artigo
explica como preencher um seletor de dados, definindo a propriedade ItemsSource e como responder a seleção de
item pelo usuário.
Xamarin. Forms 2.3.4 aprimorou o Picker exibição adicionando a capacidade para preenchê-lo com dados,
definindo sua ItemsSource propriedade e para recuperar o item selecionado do SelectedItem propriedade. Além
disso, a cor do texto do item selecionado pode ser alterada definindo a TextColor propriedade como um Color .
<Picker x:Name="picker"
Title="Select a monkey"
TitleColor="Red">
<Picker.ItemsSource>
<x:Array Type="{x:Type x:String}">
<x:String>Baboon</x:String>
<x:String>Capuchin Monkey</x:String>
<x:String>Blue Monkey</x:String>
<x:String>Squirrel Monkey</x:String>
<x:String>Golden Lion Tamarin</x:String>
<x:String>Howler Monkey</x:String>
<x:String>Japanese Macaque</x:String>
</x:Array>
</Picker.ItemsSource>
</Picker>
NOTE
Observe que o x:Array elemento requer um Type atributo que indica o tipo dos itens na matriz.
NOTE
Item de comportamento de seleção em um Picker podem ser personalizadas no iOS com uma plataforma específica. Para
obter mais informações, consulte seleção de Item de seletor controlando.
O exemplo de código a seguir mostra como recuperar o SelectedItem valor da propriedade a Picker no XAML:
Além disso, um manipulador de eventos pode ser executado quando o SelectedIndexChanged evento é acionado:
if (selectedIndex != -1)
{
monkeyNameLabel.Text = (string)picker.ItemsSource[selectedIndex];
}
}
Esse método obtém o SelectedIndex valor de propriedade e usa o valor para recuperar o item selecionado dos
ItemsSource coleção. Isso é funcionalmente equivalente ao recuperar o item selecionado dos SelectedItem
propriedade. Observe que cada item de ItemsSource coleção é do tipo object e, portanto, deve ser convertido em
um string para exibição.
NOTE
Um Picker pode ser inicializado para exibir um item específico, configurando as SelectedIndex ou SelectedItem
propriedades. No entanto, essas propriedades devem ser definidas depois de inicializar o ItemsSource coleção.
O ItemsSource associa dados de propriedade para o Monkeys propriedade do modelo de exibição conectados, que
retorna um IList<Monkey> coleção. O seguinte exemplo de código mostra o Monkey classe, que contém quatro
propriedades:
Ao associar a uma lista de objetos, o Picker deve ser informado de qual propriedade a ser exibida de cada objeto.
Isso é feito definindo a ItemDisplayBinding propriedade para a propriedade necessária de cada objeto. Nos
exemplos de código acima, o Picker estiver definido para exibir cada Monkey.Name valor da propriedade.
Respondendo a seleção de item
Associação de dados pode ser usada para definir um objeto com o SelectedItem valor da propriedade quando ele
é alterado:
NOTE
Observe que o SelectedItem e SelectedIndex ambas as propriedades dá suporte a associações bidirecionais por padrão.
Links relacionados
Demonstração de seletor (amostra)
Monkey App (amostra)
Seletor de associável (amostra)
Seletor de API
Adicionar dados à coleção de itens do seletor
12/04/2019 • 3 minutes to read
baixar o exemplo
O modo de exibição do seletor é um controle para selecionar um item de texto de uma lista de dados. Este artigo
explica como preencher um seletor de dados, adicionando -o à coleção de itens e como responder a seleção de
item pelo usuário.
Além de adicionar dados usando o Items.Add método, dados também podem ser inseridos na coleção usando o
Items.Insert método.
if (selectedIndex != -1)
{
monkeyNameLabel.Text = picker.Items[selectedIndex];
}
}
Esse método obtém o SelectedIndex valor de propriedade e usa o valor para recuperar o item selecionado dos
Items coleção. Porque cada item na Items coleção é um string , eles podem ser exibidos por uma Label sem a
necessidade de uma conversão.
NOTE
Um Picker pode ser inicializado para exibir um item específico, configurando as SelectedIndex propriedade. No entanto,
o SelectedIndex propriedade deve ser definida depois de inicializar o Items coleção.
Links relacionados
Demonstração de seletor (amostra)
Seletor
Controle deslizante do xamarin. Forms
12/04/2019 • 22 minutes to read
baixar o exemplo
Use um controle deslizante para selecionar um intervalo de valores contínuos.
O xamarin. Forms Slider é uma barra horizontal que pode ser manipulada pelo usuário para selecionar um
double valor de um intervalo contínuo.
WARNING
Internamente, o Slider garante que Minimum é menor que Maximum . Se Minimum ou Maximum nunca são definidas,
de modo que Minimum é não é menor que Maximum , uma exceção será gerada. Consulte a precauções seção abaixo para
obter mais informações sobre como o Minimum e Maximum propriedades.
O Slider impõe a Value propriedade para que ele fique entre Minimum e Maximum , inclusive. Se o Minimum
propriedade é definida como um valor maior que o Value propriedade, o Slider define o Value propriedade
Minimum . Da mesma forma, se Maximum é definido como um valor menor que Value , em seguida, Slider define
o Value propriedade para Maximum .
Slider define uma ValueChanged evento que é disparado quando o Value alterações, por meio de manipulação
de usuário do Slider ou quando o programa define o Value propriedade diretamente. Um ValueChanged
evento também é disparado quando o Value propriedade é forçada, conforme descrito no parágrafo anterior.
O objeto que acompanha o ValueChanged evento tem duas propriedades, ambos do tipo
ValueChangedEventArgs
double : OldValue e NewValue . No momento do evento é acionado, o valor de NewValue é igual a Value
propriedade do Slider objeto.
Slider também define DragStarted e DragCompleted eventos, que são acionados no início e no final da ação de
arrastar. Ao contrário o ValueChanged evento, o DragStarted e DragCompleted os eventos são disparados somente
por meio de manipulação de usuário do Slider . Quando o DragStarted evento é acionado, o
DragStartedCommand , do tipo ICommand , é executado. Da mesma forma, quando o DragCompleted evento é
acionado, o DragCompletedCommand , do tipo ICommand , é executado.
WARNING
Não use opções de layout horizontal irrestrita de Center , Start , ou End com Slider . No Android e UWP, o Slider
recolhe a uma barra de comprimento zero e no iOS, a barra é muito curto. Mantenha o padrão HorizontalOptions
configuração do Fill e não use uma largura de Auto ao colocar Slider em um Grid layout.
O Slider também define várias propriedades que afetam sua aparência:
MinimumTrackColor é a barra de cor à esquerda do elevador.
MaximumTrackColor é a barra de cor à direita do elevador.
ThumbColor é a cor do elevador.
ThumbImage é a imagem a ser usado para o elevador, do tipo FileImageSource .
NOTE
O ThumbColor e ThumbImage propriedades são mutuamente exclusivas. Se ambas as propriedades estiverem definidas, o
ThumbImage propriedade terá precedência.
O Slider é inicializado para ter um Maximum propriedade de 360. O ValueChanged manipulador do Slider usa
o Value propriedade do slider objeto para definir o Rotation propriedade do primeiro Label e usa o
String.Format método com o NewValue propriedade do argumentos de evento para definir a Text propriedade
do segundo Label . Essas duas abordagens para obter o valor atual do Slider são intercambiáveis.
Aqui está o programa em execução no iOS, Android e plataforma Universal do Windows (UWP ) dispositivos:
A segunda Label exibe o texto "(não inicializado)" até que o Slider seja manipulado, o que faz com que o
primeiro ValueChanged evento seja acionado. Observe que o número de casas decimais que são exibidos é
diferente para cada plataforma. Essas diferenças estão relacionadas às implementações de plataforma a Slider e
são discutidos neste artigo na seção diferenças de implementação de plataforma.
Criando um controle deslizante no XAML
O básico XAML do controle deslizante página é funcionalmente igual código básico do controle
deslizante implementado, mas principalmente no XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SliderDemos.BasicSliderXamlPage"
Title="Basic Slider XAML"
Padding="10, 0">
<StackLayout>
<Label x:Name="rotatingLabel"
Text="ROTATING TEXT"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider Maximum="360"
ValueChanged="OnSliderValueChanged" />
<Label x:Name="displayLabel"
Text="(uninitialized)"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Também é possível que o manipulador de eventos obter o Slider que está disparando o evento por meio de
sender argumento. O Value propriedade contém o valor atual:
Se o Slider objeto recebeu um nome no arquivo XAML com um x:Name atributo (por exemplo, "controle
deslizante") e, em seguida, o manipulador de eventos pode fazer referência a esse objeto diretamente:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SliderDemos.BasicSliderBindingsPage"
Title="Basic Slider Bindings"
Padding="10, 0">
<StackLayout>
<Label Text="ROTATING TEXT"
Rotation="{Binding Source={x:Reference slider},
Path=Value}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Slider x:Name="slider"
Maximum="360" />
<Label x:Name="displayLabel"
Text="{Binding Source={x:Reference slider},
Path=Value,
StringFormat='The Slider value is {0:F0}'}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Rotation propriedade do primeiro Label está associado ao Value propriedade do Slider , como é o Text
propriedade do segundo Label com um StringFormat especificação. O associações básicas do controle
deslizante funções da página um pouco diferente das duas páginas anteriores: Quando a página aparece pela
primeira vez, o segundo Label exibe a cadeia de caracteres de texto com o valor. Esse é um benefício do uso de
associação de dados. Para exibir texto sem a associação de dados, você precisa inicializar especificamente a Text
propriedade do Label ou simular um acionamento do ValueChanged evento chamando o manipulador de
eventos do construtor da classe.
Precauções
O valor da Minimum propriedade sempre deve ser menor que o valor da Maximum propriedade. O código a seguir
faz com que o trecho de código a Slider para gerar uma exceção:
// Throws an exception!
Slider slider = new Slider
{
Minimum = 10,
Maximum = 20
};
O compilador c# gera código que define essas duas propriedades em sequência, e quando o Minimum estiver
definida como 10, é maior que o padrão Maximum valor 1. Você pode evitar a exceção nesse caso, definindo o
Maximum propriedade primeiro:
Definindo Maximum a 20 não é um problema porque ele é maior que o padrão Minimum valor de 0. Quando
Minimum estiver definido, o valor é menor do que o Maximum valor de 20.
O mesmo problema existe no XAML. Definir as propriedades em uma ordem que garante que Maximum é sempre
maior que Minimum :
<Slider Maximum="20"
Minimum="10" ... />
Você pode definir as Minimum e Maximum valores para números negativos, mas apenas em uma ordem em que
Minimum é sempre menor que Maximum :
<Slider Minimum="-20"
Maximum="-10" ... />
O Value propriedade é sempre igual a ou maior que o Minimum valor e menor ou igual a Maximum . Se Value é
definido como um valor fora desse intervalo, o valor será ser forçado para ficar dentro do intervalo, mas
nenhuma exceção for gerada. Por exemplo, esse código vai não gerar uma exceção:
Quando Minimum é definido como 10, em seguida, Value também é definido como 10.
Se um ValueChanged manipulador de eventos foi anexado no momento em que o Value propriedade é forçada
para algo diferente de seu valor padrão de 0, em seguida, um ValueChanged evento é disparado. Aqui está um
trecho de XAML:
<Slider ValueChanged="OnSliderValueChanged"
Maximum="20"
Minimum="10" />
Quando Minimum é definido como 10, Value também é definido como 10 e o ValueChanged evento é disparado.
Isso pode ocorrer antes que o restante da página foi construído, e o manipulador pode tentar fazer referência a
outros elementos na página que ainda não tem sido criados. Você talvez queira adicionar algum código para o
ValueChanged manipulador que verifica se há null valores de outros elementos na página. Ou, você pode definir
as ValueChanged manipulador de eventos após a Slider valores foram inicializados.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="SliderDemos.RgbColorSlidersPage"
Title="RGB Color Sliders">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Slider">
<Setter Property="Maximum" Value="255" />
</Style>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10">
<BoxView x:Name="boxView"
Color="Black"
VerticalOptions="FillAndExpand" />
<Slider x:Name="redSlider"
ValueChanged="OnSliderValueChanged" />
<Slider x:Name="greenSlider"
ValueChanged="OnSliderValueChanged" />
<Slider x:Name="blueSlider"
ValueChanged="OnSliderValueChanged" />
Um Style fornece todas as três Slider elementos de um intervalo de 0 a 255. O Slider elementos
compartilham o mesmo ValueChanged manipulador, que é implementado no arquivo code-behind:
public partial class RgbColorSlidersPage : ContentPage
{
public RgbColorSlidersPage()
{
InitializeComponent();
}
boxView.Color = Color.FromRgb((int)redSlider.Value,
(int)greenSlider.Value,
(int)blueSlider.Value);
}
}
Os conjuntos de seção primeiro o Text propriedade de um do Label instâncias de uma cadeia de caracteres de
texto curto que indica o valor da Slider em hexadecimal. Em seguida, todos os três Slider instâncias são
acessadas para criar um Color valor dos componentes RGB:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SliderDemos"
x:Class="SliderDemos.HslColorSlidersPage"
Title="HSL Color Sliders">
<ContentPage.BindingContext>
<local:HslColorViewModel Color="Chocolate" />
</ContentPage.BindingContext>
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Label">
<Setter Property="HorizontalTextAlignment" Value="Center" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<StackLayout Margin="10">
<BoxView Color="{Binding Color}"
VerticalOptions="FillAndExpand" />
Como o Slider elementos são manipulados, o BoxView e Label elementos são atualizados do ViewModel:
O StringFormat componente de Binding extensão de marcação é definida para um formato de "F2" para exibir
duas casas decimais. (Cadeia de caracteres de formatação em associações de dados é discutida no artigo cadeia
de caracteres de formatação.) No entanto, a versão UWP do programa é limitada aos valores de 0, 0.1, 0.2,... 0.9 e
1.0. Este é um resultado direto da implementação da UWP Slider conforme descrito acima na seção diferenças
de implementação de plataforma.
Links relacionados
Exemplo de demonstrações do controle deslizante
API de controle deslizante
Seletor de xamarin. Forms
12/04/2019 • 12 minutes to read
baixar o exemplo
Use um seletor para selecionar um valor numérico de um intervalo de valores.
O xamarin. Forms Stepper consiste em dois botões rotulados com sinais de adição e de subtração. Esses botões
podem ser manipulados pelo usuário para selecionar incrementalmente uma double valor de um intervalo de
valores.
O Stepper define quatro propriedades do tipo double :
Increment é o valor para alterar o valor selecionado, com um valor padrão de 1.
Minimum é o mínimo do intervalo, com um valor padrão de 0.
Maximum é o máximo do intervalo, com um valor padrão de 100.
Value é o valor do seletor, o que pode variar entre Minimum e Maximum e tem um valor padrão de 0.
Todas essas propriedades têm o respaldo BindableProperty objetos. O Value propriedade tem um modo de
associação padrão de BindingMode.TwoWay , que significa que ele é adequado como uma origem da associação em
um aplicativo que usa o Model-View -ViewModel (MVVM ) arquitetura.
WARNING
Internamente, o Stepper garante que Minimum é menor que Maximum . Se Minimum ou Maximum nunca são definidas,
de modo que Minimum é não é menor que Maximum , uma exceção será gerada. Para obter mais informações sobre como
o Minimum e Maximum propriedades, consulte precauções seção.
O Stepper impõe o Value propriedade para que ele fique entre Minimum e Maximum , inclusive. Se o Minimum
propriedade é definida como um valor maior que o Value propriedade, o Stepper define o Value propriedade
Minimum . Da mesma forma, se Maximum é definido como um valor menor que Value , em seguida, Stepper
define o Value propriedade para Maximum .
Stepper define uma ValueChanged evento que é disparado quando o Value alterações, por meio da manipulação
do usuário a Stepper ou quando o aplicativo define o Value propriedade diretamente. Um ValueChanged evento
também é disparado quando o Value propriedade é forçada, conforme descrito no parágrafo anterior.
O objeto que acompanha o ValueChanged evento tem duas propriedades, ambos do tipo
ValueChangedEventArgs
double : OldValue e NewValue . No momento do evento é acionado, o valor de NewValue é igual a Value
propriedade do Stepper objeto.
O Stepper é inicializado para ter um Maximum propriedade de 360 e um Increment propriedade de 30 anos.
Manipulando o Stepper altera o valor selecionado de forma incremental entre Minimum para Maximum com base
no valor da Increment propriedade. O ValueChanged manipulador da Stepper usa os Value propriedade do
stepper objeto para definir o Rotation propriedade do primeiro Label e usa o string.Format método com o
NewValue propriedade dos argumentos do evento para definir o Text propriedade das segundo Label . Essas
duas abordagens para obter o valor atual do Stepper são intercambiáveis.
As capturas de tela a seguir mostram os código básico de escalonador página:
A segunda Label exibe o texto "(não inicializado)" até que o Stepper seja manipulado, o que faz com que o
primeiro ValueChanged evento para ser disparado.
Criando um seletor em XAML
O básico XAML de escalonador página é funcionalmente igual código básico de escalonador
implementado, mas principalmente no XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StepperDemo.BasicStepperXAMLPage"
Title="Basic Stepper XAML">
<StackLayout Margin="20">
<Label x:Name="_rotatingLabel"
Text="ROTATING TEXT"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Stepper Maximum="360"
Increment="30"
HorizontalOptions="Center"
ValueChanged="OnStepperValueChanged" />
<Label x:Name="_displayLabel"
Text="(uninitialized)"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
Também é possível que o manipulador de eventos obter o Stepper que está disparando o evento por meio de
sender argumento. O Value propriedade contém o valor atual:
Se o Stepper objeto recebeu um nome no arquivo XAML com um x:Name atributo (por exemplo, "escalonador")
e, em seguida, o manipulador de eventos pode fazer referência a esse objeto diretamente:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="StepperDemo.BasicStepperBindingsPage"
Title="Basic Stepper Bindings">
<StackLayout Margin="20">
<Label Text="ROTATING TEXT"
Rotation="{Binding Source={x:Reference _stepper}, Path=Value}"
FontSize="Large"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
<Stepper x:Name="_stepper"
Maximum="360"
Increment="30"
HorizontalOptions="Center" />
<Label Text="{Binding Source={x:Reference _stepper}, Path=Value, StringFormat='The Stepper value is
{0:F0}'}"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand" />
</StackLayout>
</ContentPage>
O Rotation propriedade do primeiro Label está associado a Value propriedade do Stepper , como é o Text
propriedade do segundo Label com um StringFormat especificação. O associações básicas de escalonador
funções da página um pouco diferente das duas páginas anteriores: quando a página aparece pela primeira vez, o
segundo Label exibe a cadeia de caracteres de texto com o valor. Esse é um benefício do uso de associação de
dados. Para exibir texto sem a associação de dados, você precisa inicializar especificamente a Text propriedade
do Label ou simular um acionamento da ValueChanged evento chamando o manipulador de eventos do
construtor de classe .
Precauções
O valor da Minimum propriedade sempre deve ser menor que o valor da Maximum propriedade. O código a seguir
faz com que o trecho de código a Stepper para gerar uma exceção:
// Throws an exception!
Stepper stepper = new Stepper
{
Minimum = 180,
Maximum = 360
};
O C# compilador gera código que define essas duas propriedades em sequência, e quando o Minimum estiver
definida como 180, é maior que o padrão Maximum valor de 100. Você pode evitar a exceção nesse caso, definindo
o Maximum propriedade primeiro:
Definindo Maximum a 360 não é um problema porque ele é maior que o padrão Minimum valor de 0. Quando
Minimum estiver definido, o valor é menor do que o Maximum valor de 360.
O mesmo problema existe no XAML. Definir as propriedades em uma ordem que garante que Maximum é sempre
maior que Minimum :
<Stepper Maximum="360"
Minimum="180" ... />
Você pode definir as Minimum e Maximum valores para números negativos, mas apenas em uma ordem em que
Minimum é sempre menor que Maximum :
<Stepper Minimum="-360"
Maximum="-180" ... />
O Value propriedade é sempre maior que ou igual de Minimum valor e menor ou igual a Maximum . Se Value é
definido como um valor fora desse intervalo, o valor será ser forçado para ficar dentro do intervalo, mas
nenhuma exceção for gerada. Por exemplo, esse código vai não gerar uma exceção:
Quando Minimum é definido para 180, então Value também é definido para 180.
Se um ValueChanged manipulador de eventos foi anexado no momento em que o Value propriedade é forçada
para algo diferente de seu valor padrão de 0, em seguida, um ValueChanged evento é disparado. Aqui está um
trecho de XAML:
<Stepper ValueChanged="OnStepperValueChanged"
Maximum="360"
Minimum="180" />
Quando Minimum é definido para 180, Value também é definido para 180 e o ValueChanged evento é disparado.
Isso pode ocorrer antes que o restante da página foi construído, e o manipulador pode tentar fazer referência a
outros elementos na página que ainda não tem sido criados. Você talvez queira adicionar algum código para o
ValueChanged manipulador que verifica se há null valores de outros elementos na página. Ou, você pode definir
a ValueChanged manipulador de eventos após os Stepper valores foram inicializados.
Links relacionados
Exemplo de demonstrações escalonador
Seletor de API
Aplicativos xamarin. Forms de estilo
12/04/2019 • 2 minutes to read
Introdução
Aplicativos xamarin. Forms geralmente contêm vários controles que têm uma aparência idêntica. Definir a
aparência de cada controle individual pode ser repetitiva e sujeito a erros. Em vez disso, podem ser criados estilos
para personalizar a aparência do controle de agrupamento e definindo as propriedades disponíveis no tipo de
controle.
Estilos explícitos
Uma explícita estilo é aquele que é aplicada aos controles seletivamente definindo suas Style propriedades.
Estilos implícitos
Uma implícita estilo é aquele que é usado por todos os controles do mesmo TargetType , sem a necessidade de
cada controle para fazer referência ao estilo.
Estilos globais
Estilos podem ser disponibilizados globalmente ao adicioná-los para o aplicativo ResourceDictionary . Isso ajuda a
evitar a duplicação de estilos em páginas ou controles.
Herança de estilo
Estilos podem herdar de outros estilos para reduzir a duplicação e habilitar a reutilização.
Estilos dinâmicos
Estilos não responder a alterações de propriedade e permanecem inalterados durante o período de um aplicativo.
No entanto, os aplicativos podem responder a alterações de estilo dinamicamente em tempo de execução usando
os recursos dinâmicos.
Estilos de dispositivo
Xamarin. Forms inclui seis dinâmica estilos, conhecidos como dispositivo estilos, o Devices.Styles classe. Todos
os seis estilos podem ser aplicados a Label somente instâncias.
Classes de estilo
Classes de estilo do xamarin. Forms permitem que vários estilos a ser aplicado a um controle, sem recorrer à
herança de estilo.
Introdução ao xamarin. Forms estilos
12/04/2019 • 7 minutes to read
Estilos permitem que a aparência dos elementos visuais para serem personalizados. Os estilos são definidos para
um tipo específico e contêm valores para as propriedades disponíveis nesse tipo.
Aplicativos xamarin. Forms geralmente contêm vários controles que têm uma aparência idêntica. Por exemplo, um
aplicativo pode ter vários Label instâncias que têm as mesmas opções de fonte e opções de layout, conforme
mostrado no exemplo de código XAML a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Styles.NoStylesPage"
Title="No Styles"
Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Label Text="These labels"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
FontSize="Large" />
<Label Text="are not"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
FontSize="Large" />
<Label Text="using styles"
HorizontalOptions="Center"
VerticalOptions="CenterAndExpand"
FontSize="Large" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Cada Label instância tem valores de propriedade idênticas para controlar a aparência do texto exibido pelo
Label . Isso resulta na aparência mostrada nas capturas de tela seguir:
Definir a aparência de cada controle individual pode ser repetitiva e sujeito a erros. Em vez disso, pode ser criado
um estilo que define a aparência e, em seguida, são aplicados aos controles necessários.
Criar um estilo
O Style classe agrupa uma coleção de valores de propriedade em um único objeto, em seguida, pode ser
aplicado a várias instâncias do elemento visual. Isso ajuda a reduzir as marcações repetitivas e permite uma
aparência de aplicativos a ser alterado com mais facilidade.
Embora os estilos foram projetados principalmente para aplicativos baseados em XAML, eles também podem ser
criados em c#:
Style instâncias criadas no XAML geralmente são definidas em uma ResourceDictionary que é atribuído ao
Resources coleção de um controle, página, ou para o Resources coleção do aplicativo.
Style as instâncias criadas na linguagem c# normalmente são definidas na classe da página, ou em uma classe
que pode ser acessada globalmente.
Escolher onde definir um Style afeta onde ele pode ser usado:
Style só podem ser aplicadas a instâncias definidas no nível de controle para o controle e seus filhos.
Style só podem ser aplicadas a instâncias definidas no nível da página para a página e seus filhos.
Style instâncias definidas no nível do aplicativo podem ser aplicadas em todo o aplicativo.
Cada Style instância contém uma coleção de um ou mais Setter objetos, com cada Setter tendo um Property
e uma Value . O Property é o nome da propriedade associável do elemento de estilo é aplicado, e o Value é o
valor que é aplicado à propriedade.
Cada Style instância pode ser explícita, ou implícita:
Uma explícita Style instância é definida especificando uma TargetType e um x:Key valor e, em seguida,
definindo o elemento de destino Style propriedade para o x:Key referência. Para obter mais informações
sobre explícita estilos, consulte estilos explícitos.
Uma implícita Style instância é definida especificando-se apenas um TargetType . O Style instância, em
seguida, serão automaticamente aplicada a todos os elementos desse tipo. Observe que pode efetuar
subclasses do TargetType não tem automaticamente o Style aplicado. Para obter mais informações sobre
implícita estilos, consulte estilos implícitos.
Ao criar uma Style , o TargetType propriedade sempre é necessária. O seguinte exemplo de código mostra uma
explícita estilo (Observe o x:Key ) criado em XAML:
Para aplicar uma Style , o objeto de destino deve ser um VisualElement que corresponde a TargetType valor da
propriedade do Style , conforme mostrado no exemplo de código XAML a seguir:
Estilos inferiores na hierarquia de exibição têm precedência sobre aquelas definidas superior para cima. Por
exemplo, definir uma Style que define Label.TextColor para Red no aplicativo de nível será substituído por um
estilo de nível de página que define Label.TextColor para Green . Da mesma forma, um estilo de nível de página
será substituído por um estilo de controle. Além disso, se Label.TextColor for definido diretamente em uma
propriedade de controle, isso tem precedência sobre todos os estilos.
Os artigos nesta seção demonstram e explicam como criar e aplicar explícita e implícita estilos, como criar estilos
globais, herança, de estilo como responder a alterações de estilo em tempo de execução e como usar os estilos
internos incluídos no xamarin. Forms.
NOTE
O que é StyleId?
Antes de xamarin. Forms 2.2, o StyleId propriedade foi usada para identificar elementos individuais em um aplicativo para
identificação em testes de interface do usuário e em mecanismos de tema como Pixate. No entanto, o xamarin. Forms 2.2
introduziu o AutomationId propriedade, que substituiu o StyleId propriedade.
Links relacionados
Extensões de marcação XAML
Estilo
Setter
Estilos explícitos no xamarin. Forms
12/04/2019 • 6 minutes to read
baixar o exemplo
Um estilo explícito é aquele que é aplicada aos controles seletivamente, definindo suas propriedades de estilo.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ExplicitStylesPage" Title="Explicit"
Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="labelRedStyle" TargetType="Label">
<Setter Property="HorizontalOptions"
Value="Center" />
<Setter Property="VerticalOptions"
Value="CenterAndExpand" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Red" />
</Style>
<Style x:Key="labelGreenStyle" TargetType="Label">
...
<Setter Property="TextColor" Value="Green" />
</Style>
<Style x:Key="labelBlueStyle" TargetType="Label">
...
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Label Text="These labels"
Style="{StaticResource labelRedStyle}" />
<Label Text="are demonstrating"
Style="{StaticResource labelGreenStyle}" />
<Label Text="explicit styles,"
Style="{StaticResource labelBlueStyle}" />
<Label Text="and an explicit style override"
Style="{StaticResource labelBlueStyle}"
TextColor="Teal" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O ResourceDictionary define três explícita estilos que são aplicados para a página Label instâncias. Cada Style é
usado para exibir texto em uma cor diferente, e também define a fonte de opções de layout de tamanho e
horizontal e vertical. Cada Style é aplicado a um outro Label definindo seu Style propriedades usando o
StaticResource extensão de marcação. Isso resulta na exibição mostrada nas capturas de tela seguir:
Além disso, o último Label tem um Style aplicado a ele, mas também substitui o TextColor propriedade para
um diferente Color valor.
Criar um estilo explícito no nível de controle
Além de criar explícita estilos no nível da página, eles também podem ser criados no nível de controle, conforme
mostrado no exemplo de código a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ExplicitStylesPage" Title="Explicit"
Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<StackLayout.Resources>
<ResourceDictionary>
<Style x:Key="labelRedStyle" TargetType="Label">
...
</Style>
...
</ResourceDictionary>
</StackLayout.Resources>
<Label Text="These labels" Style="{StaticResource labelRedStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
Neste exemplo, o explícita Style instâncias são atribuídas para o Resources coleção da StackLayout controle. Os
estilos, em seguida, podem ser aplicados para o controle e seus filhos.
Para obter informações sobre a criação de estilos em um aplicativo ResourceDictionary , consulte estilos globais.
O construtor define três explícita estilos que são aplicados para a página Label instâncias. Cada explícita Style é
adicionado para o ResourceDictionary usando o Add método, especificando um key cadeia de caracteres para se
referir a Style instância. Cada Style é aplicado a um outro Label definindo suas Style propriedades.
No entanto, não há nenhuma vantagem em usar um ResourceDictionary aqui. Em vez disso, Style instâncias
podem ser atribuídas diretamente para o Style propriedades dos elementos visuais necessários e o
ResourceDictionary poderá ser removido, conforme mostrado no exemplo a seguir exemplo de código:
public class ExplicitStylesPageCS : ContentPage
{
public ExplicitStylesPageCS ()
{
var labelRedStyle = new Style (typeof(Label)) {
...
};
var labelGreenStyle = new Style (typeof(Label)) {
...
};
var labelBlueStyle = new Style (typeof(Label)) {
...
};
...
Content = new StackLayout {
Children = {
new Label { Text = "These labels", Style = labelRedStyle },
new Label { Text = "are demonstrating", Style = labelGreenStyle },
new Label { Text = "explicit styles,", Style = labelBlueStyle },
new Label { Text = "and an explicit style override", Style = labelBlueStyle,
TextColor = Color.Teal }
}
};
}
}
O construtor define três explícita estilos que são aplicados para a página Label instâncias. Cada Style é usado
para exibir texto em uma cor diferente, e também define a fonte de opções de layout de tamanho e horizontal e
vertical. Cada Style é aplicado a um outro Label definindo seu Style propriedades. Além disso, o último
Label tem uma Style aplicados a ele, mas também substitui o TextColor propriedade em outro Color valor.
Links relacionados
Extensões de marcação XAML
Estilos básicos (amostra)
Trabalhar com estilos (amostra)
Dicionário de recurso
Estilo
Setter
Estilos implícitos no xamarin. Forms
12/04/2019 • 6 minutes to read
baixar o exemplo
Um estilo implícito é aquele que é usado por todos os controles de TargetType mesmo, sem a necessidade de cada
controle para fazer referência ao estilo.
O seguinte exemplo de código mostra uma implícita estilo declarado em XAML em uma página
ResourceDictionary e aplicadas para a página Entry instâncias:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Styles;assembly=Styles"
x:Class="Styles.ImplicitStylesPage" Title="Implicit" Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BackgroundColor" Value="Yellow" />
<Setter Property="FontAttributes" Value="Italic" />
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Entry Text="These entries" />
<Entry Text="are demonstrating" />
<Entry Text="implicit styles," />
<Entry Text="and an implicit style override" BackgroundColor="Lime" TextColor="Red" />
<local:CustomEntry Text="Subclassed Entry is not receiving the style" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O ResourceDictionary define um único implícita estilo é aplicado para a página Entry instâncias. O Style é
usado para exibir o texto azul em um plano de fundo amarelo, enquanto também definir outras opções de
aparência. O Style é adicionado para a página ResourceDictionary sem especificar um x:Key atributo. Portanto,
o Style é aplicada a todos os a Entry instâncias implicitamente, conforme eles correspondem a TargetType
propriedade do Style exatamente. No entanto, o Style não é aplicada para o CustomEntry instância, que é uma
subclasse Entry . Isso resulta na exibição mostrada nas capturas de tela seguir:
Além disso, o quarto Entry substitui o BackgroundColor e TextColor propriedades do estilo implícito para
diferentes Color valores.
Criar um estilo implícito no nível de controle
Além de criar implícita estilos no nível da página, eles também podem ser criados no nível de controle, conforme
mostrado no exemplo de código a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:Styles;assembly=Styles"
x:Class="Styles.ImplicitStylesPage" Title="Implicit" Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<StackLayout.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Setter Property="HorizontalOptions" Value="Fill" />
...
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<Entry Text="These entries" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
Neste exemplo, o implícita Style é atribuído para o Resources coleção da StackLayout controle. O implícita
estilo, em seguida, pode ser aplicado ao controle e seus filhos.
Para obter informações sobre a criação de estilos em um aplicativo ResourceDictionary , consulte estilos globais.
...
Resources = new ResourceDictionary ();
Resources.Add (entryStyle);
O construtor define uma única implícita estilo é aplicado para a página Entry instâncias. O Style é usado para
exibir o texto azul em um plano de fundo amarelo, enquanto também definir outras opções de aparência. O Style
é adicionado para a página ResourceDictionary sem especificar um key cadeia de caracteres. Portanto, o Style é
aplicada a todos os a Entry instâncias implicitamente, conforme eles correspondem a TargetType propriedade do
Style exatamente. No entanto, o Style não é aplicada para o CustomEntry instância, que é uma subclasse Entry
.
<Style TargetType="Button"
ApplyToDerivedTypes="True">
<Setter Property="BackgroundColor"
Value="Red" />
</Style>
Colocando esse estilo em um nível de página ResourceDictionary resultará em que ele está sendo aplicada a todos
os Button instâncias na página e também para todos os controles que derivam de Button . No entanto, se o
ApplyToDerivedTypes propriedade permanece definida, o estilo só deve ser aplicado a Button instâncias.
O código C# equivalente é:
var buttonStyle = new Style(typeof(Button))
{
ApplyToDerivedTypes = true,
Setters =
{
new Setter
{
Property = VisualElement.BackgroundColorProperty,
Value = Color.Red
}
}
};
Links relacionados
Extensões de marcação XAML
Estilos básicos (amostra)
Trabalhar com estilos (amostra)
Dicionário de recurso
Estilo
Setter
Estilos globais no xamarin. Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Estilos podem se tornar disponíveis globalmente ao adicioná -los a dicionário de recursos do aplicativo. Isso ajuda
a evitar a duplicação de estilos em páginas ou controles.
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.App">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="buttonStyle" TargetType="Button">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="BorderColor" Value="Lime" />
<Setter Property="BorderRadius" Value="5" />
<Setter Property="BorderWidth" Value="5" />
<Setter Property="WidthRequest" Value="200" />
<Setter Property="TextColor" Value="Teal" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
Isso ResourceDictionary define um único explícita estilo, buttonStyle , que será usado para definir a aparência da
Button instâncias. No entanto, os estilos globais podem ser explícita ou implícita.
O exemplo de código a seguir mostra uma página do XAML aplicando o buttonStyle para a página Button
instâncias:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ApplicationStylesPage"
Title="Application" Icon="xaml.png">
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Button Text="These buttons" Style="{StaticResource buttonStyle}" />
<Button Text="are demonstrating" Style="{StaticResource buttonStyle}" />
<Button Text="application style overrides" Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.ApplicationStylesPage"
Title="Application" Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="buttonStyle" TargetType="Button">
...
<Setter Property="TextColor" Value="Red" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<StackLayout.Resources>
<ResourceDictionary>
<Style x:Key="buttonStyle" TargetType="Button">
...
<Setter Property="TextColor" Value="Blue" />
</Style>
</ResourceDictionary>
</StackLayout.Resources>
<Button Text="These buttons" Style="{StaticResource buttonStyle}" />
<Button Text="are demonstrating" Style="{StaticResource buttonStyle}" />
<Button Text="application style overrides" Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
O original buttonStyle , definidas no nível do aplicativo, é substituído pelo buttonStyle instância definida no nível
da página. Além disso, o estilo de nível de página é substituído pelo nível de controle buttonStyle . Portanto, o
Button instâncias são exibidas com o texto azul, conforme mostrado nas capturas de tela seguir:
O construtor define uma única explícita estilo para a aplicação Button instâncias em todo o aplicativo. Explícito
Style instâncias são adicionadas para o ResourceDictionary usando o Add método, especificando um key cadeia
de caracteres para se referir a Style instância. O Style instância, em seguida, pode ser aplicada a todos os
controles do tipo correto no aplicativo. No entanto, os estilos globais podem ser explícita ou implícita.
O exemplo de código a seguir mostra um C# página aplicando o buttonStyle para a página Button instâncias:
public class ApplicationStylesPageCS : ContentPage
{
public ApplicationStylesPageCS ()
{
...
Content = new StackLayout {
Children = {
new Button { Text = "These buttons", Style = (Style)Application.Current.Resources
["buttonStyle"] },
new Button { Text = "are demonstrating", Style = (Style)Application.Current.Resources
["buttonStyle"] },
new Button { Text = "application styles", Style = (Style)Application.Current.Resources
["buttonStyle"]
}
}
};
}
}
O buttonStyle é aplicado ao Button instâncias, definindo suas Style propriedades e controla a aparência do
Button instâncias.
Links relacionados
Extensões de marcação XAML
Estilos básicos (amostra)
Trabalhar com estilos (amostra)
Dicionário de recurso
Estilo
Setter
Herança de estilo no xamarin. Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Estilos podem herdar de outros estilos para reduzir a duplicação e habilitar a reutilização.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.StyleInheritancePage"
Title="Inheritance" Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
<Setter Property="HorizontalOptions"
Value="Center" />
<Setter Property="VerticalOptions"
Value="CenterAndExpand" />
</Style>
<Style x:Key="labelStyle" TargetType="Label"
BasedOn="{StaticResource baseStyle}">
...
<Setter Property="TextColor" Value="Teal" />
</Style>
<Style x:Key="buttonStyle" TargetType="Button"
BasedOn="{StaticResource baseStyle}">
<Setter Property="BorderColor" Value="Lime" />
...
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Label Text="These labels"
Style="{StaticResource labelStyle}" />
...
<Button Text="So is the button"
Style="{StaticResource buttonStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
NOTE
Um estilo implícito pode ser derivado de um estilo explícito, mas um estilo explícito não pode ser derivado de um estilo
implícito.
Neste exemplo, labelStyle e buttonStyle é recursos de nível de controle enquanto baseStyle é um recurso de
nível de página. No entanto, enquanto labelStyle e buttonStyle herdar baseStyle , não é possível baseStyle
herdar de labelStyle ou buttonStyle , devido aos seus respectivos locais na hierarquia de exibição.
Herança de estilo em C#
A equivalente C# página, onde Style instâncias são atribuídas diretamente para o Style propriedades dos
controles necessários, é mostrado no exemplo de código a seguir:
public class StyleInheritancePageCS : ContentPage
{
public StyleInheritancePageCS ()
{
var baseStyle = new Style (typeof(View)) {
Setters = {
new Setter {
Property = View.HorizontalOptionsProperty, Value = LayoutOptions.Center },
...
}
};
Links relacionados
Extensões de marcação XAML
Estilos básicos (amostra)
Trabalhar com estilos (amostra)
Dicionário de recurso
Estilo
Setter
Estilos dinâmicos no xamarin. Forms
12/04/2019 • 7 minutes to read
baixar o exemplo
Estilos não responder a alterações de propriedade e permanecem inalterados durante o período de um aplicativo.
Por exemplo, depois de atribuir um estilo a um elemento visual, se uma das instâncias de Setter for modificada,
removido, ou uma nova instância de Setter adicionada, as alterações não aplicadas para o elemento visual. No
entanto, os aplicativos podem responder a alterações de estilo dinamicamente em tempo de execução usando os
recursos dinâmicos.
O DynamicResource extensão de marcação é semelhante de StaticResource extensão de marcação em que ambos
usam uma chave de dicionário para buscar um valor de uma ResourceDictionary . No entanto, enquanto o
StaticResource executa uma pesquisa de dicionário único, o DynamicResource mantém um link para a chave do
dicionário. Portanto, se a entrada de dicionário associada com a chave for substituída, a alteração é aplicada ao
elemento visual. Isso permite que as alterações de estilo de tempo de execução a ser feita em um aplicativo.
O exemplo de código a seguir demonstra dinâmico estilos em uma página XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DynamicStylesPage" Title="Dynamic"
Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="baseStyle" TargetType="View">
...
</Style>
<Style x:Key="blueSearchBarStyle"
TargetType="SearchBar"
BasedOn="{StaticResource baseStyle}">
...
</Style>
<Style x:Key="greenSearchBarStyle"
TargetType="SearchBar">
...
</Style>
...
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<SearchBar Placeholder="These SearchBar controls"
Style="{DynamicResource searchBarStyle}" />
...
</StackLayout>
</ContentPage.Content>
</ContentPage>
O SearchBar instâncias uso o DynamicResource extensão de marcação para fazer referência a um Style chamado
searchBarStyle , que não é definido no XAML. No entanto, porque o Style propriedades do SearchBar instâncias
são definidas usando um DynamicResource , a chave de dicionário ausente não resulta em uma exceção sendo
lançada.
Em vez disso, no arquivo code-behind, o construtor cria um ResourceDictionary entrada com a chave
searchBarStyle , conforme mostrado no exemplo de código a seguir:
public partial class DynamicStylesPage : ContentPage
{
bool originalStyle = true;
public DynamicStylesPage ()
{
InitializeComponent ();
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
}
] (dynamic-images/dynamic-style-green-
large.png#lightbox "Verde estilo dinâmico de exemplo")
O exemplo de código a seguir demonstra a página equivalente em C#:
public DynamicStylesPageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
...
var searchBar1 = new SearchBar { Placeholder = "These SearchBar controls" };
searchBar1.SetDynamicResource (VisualElement.StyleProperty, "searchBarStyle");
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
O SearchBar instâncias de uso de StaticResource extensão de marcação para fazer referência a um Style
chamado tealSearchBarStyle . Isso Style define algumas propriedades adicionais e usa o BaseResourceKey
propriedade a referenciar searchBarStyle . O DynamicResource extensão de marcação não é necessária porque
tealSearchBarStyle não será alterado, exceto para o Style deriva. Portanto, tealSearchBarStyle mantém um link
para searchBarStyle e é alterado quando o estilo de base é alterado.
No arquivo code-behind, o construtor cria um ResourceDictionary entrada com a chave searchBarStyle , de
acordo com o exemplo anterior que demonstrou estilos dinâmicos. Quando o OnButtonClicked manipulador de
eventos é executado, searchBarStyle alternará entre blueSearchBarStyle e greenSearchBarStyle . Isso resulta na
exibição mostrada nas capturas de tela seguir:
O exemplo de código a seguir demonstra a página equivalente em C#:
public DynamicStylesInheritancePageCS ()
{
...
var baseStyle = new Style (typeof(View)) {
...
};
var blueSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var greenSearchBarStyle = new Style (typeof(SearchBar)) {
...
};
var tealSearchBarStyle = new Style (typeof(SearchBar)) {
BaseResourceKey = "searchBarStyle",
...
};
...
Resources = new ResourceDictionary ();
Resources.Add ("blueSearchBarStyle", blueSearchBarStyle);
Resources.Add ("greenSearchBarStyle", greenSearchBarStyle);
Resources ["searchBarStyle"] = Resources ["blueSearchBarStyle"];
O tealSearchBarStyle é atribuído diretamente para o Style propriedade do SearchBar instâncias. Isso Style
define algumas propriedades adicionais e usa o BaseResourceKey propriedade a referenciar searchBarStyle . O
SetDynamicResource método não é necessário aqui porque tealSearchBarStyle não será alterado, exceto para o
Style deriva. Portanto, tealSearchBarStyle mantém um link para searchBarStyle e é alterado quando o estilo de
base é alterado.
Links relacionados
Extensões de marcação XAML
Estilos dinâmicos (amostra)
Trabalhar com estilos (amostra)
Dicionário de recurso
Estilo
Setter
Estilos de dispositivo no xamarin. Forms
12/04/2019 • 4 minutes to read
baixar o exemplo
Xamarin. Forms inclui seis estilos dinâmicos, conhecidos como estilos de dispositivo, na classe Device.Styles.
O dispositivo estilos são:
BodyStyle
CaptionStyle
ListItemDetailTextStyle
ListItemTextStyle
SubtitleStyle
TitleStyle
Todos os estilos de seis só podem ser aplicados a Label instâncias. Por exemplo, uma Label que está exibindo o
corpo de um parágrafo pode definir seus Style propriedade a ser BodyStyle .
O exemplo de código a seguir demonstra como usar o dispositivo estilos em uma página XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Styles.DeviceStylesPage" Title="Device"
Icon="xaml.png">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="myBodyStyle" TargetType="Label"
BaseResourceKey="BodyStyle">
<Setter Property="TextColor" Value="Accent" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout Padding="0,20,0,0">
<Label Text="Title style"
Style="{DynamicResource TitleStyle}" />
<Label Text="Subtitle text style"
Style="{DynamicResource SubtitleStyle}" />
<Label Text="Body style"
Style="{DynamicResource BodyStyle}" />
<Label Text="Caption style"
Style="{DynamicResource CaptionStyle}" />
<Label Text="List item detail text style"
Style="{DynamicResource ListItemDetailTextStyle}" />
<Label Text="List item text style"
Style="{DynamicResource ListItemTextStyle}" />
<Label Text="No style" />
<Label Text="My body style"
Style="{StaticResource myBodyStyle}" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Os estilos de dispositivo são associados ao uso de DynamicResource extensão de marcação. A natureza dinâmica
dos estilos pode ser vista no iOS, alterando a acessibilidade configurações para o tamanho do texto. A aparência
do dispositivo estilos é diferente em cada plataforma, conforme mostrado nas capturas de tela seguir:
Dispositivo estilos também podem ser derivados de definindo o BaseResourceKey propriedade para o nome da
chave para o estilo de dispositivo. No exemplo de código acima, myBodyStyle herda BodyStyle e define uma cor
do texto acentuados. Para obter mais informações sobre herança de estilo dinâmica, consulte herança de estilo
dinâmica.
O exemplo de código a seguir demonstra a página equivalente em C#:
Title = "Device";
Icon = "csharp.png";
Padding = new Thickness (0, 20, 0, 0);
O Style propriedade de cada Label instância é definida como a propriedade apropriada do Devices.Styles
classe.
Acessibilidade
O dispositivo estilos respeitarem as preferências de acessibilidade, para que os tamanhos de fonte serão alterado
conforme as preferências de acessibilidade são alteradas em cada plataforma. Portanto, para dar suporte a texto
acessível, certifique-se de que o dispositivo estilos são usados como base para qualquer estilo de texto dentro de
seu aplicativo.
As capturas de tela a seguir demonstram os estilos de dispositivo em cada plataforma, com o menor tamanho de
fonte acessível:
As capturas de tela a seguir demonstram os estilos de dispositivo em cada plataforma, com o maior tamanho de
fonte acessível:
Links relacionados
Estilos de texto
Extensões de marcação XAML
Estilos dinâmicos (amostra)
Trabalhar com estilos (amostra)
Device.Styles
Dicionário de recurso
Estilo
Setter
Classes de estilo do xamarin. Forms
12/04/2019 • 5 minutes to read
Baixar o exemplo
Classes de estilo do xamarin. Forms permitem que vários estilos a ser aplicado a um controle, sem recorrer à
herança de estilo.
IMPORTANT
Vários estilos podem compartilhar o mesmo nome de classe, desde que eles se destinam a diferentes tipos. Isso permite que
várias classes de estilo, que são nomeadas de maneira idêntica, para tipos diferentes de destino.
O exemplo a seguir mostra três BoxView classes, estilo e uma VisualElement classe de estilo:
<ContentPage ...>
<ContentPage.Resources>
<Style TargetType="BoxView"
Class="Separator">
<Setter Property="BackgroundColor"
Value="#CCCCCC" />
<Setter Property="HeightRequest"
Value="1" />
</Style>
<Style TargetType="BoxView"
Class="Rounded">
<Setter Property="BackgroundColor"
Value="#1FAECE" />
<Setter Property="HorizontalOptions"
Value="Start" />
<Setter Property="CornerRadius"
Value="10" />
</Style>
<Style TargetType="BoxView"
Class="Circle">
<Setter Property="BackgroundColor"
Value="#1FAECE" />
<Setter Property="WidthRequest"
Value="100" />
<Setter Property="HeightRequest"
Value="100" />
<Setter Property="HorizontalOptions"
Value="Start" />
<Setter Property="CornerRadius"
Value="50" />
</Style>
<Style TargetType="VisualElement"
Class="Rotated"
ApplyToDerivedTypes="true">
<Setter Property="Rotation"
Value="45" />
</Style>
</ContentPage.Resources>
</ContentPage>
O Separator , Rounded ,e Circle cada conjunto de classes do estilo BoxView propriedades com valores
específicos.
O Rotated classe de estilo tem uma TargetType dos VisualElement , que significa que ele só pode ser aplicado a
VisualElement instâncias. No entanto, sua ApplyToDerivedTypes estiver definida como true , que garante que ele
pode ser aplicado a todos os controles que derivam VisualElement , como BoxView . Para obter mais informações
sobre como aplicar um estilo a um tipo derivado, consulte aplicar um estilo a tipos derivados.
O código C# equivalente é:
<ContentPage ...>
<ContentPage.Resources>
...
</ContentPage.Resources>
<StackLayout Margin="20">
<BoxView StyleClass="Separator" />
<BoxView WidthRequest="100"
HeightRequest="100"
HorizontalOptions="Center"
StyleClass="Rounded, Rotated" />
<BoxView HorizontalOptions="Center"
StyleClass="Circle" />
</StackLayout>
</ContentPage>
Neste exemplo, a primeira BoxView estilo é feito para ser um separador de linha, enquanto o terceiro BoxView é
circular. O segundo BoxView tem duas classes do estilo aplicado a ele, que dê cantos arredondado de it e girá-lo 45
graus:
IMPORTANT
Várias classes de estilo podem ser aplicadas a um controle porque o StyleClass propriedade é do tipo IList<string> .
Quando isso ocorre, as classes de estilo são aplicadas na lista ordem crescente. Portanto, quando várias classes de estilo
define as propriedades idênticas, a propriedade na classe de estilo que está em posição mais elevada lista terá precedência.
O código C# equivalente é:
...
Content = new StackLayout
{
Children =
{
new BoxView { StyleClass = new [] { "Separator" } },
new BoxView { WidthRequest = 100, HeightRequest = 100, HorizontalOptions = LayoutOptions.Center,
StyleClass = new [] { "Rounded", "Rotated" } },
new BoxView { HorizontalOptions = LayoutOptions.Center, StyleClass = new [] { "Circle" } }
}
};
Links relacionados
Estilos básicos (amostra)
Aplicar estilo a aplicativos xamarin. Forms usando
folhas de estilo em cascata (CSS)
12/04/2019 • 23 minutes to read
baixar o exemplo
Xamarin. Forms dá suporte a elementos visuais de estilo usando folhas de estilo em cascata (CSS ).
Aplicativos xamarin. Forms podem ser estilizados usando CSS. Uma folha de estilos consiste em uma lista de
regras, com cada regra consiste em um bloco de declaração e um ou mais dos seletores. Um bloco de declaração
consiste em uma lista de declarações entre chaves, com cada declaração consiste em uma propriedade, dois-
pontos e um valor. Quando há várias declarações em um bloco, uma ponto e vírgula é inserida como um
separador. O exemplo de código a seguir mostra o CSS em conformidade com xamarin. Forms:
navigationpage {
-xf-bar-background-color: lightgray;
}
^contentpage {
background-color: lightgray;
}
#listView {
background-color: lightgray;
}
stacklayout {
margin: 20;
}
.mainPageTitle {
font-style: bold;
font-size: medium;
}
.mainPageSubtitle {
margin-top: 15;
}
.detailPageTitle {
font-style: bold;
font-size: medium;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
listview image {
height: 60;
width: 60;
}
stacklayout>image {
height: 200;
width: 200;
}
No xamarin. Forms, folhas de estilo CSS são analisadas e avaliadas em tempo de execução, em vez de tempo de
compilação e folhas de estilo são analisadas novamente em uso.
NOTE
Atualmente, todos os estilos que são possíveis com estilo de XAML não podem ser executados com CSS. No entanto, os
estilos XAML podem ser usados para complementar o CSS para propriedades que não são atualmente suportadas pelo
xamarin. Forms. Para obter mais informações sobre estilos XAML, consulte estilos aplicativos xamarin. Forms usando os
estilos XAML.
O MonkeyAppCSS exemplo demonstra como usar CSS para definir o estilo de um aplicativo simples e é
mostrado nas capturas de tela seguir:
Consumindo uma folha de estilos
O processo para adicionar uma folha de estilos a uma solução é da seguinte maneira:
1. Adicione um arquivo CSS vazio ao seu projeto de biblioteca .NET Standard.
2. Defina a ação de compilação do arquivo CSS para EmbeddedResource.
Carregando uma folha de estilos
Há várias abordagens que podem ser usados para carregar uma folha de estilos.
XAML
Uma folha de estilos pode ser carregada e analisada com o StyleSheet classe antes de serem adicionados a um
ResourceDictionary :
<Application ...>
<Application.Resources>
<StyleSheet Source="/Assets/styles.css" />
</Application.Resources>
</Application>
O StyleSheet.Source propriedade especifica a folha de estilos como um URI relativo ao local do arquivo XAML
delimitador ou relativa à raiz do projeto se o URI começa com um / .
WARNING
O arquivo CSS não carregará se sua ação de compilação não está definida como EmbeddedResource.
Como alternativa, uma folha de estilos pode ser carregada e analisada com o StyleSheet classe antes de serem
adicionados a um ResourceDictionary , por inlining-lo em um CDATA seção:
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet>
<![CDATA[
^contentpage {
background-color: lightgray;
}
]]>
</StyleSheet>
</ContentPage.Resources>
...
</ContentPage>
Para obter mais informações sobre dicionários de recursos, consulte dicionários de recursos.
C#
No C#, uma folha de estilos pode ser carregada como um recurso inserido e adicionada a um ResourceDictionary
:
this.Resources.Add(StyleSheet.FromAssemblyResource(
IntrospectionExtensions.GetTypeInfo(typeof(MyPage)).Assembly,
"MyProject.Assets.styles.css"));
}
}
stacklayout {
margin: 20;
}
Este seletor identifica qualquer StackLayout elementos nas páginas que consomem a folha de estilos e define
suas margens para uma espessura uniforme de 20.
NOTE
O element seletor não identifica as subclasses do tipo especificado.
^contentpage {
background-color: lightgray;
}
Este seletor identifica qualquer ContentPage elementos que consomem a folha de estilos e define seu plano de
fundo de cor para lightgray .
NOTE
O ^base seletor é específico ao xamarin. Forms e não faz parte da especificação do CSS.
#listView {
background-color: lightgray;
}
Este seletor identifica o elemento cujos StyleId estiver definida como listView . No entanto, se o StyleId não
está definida, o seletor de fará o fallback para usar o x:Name do elemento. Portanto, no exemplo XAML a seguir, o
#listView seletor identificará a ListView cujo x:Name atributo é definido como listView e definirá a cor do
plano de fundo como lightgray .
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView x:Name="listView" ...>
...
</ListView>
</StackLayout>
</ContentPage>
.detailPageTitle {
font-style: bold;
font-size: medium;
text-align: center;
}
.detailPageSubtitle {
text-align: center;
font-style: italic;
}
Uma classe CSS pode ser atribuída a um elemento XAML, definindo o StyleClass propriedade do elemento a
ser o nome da classe CSS. Portanto, no exemplo XAML a seguir, os estilos definidos pelo .detailPageTitle classe
são atribuídos à primeira Label , enquanto os estilos definidos pelo .detailPageSubtitle classe são atribuídos ao
segundo Label .
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
<Label ... StyleClass="detailPageTitle" />
<Label ... StyleClass="detailPageSubtitle"/>
...
</StackLayout>
</ScrollView>
</ContentPage>
listview image {
height: 60;
width: 60;
}
Este seletor identifica qualquer Image elementos que são filhos do ListView elementos e define sua altura e
largura para 60. Portanto, no exemplo XAML a seguir, o listview image seletor identificará as Image que é um
filho do ListView e define sua altura e largura para 60.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<StackLayout>
<ListView ...>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
...
<Image ... />
...
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
NOTE
O element element seletor não exige o elemento filho a ser uma direto filho do pai – o elemento filho pode ter um pai
diferente. Seleção ocorre desde que um ancestral seja o primeiro elemento especificado.
stacklayout>image {
height: 200;
width: 200;
}
Este seletor identifica qualquer Image direcionam de elementos que são filhos do StackLayout elementos e
define sua altura e largura para 200. Portanto, no exemplo XAML a seguir, o stacklayout>image seletor
identificará as Image que é um filho direto do StackLayout e define sua altura e largura para 200.
<ContentPage ...>
<ContentPage.Resources>
<StyleSheet Source="/Assets/styles.css" />
</ContentPage.Resources>
<ScrollView>
<StackLayout>
...
<Image ... />
...
</StackLayout>
</ScrollView>
</ContentPage>
NOTE
O element>element seletor requer que o elemento filho é um direto filho do pai.
Referência do seletor
Os seguintes seletores CSS são suportados pelo xamarin. Forms:
TIP
Seletores podem ser combinadas sem limitação, tais como StackLayout>ContentView>label.email .
NOTE
Não há suporte a especificidade e substituições de especificidade.
Referência de propriedade
As propriedades CSS a seguir têm suporte pelo xamarin. Forms (na valores tipos de coluna, são itálico, enquanto
os literais de cadeia de caracteres são gray ):
spacebetween |
spacearound |
spaceevenly |
flex-start | flex-end |
space-between |
space-around | initial
DatePicker , Editor ,
Entry , Label , Picker ,
ProgressBar , SearchBar ,
Switch , TimePicker
row-reverse |
column-reverse |
initial
initial
spacearound |
spaceevenly |
flex-start | flex-end |
space-between |
space-around | initial
scaleX , scaleY ,
translate , translateX ,
translateY , initial
Também há suporte para as seguintes propriedades CSS específicas do xamarin. Forms (na valores tipos de
coluna, são itálico, enquanto os literais de cadeia de caracteres são gray ):
só é compatível com um
ScrollView .
NOTE
initial é um valor válido para todas as propriedades. Limpa o valor (redefine como padrão) que foi definido de outro
estilo.
NOTE
CSS thickness valores diferentes de XAML Thickness valores. Por exemplo, em XAML, um valor de dois Thickness
indica a espessura horizontal e vertical, enquanto um valor de quatro Thickness indica à esquerda, em seguida, superior e
direita, inferior, em seguida, espessura. Além disso, o XAML Thickness valores são delimitados por vírgula.
NamedSize
O seguinte diferencia maiusculas de minúsculas namedsize valores têm suporte:
default
micro
small
medium
large
O significado exato de cada namedsize valor é dependente de plataforma e dependente do modo de exibição.
Links relacionados
MonkeyAppCSS (amostra)
Dicionários de recurso
Aplicar estilo a aplicativos do Xamarin.Forms usando os estilos XAML
Modo de tabela do xamarin. Forms
12/04/2019 • 10 minutes to read
Baixar o exemplo
TableView é um modo de exibição de lista rolável de dados ou opções em que existem linhas que não
compartilham o mesmo modelo. Diferentemente ListView, TableView não tem o conceito de um ItemsSource ,
portanto, os itens devem ser adicionados como filhos.
Casos de uso
TableView é útil quando:
apresentar uma lista de configurações,
coleta de dados em um formulário, ou
mostrando dados que são apresentados diferente da linha a linha (por exemplo, números, porcentagens e
imagens).
TableView manipula a rolagem e layout de linhas nas seções atraentes, uma necessidade comum para os
cenários acima. O TableView usa o controle de exibição equivalente quando estiverem disponíveis, criar uma
aparência nativa para cada plataforma de base de cada plataforma.
Estrutura
Elementos em uma TableView são organizados em seções. Na raiz do TableView é o TableRoot , que é o pai
de um ou mais TableSection instâncias. Cada TableSection consiste em um título e um ou mais ViewCell
instâncias:
<TableView Intent="Settings">
<TableRoot>
<TableSection Title="Ring">
<SwitchCell Text="New Voice Mail" />
<SwitchCell Text="New Mail" On="true" />
</TableSection>
</TableRoot>
</TableView>
O código C# equivalente é:
Aparência
TableView expõe o Intent propriedade, que pode ser definida para qualquer um dos TableIntent membros
de enumeração:
Data – para uso ao exibir entradas de dados. Observe que ListView pode ser uma opção melhor para listas
de dados de rolagem.
Form – para uso quando o modo de tabela está agindo como um formulário.
Menu – para uso ao apresentar um menu das seleções.
Settings – para uso ao exibir uma lista de definições de configuração.
O TableIntent valor escolhido pode afetar como o TableView aparece em cada plataforma. Mesmo que haja
não limpará as diferenças, é uma prática recomendada para selecionar o TableIntent que mais se aproxima
como você pretende usar a tabela.
Além disso, a cor do texto exibida para cada TableSection pode ser alterado definindo o TextColor
propriedade a um Color .
Células internas
Xamarin. Forms é fornecido com células internas para coletar e exibir informações. Embora ListView e
TableView pode usar todas as células mesmas, SwitchCell e EntryCell são mais relevantes para um
TableView cenário.
Ver aparência de célula do ListView para obter uma descrição detalhada dos TextCell e ImageCell.
SwitchCell
SwitchCell é o controle a ser usado para apresentar e capturar um ligado/desligado ou true / false estado.
Ele define as propriedades a seguir:
Text – texto a ser exibido ao lado do comutador.
On – Se a opção é exibida como em ou desativado.
OnColor – o Color do comutador quando ele está em posição de ligado.
EntryCell
EntryCell é útil quando você precisa exibir dados de texto que o usuário pode editar. Ele define as
propriedades a seguir:
Keyboard – O teclado para exibir durante a edição. Há opções para coisas como valores numéricos, email,
números de telefone, etc. Consulte os documentos de API.
Label – O texto de rótulo a ser exibida à esquerda do campo de entrada de texto.
LabelColor – A cor do texto do rótulo.
Placeholder – Texto exibido no campo de entrada quando ele é nulo ou vazio. Esse texto desaparece quando
a entrada de texto começa.
Text – O texto no campo de entrada.
HorizontalTextAlignment – O alinhamento horizontal do texto. Pode ser centro, esquerdo ou direito
alinhado. Consulte os documentos de API.
EntryCell também expõe o Completed evento, que é disparado quando o usuário pressiona o botão
'concluído' no teclado durante a edição de texto.
Células personalizadas
Quando as células internas não forem suficientes, células personalizadas podem ser usadas para apresentar e
capturar dados da maneira que faça sentido para seu aplicativo. Por exemplo, você talvez queira apresentar um
controle deslizante para permitir ao usuário escolher a opacidade de uma imagem.
Todas as células personalizadas devem derivar de ViewCell , a mesma classe base que todos os internos célula
tipos de uso.
Este é um exemplo de uma célula personalizada:
O exemplo a seguir mostra o XAML usado para criar o TableView nas capturas de tela acima:
O código C# equivalente é:
var table = new TableView();
table.Intent = TableIntent.Settings;
var layout = new StackLayout() { Orientation = StackOrientation.Horizontal };
layout.Children.Add (new Image() { Source = "bulb.png"});
layout.Children.Add (new Label()
{
Text = "left",
TextColor = Color.FromHex("#f35e20"),
VerticalOptions = LayoutOptions.Center
});
layout.Children.Add (new Label ()
{
Text = "right",
TextColor = Color.FromHex ("#503026"),
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.EndAndExpand
});
table.Root = new TableRoot ()
{
new TableSection("Getting Started")
{
new ViewCell() {View = layout}
}
};
Content = table;
NOTE
Diferentemente ListView , TableView não exige que personalizado (ou qualquer) as células são definidas em um
ItemTemplate .
Altura da linha
O TableView classe tem duas propriedades que podem ser usadas para alterar a altura da linha de células:
RowHeight – Define a altura de cada linha para um int .
HasUnevenRows – linhas têm diferentes alturas se definido como true . Observe que, ao definir essa
propriedade como true , as alturas das linhas automaticamente serão calculadas e aplicadas pelo xamarin.
Forms.
Quando a altura do conteúdo em uma célula em uma TableView for alterado, a linha de altura é atualizada
implicitamente no Android e Universal Windows Platform (UWP ). No entanto, no iOS ele deve ser forçado a
atualizar definindo a HasUnevenRows propriedade true e chamando o Cell.ForceUpdateSize método.
A exemplo XAML a seguir mostra uma TableView que contém um ViewCell :
<ContentPage ...>
<TableView ...
HasUnevenRows="true">
<TableRoot>
...
<TableSection ...>
...
<ViewCell x:Name="_viewCell"
Tapped="OnViewCellTapped">
<Grid Margin="15,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Label Text="Tap this cell." />
<Label x:Name="_target"
Grid.Row="1"
Text="The cell has changed size."
IsVisible="false" />
</Grid>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
</ContentPage>
IMPORTANT
Há uma grande possibilidade de degradação do desempenho se esse recurso está sendo usado em excesso.
Links relacionados
Modo de tabela (amostra)
Texto no xamarin. Forms
12/04/2019 • 3 minutes to read
baixar o exemplo
Usando o xamarin. Forms para inserir ou exibir texto.
Xamarin. Forms tem três modos de exibição primários para trabalhar com texto:
Rótulo — para a apresentação de texto único ou várias linha. Pode mostrar o texto com várias opções de
formatação na mesma linha.
Entrada — para inserção de texto que é apenas uma linha. Entrada tem um modo de senha.
Editor — para inserção de texto que pode levar mais de uma linha.
Aparência do texto pode ser alterada usando internas ou personalizadas estilos e alguns controles oferecem
suporte personalizado fontes.
Rótulo
O Label exibição é usada para exibir o texto. Ele pode mostrar várias linhas de texto ou uma única linha de texto.
Label pode apresentar texto com várias opções de formatação usadas em embutido. O modo de exibição do
rótulo pode encapsular ou truncar o texto quando ela não couber em uma única linha.
Editor
Editor é usado para aceitar a entrada de texto de várias linhas. Editor controle de ofertas sobre fontes e cores.
Consulte a Editor artigo para obter mais informações.
Fontes
Muitos controles oferecem suporte a configurações de fonte diferente usando as fontes internas em cada
plataforma, ou fontes personalizadas, incluídas com o seu aplicativo. Consulte a fontes do artigo para obter mais
informações.
Estilos
Consulte a trabalhar com estilos para saber como configurar a fonte, core outras propriedades de exibição que se
aplicam a vários controles.
Links relacionados
Texto (exemplo)
Rótulo do xamarin. Forms
12/04/2019 • 18 minutes to read
baixar o exemplo
Exibir o texto no xamarin. Forms
O Label exibição é usada para exibir o texto, único e de várias linha. Rótulos podem ter as decorações de texto,
texto colorido e usar fontes personalizadas (famílias, tamanhos e opções).
Decorações de texto
Decorações de texto sublinhado e tachado podem ser aplicadas a Label instâncias, definindo o
Label.TextDecorations propriedade a um ou mais TextDecorations membros de enumeração:
None
Underline
Strikethrough
O código C# equivalente é:
NOTE
Decorações de texto também podem ser aplicadas a Span instâncias. Para obter mais informações sobre o Span classe,
consulte texto formatado em.
Cores
Rótulos podem ser definidos para usar uma cor de texto personalizado por meio de associável TextColor
propriedade.
Cuidado especial é necessário para garantir que as cores poderá ser usadas em cada plataforma. Como cada
plataforma tem diferentes padrões de cores de plano de fundo e texto, você precisará ter cuidado para escolher
um padrão que funciona em cada um.
O exemplo XAML a seguir define a cor do texto de um Label :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TextSample.LabelPage"
Title="Label Demo">
<StackLayout Padding="5,10">
<Label TextColor="#77d065" FontSize = "20" Text="This is a green label." />
</StackLayout>
</ContentPage>
O código C# equivalente é:
Fontes
Para obter mais informações sobre como especificar fontes em uma Label , consulte fontes.
<Label Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla
vulputate. Nullam porta eleifend lacinia. Donec at iaculis tellus."
LineBreakMode="WordWrap"
MaxLines="2" />
O código C# equivalente é:
var label =
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla
vulputate. Nullam porta eleifend lacinia. Donec at iaculis tellus.", LineBreakMode = LineBreakMode.WordWrap,
MaxLines = 2
};
As capturas de tela a seguir mostram o resultado da configuração de MaxLines propriedade como 2, quando o
texto é longo o suficiente para ocupar mais de 2 linhas:
Texto formatado
Rótulos de expõem uma FormattedText propriedade que permite que a apresentação de texto com várias fontes
e cores na mesma exibição.
O FormattedText propriedade é do tipo FormattedString , que consiste em um ou mais Span instâncias,
definidas por meio de Spans propriedade . O seguinte Span propriedades podem ser usadas para definir a
aparência visual:
BackgroundColor – a cor do plano de fundo span.
Font – a fonte do texto no trecho.
FontAttributes – os atributos de fonte para o texto no trecho.
FontFamily – a família de fontes ao qual pertence a fonte do texto no trecho.
FontSize – o tamanho da fonte para o texto no trecho.
ForegroundColor – a cor do texto no trecho. Essa propriedade está obsoleta e foi substituída pelo TextColor
propriedade.
LineHeight -o multiplicador para aplicar a altura de linha padrão da extensão. Para obter mais informações,
consulte altura da linha.
Text – o estilo a ser aplicado para o período.
Text – o texto da marca span.
TextColor – a cor do texto no trecho.
TextDecorations -as decorações para aplicar ao texto no trecho. Para obter mais informações, consulte
decorações de texto.
NOTE
O BackgroundColor , Text , e Text propriedades vinculáveis têm um modo de associação padrão do OneWay . Para
obter mais informações sobre esse modo de associação, consulte o modo de associação padrão na modo de associação
guia.
Além disso, o GestureRecognizers propriedade pode ser usada para definir uma coleção dos reconhecedores de
gestos que irá responder a gestos no Span .
O exemplo XAML a seguir demonstra uma FormattedText propriedade consiste em três Span instâncias:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TextSample.LabelPage"
Title="Label Demo - XAML">
<StackLayout Padding="5,10">
...
<Label LineBreakMode="WordWrap">
<Label.FormattedText>
<FormattedString>
<Span Text="Red Bold, " TextColor="Red" FontAttributes="Bold" />
<Span Text="default, " Style="{DynamicResource BodyStyle}">
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}" />
</Span.GestureRecognizers>
</Span>
<Span Text="italic small." FontAttributes="Italic" FontSize="Small" />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ContentPage>
O código C# equivalente é:
public class LabelPageCode : ContentPage
{
public LabelPageCode ()
{
var layout = new StackLayout{ Padding = new Thickness (5, 10) };
...
var formattedString = new FormattedString ();
formattedString.Spans.Add (new Span{ Text = "Red bold, ", ForegroundColor = Color.Red, FontAttributes
= FontAttributes.Bold });
IMPORTANT
O Text propriedade de um Span pode ser definido por meio da vinculação de dados. Para obter mais informações,
consulte associação de dados.
Observe que um Span também pode responder a qualquer gestos que são adicionados para o período
GestureRecognizers coleção. Por exemplo, uma TapGestureRecognizer foi adicionada à segunda Span nos
exemplos de código acima. Portanto, quando isso Span é tocado a TapGestureRecognizer responderá executando
o ICommand definido pelo Command propriedade. Para obter mais informações sobre os reconhecedores de
gestos, consulte xamarin. Forms gestos.
As capturas de tela a seguir mostram o resultado da configuração de FormattedString propriedade para três
Span instâncias:
Altura da linha
A altura vertical de um Label e uma Span pode ser personalizado definindo o Label.LineHeight propriedade
ou Span.LineHeight para um double valor. No iOS e Android, esses valores são multiplicadores da altura da
linha original e na plataforma Universal de Windows (UWP ) o Label.LineHeight valor da propriedade é um
multiplicador de tamanho da fonte do rótulo.
NOTE
No iOS, o Label.LineHeight e Span.LineHeight propriedades alterar a altura da linha de texto que cabem em uma
única linha e o texto que é quebrada em várias linhas.
No Android, o Label.LineHeight e Span.LineHeight propriedades apenas alterar a altura da linha de texto que é
quebrada em várias linhas.
Na UWP, o Label.LineHeight propriedade altera a altura da linha de texto que é quebrada em várias linhas, e o
Span.LineHeight propriedade não tem nenhum efeito.
<Label Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla
vulputate. Nullam porta eleifend lacinia. Donec at iaculis tellus."
LineBreakMode="WordWrap"
LineHeight="1.8" />
O código C# equivalente é:
var label =
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla
vulputate. Nullam porta eleifend lacinia. Donec at iaculis tellus.", LineBreakMode = LineBreakMode.WordWrap,
LineHeight = 1.8
};
As capturas de tela a seguir mostram o resultado da configuração de Label.LineHeight propriedade para o 1.8:
<Label LineBreakMode="WordWrap">
<Label.FormattedText>
<FormattedString>
<Span Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. In a tincidunt sem.
Phasellus mollis sit amet turpis in rutrum. Sed aliquam ac urna id scelerisque. "
LineHeight="1.8"/>
<Span Text="Nullam feugiat sodales elit, et maximus nibh vulputate id."
LineHeight="1.8" />
</FormattedString>
</Label.FormattedText>
</Label>
O código C# equivalente é:
var formattedString = new FormattedString();
formattedString.Spans.Add(new Span
{
Text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. In a tincidunt sem. Phasellus mollis sit
amet turpis in rutrum. Sed aliquam ac urna id scelerisque. ",
LineHeight = 1.8
});
formattedString.Spans.Add(new Span
{
Text = "Nullam feugiat sodales elit, et maximus nibh vulputate id.",
LineHeight = 1.8
});
var label = new Label
{
FormattedText = formattedString,
LineBreakMode = LineBreakMode.WordWrap
};
As capturas de tela a seguir mostram o resultado da configuração de Span.LineHeight propriedade para o 1.8:
Hiperlinks
O texto exibido pelo Label e Span instâncias podem ser transformadas em hiperlinks com a seguinte
abordagem:
1. Defina as TextColor e TextDecoration propriedades da Label ou Span .
2. Adicionar um TapGestureRecognizer para o GestureRecognizers coleção do Label ou Span , cuja Command
propriedade associa a um ICommand e cujo CommandParameter propriedade contém a URL para abrir.
3. Definir as ICommand que será executado pelo TapGestureRecognizer .
4. Escrever o código que será executado pelo ICommand .
O exemplo de código a seguir, extraído o demonstrações de hiperlink exemplo mostra um Label cujo conteúdo
é definido de vários Span instâncias:
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Alternatively, click " />
<Span Text="here"
TextColor="Blue"
TextDecorations="Underline">
<Span.GestureRecognizers>
<TapGestureRecognizer Command="{Binding TapCommand}"
CommandParameter="https://docs.microsoft.com/xamarin/" />
</Span.GestureRecognizers>
</Span>
<Span Text=" to view Xamarin documentation." />
</FormattedString>
</Label.FormattedText>
</Label>
Neste exemplo, o primeiro e terceiro Span instâncias abrangem o texto, enquanto o segundo Span representa
um hiperlink tappable. Ele tem a sua cor de texto definido como azul e tem uma decoração de texto sublinhado.
Isso cria a aparência de um hiperlink, conforme mostrado nas capturas de tela seguir:
Quando o hiperlink é tocado, o TapGestureRecognizer responderá executando o ICommand definidas pelo seu
Command propriedade. Além disso, a URL especificada o CommandParameter propriedade será passada para o
ICommand como um parâmetro.
public MainPage()
{
InitializeComponent();
BindingContext = this;
}
public HyperlinkSpan()
{
TextDecorations = TextDecorations.Underline;
TextColor = Color.Blue;
GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(() => Device.OpenUri(new Uri(Url)))
});
}
}
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HyperlinkDemo"
x:Class="HyperlinkDemo.MainPage">
<StackLayout>
...
<Label>
<Label.FormattedText>
<FormattedString>
<Span Text="Alternatively, click " />
<local:HyperlinkSpan Text="here"
Url="https://docs.microsoft.com/appcenter/" />
<Span Text=" to view AppCenter documentation." />
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ContentPage>
Estilo de rótulos
As seções anteriores coberto configuração Label e Span propriedades em uma base por instância. No entanto,
os conjuntos de propriedades podem ser agrupados em um estilo que é aplicado consistentemente a um ou
vários modos de exibição. Isso pode aumentar a legibilidade do código e fazer alterações de design mais fácil de
implementar. Para obter mais informações, consulte estilos.
Links relacionados
Texto (exemplo)
Hiperlinks (amostra)
Criação de aplicativos móveis com xamarin. Forms, capítulo 3
API de rótulo
API de alcance
Entrada do xamarin. Forms
12/04/2019 • 17 minutes to read
baixar o exemplo
Texto de linha única ou de entrada de senha
O xamarin. Forms Entry é usado para entrada de texto de linha única. O Entry , como o Editor exibir, dá
suporte a vários tipos de teclado. Além disso, o Entry pode ser usado como um campo de senha.
Personalização da exibição
Definir e ler texto
O Entry , assim como outras exibições de apresentação de texto, expõe o Text propriedade. Essa propriedade
pode ser usada para definir e ler o texto apresentado pelo Entry . O exemplo a seguir demonstra a configuração
de Text propriedade em XAML:
No C#:
NOTE
A largura de uma Entry pode ser definida ao configurar seu WidthRequest propriedade. Não dependem da largura de
uma Entry que está sendo definida com base no valor de seu Text propriedade.
var entry = new Entry { Text = "This is a read-only Entry", IsReadOnly = true });
NOTE
O IsReadonly propriedade não altera a aparência visual de um Entry , ao contrário o IsEnabled propriedade que
também altera a aparência visual do Entry em cinza.
Um MaxLength valor de propriedade de 0 indica que nenhuma entrada será permitida e um valor de
int.MaxValue , que é o valor padrão para um Entry , indica que não há nenhum limite efetivo no número de
caracteres que podem ser inseridos.
Campos de senha
Entry fornece o IsPassword propriedade. Quando IsPassword é true , o conteúdo do campo será apresentado
como círculos pretos:
No XAML:
No C#:
No C#:
O valor padrão de CursorPosition propriedade é 0, que indica que o texto será inserido no início do Entry .
Além disso, o SelectionLength propriedade pode ser usada para retornar ou definir o comprimento da seleção
de texto dentro de Entry :
<Entry Text="Cursor position and selection length set" CursorPosition="2" SelectionLength="10" />
var entry = new Entry { Text = "Cursor position and selection length set", CursorPosition = 2,
SelectionLength = 10 };
O valor padrão de SelectionLength propriedade é 0, que indica que nenhum texto estiver selecionado.
Personalizando o teclado
O teclado que é apresentado quando os usuários interagem com um Entry podem ser definidas
programaticamente por meio dos Keyboard propriedade a uma das seguintes propriedades do Keyboard classe:
Chat – usado para mandar um texto e locais em que o emoji são úteis.
Default – o teclado padrão.
Email – usado ao inserir endereços de email.
Numeric – usado ao inserir números.
Plain – usado ao inserir texto, sem nenhuma KeyboardFlags especificado.
Telephone – usado ao inserir números de telefone.
Text – usado ao inserir texto.
Url – usado para inserir caminhos de arquivo & endereços da web.
O código c# equivalente é:
O código c# equivalente é:
O código c# equivalente é:
NOTE
A aparência exata da chave de retorno depende da plataforma. No iOS, a tecla return é um botão com base em texto. No
entanto, nas plataformas universais do Windows e Android, a tecla return é um botão de ícone.
Quando a tecla return é pressionada, o Completed evento é acionado e qualquer ICommand especificado pela
ReturnCommand propriedade é executada. Além disso, qualquer object especificado pelo ReturnCommandParameter
propriedade será passada para o ICommand como um parâmetro. Para obter mais informações sobre comandos,
consulte a Interface de comando.
Habilitar e desabilitar a verificação ortográfica
O IsSpellCheckEnabled propriedade controla se verificação ortográfica está habilitada. Por padrão, a propriedade
é definida como true . Enquanto o usuário insere texto, erros de ortografia são indicados.
No entanto, para alguns cenários de entrada de texto, como inserir um nome de usuário, verificação ortográfica
fornece uma experiência negativa e deve ser desabilitada definindo a IsSpellCheckEnabled propriedade false :
NOTE
Quando o IsSpellCheckEnabled estiver definida como false e um teclado personalizado não está sendo usado, o
verificador ortográfico nativo será desabilitado. No entanto, se um Keyboard tem sido conjunto que desabilita ortográfica
verificação, como Keyboard.Chat , o IsSpellCheckEnabled propriedade será ignorada. Portanto, a propriedade não
pode ser usada para habilitar a verificação ortográfica para um Keyboard que desabilita explicitamente a ele.
NOTE
Quando o IsTextPredictionEnabled estiver definida como false , e um teclado personalizado não está sendo usado, a
previsão de texto e automático correção de texto está desabilitada. No entanto, se um Keyboard tiver sido definido que
desabilita a previsão de texto, o IsTextPredictionEnabled propriedade será ignorada. Portanto, a propriedade não pode
ser usada para habilitar a previsão de texto para um Keyboard que desabilita explicitamente a ele.
Cores
Pode ser configurada para usar um plano de fundo personalizado e as cores de texto por meio das seguintes
propriedades vinculáveis:
TextColor – define a cor do texto.
BackgroundColor – define a cor mostrada atrás do texto.
Cuidado especial é necessário para garantir que as cores poderá ser usadas em cada plataforma. Como cada
plataforma tem diferentes padrões de cores de plano de fundo e texto, geralmente você precisará definir ambos
se você definir um.
Use o código a seguir para definir a cor do texto de uma entrada:
No XAML:
No C#:
No C#:
Eventos e interatividade
Entrada expõe dois eventos:
TextChanged – gerado quando o texto é alterado na entrada. Fornece o texto antes e após a alteração.
Completed – gerado quando o usuário terminou entrada pressionando a tecla return no teclado.
NOTE
O VisualElement classe da qual Entry herda, também tem Focused e Unfocused eventos.
Concluído
O Completed evento é usado para responder à realização de uma interação com uma entrada. Completed é
gerado quando o usuário encerra a entrada com um campo, pressionando a tecla return no teclado. O
manipulador para o evento é um manipulador de eventos genéricos, levando o remetente e EventArgs :
e o c#:
Após o Completed evento é acionado, qualquer ICommand especificado pela ReturnCommand propriedade for
executada, com o object especificado pelo ReturnCommandParameter propriedade que está sendo passada para o
ICommand .
TextChanged
O TextChanged evento é usado para responder a uma alteração no conteúdo de um campo.
TextChanged é gerado sempre que o Text do Entry alterações. O manipulador para o evento usa uma instância
de TextChangedEventArgs . TextChangedEventArgs fornece acesso aos valores novos e antigos do Entry Text por
meio de OldTextValue e NewTextValue propriedades:
e o c#:
Links relacionados
Texto (exemplo)
Entrada de API
Editor do xamarin. Forms
12/04/2019 • 14 minutes to read
baixar o exemplo
Entrada de texto de várias linhas
O Editor controle é usado para aceitar a entrada de várias linha. Este artigo aborda:
Personalização – opções de teclado e cor.
Interatividade – eventos que podem ser escutados para fornecer interatividade.
Personalização
Definir e ler texto
O Editor , assim como outras exibições de apresentação de texto, expõe o Text propriedade. Essa propriedade
pode ser usada para definir e ler o texto apresentado pelo Editor . O exemplo a seguir demonstra a configuração
de Text propriedade em XAML:
No C#:
var editor = new Editor { Placeholder = "Enter text here", PlaceholderColor = Color.Olive };
NOTE
O IsReadonly propriedade não altera a aparência visual de um Editor , ao contrário o IsEnabled propriedade que
também altera a aparência visual do Editor em cinza.
Um MaxLength valor de propriedade de 0 indica que nenhuma entrada será permitida e um valor de
int.MaxValue , que é o valor padrão para um Editor , indica que não há nenhum limite efetivo no número de
caracteres que podem ser inseridos.
Um Editor de dimensionamento automático
Uma Editor podem ser feitas para dimensionar automaticamente ao seu conteúdo, definindo o
Editor.AutoSize propriedade TextChanges , que é um valor da EditoAutoSizeOption enumeração. Esta
enumeração tem dois valores:
Disabled indica que o redimensionamento automático está desabilitado e é o valor padrão.
TextChanges indica que o redimensionamento automático está habilitado.
var editor = new Editor { Text = "Enter text here", AutoSize = EditorAutoSizeOption.TextChanges };
Quando o redimensionamento automático está habilitado, a altura do Editor aumentarão quando o usuário
preenche com texto e a altura diminuirá conforme o usuário exclui texto.
NOTE
Uma Editor será tamanho automático não se o HeightRequest propriedade foi definida.
Personalizando o teclado
O teclado que é apresentado quando os usuários interagem com um Editor podem ser definidas
programaticamente por meio dos Keyboard propriedade a uma das seguintes propriedades do Keyboard classe:
Chat – usado para mandar um texto e locais em que o emoji são úteis.
Default – o teclado padrão.
Email – usado ao inserir endereços de email.
Numeric – usado ao inserir números.
Plain – usado ao inserir texto, sem nenhuma KeyboardFlags especificado.
Telephone – usado ao inserir números de telefone.
Text – usado ao inserir texto.
Url – usado para inserir caminhos de arquivo & endereços da web.
O código c# equivalente é:
<Editor>
<Editor.Keyboard>
<Keyboard x:FactoryMethod="Create">
<x:Arguments>
<KeyboardFlags>Suggestions,CapitalizeCharacter</KeyboardFlags>
</x:Arguments>
</Keyboard>
</Editor.Keyboard>
</Editor>
O código c# equivalente é:
NOTE
Quando o IsSpellCheckEnabled estiver definida como false e um teclado personalizado não está sendo usado, o
verificador ortográfico nativo será desabilitado. No entanto, se um Keyboard tem sido conjunto que desabilita ortográfica
verificação, como Keyboard.Chat , o IsSpellCheckEnabled propriedade será ignorada. Portanto, a propriedade não
pode ser usada para habilitar a verificação ortográfica para um Keyboard que desabilita explicitamente a ele.
NOTE
Quando o IsTextPredictionEnabled estiver definida como false , e um teclado personalizado não está sendo usado, a
previsão de texto e automático correção de texto está desabilitada. No entanto, se um Keyboard tiver sido definido que
desabilita a previsão de texto, o IsTextPredictionEnabled propriedade será ignorada. Portanto, a propriedade não pode
ser usada para habilitar a previsão de texto para um Keyboard que desabilita explicitamente a ele.
Cores
Editor pode ser definido para usar uma cor de plano de fundo personalizado por meio de BackgroundColor
propriedade. Cuidado especial é necessário para garantir que as cores poderá ser usadas em cada plataforma.
Como cada plataforma tem diferentes padrões de cor do texto, você talvez precise definir uma cor de plano de
fundo personalizado para cada plataforma. Ver trabalhando com ajustes de plataforma para obter mais
informações sobre como otimizar a interface do usuário para cada plataforma.
No C#:
public partial class EditorPage : ContentPage
{
public EditorPage ()
{
InitializeComponent ();
var layout = new StackLayout { Padding = new Thickness(5,10) };
this.Content = layout;
//dark blue on UWP & Android, light blue on iOS
var editor = new Editor { BackgroundColor = Device.RuntimePlatform == Device.iOS ?
Color.FromHex("#A4EAFF") : Color.FromHex("#2c3e50") };
layout.Children.Add(editor);
}
}
No XAML:
Interatividade
Editor expõe dois eventos:
TextChanged – gerado quando o texto é alterado no editor. Fornece o texto antes e após a alteração.
Concluída – gerado quando o usuário terminou entrada pressionando a tecla return no teclado.
NOTE
O VisualElement classe da qual Entry herda, também tem Focused e Unfocused eventos.
Concluído
O Completed evento é usado para responder à realização de uma interação com um Editor . Completed é
gerado quando o usuário encerra a entrada com um campo, inserindo a tecla return no teclado. O manipulador
para o evento é um manipulador de eventos genéricos, levando o remetente e EventArgs :
No XAML:
TextChanged
O TextChanged evento é usado para responder a uma alteração no conteúdo de um campo.
TextChanged é gerado sempre que o Text do Editor alterações. O manipulador para o evento usa uma
instância de TextChangedEventArgs . TextChangedEventArgs fornece acesso aos valores novos e antigos do Editor
Text por meio de OldTextValue e NewTextValue propriedades:
No XAML:
<?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="TextSample.EditorPage"
Title="Editor Demo">
<ContentPage.Content>
<StackLayout Padding="5,10">
<Editor TextChanged="EditorTextChanged" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Links relacionados
Texto (exemplo)
Editor de API
Fontes no xamarin. Forms
12/04/2019 • 11 minutes to read
baixar o exemplo
Este artigo descreve como o xamarin. Forms permite especificar atributos de fonte (incluindo o tamanho e
peso) em controles que exibem texto. Informações de fonte podem ser especificado no código ou especificado
no XAML. Ele tem ' também é possível usar um fonte personalizada, e exibir ícones de fonte.
Este código mostra como criar um rótulo e especificar o tamanho da fonte e o peso para exibir:
Tamanho da fonte
O FontSize propriedade pode ser definida como um valor duplo, por exemplo:
label.FontSize = 24;
Você também pode usar o NamedSize enumeração que tem quatro opções internas; Xamarin. Forms escolhe o
melhor tamanho de cada plataforma.
Micro
Pequeno
Médio
Grande
O NamedSizeenumeração pode ser usado onde quer que um FontSize pode ser especificado usando o
Device.GetNamedSize método para converter o valor de um double :
Atributos de fonte
Estilos de fonte, como negrito e itálico podem ser definidos na FontAttributes propriedade. Atualmente, há
suporte para os seguintes valores:
Nenhum
Negrito
Itálico
O FontAttribute enumeração pode ser usada da seguinte maneira (você pode especificar um único atributo
ou OR -los juntos):
Não há um conversor interno para o FontSize propriedade que permite que todas as configurações de fonte
a ser expressa como um valor de cadeia de caracteres em XAML. Além disso, o FontAttributes propriedade
pode ser usada para especificar atributos de fonte:
Device.RuntimePlatform também pode ser usado em XAML para renderizar uma fonte diferente em cada
plataforma. O exemplo a seguir usa uma face de fonte personalizada no iOS (MarkerFelt-finos) e especifica o
tamanho/atributos somente em outras plataformas:
Ao especificar uma face de fonte personalizado, é sempre uma boa ideia usar OnPlatform , que é difícil
encontrar uma fonte que está disponível em todas as plataformas.
Usar uma fonte personalizada
Usando uma fonte que não sejam de tipos internos requer alguma codificação específicos da plataforma. Esta
captura de tela mostra a fonte personalizada Lobster partir fontes de código-fonte aberto do Google
renderizado usando o xamarin. Forms.
As etapas necessárias para cada plataforma são descritas abaixo. Ao incluir arquivos de fonte personalizado
com um aplicativo, certifique-se de verificar que permite a licença da fonte para distribuição.
iOS
É possível exibir uma fonte personalizada primeiro garantir que ele é carregado e, em seguida, fazendo
referência a ele por nome usando o xamarin. Forms Font métodos. Siga as instruções em esta postagem de
blog:
1. Adicione o arquivo de fonte com ação de compilação: BundleResource, e
2. Atualização do Info. plist arquivo (fontes fornecidas pelo aplicativo, ou UIAppFonts , key), em seguida,
3. Fazer referência a ele por nome sempre que você definir uma fonte no xamarin. Forms!
new Label
{
Text = "Hello, Forms!",
FontFamily = Device.RuntimePlatform == Device.iOS ? "Lobster-Regular" : null // set only for iOS
}
Android
Xamarin. Forms para Android pode fazer referência a uma fonte personalizada que foi adicionada ao projeto
seguindo um padrão de nomenclatura específico. Primeiro, adicione o arquivo de fonte para o ativos pasta no
projeto de aplicativo e defina ação de compilação: AndroidAsset. Em seguida, use o caminho completo e nome
da fonte separados por um hash (#) como o nome da fonte no xamarin. Forms, como o trecho de código a
seguir demonstra:
new Label
{
Text = "Hello, Forms!",
FontFamily = Device.RuntimePlatform == Device.Android ? "Lobster-Regular.ttf#Lobster-Regular" : null //
set only for Android
}
Windows
Xamarin. Forms para plataformas do Windows pode fazer referência a uma fonte personalizada que foi
adicionada ao projeto seguindo um padrão de nomenclatura específico. Primeiro, adicione o arquivo de fonte
para o /Assets/fontes/ pasta no projeto de aplicativo e defina as compilar: conteúdo da ação. Em seguida, use
a fonte e o caminho do nome de arquivo completo, seguido por um hash (#) e o nome da fonte, como o trecho
de código a seguir demonstra:
new Label
{
Text = "Hello, Forms!",
FontFamily = Device.RuntimePlatform == Device.UWP ? "Assets/Fonts/Lobster-Regular.ttf#Lobster" : null
// set only for UWP apps
}
NOTE
Observe que o nome do arquivo de fonte e o nome da fonte podem ser diferentes. Para descobrir o nome da fonte no
Windows, clique no arquivo. ttf e selecione visualização. O nome da fonte pode ser determinado, em seguida, na janela
de visualização.
Agora o código comum para o aplicativo está concluído. O código de discagem do telefone específico da
plataforma agora será implementado como um DependencyService.
XAML
Você também pode usar Device.RuntimePlatform no XAML para renderizar uma fonte personalizada:
Esses dados são usados para criar um arquivo PNG, que pode ser exibido por qualquer exibição que pode
exibir um ImageSource . Essa abordagem permite que os ícones de fonte, como emojis, a ser exibido por vários
modos de exibição, em vez de limitar a exibição do ícone de fonte para um único texto apresentando o modo
de exibição, como um Label .
IMPORTANT
Ícones de fonte no momento somente podem ser especificados por sua representação de caractere unicode.
O exemplo XAML a seguir tem um ícone de fonte única que está sendo exibido por um Image exibição:
<Image BackgroundColor="#D1D1D1">
<Image.Source>
<FontImageSource Glyph=""
FontFamily="{OnPlatform iOS=Ionicons, Android=ionicons.ttf#}"
Size="44" />
</Image.Source>
</Image>
Esse código exibe um ícone do XBox, da família de fonte Ionicons, em um Image exibição. Observe que,
enquanto o unicode, para esse ícone é de caractere \uf30c , ele tem que ser substituídos no XAML e portanto
se torna  . O código c# equivalente é:
Capturas de tela as seguir, do Layouts associável de exemplo, mostrar vários ícones de fonte que está sendo
exibidos por um layout associável:
Links relacionados
FontsSample
Texto (exemplo)
Layouts associáveis (amostra)
Layouts Associáveis
Estilos de texto do xamarin. Forms
12/04/2019 • 4 minutes to read
baixar o exemplo
Estilo do texto no xamarin. Forms
Estilos podem ser usados para ajustar a aparência de rótulos, entradas e editores. Estilos podem ser definidos
uma vez e usados por muitas exibições, mas um estilo só pode ser usado com modos de exibição de um tipo.
Estilos podem ser fornecidos um Key e aplicadas seletivamente usando um controle específico Style
propriedade.
Estilos internos
Xamarin. Forms inclui vários internos estilos para cenários comuns:
BodyStyle
CaptionStyle
ListItemDetailTextStyle
ListItemTextStyle
SubtitleStyle
TitleStyle
Para aplicar um dos estilos internos, use o DynamicResource extensão de marcação para especificar o estilo:
label.Style = Device.Styles.TitleStyle;
Estilos personalizados
Estilos consistem em setters e setters consistem em propriedades e os valores de propriedades serão definidos
como.
No c#, um estilo personalizado para um rótulo com texto vermelho de tamanho 30 seria definido da seguinte
maneira:
var label = new Label { Text = "Check out my style.", Style = LabelStyle };
No XAML:
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="LabelStyle" TargetType="Label">
<Setter Property="TextColor" Value="Red"/>
<Setter Property="FontSize" Value="30"/>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<Label Text="Check out my style." Style="{StaticResource LabelStyle}" />
</StackLayout>
</ContentPage.Content>
Observe que os recursos (incluindo todos os estilos) são definidos dentro ContentPage.Resources , que é um irmão
de mais familiar ContentPage.Content elemento.
Aplicando estilos
Quando um estilo tiver sido criado, ele pode ser aplicado a qualquer correspondência de exibição seu TargetType .
No XAML, estilos personalizados são aplicados aos modos de exibição, fornecendo seus Style propriedade com
um StaticResource referenciando o estilo desejado de extensão de marcação:
No c#, estilos podem ser aplicados diretamente a um modo de exibição ou adicionados ao e recuperados de uma
página ResourceDictionary . Para adicionar diretamente:
var label = new Label { Text = "Check out my style.", Style = LabelStyle };
Estilos internos são aplicados de forma diferente, pois eles precisam responder às configurações de acessibilidade.
Para aplicar estilos internos em XAML, o DynamicResource extensão de marcação é usada:
label.Style = Device.Styles.TitleStyle;
Acessibilidade
Os estilos internos existem para tornar mais fácil respeitar as preferências de acessibilidade. Ao usar qualquer um
dos estilos internos, tamanhos de fonte aumentará automaticamente se um usuário define suas preferências de
acessibilidade adequadamente.
Considere o exemplo a seguir da mesma página de modos de exibição estilizada com os estilos internos com as
configurações de acessibilidade habilitados e desabilitados:
Desabilitado:
Habilitado:
Para garantir a acessibilidade, certifique-se de que os estilos internos são usados como base para todos os estilos
relacionada ao texto dentro de seu aplicativo e que você está usando estilos de forma consistente. Ver estilos para
obter mais detalhes sobre a extensão e trabalhar com estilos, em geral.
Links relacionados
Criação de aplicativos móveis com xamarin. Forms, capítulo 12
Estilos
Texto (exemplo)
Estilo
Temas do xamarin. Forms
12/04/2019 • 3 minutes to read
baixar o exemplo
Temas do xamarin. Forms foram lançados no Evolve 2016 e estão disponíveis como uma visualização para que
os clientes experimentar e fornecer comentários.
Um tema é adicionado a um aplicativo xamarin. Forms, incluindo o Xamarin.Forms.Theme.Base de pacote
do Nuget, além de um pacote adicional que define um tema específico (por exemplo.
Xamarin.Forms.Theme.Light) ou outro um tema local pode ser definido para o aplicativo.
Consulte a tema claro e tema escuro páginas para obter instruções sobre como adicioná-los a um aplicativo ou
fazer check-out a tema personalizado de exemplo.
IMPORTANTE: você também deve seguir as etapas a serem carregar assemblies de tema (abaixo)
adicionando um código clichê para o iOS AppDelegate e Android MainActivity . Isso será melhorado em uma
versão de visualização futura.
Aparência do controle
O Light e escuro ambos os temas definem uma aparência visual específica para os controles padrão. Depois
que você adiciona um tema para o dicionário de recursos do aplicativo, a aparência dos controles padrão será
alterado.
A marcação XAML a seguir mostra alguns controles comuns:
<StackLayout Padding="40">
<Label Text="Regular label" />
<Entry Placeholder="type here" />
<Button Text="OK" />
<BoxView Color="Yellow" />
<Switch />
</StackLayout>
<StackLayout Padding="40">
<BoxView StyleClass="HorizontalRule" />
<BoxView StyleClass="Circle" />
<BoxView StyleClass="Rounded" />
</StackLayout>
Classes internas
Além de definir o estilo automaticamente comum controla a luz e temas escuros atualmente suportam as
seguintes classes que podem ser aplicadas, definindo o StyleClass nesses controles:
BoxView
HorizontalRule
Círculo
Arredondado
Image
Círculo
Arredondado
Miniatura
Button
Padrão
Primária
Êxito
Info
Aviso
Perigo
Link
Pequeno
Grande
Rótulo
Cabeçalho
Subcabeçalho
Corpo
Link
Inverso
Solução de problemas
Não foi possível carregar arquivo ou assembly 'Xamarin.Forms.Theme.Light' ou uma de suas dependências
Na versão de visualização, temas podem não ser capazes de carregar no tempo de execução. Adicione o código
mostrado abaixo nos projetos relevantes para corrigir esse erro.
iOS
No AppDelegate.cs adicione as seguintes linhas depois de LoadApplication
var x = typeof(Xamarin.Forms.Themes.DarkThemeResources);
x = typeof(Xamarin.Forms.Themes.LightThemeResources);
x = typeof(Xamarin.Forms.Themes.iOS.UnderlineEffect);
Android
No MainActivity.cs adicione as seguintes linhas depois de LoadApplication
var x = typeof(Xamarin.Forms.Themes.DarkThemeResources);
x = typeof(Xamarin.Forms.Themes.LightThemeResources);
x = typeof(Xamarin.Forms.Themes.Android.UnderlineEffect);
Links relacionados
Exemplo de ThemesDemo
Tema claro do xamarin. Forms
12/04/2019 • 2 minutes to read
NOTE
Temas exigem a versão de visualização do xamarin. Forms 2.3. Verifique as dicas de solução de problemas se ocorrerem
erros.
4. Usar StyleClass
Aqui está um exemplo de botões e rótulos no tema claro, juntamente com a marcação que produz-los.
<StackLayout Padding="20">
<Button Text="Button Default" />
<Button Text="Button Class Default" StyleClass="Default" />
<Button Text="Button Class Primary" StyleClass="Primary" />
<Button Text="Button Class Success" StyleClass="Success" />
<Button Text="Button Class Info" StyleClass="Info" />
<Button Text="Button Class Warning" StyleClass="Warning" />
<Button Text="Button Class Danger" StyleClass="Danger" />
<Button Text="Button Class Link" StyleClass="Link" />
<Button Text="Button Class Default Small" StyleClass="Small" />
<Button Text="Button Class Default Large" StyleClass="Large" />
</StackLayout>
O uma lista completa de classes internas mostra quais estilos disponíveis para alguns controles comuns.
Tema escuro do xamarin. Forms
12/04/2019 • 2 minutes to read
NOTE
Temas exigem a versão de visualização do xamarin. Forms 2.3. Verifique as dicas de solução de problemas se ocorrerem
erros.
4. Usar StyleClass
Aqui está um exemplo de botões e rótulos no tema escuro, juntamente com a marcação que produz-los.
<StackLayout Padding="20">
<Button Text="Button Default" />
<Button Text="Button Class Default" StyleClass="Default" />
<Button Text="Button Class Primary" StyleClass="Primary" />
<Button Text="Button Class Success" StyleClass="Success" />
<Button Text="Button Class Info" StyleClass="Info" />
<Button Text="Button Class Warning" StyleClass="Warning" />
<Button Text="Button Class Danger" StyleClass="Danger" />
<Button Text="Button Class Link" StyleClass="Link" />
O uma lista completa de classes internas mostra quais estilos disponíveis para alguns controles comuns.
Criando um tema personalizado xamarin. Forms
12/04/2019 • 4 minutes to read
Além de adicionar um tema de um pacote Nuget (como o Light e escuro temas), você pode criar seus próprios
recursos temas de dicionário que podem ser referenciados em seu aplicativo.
Exemplo
Os três BoxView s mostrada na página de temas são denominados de acordo com as três classes definidas nos
dois temas para download.
Para entender como eles funcionam, a marcação a seguir cria um estilo equivalente que você poderá adicionar
diretamente para seu App. XAML.
Observe a Class atributo Style (em oposição à x:Key atributo disponível em versões anteriores do xamarin.
Forms).
<ResourceDictionary>
<!-- DEFINE ANY CONSTANTS -->
<Color x:Key="SeparatorLineColor">#CCCCCC</Color>
<Color x:Key="iOSDefaultTintColor">#007aff</Color>
<Color x:Key="AndroidDefaultAccentColorColor">#1FAECE</Color>
<OnPlatform x:TypeArguments="Color" x:Key="AccentColor">
<On Platform="iOS" Value="{StaticResource iOSDefaultTintColor}" />
<On Platform="Android" Value="{StaticResource AndroidDefaultAccentColorColor}" />
</OnPlatform>
<!-- BOXVIEW CLASSES -->
<Style TargetType="BoxView" Class="HorizontalRule">
<Setter Property="BackgroundColor" Value="{ StaticResource SeparatorLineColor }" />
<Setter Property="HeightRequest" Value="1" />
</Style>
Você observará que o Rounded classe se refere a um efeito personalizado CornerRadius . O código para esse efeito
é fornecido abaixo - referenciá-lo corretamente um personalizado xmlns deve ser adicionado para o App.
XAMLdo elemento raiz:
xmlns:local="clr-namespace:ThemesDemo;assembly=ThemesDemo"
namespace ThemesDemo
{
public static class ThemeEffects
{
public static readonly BindableProperty CornerRadiusProperty =
BindableProperty.CreateAttached("CornerRadius", typeof(double), typeof(ThemeEffects), 0.0,
propertyChanged: OnChanged<CornerRadiusEffect, double>);
private static void OnChanged<TEffect, TProp>(BindableObject bindable, object oldValue, object newValue)
where TEffect : Effect, new()
{
if (!(bindable is View view))
{
return;
}
if (EqualityComparer<TProp>.Equals(newValue, default(TProp)))
{
var toRemove = view.Effects.FirstOrDefault(e => e is TEffect);
if (toRemove != null)
{
view.Effects.Remove(toRemove);
}
}
else
{
view.Effects.Add(new TEffect());
}
}
public static void SetCornerRadius(BindableObject view, double radius)
{
view.SetValue(CornerRadiusProperty, radius);
}
namespace ThemesDemo.iOS
{
public class CornerRadiusEffect : PlatformEffect
{
private nfloat _originalRadius;
UpdateCorner();
}
}
if (args.PropertyName == ThemeEffects.CornerRadiusProperty.PropertyName)
{
UpdateCorner();
}
}
namespace ThemesDemo.Droid
{
public class CornerRadiusEffect : BaseEffect
{
private ViewOutlineProvider _originalProvider;
if (!Attached)
{
return;
}
if (args.PropertyName == ThemeEffects.CornerRadiusProperty.PropertyName)
{
Container.Invalidate();
}
}
baixar o exemplo
Uma exibição do xamarin. Forms que permite que o usuário selecione uma hora.
O xamarin. Forms TimePicker invoca o controle de seletor de tempo da plataforma e permite que o usuário
selecione uma hora. TimePicker Define as propriedades a seguir:
Time do tipo TimeSpan , o tempo selecionado, que assume como padrão um TimeSpan igual a 0. O TimeSpan
tipo indica uma duração de tempo desde a meia-noite.
Format do tipo string , um padrão ou personalizado .NET formatação de cadeia de caracteres, cujo padrão é
"t", o padrão de hora abreviada.
TextColor do tipo Color , a cor usada para exibir o tempo selecionado, cujo padrão é Color.Default .
FontAttributes do tipo FontAttributes , cujo padrão é FontAtributes.None .
FontFamily do tipo string , cujo padrão é null .
FontSize do tipo double , cujo padrão é de -1,0.
Todas essas propriedades têm o respaldo BindableProperty objetos, o que significa que eles podem ser
estilizados e as propriedades podem ser alvos de vinculações de dados. O Time propriedade tem um modo de
associação padrão de BindingMode.TwoWay , que significa que ele pode ser um destino de associação de dados em
um aplicativo que usa o Model-View -ViewModel (MVVM ) arquitetura.
O TimePicker não inclui um evento para indicar um novo selecionado Time valor. Se você precisar ser notificado
sobre isso, você pode adicionar um manipulador para o PropertyChanged eventos.
Quando o Time propriedade é especificada no XAML, o valor é convertido em um TimeSpan e validadas para
garantir que o número de milissegundos é maior que ou igual a 0 e o número de horas é menor que 24. Os
componentes de tempo devem ser separados por dois-pontos:
Se o BindingContext propriedade do TimePicker é definido como uma instância de um ViewModel que contém
uma propriedade de tipo TimeSpan chamado SelectedTime (por exemplo), você pode criar uma instância o
TimePicker semelhante a esta:
Neste exemplo, o Time propriedade é inicializada para o SelectedTime propriedade no ViewModel. Porque o
Time propriedade tem um modo de associação da TwoWay , qualquer novo tempo em que o usuário selecionar
será propagado automaticamente para o ViewModel.
Se o TimePicker não contém uma associação em seu Time propriedade, um aplicativo deve anexar um
manipulador para o PropertyChanged eventos para ser informado quando o usuário seleciona um novo tempo.
Para obter informações sobre como definir propriedades de fonte, consulte fontes.
TimePicker e layout
É possível usar uma opção de layout horizontal irrestrito, como Center , Start , ou End com TimePicker :
<TimePicker ···
HorizontalOptions="Center"
··· />
No entanto, isso não é recomendado. Dependendo da configuração do Format propriedade, selecionada vezes
podem exigir que as larguras de exibição diferentes. Por exemplo, a cadeia de caracteres de formato "T" faz com
que o TimePicker exibir para exibir os tempos de em um formato longo e ": 15:26 4AM" requer uma maior
largura de exibição do formato de hora abreviada ("t") da ": 15 4AM". Dependendo da plataforma, essa diferença
pode causar a TimePicker exibição para alterar a largura de layout, ou para a exibição a ser truncado.
TIP
É melhor usar o padrão HorizontalOptions configuração do Fill com TimePicker e não deve usar uma largura de
Auto ao colocar TimePicker em um Grid célula.
TimePicker em um aplicativo
O SetTimer exemplo inclui TimePicker , Entry , e Switch modos de exibição em sua página. O TimePicker
pode ser usado para selecionar uma hora, e quando de tempo que ocorre uma caixa de diálogo de alerta é exibida
que lembra o usuário do texto na Entry , fornecido o Switch é ativado. Aqui está o arquivo XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:SetTimer"
x:Class="SetTimer.MainPage">
<StackLayout>
...
<Entry x:Name="_entry"
Placeholder="Enter event to be reminded of" />
<Label Text="Select the time below to be reminded at." />
<TimePicker x:Name="_timePicker"
Time="11:00:00"
Format="T"
PropertyChanged="OnTimePickerPropertyChanged" />
<StackLayout Orientation="Horizontal">
<Label Text="Enable timer:" />
<Switch x:Name="_switch"
HorizontalOptions="EndAndExpand"
Toggled="OnSwitchToggled" />
</StackLayout>
</StackLayout>
</ContentPage>
O permite que você insira o texto de lembrete que será exibido quando ocorre o tempo selecionado. O
Entry
TimePicker é atribuído um Format propriedade de "T" para o formato de hora longa. Ele tem um manipulador
de eventos anexado à PropertyChanged eventos e o Switch tem um manipulador anexado ao seu Toggled
eventos. Esses manipuladores de eventos estão no arquivo code-behind e chamada o SetTriggerTime método:
public MainPage()
{
InitializeComponent();
Device.StartTimer(TimeSpan.FromSeconds(1), OnTimerTick);
}
bool OnTimerTick()
{
if (_switch.IsToggled && DateTime.Now >= _triggerTime)
{
_switch.IsToggled = false;
DisplayAlert("Timer Alert", "The '" + _entry.Text + "' timer has elapsed", "OK");
}
return true;
}
void SetTriggerTime()
{
if (_switch.IsToggled)
{
_triggerTime = DateTime.Today + _timePicker.Time;
if (_triggerTime < DateTime.Now)
{
_triggerTime += TimeSpan.FromDays(1);
}
}
}
}
O SetTriggerTime método calcula um tempo de timer com base no DateTime.Today o valor da propriedade e o
TimeSpan valor retornado da TimePicker . Isso é necessário porque o DateTime.Today propriedade retorna um
DateTime que indica a data atual, mas com um tempo de meia-noite. Se já tiver passado tempo o temporizador
hoje em dia, em seguida, supõe-se para ser amanhã.
Os tiques do temporizador cada segundo, executando o OnTimerTick método que verifica se o Switch é sobre
como e se a hora atual é maior que ou igual ao tempo de temporizador. Quando ocorre o tempo de timer, o
DisplayAlert método apresenta uma caixa de diálogo de alerta para o usuário como um lembrete.
Quando o exemplo é executado pela primeira vez, o TimePicker exibição é inicializada como às 11h. Tocar o
TimePicker invoca o seletor de tempo de plataforma. As plataformas de implementam o seletor de hora em duas
maneiras diferentes, mas cada abordagem é familiar aos usuários da plataforma:
TIP
No Android, o TimePicker caixa de diálogo pode ser personalizada substituindo o CreateTimePickerDialog método em
um renderizador personalizado. Isso permite, por exemplo, botões adicionais a serem adicionados à caixa de diálogo.
Desde que o Switch seja alternado para a posição ligada, o aplicativo exibe uma caixa de diálogo alerta lembrar o
usuário do texto no Entry quando ocorre o tempo selecionado:
Assim que a caixa de diálogo de alerta é exibida, o Switch seja alternado para a posição off.
Links relacionados
Exemplo de SetTimer
TimePicker API
Visual do xamarin. Forms
12/04/2019 • 2 minutes to read
Baixar o exemplo
Design de material é um sistema de design "teimosa" criado pelo Google, que determina o tamanho, cor,
espaçamento e outros aspectos de como layouts e modos de exibição devem parecer e se comportam.
Material do xamarin. Forms Visual pode ser usado para aplicar regras de Design de Material para aplicativos
xamarin. Forms, criação de aplicativos que se parecem idênticos ou praticamente idênticas, no iOS e Android.
Quando o Visual de Material é habilitado, modos de exibição com suporte adotam a mesmo design
multiplataforma, criando uma aparência unificada. Isso é obtido com processadores de material, que se aplicam as
regras de Design de Material.
O processo para habilitar o xamarin. Forms Material Visual em seu aplicativo é:
1. Adicione a Xamarin.Forms.Visual.Material pacote do NuGet para seus projetos de plataforma Android e iOS.
Este pacote NuGet entrega otimizados renderizadores de Design de Material em iOS e Android. No iOS, o
pacote fornece a dependência transitiva Xamarin.iOS.MaterialComponents, que é um C# associação do Google
componentes do Material para iOS. No Android, o pacote fornece destinos de compilação para garantir que
seu TargetFramework está configurado corretamente.
2. Inicialize os renderizadores de material em cada projeto de plataforma. Para obter mais informações, consulte
inicializar renderizadores materiais.
3. Consumir os renderizadores de material, definindo o Visual propriedade Material em todas as páginas que
devem adotar as regras de Design de Material. Para obter mais informações, consulte consumir renderizadores
materiais.
4. [opcional] Personalize os renderizadores de material. Para obter mais informações, consulte personalizar
renderizadores materiais.
IMPORTANT
No Android, os renderizadores de material exigem a versão mínima do 5.0 (API 21) ou superior e um TargetFramework da
versão 9.0 (28 de API). Além disso, seu projeto de plataforma requer bibliotecas de suporte do Android 28.0.0 ou superior, e
seu tema precisa herdar de um tema de Material componentes ou continuar herdar de um tema AppCompat. Para obter
mais informações, consulte Introdução aos componentes de Material para Android.
global::Xamarin.Forms.Forms.Init();
FormsMaterial.Init();
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
FormsMaterial.Init(this, savedInstanceState);
<ContentPage Visual="Material"
...>
...
</ContentPage>
O código C# equivalente é:
O Visual propriedade pode ser definida como qualquer tipo que implemente IVisual , com o VisualMarker
classe que fornece o seguinte IVisual propriedades:
Default – indica que o modo de exibição deve ser renderizados usando o renderizador padrão.
MatchParent – indica que o modo de exibição deve usar o renderizador do mesmo como pai direto.
Material – indica que o modo de exibição deve ser renderizados usando um renderizador de material.
IMPORTANT
O Visual propriedade está definida no VisualElement classe, com modos de exibição herdando a Visual valor da
propriedade de seus pais. Portanto, definir a Visual propriedade em um ContentPage garante que todas as exibições
com suporte na página usarão esse elemento Visual. Além disso, o Visual propriedade pode ser substituída em uma
exibição.
As capturas de tela a seguir mostram uma interface do usuário renderizada usando os processadores de padrão:
As capturas de tela a seguir mostram a mesma interface do usuário renderizado usando os processadores de
materiais:
As principais diferenças visíveis entre os renderizadores de material, mostrados aqui e o renderizadores padrão
são os renderizadores de material em maiuscula Button texto e arredondar os cantos do Frame bordas. No
entanto, os renderizadores de material usam controles nativos e, portanto, ainda pode haver diferenças de
interface de usuário entre plataformas para áreas como sombras, fontes, cores e elevação.
NOTE
Componentes de Design de material risca diretrizes do Google. Como resultado, os renderizadores de Design de Material são
mais adequados para dimensionamento e o comportamento. Quando você precisar de maior controle dos estilos ou
comportamento, você ainda pode criar seus próprios efeito, comportamento, ou renderizador personalizado para alcançar o
detalhe que você precisa.
using Xamarin.Forms.Material.Android;
NOTE
Um renderizador que especifica um IVisual tipo, como parte da sua ExportRendererAttribute , será usado para
renderizar aceitado modos de exibição, em vez do renderizador padrão. Em tempo de seleção do renderizador, o Visual
propriedade do modo de exibição é inspecionada e incluída no processo de seleção do renderizador.
Para obter mais informações sobre renderizadores personalizados, consulte renderizadores personalizados.
Links relacionados
Material Visual (amostra)
Criar um renderizador Visual do xamarin. Forms
Renderizadores personalizados
Criar um renderizador Visual do xamarin. Forms
12/04/2019 • 6 minutes to read
Baixar o exemplo
Visual do xamarin. Forms permite renderizadores seja criada e aplicada seletivamente VisualElement objetos, sem
ter de exibições do xamarin. Forms subclasse. Um renderizador que especifica um IVisual tipo, como parte da
sua ExportRendererAttribute , será usado para renderizar aceitado modos de exibição, em vez do renderizador
padrão. Em tempo de seleção do renderizador, o Visual propriedade do modo de exibição é inspecionada e
incluída no processo de seleção do renderizador.
IMPORTANT
Atualmente, o Visual propriedade não pode ser alterada depois que o modo de exibição foi renderizado, mas isso será
alterado em uma versão futura.
if (e.OldElement != null)
{
// Cleanup
}
if (e.NewElement != null)
{
Control.TitleShadowOffset = new CoreGraphics.CGSize(1, 1);
Control.SetTitleShadowColor(Color.Black.ToUIColor(), UIKit.UIControlState.Normal);
}
}
}
Android
O exemplo de código a seguir mostra o renderizador do botão para Android:
if (e.OldElement != null)
{
// Cleanup
}
if (e.NewElement != null)
{
Control.SetShadowLayer(5, 3, 3, Color.Black.ToAndroid());
}
}
}
O CustomVisual tipo, em seguida, pode ser registrado em classes de renderizador, permitindo Button objetos a
serem optarem por usar os renderizadores.
Neste exemplo, o ExportRendererAttribute Especifica que o CustomButtonRenderer classe será usada para
renderizar consumindo Button objetos, com o IVisual tipo registrado como o terceiro argumento. Um
renderizador que especifica um IVisual tipo, como parte da sua ExportRendererAttribute , será usado para
renderizar aceitado modos de exibição, em vez do renderizador padrão.
<Button Visual="Custom"
Text="CUSTOM BUTTON"
BackgroundColor="{StaticResource PrimaryColor}"
TextColor="{StaticResource SecondaryTextColor}"
HorizontalOptions="FillAndExpand" />
NOTE
No XAML, um conversor de tipo remove a necessidade de incluir o sufixo "Visual" na Visual valor da propriedade. No
entanto, o nome de tipo completo também pode ser especificado.
O código c# equivalente é:
O IVisual tipo pode ser consumido por meio de seu nome registrado:
<Button Visual="MyVisual"
... />
NOTE
Ao consumir um Visual por meio de seu nome registrado, qualquer sufixo "Visual" deve ser incluído.
Links relacionados
Material Visual (amostra)
Material do xamarin. Forms Visual
Renderizadores personalizados
O xamarin. Forms Visual State Manager
12/04/2019 • 27 minutes to read
baixar o exemplo
Use o Gerenciador de estado Visual para fazer alterações em elementos XAML com base em estados visuais
definido no código.
O Gerenciador de VSM (Visual State) é nova no xamarin. Forms 3.0. O VSM fornece uma maneira estruturada
para fazer alterações visual para a interface do usuário do código. Na maioria dos casos, a interface do usuário
do aplicativo é definida em XAML, e este XAML inclui a marcação que descreve como o Gerenciador de estado
Visual afeta os visuais da interface do usuário.
O VSM apresenta o conceito de estados visuais. Um modo de exibição do xamarin. Forms, como um Button
pode ter várias aparências diferentes dependendo do seu estado subjacente — se ele estiver desabilitado, ou
pressionado ou se tem o foco de entrada. Esses são os estados do botão.
Estados visuais são coletados no grupos de estado visual. Todos os estados visuais dentro de um grupo de
estado visual são mutuamente exclusivos. Estados visuais e grupos de estado visual são identificados por
cadeias de caracteres de texto simples.
O Gerenciador de estado Visual do xamarin. Forms define um grupo de estado visual chamado
"CommonStates" com três estados visuais:
"Normal"
"Desabilitado"
"Com foco"
Há suporte para esse grupo de estados visuais para todas as classes que derivam de VisualElement , que é a
classe base para View e Page .
Você também pode definir seus próprios grupos de estado visual e os estados visuais, como este artigo irá
demonstrar.
NOTE
Os desenvolvedores de xamarin. Forms familiarizados com gatilhos estão cientes de que os gatilhos também podem fazer
alterações aos visuais na interface do usuário com base em alterações em Propriedades da exibição ou o acionamento de
eventos. No entanto, usando gatilhos para lidar com várias combinações dessas alterações pode se tornar bastante
confuso. Historicamente, o Gerenciador de estado Visual foi introduzido em ambientes baseados em XAML do Windows
para minimizar a confusão resultante de combinações de estados visuais. Os estados visuais dentro de um grupo de
estado visual com o VSM, sempre são mutuamente exclusivos. A qualquer momento, apenas um estado em cada grupo é
o estado atual.
Os estados comuns
O Gerenciador de estado Visual permite que você inclua seções no arquivo XAML que pode alterar a aparência
visual de um modo de exibição, se o modo de exibição é normal ou desabilitado ou se tiver o foco de entrada.
Eles são conhecidos como o estados comuns.
Por exemplo, suponha que você tenha um Entry modo de exibição em sua página, e você deseja que a
aparência visual do Entry alterar das seguintes maneiras:
O Entry deve ter uma rosa em segundo plano quando o Entry está desabilitado.
O Entry deve ter um plano de fundo verde-limão normalmente.
O Entry deve expandir para duas vezes sua altura normal quando ele tem foco de entrada.
Você pode anexar a marcação VSM a uma exibição individual, ou você pode defini-la em um estilo se apliquem
a vários modos de exibição. As duas próximas seções descrevem essas abordagens.
Marcação VSM em uma exibição
Anexar marcação VSM para um Entry exibir, primeiro separe o Entry nas marcas de início e término:
<Entry FontSize="18">
</Entry>
Isso tenha dado a um tamanho de fonte explícito porque um dos Estados usará o FontSize propriedade para
dobrar o tamanho do texto no Entry .
Em seguida, inserir VisualStateManager.VisualStateGroups marcas entre essas marcas:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
</VisualStateManager.VisualStateGroups>
</Entry>
VisualStateGroups é uma propriedade associável anexada definida pelo VisualStateManager classe. (Para obter
mais informações sobre propriedades vinculáveis anexadas, consulte o artigo propriedades anexadas.) Isso é
como o VisualStateGroups propriedade está anexada a Entry objeto.
O VisualStateGroups propriedade é do tipo VisualStateGroupList , que é uma coleção de VisualStateGroup
objetos. Dentro de VisualStateManager.VisualStateGroups marcas, inserir um par de VisualStateGroup marcas
para cada grupo de estados visuais que deseja incluir:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Observe que o VisualStateGroup marca tem um x:Name atributo que indica o nome do grupo. O
VisualStateGroup classe define um Name propriedade que você pode usar em vez disso:
<VisualStateGroup Name="CommonStates">
Você pode usar tanto x:Name ou Name , mas não ambos no mesmo elemento.
O VisualStateGroup classe define uma propriedade chamada States , que é uma coleção de VisualState
objetos. States é o propriedade de conteúdo dos VisualStateGroups para que você possa incluir o
VisualState marcas diretamente entre o VisualStateGroup marcas. ( Conteúdo de propriedades são discutidas
no artigo sintaxe de XAML essencial.)
A próxima etapa é incluir um par de marcas para cada estado visual nesse grupo. Eles também podem ser
identificados usando x:Name ou Name :
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
</VisualState>
<VisualState x:Name="Focused">
</VisualState>
<VisualState x:Name="Disabled">
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
VisualStatedefine uma propriedade chamada Setters , que é uma coleção de Setter objetos. Essas são as
mesmas Setter objetos que podem ser usados em um Style objeto.
Setters está não a propriedade content de VisualState , portanto, é necessário incluir marcas de elemento de
propriedade para o Setters propriedade:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Agora você pode inserir um ou mais Setter objetos entre cada par de Setters marcas. Esses são os Setter
objetos que definem os estados visuais descritos anteriormente:
<Entry FontSize="18">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Entry>
Cada Setter marca indica o valor de uma propriedade específica quando esse estado é atual. Qualquer
propriedade referenciada por uma Setter objeto deve ser feito por uma propriedade associável.
Marcação semelhante a esta é a base para o VSM na exibição página na VsmDemos programa de exemplo.
A página inclui três Entry modos de exibição, mas apenas um segundo tem a marcação VSM anexada a ele:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:VsmDemos"
x:Class="VsmDemos.MainPage"
Title="VSM Demos">
<StackLayout>
<StackLayout.Resources>
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
</Style>
<Style TargetType="Label">
<Setter Property="Margin" Value="20, 30, 20, 0" />
<Setter Property="FontSize" Value="Large" />
</Style>
</StackLayout.Resources>
<Entry />
<Entry>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Entry.Triggers>
<DataTrigger TargetType="Entry"
Binding="{Binding Source={x:Reference entry3},
Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
<Entry x:Name="entry3"
Text=""
Placeholder="Type something to enable 2nd Entry" />
</StackLayout>
</ContentPage>
Observe que a segunda Entry também tem um DataTrigger como parte de seu Trigger coleção. Isso faz
com que o Entry será desabilitada até que algo seja digitado à terceira Entry . Aqui está a página na
inicialização em execução no iOS, Android e Universal Windows Platform (UWP ):
O estado visual atual é "Disabled" para que o plano de fundo do segundo Entry é rosa em telas de Android e
iOS. A implementação de UWP do Entry não permite definir o plano de fundo de cor quando o Entry está
desabilitado.
Quando você digitar um texto à terceira Entry , o segundo Entry alterna para o estado "Normal" e o plano de
fundo agora está verde-limão:
Quando você tocar o segundo Entry , ele obtém o foco de entrada. Ele muda para o estado de "Focalizado" e se
expande para duas vezes sua altura:
Observe que o Entry não retém o plano de fundo verde-limão quando ele recebe o foco de entrada. Como o
Gerenciador de estado Visual alterna entre os estados visuais, as propriedades definidas pelo estado anterior
são não definidas. Tenha em mente que os estados visuais são mutuamente exclusivos. O estado "Normal" não
significa apenas que o Entry está habilitado. Isso significa que o Entry está habilitado e não tem o foco de
entrada.
Se você quiser que o Entry para ter um plano de fundo verde-limão em estado "Focalizado", adicione outro
Setter para que o estado visual:
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
Para que eles Setter objetos funcione corretamente, um VisualStateGroup deve conter VisualState objetos
para todos os estados no grupo. Se não houver um estado visual que não tem nenhum Setter objetos, incluí-
lo mesmo assim como uma marca vazia:
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
</Style>
</Setter>
</Style>
A propriedade de conteúdo para Setter está Value , portanto, o valor da Value propriedade pode ser
especificada diretamente dentro de marcas. Se a propriedade é do tipo VisualStateGroupList :
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Entry">
<Setter Property="Margin" Value="20, 0" />
<Setter Property="FontSize" Value="18" />
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Focused">
<VisualState.Setters>
<Setter Property="FontSize" Value="36" />
<Setter Property="BackgroundColor" Value="Lime" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Property="BackgroundColor" Value="Pink" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<Style TargetType="Label">
<Setter Property="Margin" Value="20, 30, 20, 0" />
<Setter Property="FontSize" Value="Large" />
</Style>
</StackLayout.Resources>
<Entry />
<Entry>
<Entry.Triggers>
<DataTrigger TargetType="Entry"
Binding="{Binding Source={x:Reference entry3},
Path=Text.Length}"
Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
<Entry x:Name="entry3"
Text=""
Placeholder="Type something to enable 2nd Entry" />
</StackLayout>
</ContentPage>
Agora todos os Entry exibições nesta página respondem da mesma maneira para seus estados visuais.
Observe também que o estado "Focalizado" inclui agora uma segunda Setter que dá a cada Entry um verde-
limão em segundo plano também quando ele tem o foco de entrada:
VisualStateManager.GoToState(this, "Focused");
Isso é o único código do Gerenciador de estado Visual que você encontrará o VisualElement classe. Porque
GoToState é chamado para cada objeto com base em cada classe que deriva de VisualElement , você pode usar
o Gerenciador de estado Visual com qualquer VisualElement objeto para responder a essas alterações.
Curiosamente, o nome do grupo de estados visuais "CommonStates" não é explicitamente referenciado nos
VisualElement . O nome do grupo não é parte da API para o Gerenciador de estado Visual. Dentro de um a
dois programa de exemplo mostrado até agora, você pode alterar o nome do grupo de "CommonStates" para
qualquer outra coisa, e o programa ainda funcionará. O nome do grupo é meramente uma descrição geral dos
estados no grupo. É implicitamente entendido que os estados visuais em qualquer grupo são mutuamente
exclusivos: uma e apenas um estado é atual a qualquer momento.
Se você quiser implementar seus próprios estados visuais, você precisará chamar
VisualStateManager.GoToState do código. Geralmente, você fará essa chamada do arquivo code-behind da sua
classe de página.
O VSM validação página de VsmDemos exemplo mostra como usar o Gerenciador de estado Visual em
conexão com a validação de entrada. O arquivo XAML consiste em dois Label elementos, uma Entry , e
Button :
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmValidationPage"
Title="VSM Validation">
<StackLayout Padding="10, 10">
<Entry Placeholder="555-555-5555"
FontSize="Large"
Margin="30, 0, 0, 0"
TextChanged="OnTextChanged" />
<Label x:Name="helpLabel"
Text="Phone number must be of the form 555-555-5555, and not begin with a 0 or 1">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValidityStates">
<VisualState Name="Valid">
<VisualState.Setters>
<Setter Property="TextColor" Value="Transparent" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Label>
<Button x:Name="submitButton"
Text="Submit"
FontSize="Large"
Margin="0, 20"
VerticalOptions="Center"
HorizontalOptions="Center">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValidityStates">
<VisualState Name="Invalid">
<VisualState.Setters>
<Setter Property="IsEnabled" Value="False" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Button>
</StackLayout>
</ContentPage>
Marcação VSM está anexada à segunda Label (chamado helpLabel ) e o Button (chamado submitButton ). Há
dois estados mutuamente exclusivas, chamados de "Válido" e "Inválido". Observe que cada um dos dois grupos
de "ValidationState" contém VisualState marcas para "Válido" e "Inválido", embora um deles está vazio em
cada caso.
Se o Entry não contém um número de telefone válido, em seguida, o estado atual é "Inválido" e, portanto, a
segunda Label está visível e o Button está desabilitado:
Quando um número de telefone válido for inserido, em seguida, o estado atual se torna "Válido". A segunda
Entry desaparece e a Button agora está habilitado:
GoToState(false);
}
Observe também que o GoToState método é chamado de construtor para inicializar o estado. Sempre deve
haver um estado atual. Mas não no código há qualquer referência ao nome do grupo de estados visuais,
embora ela é referenciada no XAML como "ValidationStates" para fins de clareza.
Observe que o arquivo code-behind deve levar em conta todos os objetos na página que é afetada por esses
estados visuais e chamar VisualStateManager.GoToState para cada um desses objetos. Neste exemplo, ele é
apenas dois objetos (o Label e o Button ), mas poderia ser vários mais.
Você talvez esteja se perguntando: se o arquivo code-behind deve fazer referência a todos os objetos na página
que é afetado por esses estados visuais, por que não o arquivo code-behind simplesmente acessar os objetos
diretamente? Obviamente, foi possível. No entanto, a vantagem de usar o VSM é que você pode controlar os
elementos visuais como reagir a estado diferente inteiramente em XAML, que mantém todos o design de
interface do usuário em um único local. Isso evita a aparência visual de configuração por meio de acessar
elementos visuais diretamente no code-behind.
Pode ser tentador considere derivar uma classe de Entry e talvez definindo uma propriedade que você pode
definir uma função externa de validação. A classe que deriva de Entry , em seguida, pode chamar o
VisualStateManager.GoToState método. Esse esquema funcionaria bem, mas somente se o Entry foram o único
objeto afetado pelos estados visuais diferentes. Neste exemplo, uma Label e um Button também são
afetados. Não é possível para marcação VSM anexados a um Entry para controlar outros objetos na página e
nenhuma maneira para marcação VSM anexados a esses outros objetos para fazer referência a uma alteração
de estado visual de outro objeto.
No modo paisagem, a matriz de botões pode ser movida para um lado e exibida em uma coluna:
De cima para baixo, o programa está em execução a plataforma Universal do Windows, Android e iOS.
O Layout adaptável do VSM página de VsmDemos exemplo define um grupo chamado "OrientationStates"
com dois estados visuais denominados "Retrato" e "Paisagem". (Uma abordagem mais complexa pode ser
baseada em várias larguras de página ou janela diferentes).
Marcação VSM ocorre em quatro lugares no arquivo XAML. O StackLayout nomeado mainStack contém o
menu e o conteúdo, que é um Image elemento. Isso StackLayout deve ter uma orientação vertical no modo
retrato e uma orientação horizontal no modo paisagem:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="VsmDemos.VsmAdaptiveLayoutPage"
Title="VSM Adaptive Layout">
<StackLayout x:Name="mainStack">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ScrollView x:Name="menuScroll">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackLayout x:Name="menuStack">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="Orientation" Value="Horizontal" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="Orientation" Value="Vertical" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<StackLayout.Resources>
<Style TargetType="Button">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup Name="OrientationStates">
<VisualState Name="Portrait">
<VisualState Name="Portrait">
<VisualState.Setters>
<Setter Property="HorizontalOptions" Value="CenterAndExpand" />
<Setter Property="Margin" Value="10, 5" />
</VisualState.Setters>
</VisualState>
<VisualState Name="Landscape">
<VisualState.Setters>
<Setter Property="VerticalOptions" Value="CenterAndExpand" />
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="Margin" Value="10" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</StackLayout.Resources>
<Button Text="Banana"
Command="{Binding SelectedCommand}"
CommandParameter="Banana.jpg" />
<Button Text="Monkey"
Command="{Binding SelectedCommand}"
CommandParameter="monkey.png" />
<Image x:Name="image"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand" />
</StackLayout>
</ContentPage>
menuStack.BindingContext = this;
}
Pode parecer como se o arquivo code-behind pode lidar com alterações de orientação mais diretamente,
definindo as propriedades dos elementos no arquivo XAML, mas o Gerenciador de estado Visual é
definitivamente uma abordagem mais estruturada. Todos os elementos visuais são mantidos no arquivo XAML,
onde eles se tornam mais fácil de examinar, manutenção e modificar.
Links relacionados
VsmDemos
WebView do xamarin. Forms
12/04/2019 • 18 minutes to read
baixar o exemplo
WebView é um modo de exibição da web e o conteúdo HTML em seu aplicativo. Diferentemente OpenUri , que
leva o usuário para o navegador da web no dispositivo, WebView exibe o conteúdo HTML dentro de seu
aplicativo.
Conteúdo
WebView suporta os seguintes tipos de conteúdo:
Sites HTML e CSS – WebView tem suporte completo para sites da Web escritos usando HTML e CSS,
incluindo suporte a JavaScript.
Documentos – como WebView é implementado usando componentes nativos em cada plataforma, WebView
é capaz de mostrar os documentos que podem ser exibidos em cada plataforma. Isso significa que os arquivos
PDF funcionam no iOS e Android.
Cadeias de caracteres HTML – WebView pode mostrar cadeias de caracteres HTML da memória.
Arquivos locais – WebView pode apresentar qualquer um dos tipos de conteúdo acima inserido no aplicativo.
NOTE
WebView no Windows não oferece suporte do Silverlight, Flash ou todos os controles ActiveX, mesmo se eles são
suportados pelo Internet Explorer nessa plataforma.
Sites
Para exibir um site da internet, defina as WebView do Source propriedade como uma cadeia de caracteres de URL:
var browser = new WebView
{
Source = "http://xamarin.com"
};
NOTE
URLs devem ser totalmente formadas com o protocolo especificado (ou seja, ele deve ter "http://" ou "https://" acrescentado
a ele).
iOS e ATS
Desde a versão 9, iOS só permitirá que seu aplicativo para se comunicar com servidores que implementam as
práticas recomendadas de segurança por padrão. Valores devem ser definidos Info.plist para habilitar a
comunicação com servidores inseguros.
NOTE
Se seu aplicativo requer uma conexão em um site inseguro, você sempre deve inserir o domínio como uma exceção usando
NSExceptionDomains em vez de como o ATS desativar completamente usando NSAllowsArbitraryLoads .
NSAllowsArbitraryLoads só deve ser usado em situações extremas de emergências.
O exemplo a seguir demonstra como habilitar um domínio específico (em xamarin.com neste caso) para ignorar
os requisitos de ATS:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>xamarin.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
...
</key>
É uma prática recomendada para permitir que somente alguns domínios ignorar a ATS, permitindo que você use
sites confiáveis enquanto se beneficia com a segurança adicional em domínios não confiáveis. O exemplo a seguir
demonstra o método menos seguro de desabilitar o ATS para o aplicativo:
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
...
</key>
Ver segurança de transporte de aplicativo para obter mais informações sobre esse novo recurso no iOS 9.
Cadeias de caracteres HTML
Se você quiser apresentar uma cadeia de caracteres de HTML definida dinamicamente no código, você precisará
criar uma instância do HtmlWebViewSource :
No código acima, @ é usado para marcar o HTML como uma cadeia de caracteres literal, o que significa que
todos os caracteres de escape comuns são ignorados.
Conteúdo HTML local
WebView pode exibir o conteúdo do HTML, CSS e Javascript inserido dentro do aplicativo. Por exemplo:
<html>
<head>
<title>Xamarin Forms</title>
</head>
<body>
<h1>Xamrin.Forms</h1>
<p>This is an iOS web page.</p>
<img src="XamarinLogo.png" />
</body>
</html>
CSS:
html,body {
margin:0;
padding:10;
}
body,p,h1 {
font-family: Chalkduster;
}
Observe que as fontes especificadas no CSS acima precisará ser personalizado para cada plataforma, pois nem
todas as plataforma tem as mesmas fontes.
Para exibição local conteúdo usando um WebView , você precisará abrir o arquivo HTML como qualquer outro e,
em seguida, carregar o conteúdo como uma cadeia de caracteres para o Html propriedade de um
HtmlWebViewSource . Para obter mais informações sobre a abertura de arquivos, consulte trabalhando com
arquivos.
As capturas de tela a seguir mostram o resultado de exibição de conteúdo local em cada plataforma:
Embora a primeira página é carregada, o WebView não tem conhecimento de onde veio o HTML. Isso é um
problema ao lidar com páginas que fazem referência a recursos locais. Quando o link de páginas locais aos
outros, uma página faz uso de um arquivo JavaScript separado ou uma página contém links para uma folha de
estilos CSS são exemplos de quando isso pode acontecer.
Para resolver isso, você precisa informar o WebView onde localizar os arquivos no sistema de arquivos. Fazer isso
definindo a BaseUrl propriedade em de HtmlWebViewSource usado pelo WebView .
Como o sistema de arquivos em cada um dos sistemas operacionais é diferente, você precisa determinar essa
URL em cada plataforma. Xamarin. Forms expõe a DependencyService para resolução de dependências em tempo
de execução em cada plataforma.
Para usar o DependencyService , primeiro defina uma interface que pode ser implementada em cada plataforma:
Observe que, até que a interface é implementada em cada plataforma, o aplicativo não será executado. No projeto
comuns, certifique-se de que você se lembrar de definir a BaseUrl usando o DependencyService :
Android
No Android, coloque o HTML, CSS e imagens na pasta ativos com a ação de build AndroidAsset como
demonstrado a seguir:
Visual Studio
Visual Studio para Mac
No Android, arquivos de ativos pasta também pode ser acessada por meio do contexto Android atual, que é
exposto pelo MainActivity.Instance propriedade:
[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
public class BaseUrl : IBaseUrl
{
public string Get()
{
return "ms-appx-web:///";
}
}
}
Navegação
WebView dá suporte à navegação por meio de vários métodos e propriedades que ele se torna disponível:
GoForward() – se CanGoForward for true, chamar GoForward navega para a próxima página visitada.
GoBack() – se CanGoBack for true, chamar GoBack navegará para a última página visitada.
CanGoBack – true se não houver páginas para navegar de volta para false se o navegador é a URL inicial.
CanGoForward – true se o usuário navegar para trás e avance até uma página que já foi visitada.
Em páginas, WebView não oferece suporte a gestos multitoque. É importante para garantir que o conteúdo é
otimizada para celular e é exibido sem a necessidade de aumentar o zoom.
É comum para aplicativos mostrar um link dentro de um WebView , em vez do navegador do dispositivo. Nessas
situações, é útil permitir a navegação normal, mas quando o usuário optou novamente enquanto estiverem no
link inicial, o aplicativo deve retornar ao modo de exibição normal do aplicativo.
Use as propriedades e métodos de navegação interna para habilitar esse cenário.
Comece criando a página para o modo de exibição do navegador:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.InAppBrowserXaml"
Title="Browser">
<StackLayout Margin="20">
<StackLayout Orientation="Horizontal">
<Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
<Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
</StackLayout>
<!-- WebView needs to be given height and width request within layouts to render. -->
<WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
</StackLayout>
</ContentPage>
No code-behind:
public partial class InAppBrowserXaml : ContentPage
{
public InAppBrowserXaml(string URL)
{
InitializeComponent();
webView.Source = URL;
}
É só isso!
Eventos
WebView aciona os eventos a seguir para ajudá-lo a responder a alterações no estado:
Navigating – Evento gerado quando o WebView começa a carregar uma nova página.
Navigated – Evento gerado quando a página é carregada e navegação foi interrompido.
ReloadRequested – Evento gerado quando uma solicitação é feita para recarregar o conteúdo atual.
O WebNavigatingEventArgs objeto que acompanha o Navigating eventos tem quatro propriedades:
Cancel – Indica se deve ou não cancelar a navegação.
NavigationEvent – o evento de navegação que foi gerado.
Source – o elemento que executou a navegação.
Url – o destino de navegação.
Se você antecipar o uso de páginas da Web que levam muito tempo para carregar, considere usar o Navigating e
Navigated eventos para implementar um indicador de status. Por exemplo:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.LoadingLabelXaml"
Title="Loading Demo">
<StackLayout>
<!--Loading label should not render by default.-->
<Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
<WebView HeightRequest="1000" WidthRequest="1000" Source="http://www.xamarin.com"
Navigated="webviewNavigated" Navigating="webviewNavigating" />
</StackLayout>
</ContentPage>
Quando o Reload método é invocado o ReloadRequested evento é acionado, o que indica que uma solicitação foi
feita para recarregar o conteúdo atual.
Desempenho
Os navegadores da web populares agora adotam tecnologias, como a compilação de JavaScript e renderização
acelerada por hardware. No iOS, por padrão, o xamarin. Forms WebView é implementado pelo UIWebView classe e
várias dessas tecnologias não estão disponíveis nesta implementação. No entanto, um aplicativo pode participar
de uso do iOS WkWebView classe para implementar o xamarin. Forms WebView , que dá suporte à navegação mais
rápida. Isso pode ser feito adicionando o seguinte código para o AssemblyInfo.cs arquivo no projeto da
plataforma iOS para o aplicativo:
Permissões
Para que WebView para trabalhar, certifique-se de que as permissões são definidas para cada plataforma. Observe
que, em algumas plataformas, WebView funcionará no modo de depuração, mas não quando compilado para
versão. Isso ocorre porque algumas permissões, como aqueles para acesso à internet no Android, são definidos
por padrão pelo Visual Studio para Mac quando no modo de depuração.
UWP – exige a funcionalidade de Internet (cliente e servidor), ao exibir o conteúdo de rede.
Android – requer INTERNET apenas ao exibir o conteúdo da rede. Conteúdo local não requer nenhuma
permissão especial.
iOS – não exige nenhuma permissão especial.
Layout
Ao contrário da maioria dos outros modos de xamarin. Forms WebView exige que HeightRequest e WidthRequest
são especificados quando contido em StackLayout ou RelativeLayout. Se você não especificar essas propriedades,
o WebView não será renderizado.
Os exemplos a seguir demonstram os layouts que resultam em funcionamento, renderização WebView s:
StackLayout com WidthRequest & HeightRequest:
<StackLayout>
<Label Text="test" />
<WebView Source="http://www.xamarin.com/"
HeightRequest="1000"
WidthRequest="1000" />
</StackLayout>
<RelativeLayout>
<Label Text="test"
RelativeLayout.XConstraint= "{ConstraintExpression
Type=Constant, Constant=10}"
RelativeLayout.YConstraint= "{ConstraintExpression
Type=Constant, Constant=20}" />
<WebView Source="http://www.xamarin.com/"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
Constant=10}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
Constant=50}"
WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>
<AbsoluteLayout>
<Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
<WebView Source="http://www.xamarin.com/"
AbsoluteLayout.LayoutBounds="0,150,500,500" />
</AbsoluteLayout>
Grade sem WidthRequest & HeightRequest. A grade é um dos layouts de alguns que não exigem a especificação
de larguras e alturas solicitadas.:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="test" Grid.Row="0" />
<WebView Source="http://www.xamarin.com/" Grid.Row="1" />
</Grid>
Invocação de JavaScript
WebView inclui a capacidade de invocar uma função de JavaScript do C#e retornar qualquer resultado para a
chamada C# código. Isso é feito com o WebView.EvaluateJavaScriptAsync método, que é mostrado no exemplo a
seguir do WebView exemplo:
<html>
<body>
<script type="text/javascript">
function factorial(num) {
if (num === 0 || num === 1)
return 1;
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
return num;
}
</script>
</body>
</html>
Links relacionados
Trabalhando com WebView (amostra)
WebView (amostra)
Recursos da plataforma xamarin. Forms
12/04/2019 • 2 minutes to read
Xamarin. Forms é extensível e permite que você incorpore recursos específicos à plataforma usando efeitos,
renderizadores personalizados, o DependencyService, o MessagingCentere muito mais.
Android
Este guia descreve as Android-especificidades da plataforma fornecidas pelo xamarin. Forms e como implementar
o Design de Material Atualizando aplicativos existentes do Android do xamarin. Forms.
Classe de dispositivo
Como usar o Device classe para criar o comportamento específico de plataforma em código compartilhado e a
interface do usuário (incluindo usando XAML ). Também aborda BeginInvokeOnMainThread que é essencial ao
modificar controles de interface do usuário de threads em segundo plano.
iOS
Este guia descreve as iOS -especificidades da plataforma fornecidas pelo xamarin. Forms e como executar
adicionais criando estilos por meio do iOS Info. plist e o UIAppearance API.
Formulários nativos
Formulários nativos permitem que o xamarin. Forms ContentPage -derivado de páginas a ser consumido por
projetos nativos do xamarin. IOS, xamarin. Android e plataforma Universal do Windows (UWP ).
Exibições nativas
Exibições nativas do iOS, Android e plataforma Universal do Windows podem ser referenciadas diretamente do
xamarin. Forms. Propriedades e os manipuladores de eventos podem ser definidos em exibições nativas e eles
podem interagir com exibições do xamarin. Forms.
Especificidades da plataforma
Especificidades da plataforma permitem que você consumir funcionalidade só está disponível em uma plataforma
específica, sem a necessidade de renderizadores personalizados ou efeitos. Além disso, os fornecedores podem
criar seus próprios itens específicos à plataforma com efeitos.
Windows
Este guia descreve as Windows-especificidades da plataforma fornecidas pelo xamarin. Forms e como adicionar
um projeto UWP a uma solução xamarin. Forms existente.
Recursos da plataforma Android
12/04/2019 • 5 minutes to read
Desenvolvimento de aplicativos xamarin. Forms para Android requer o Visual Studio. O página de requisitos
contém mais informações sobre os pré-requisitos.
Especificidades da plataforma
Especificidades da plataforma permitem que você consumir funcionalidade só está disponível em uma plataforma
específica, sem implementar renderizadores personalizados ou efeitos.
A seguinte funcionalidade específica da plataforma é fornecida para modos de exibição, páginas e layouts no
Android do xamarin. Forms:
Controlando a ordem Z dos elementos visuais para determinar a ordem de desenho. Para obter mais
informações, consulte VisualElement elevação no Android.
Desabilitar o modo de cor herdados em um com suporte VisualElement . Para obter mais informações,
consulte modo de cor VisualElement herdado no Android.
A seguinte funcionalidade específica da plataforma é fornecida para modos de exibição do xamarin. Forms no
Android:
Usando o preenchimento padrão e os valores de sombra dos botões do Android. Para obter mais informações,
consulte sombras no Android e o preenchimento do botão.
Configurando o método de entrada opções do editor para o teclado virtual para um Entry . Para obter mais
informações, consulte opções do Editor de método de entrada de entrada no Android.
Habilitando uma sombra em um ImageButton . Para obter mais informações, consulte ImageButton Drop
sombras no Android.
Habilitar a rolagem rápida em um ListView para obter mais informações, consulte ListView rolagem rápida
no Android.
Controlar se uma WebView pode exibir o conteúdo misto. Para obter mais informações, consulte WebView
misto conteúdo no Android.
A seguinte funcionalidade específica da plataforma é fornecida para páginas do xamarin. Forms no Android:
Definir a altura da barra de navegação em um NavigationPage . Para obter mais informações, consulte
NavigationPage altura da barra no Android.
Desabilitar animações de transição ao navegar entre páginas em um TabbedPage . Para obter mais
informações, consulte animações de transição de página TabbedPage no Android.
Habilitando o dedo entre páginas em um TabbedPage . Para obter mais informações, consulte TabbedPage
página passar o dedo no Android.
Definir o posicionamento da barra de ferramentas e a cor em um TabbedPage . Para obter mais informações,
consulte TabbedPage posicionamento de barra de ferramentas e a cor no Android.
A seguinte funcionalidade específica da plataforma é fornecida para o xamarin. Forms Application classe no
Android:
Definindo o modo de operação de um teclado virtual. Para obter mais informações, consulte reversível modo
de entrada de teclado no Android.
Desabilitando o Disappearing e Appearing página eventos de ciclo de vida em pausa e retomar,
respectivamente, para aplicativos que usam AppCompat. Para obter mais informações, consulte eventos de
ciclo de vida da página no Android.
Suporte de plataforma
Originalmente, o projeto do Android do xamarin. Forms padrão usado um estilo mais antigo de renderização de
controle do que era comum antes do Android 5.0. Aplicativos criados usando o modelo tem
FormsApplicationActivity como a classe base da sua atividade principal.
E isso é o mesmo código depois de atualizar o projeto para usar FormsAppCompatActivity (e adicionar as
informações de tema adicionais):
NOTE
Ao usar FormsAppCompatActivity , o classes de base para alguns renderizadores personalizados Android será diferente.
Links relacionados
Adicionar suporte de Design de Material
Adicionando AppCompat e Design de Material
12/04/2019 • 4 minutes to read
Siga estas etapas para converter aplicativos existentes do Android do xamarin. Forms para usar AppCompat e
Design de Material
Visão geral
Estas instruções explicam como atualizar seus aplicativos existentes do Android do xamarin. Forms para usar a
biblioteca AppCompat e habilitar o Design de Material na versão Android de seus aplicativos xamarin. Forms.
1. Atualizar o xamarin. Forms
Certifique-se de que a solução está usando o xamarin. Forms 2.0 ou mais recente. Atualize o pacote Nuget do
xamarin. Forms para 2.0, se necessário.
2. Verificar a versão do Android
Verifique se a que estrutura de destino do projeto Android é o Android 6.0 (Marshmallow ). Verifique a projeto
Android > Opções > Build > geral configurações para garantir que o framework corrent está selecionada:
<resources>
<color name="primary">#2196F3</color>
<color name="primaryDark">#1976D2</color>
<color name="accent">#FFC107</color>
<color name="window_background">#F5F5F5</color>
</resources>
Resources/values/style.xml
<resources>
<style name="MyTheme" parent="MyTheme.Base">
</style>
<style name="MyTheme.Base" parent="Theme.AppCompat.Light.NoActionBar">
<item name="colorPrimary">@color/primary</item>
<item name="colorPrimaryDark">@color/primaryDark</item>
<item name="colorAccent">@color/accent</item>
<item name="android:windowBackground">@color/window_background</item>
<item name="windowActionModeOverlay">true</item>
</style>
</resources>
Um estilo adicionais deve ser incluído na v21 valores pasta para aplicar as propriedades específicas ao executar
no Android Lollipop e mais recentes.
Resources/values-v21/style.xml
<resources>
<style name="MyTheme" parent="MyTheme.Base">
<!--If you are using MasterDetailPage you will want to set these, else you can leave them out-->
<!--<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>-->
</style>
</resources>
4. Update AndroidManifest.xml
Para garantir que esse novo tema informações são usado, definido tema na AndroidManifest arquivo
adicionando android:theme="@style/MyTheme" (deixe o restante do XML como ele era).
Properties/AndroidManifest.xml
...
<application android:label="AppName" android:icon="@drawable/icon"
android:theme="@style/MyTheme">
...
<android.support.design.widget.TabLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/sliding_tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:tabIndicatorColor="@android:color/white"
app:tabGravity="fill"
app:tabMode="fixed" />
Algumas propriedades para as guias foram definidas incluindo a gravidade da guia para fill e o modo para
fixed . Se você tiver várias guias você talvez queira mudar isso para rolável - ler por meio do Android TabLayout
documentação para saber mais.
Resources/layout/Toolbar.axml
<android.support.v7.widget.Toolbar
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_scrollFlags="scroll|enterAlways" />
Esses arquivos, estamos criando um tema específico para a barra de ferramentas que pode variar para seu
aplicativo. Consulte a barra de ferramentas Hello postagem de blog para saber mais.
6. Atualização do MainActivity
Em aplicativos do xamarin. Forms existentes a MainActivity.cs classe herda FormsApplicationActivity . Isso deve
ser substituído por FormsAppCompatActivity para habilitar a nova funcionalidade.
MainActivity.cs
Por fim, "conectar" novos layouts da etapa 5 no OnCreate método, conforme mostrado aqui:
Baixar o exemplo
Este específicos da plataforma Android controla se os botões do xamarin. Forms usam o preenchimento padrão e
os valores de sombra dos botões do Android. Ele é consumido em XAML, definindo o Button.UseDefaultPadding e
Button.UseDefaultShadow propriedades para anexadas boolean valores:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
...
<Button ...
android:Button.UseDefaultPadding="true"
android:Button.UseDefaultShadow="true" />
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
button.On<Android>().SetUseDefaultPadding(true).SetUseDefaultShadow(true);
O Button.On<Android> método Especifica que este específicos da plataforma serão executado apenas no Android.
O Button.SetUseDefaultPadding e Button.SetUseDefaultShadow métodos, no
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, são usadas para controlar se os botões de
xamarin. Forms usam o padrão preenchimento e valores de sombra dos botões do Android. Além disso, o
Button.UseDefaultPadding e Button.UseDefaultShadow métodos podem ser usados para retornar se um botão usa o
padrão de preenchimento de valor e o valor padrão de sombra, respectivamente.
O resultado é que os botões de xamarin. Forms podem usar o preenchimento padrão e os valores de sombra dos
botões do Android:
Observe que, na captura de tela acima de cada Button tem definições idênticas, exceto que o direito Button usa o
preenchimento padrão e valores de sombra dos botões do Android.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Opções do Editor de método de entrada de entrada
no Android
12/04/2019 • 3 minutes to read
Baixar o exemplo
Este específicos da plataforma Android define o método de entrada opções de IME (editor) para o teclado virtual
para um Entry . Isso inclui a definição no botão de ação do usuário no canto inferior do teclado virtual e as
interações com o Entry . Ele é consumido em XAML, definindo o Entry.ImeOptions propriedade anexada a um
valor da ImeFlags enumeração:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<StackLayout ...>
<Entry ... android:Entry.ImeOptions="Send" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
entry.On<Android>().SetImeOptions(ImeFlags.Send);
O Entry.On<Android> método Especifica que este específicos da plataforma serão executado apenas no Android. O
Entry.SetImeOptions método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é usado para
definir a opção de ação do método de entrada para o teclado virtual para o Entry , com o ImeFlags fornecendo
os seguintes valores de enumeração:
Default – indica que nenhuma chave de ação específica é necessária e que o controle subjacente produzirá o
seu próprio se possível. Isso será Next ou Done .
None – indica que nenhuma chave de ação será disponibilizado.
Go – indica que a chave de ação executará uma operação de "Ir", direcionando o usuário para o destino do
texto digitado.
Search – indica que a chave de ação executa uma operação de "Pesquisar", direcionando o usuário para os
resultados da pesquisa para o texto que tiver digitado.
Send – indica que a chave de ação executará uma operação de "Enviar", fornecendo o texto para seu destino.
Next – indica que a chave de ação executará uma operação de "next", direcionando o usuário para o próximo
campo que aceita texto.
Done – indica que a chave de ação executará uma operação de "done", fechando o teclado virtual.
Previous – indica que a chave de ação executará uma operação "anterior", direcionando o usuário para o
campo anterior que aceita texto.
ImeMaskAction – a máscara para selecionar opções de ação.
NoPersonalizedLearning – indica que o verificador ortográfico não saiba do usuário, nem sugerir correções com
base no qual o usuário tiver digitado anteriormente.
NoFullscreen – indica que a interface do usuário não deve estar em tela inteira.
NoExtractUi – indica que nenhuma interface do usuário será mostrada para texto extraído.
NoAccessoryAction – indica que nenhuma interface do usuário será exibido para ações personalizadas.
O resultado é que a especificada ImeFlags valor é aplicado para o teclado virtual para o Entry , que define o
método de entrada, as opções do editor:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Sombras ImageButton no Android
12/04/2019 • 3 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para habilitar uma sombra em um ImageButton . Ele é consumido
em XAML, definindo o ImageButton.IsShadowEnabled para a propriedade associável true , junto com um número
opcional associável propriedades adicionais que controlam a sombra:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ImageButton ...
Source="XamarinLogo.png"
BackgroundColor="GhostWhite"
android:ImageButton.IsShadowEnabled="true"
android:ImageButton.ShadowColor="Gray"
android:ImageButton.ShadowRadius="12">
<android:ImageButton.ShadowOffset>
<Size>
<x:Arguments>
<x:Double>10</x:Double>
<x:Double>10</x:Double>
</x:Arguments>
</Size>
</android:ImageButton.ShadowOffset>
</ImageButton>
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
IMPORTANT
Uma sombra é desenhada como parte do ImageButton em segundo plano e o plano de fundo é desenhada apenas se o
BackgroundColor propriedade está definida. Portanto, uma sombra não será desenhada se o
ImageButton.BackgroundColor propriedade não está definida.
O ImageButton.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O ImageButton.SetIsShadowEnabled método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific
namespace, é usada para controlar se uma sombra está habilitada no ImageButton . Além disso, os métodos a
seguir podem ser invocados para controlar a sombra:
SetShadowColor – Define a cor da sombra. A cor padrão é Color.Default .
SetShadowOffset – Define o deslocamento da sombra. O deslocamento altera a direção da sombra é convertida
e é especificada como uma Size valor. O Size valores de estrutura são expressos em unidades
independentes de dispositivo, com o primeiro valor que está sendo a distância para a esquerda (valor negativo)
ou a direita (valor positivo) e o segundo valor sendo a distância acima (valor negativo) ou abaixo (valor
positivo) . O valor padrão dessa propriedade é (0,0, 0,0), que resulta na sombra que está sendo convertido em
torno de cada lado do ImageButton .
SetShadowRadius – Define o raio de desfoque usado para renderizar a sombra projetada. O valor de raio padrão
é 10.0.
NOTE
O estado de uma sombra pode ser consultado por meio da chamada a GetIsShadowEnabled , GetShadowColor ,
GetShadowOffset , e GetShadowRadius métodos.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Fast de ListView, rolagem no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para habilitar a rolagem rápida por meio de dados em um
ListView . Ele é consumido em XAML, definindo o ListView.IsFastScrollEnabled anexado à propriedade um
boolean valor:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
...
<ListView ItemsSource="{Binding GroupedEmployees}"
GroupDisplayBinding="{Binding Key}"
IsGroupingEnabled="true"
android:ListView.IsFastScrollEnabled="true">
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
O ListView.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O ListView.SetIsFastScrollEnabled método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific
namespace, é usado para habilitar a rolagem rápida por meio de dados em um ListView . Além disso, o
SetIsFastScrollEnabled método pode ser usado para ativar/desativar a rolagem rápida chamando o
IsFastScrollEnabled método para retornar se a rolagem rápida está habilitada:
listView.On<Android>().SetIsFastScrollEnabled(!listView.On<Android>().IsFastScrollEnabled());
O resultado é que rolagem rápida por meio de dados em um ListView pode ser habilitado, que altera o tamanho
de rolagem:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Altura da barra de NavigationPage no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android define a altura da barra de navegação de um NavigationPage . Ele é
consumido em XAML, definindo o NavigationPage.BarHeight propriedade associável para um valor inteiro:
<NavigationPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat;assembly=Xamarin.Forms.Core"
android:NavigationPage.BarHeight="450">
...
</NavigationPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat;
...
Baixar o exemplo
Este específicos da plataforma Android é usado para desabilitar o Disappearing e Appearing eventos de página
no aplicativo pausar e retomar, respectivamente, para aplicativos que usam AppCompat. Além disso, ele inclui a
capacidade de controlar se o teclado virtual é exibido ao continuar, se ele foi exibido em pausa, desde que o modo
de operação do teclado virtual é definido para WindowSoftInputModeAdjust.Resize .
NOTE
Observe que esses eventos são habilitados por padrão para preservar o comportamento existente para aplicativos que
dependem dos eventos. Desabilitar esses eventos faz com que o ciclo de eventos AppCompat corresponder o ciclo de evento
de pré-AppCompat.
<Application ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
xmlns:androidAppCompat="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat;assembly=Xamarin.Forms.Core"
android:Application.WindowSoftInputModeAdjust="Resize"
androidAppCompat:Application.SendDisappearingEventOnPause="false"
androidAppCompat:Application.SendAppearingEventOnResume="false"
androidAppCompat:Application.ShouldPreserveKeyboardOnResume="true">
...
</Application>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat;
...
Xamarin.Forms.Application.Current.On<Android>()
.UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize)
.SendDisappearingEventOnPause(false)
.SendAppearingEventOnResume(false)
.ShouldPreserveKeyboardOnResume(true);
O Application.Current.On<Android> método Especifica que este específicos da plataforma serão executado apenas
no Android. O Application.SendDisappearingEventOnPause método, no
Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat namespace, é usado para habilitar ou desabilitar o
acionamento de Disappearing eventos de página, quando o aplicativo entra em segundo plano. O
Application.SendAppearingEventOnResume método é usado para habilitar ou desabilitar o acionamento de
Appearing evento de página, quando o aplicativo é retomado do plano de fundo. O
Application.ShouldPreserveKeyboardOnResume método é usado o controle se o teclado virtual é exibido ao continuar,
se ele foi exibido em pausa, fornecido que o modo de operação do teclado virtual é definido como
WindowSoftInputModeAdjust.Resize .
O resultado é que o Disappearing e Appearing eventos de página não serão acionados em Pausar o aplicativo e
retomar, respectivamente, e o teclado virtual de que, se foi exibido quando o aplicativo foi colocado em pausa, ele
também será exibido quando o aplicativo é retomado:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Modo de entrada de teclado virtual no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para definir o modo de operação para uma área de entrada do
teclado virtual e é consumido em XAML, definindo o Application.WindowSoftInputModeAdjust propriedade anexada
a um valor da WindowSoftInputModeAdjust enumeração:
<Application ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:Application.WindowSoftInputModeAdjust="Resize">
...
</Application>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
App.Current.On<Android>().UseWindowSoftInputModeAdjust(WindowSoftInputModeAdjust.Resize);
O Application.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O Application.UseWindowSoftInputModeAdjust método, no
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é usado para definir o modo de operação de
área de entrada de teclado virtual, com o WindowSoftInputModeAdjust enumeração fornecendo dois valores: Pan e
Resize . O Pan valor usa o AdjustPan opção de ajuste, o que não redimensione a janela quando um controle de
entrada tem o foco. Em vez disso, o conteúdo da janela estendido para que o foco atual não é obscurecido pelo
teclado virtual. O Resize valor usa o AdjustResize opção de ajuste, que redimensiona a janela quando um
controle de entrada tem o foco, para liberar espaço para o teclado virtual.
O resultado é que o teclado virtual área modo operacional pode ser definido quando um controle de entrada tem
o foco de entrada:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Página TabbedPage passar o dedo no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para habilitar o dedo com um gesto horizontal dedo entre páginas
em um TabbedPage . Ele é consumido em XAML, definindo o TabbedPage.IsSwipePagingEnabled anexado à
propriedade um boolean valor:
<TabbedPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.OffscreenPageLimit="2"
android:TabbedPage.IsSwipePagingEnabled="true">
...
</TabbedPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
On<Android>().SetOffscreenPageLimit(2)
.SetIsSwipePagingEnabled(true);
O TabbedPage.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O TabbedPage.SetIsSwipePagingEnabled método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific
namespace, é usado para habilitar o dedo entre páginas em um TabbedPage . Além disso, o TabbedPage classe na
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace também tem um EnableSwipePaging método
que permite que esse específicos da plataforma, e uma DisableSwipePaging método desabilita Essa plataforma
específica. O TabbedPage.OffscreenPageLimit propriedade anexada e SetOffscreenPageLimit método, são usadas
para definir o número de páginas que devem ser mantidos em um estado ocioso em ambos os lados da página
atual.
O resultado é que paginação passe o dedo para as páginas exibidas por um TabbedPage está habilitado:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Animações de transição de página TabbedPage no
Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para desabilitar animações de transição ao navegar pelas páginas,
seja programaticamente ou ao usar a barra de guias, em um TabbedPage . Ele é consumido em XAML, definindo o
TabbedPage.IsSmoothScrollEnabled para a propriedade associável false :
<TabbedPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.IsSmoothScrollEnabled="false">
...
</TabbedPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
On<Android>().SetIsSmoothScrollEnabled(false);
O TabbedPage.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O TabbedPage.SetIsSmoothScrollEnabled método, no
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é usada para controlar se as animações de
transição serão exibidas quando navegar entre páginas em um TabbedPage . Além disso, o TabbedPage classe o
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace também tem os seguintes métodos:
IsSmoothScrollEnabled , que é usada para recuperar se animações de transição serão exibidas quando navegar
entre páginas em um TabbedPage .
EnableSmoothScroll , que é usado para habilitar animações de transição ao navegar entre páginas em um
TabbedPage .
DisableSmoothScroll , que é usado para desabilitar animações de transição ao navegar entre páginas em um
TabbedPage .
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Posicionamento da barra de ferramentas
TabbedPage e cor no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Esses itens específicos à plataforma são usadas para definir o posicionamento e a cor da barra de ferramentas em
uma TabbedPage . Eles são consumidos no XAML, definindo o TabbedPage.ToolbarPlacement propriedade anexada
a um valor da ToolbarPlacement enumeração e o TabbedPage.BarItemColor e TabbedPage.BarSelectedItemColor
anexado propriedades para um Color :
<TabbedPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
android:TabbedPage.ToolbarPlacement="Bottom"
android:TabbedPage.BarItemColor="Black"
android:TabbedPage.BarSelectedItemColor="Red">
...
</TabbedPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
On<Android>().SetToolbarPlacement(ToolbarPlacement.Bottom)
.SetBarItemColor(Color.Black)
.SetBarSelectedItemColor(Color.Red);
O TabbedPage.On<Android> método Especifica que esses itens específicos à plataforma será executado apenas no
Android. O TabbedPage.SetToolbarPlacement método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific
namespace, é usado para definir o posicionamento da barra de ferramentas em um TabbedPage , com o
ToolbarPlacement fornecendo os seguintes valores de enumeração:
Default – indica que a barra de ferramentas é colocada no local padrão na página. Esta é a parte superior da
página em telefones e a parte inferior da página em outros idiomas de dispositivo.
Top – indica que a barra de ferramentas é colocada na parte superior da página.
Bottom – indica que a barra de ferramentas é colocada na parte inferior da página.
NOTE
O GetToolbarPlacement , GetBarItemColor , e GetBarSelectedItemColor métodos podem ser usados para recuperar
o posicionamento e as cores a TabbedPage barra de ferramentas.
O resultado é que o posicionamento da barra de ferramentas, a cor dos itens da barra de ferramentas e a cor do
item da barra de ferramentas selecionado podem ser definidas em um TabbedPage :
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Elevação VisualElement no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android é usado para controlar a ordem Z, de elementos visuais em aplicativos ou
a elevação destinados API 21 ou maior. A elevação de um elemento visual determina sua ordem de desenho, com
elementos visuais com valores mais altos de Z occluding elementos visuais com baixos valores de Z. Ele é
consumido em XAML, definindo o VisualElement.Elevation anexado à propriedade um boolean valor:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core"
Title="Elevation">
<StackLayout>
<Grid>
<Button Text="Button Beneath BoxView" />
<BoxView Color="Red" Opacity="0.2" HeightRequest="50" />
</Grid>
<Grid Margin="0,20,0,0">
<Button Text="Button Above BoxView - Click Me" android:VisualElement.Elevation="10"/>
<BoxView Color="Red" Opacity="0.2" HeightRequest="50" />
</Grid>
</StackLayout>
</ContentPage>
O Button.On<Android> método Especifica que este específicos da plataforma serão executado apenas no Android.
O VisualElement.SetElevation método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é
usado para definir a elevação do elemento visual como um valor anulável float . Além disso, o
VisualElement.GetElevation método pode ser usado para recuperar o valor de elevação de um elemento visual.
O resultado é que a elevação de elementos visuais pode ser controlada, de modo que os elementos visuais com
valores de Z maior occlude elementos visuais com baixos valores de Z. Portanto, no exemplo a segunda Button é
renderizado acima a BoxView porque ele tem um valor mais alto de elevação:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Modo de cor VisualElement herdado no Android
12/04/2019 • 2 minutes to read
Baixar o exemplo
Algumas das exibições de xamarin. Forms apresentam um modo de cor herdado. Nesse modo, quando o
IsEnabled propriedade do modo de exibição é definida como false , o modo de exibição substituirá as cores
definidas pelo usuário com os nativo as cores padrão para o estado desabilitado. Para versões anteriores
compatibilidade, esse modo herdado cor permanece o comportamento padrão para modos de exibição com
suporte.
Este específicos da plataforma Android desabilita nesse modo herdado de cor, para que permaneçam de cores
definido em uma exibição pelo usuário, mesmo quando o modo de exibição está desabilitado. Ele é consumido em
XAML, definindo o VisualElement.IsLegacyColorModeEnabled anexado à propriedade false :
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
...
<Button Text="Button"
TextColor="Blue"
BackgroundColor="Bisque"
android:VisualElement.IsLegacyColorModeEnabled="False" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
_legacyColorModeDisabledButton.On<Android>().SetIsLegacyColorModeEnabled(false);
O VisualElement.On<Android> método Especifica que este específicos da plataforma serão executado apenas no
Android. O VisualElement.SetIsLegacyColorModeEnabled método, no
Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é usada para controlar se o modo de cor
herdados é desabilitado. Além disso, o VisualElement.GetIsLegacyColorModeEnabled método pode ser usado para
retornar se o modo de cor herdado está desabilitado.
O resultado é que o modo herdado de cor pode ser desabilitado, para que as cores definidas em uma exibição pelo
usuário permaneçam até mesmo quando o modo de exibição está desabilitado:
NOTE
Ao definir uma VisualStateGroup em uma exibição, o modo herdado de cor é totalmente ignorado. Para obter mais
informações sobre estados visuais, consulte o Gerenciador de estado Visual xamarin. Forms.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
WebView conteúdo no Android misturadas
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma Android controla se um WebView pode exibir conteúdo misto em aplicativos
destinados a API 21 ou maior. Conteúdo misto é que é inicialmente carregada em uma conexão HTTPS, mas que
carrega os recursos (como imagens, áudio, vídeo, folhas de estilo, scripts) em uma conexão HTTP. Ele é consumido
em XAML, definindo o WebView.MixedContentMode propriedade anexada a um valor da MixedContentHandling
enumeração:
<ContentPage ...
xmlns:android="clr-
namespace:Xamarin.Forms.PlatformConfiguration.AndroidSpecific;assembly=Xamarin.Forms.Core">
<WebView ... android:WebView.MixedContentMode="AlwaysAllow" />
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.AndroidSpecific;
...
webView.On<Android>().SetMixedContentMode(MixedContentHandling.AlwaysAllow);
O WebView.On<Android> método Especifica que este específicos da plataforma serão executado apenas no Android.
O WebView.SetMixedContentMode método, no Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace, é
usada para controlar se o conteúdo misto pode ser exibido, com o MixedContentHandling enumeração fornecendo
três valores possíveis:
AlwaysAllow – indica que o WebView permitirá que uma origem HTTPS carregar conteúdo de uma origem
HTTP.
NeverAllow – indica que o WebView não permitirá que uma origem HTTPS carregar conteúdo de uma origem
HTTP.
CompatibilityMode – indica que o WebView tentará ser compatível com a abordagem do navegador da web
mais recente do dispositivo. Parte do conteúdo HTTP poderá ter permissão para ser carregado por uma origem
HTTPS e outros tipos de conteúdo serão bloqueados. Os tipos de conteúdo que são bloqueados ou permitidos
podem ser alterados a cada versão do sistema operacional.
O resultado é que a especificada MixedContentHandling valor é aplicado para o WebView , que controla se o
conteúdo misto pode ser exibido:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
AndroidSpecific API
AndroidSpecific.AppCompat API
Classe de dispositivo do xamarin. Forms
12/04/2019 • 9 minutes to read
baixar o exemplo
O Device classe contém um número de propriedades e métodos para ajudar os desenvolvedores personalizar o
layout e a funcionalidade em uma base por plataforma.
Além dos métodos e propriedades para o código de destino em tipos específicos de hardware e tamanhos, o
Device classe inclui o BeginInvokeOnMainThread método que deve ser usado ao interagir com a interface do
usuário controla de threads em segundo plano.
double top;
switch (Device.RuntimePlatform)
{
case Device.iOS:
top = 20;
break;
case Device.Android:
case Device.UWP:
default:
top = 0;
break;
}
layout.Margin = new Thickness(5, top, 5, 0);
O OnPlatform é uma classe genérica que deve ser instanciada com um x:TypeArguments atributo que
corresponde ao tipo de destino. No On classe, o Platform atributo pode aceitar um único string valor ou
vários delimitada por vírgula string valores.
IMPORTANT
Fornecendo um incorreto Platform valor no atributo de On classe não resultará em erro. Em vez disso, o código será
executado sem o valor específico da plataforma que está sendo aplicado.
Como alternativa, o OnPlatform extensão de marcação pode ser usada em XAML para personalizar a aparência
da interface do usuário em uma base por plataforma. Para obter mais informações, consulte extensão de
marcação OnPlatform.
Device.Idiom
O Device.Idiom propriedade pode ser usada para alterar os layouts ou funcionalidade dependendo do
dispositivo em que o aplicativo está em execução no. O TargetIdiom enumeração contém os seguintes valores:
Telefone – iPhone, iPod touch e dispositivos Android mais estreitos do que 600 quedas ^
Tablet – iPad, dispositivos Windows e dispositivos Android mais de 600 quedas ^
Área de trabalho – somente retornado no aplicativos da UWP em computadores desktop do Windows 10
(retorna Phone em dispositivos móveis do Windows, incluindo em cenários de continuidade)
TV – dispositivos Tizen TV
Assista – Tizen dispositivos de inspeção
Não há suporte para – não utilizados
^ dips não é necessariamente a contagem de pixel físico
O Idiom propriedade é especialmente útil para a criação de layouts que tiram proveito de telas maiores, como
este:
if (Device.Idiom == TargetIdiom.Phone) {
// layout views vertically
} else {
// layout views horizontally for a larger display (tablet or desktop)
}
O OnIdiom é uma classe genérica que deve ser instanciada com um x:TypeArguments atributo que corresponde
ao tipo de destino.
Como alternativa, o OnIdiom extensão de marcação pode ser usada em XAML para personalizar a aparência da
interface do usuário com base no idioma do dispositivo em que o aplicativo está sendo executado. Para obter
mais informações, consulte extensão de marcação OnIdiom.
Device.FlowDirection
O Device.FlowDirection valor recupera uma FlowDirection valor de enumeração que representa a direção do
fluxo atual que está sendo usada pelo dispositivo. A direção do fluxo é a direção na qual os elementos de
interface do usuário na página são detectados pelos olhos. Os valores de enumeração são:
LeftToRight
RightToRight
MatchParent
No XAML, o Device.FlowDirection valor pode ser recuperado usando o x:Static extensão de marcação:
O código equivalente no C# é:
this.FlowDirection = Device.FlowDirection;
Para obter mais informações sobre a direção do fluxo, consulte localização da direita para esquerda.
Device.Styles
O Styles propriedade contém as definições de estilo interno que podem ser aplicadas a alguns dos controles
(como Label ) Style propriedade. Os estilos disponíveis são:
BodyStyle
CaptionStyle
ListItemDetailTextStyle
ListItemTextStyle
SubtitleStyle
TitleStyle
Device.GetNamedSize
GetNamedSize pode ser usado ao definir FontSize em C# código:
myLabel.FontSize = Device.GetNamedSize (NamedSize.Small, myLabel);
someLabel.FontSize = Device.OnPlatform (
24, // hardcoded size
Device.GetNamedSize (NamedSize.Medium, someLabel),
Device.GetNamedSize (NamedSize.Large, someLabel)
);
Device.OpenUri
O OpenUri método pode ser usado para disparar operações na plataforma subjacente, como abrir uma URL no
navegador da web nativos (Safari no iOS ou Internet no Android).
Device.OpenUri(new Uri("https://evolve.xamarin.com/"));
O amostra WebView inclui um exemplo do uso OpenUri para abrir URLs e também disparar chamadas
telefônicas.
O exemplo de mapas também usa Device.OpenUri para exibir mapas e das direções usando nativo mapeia
aplicativos no iOS e Android.
Device.StartTimer
O Device classe também tem um StartTimer método que fornece uma maneira simple para disparar tarefas
dependentes de tempo que funciona em código comum do xamarin. Forms, incluindo uma biblioteca .NET
Standard. Passar uma TimeSpan para definir o intervalo e retornar true para manter a execução do
temporizador ou false para interrompê-la depois da chamada atual.
Se o código dentro do temporizador interage com a interface do usuário (como definir o texto de um Label ou
exibindo um alerta) deve ser feita dentro de um BeginInvokeOnMainThread expressão (veja abaixo).
Device.BeginInvokeOnMainThread
Elementos da interface do usuário nunca devem ser acessados por threads em segundo plano, como o código
em execução em um temporizador ou um manipulador de conclusão para operações assíncronas, como
solicitações da web. Qualquer código em segundo plano que precisa atualizar a interface do usuário deve ser
encapsulado dentro de BeginInvokeOnMainThread . Este é o equivalente de InvokeOnMainThread no iOS,
RunOnUiThread no Android, e Dispatcher.RunAsync na plataforma Universal do Windows.
Device.BeginInvokeOnMainThread ( () => {
// interact with UI elements
});
Observe que usando os métodos async/await não é necessário usar BeginInvokeOnMainThread se eles estão em
execução do thread principal da interface do usuário.
Resumo
O xamarin. Forms Device classe permite controle refinado sobre layouts e funcionalidade em uma base por
plataforma – até mesmo o código (projetos da biblioteca .NET Standard ou projetos compartilhados) em
comum.
Links relacionados
Exemplo de dispositivo
Exemplo de estilos
Dispositivo
recursos da plataforma iOS no xamarin. Forms
12/04/2019 • 6 minutes to read
Desenvolvimento de aplicativos xamarin. Forms para iOS requer o Visual Studio. O página de requisitos contém
mais informações sobre os pré-requisitos.
Especificidades da plataforma
Especificidades da plataforma permitem que você consumir funcionalidade só está disponível em uma plataforma
específica, sem implementar renderizadores personalizados ou efeitos.
A seguinte funcionalidade específica da plataforma é fornecida para exibições do xamarin. Forms, páginas e
layouts no iOS:
Suporte para qualquer um de desfoque VisualElement . Para obter mais informações, consulte VisualElement
desfoque no iOS.
Desabilitar o modo de cor herdados em um com suporte VisualElement . Para obter mais informações,
consulte modo de cor VisualElement herdado no iOS.
Habilitando uma sombra em um VisualElement . Para obter mais informações, consulte VisualElement Drop
sombras no iOS.
A seguinte funcionalidade específica da plataforma é fornecida para modos de exibição do xamarin. Forms no iOS:
Definindo o Cell cor do plano de fundo. Para obter mais informações, consulte cor de plano de fundo da
célula no iOS.
Garantir que inseridos texto se adapta a um Entry ajustando o tamanho da fonte. Para obter mais
informações, consulte tamanho da fonte de entrada no iOS.
Configurando a cor do cursor uma Entry . Para obter mais informações, consulte entrada de cor do Cursor no
iOS.
Controlando se ListView células de cabeçalho float durante a rolagem. Para obter mais informações, consulte
ListView estilo do cabeçalho de grupo no iOS.
Controlar se as animações de linha estão desabilitadas quando o ListView coleção de itens está sendo
atualizada. Para obter mais informações, consulte ListView linha animações no iOS.
Definindo o estilo do separador em um ListView . Para obter mais informações, consulte ListView estilo do
separador no iOS.
Controlando quando a seleção de item ocorre em um Picker . Para obter mais informações, consulte seletor
de seleção de Item no iOS.
Habilitando a Slider.Value propriedade a ser definido tocando em uma posição no Slider barra, em vez de
precisar arrastar o Slider thumb. Para obter mais informações, consulte controle deslizante Thumb toque no
iOS.
A seguinte funcionalidade específica da plataforma é fornecida para páginas do xamarin. Forms no iOS:
Ocultando o separador de barra de navegação em um NavigationPage . Para obter mais informações, consulte
NavigationPage separador de barra no iOS.
Controlar se a barra de navegação é translúcida. Para obter mais informações, consulte Translucência da barra
de navegação no iOS.
Controlar se o texto da barra de status de cor em um NavigationPage é ajustado para coincidir com a
luminosidade da barra de navegação. Para obter mais informações, consulte modo de cor de texto
NavigationPage barra no iOS.
Controlar se o título da página é exibido como um título grande na barra de navegação de página. Para obter
mais informações, consulte títulos de página grande no iOS.
Definindo a visibilidade da barra de status em uma Page . Para obter mais informações, consulte página de
visibilidade da barra de Status no iOS.
Garantir que esse conteúdo da página está posicionado em uma área da tela que é segura para todos os
dispositivos iOS. Para obter mais informações, consulte guia do Layout da área de segurança no iOS.
Definindo o estilo de apresentação de páginas modais em um iPad. Para obter mais informações, consulte iPad
estilo de apresentação de página Modal.
A seguinte funcionalidade específica da plataforma é fornecida para layouts do xamarin. Forms no iOS:
Controlar se uma ScrollView manipula um gesto de toque ou passá-lo ao seu conteúdo. Para obter mais
informações, consulte ScrollView toques de conteúdo no iOS.
A seguinte funcionalidade específica da plataforma é fornecida para o xamarin. Forms Application classe no iOS:
Habilitando o controle de layout e renderização atualizações a serem executadas no thread principal. Para obter
mais informações, consulte atualizações de controle do Thread principal no iOS.
Habilitando um PanGestureRecognizer em uma exibição de rolagem para capturar e compartilhar o gesto de
panorâmica com o modo de exibição de rolagem. Para obter mais informações, consulte simultâneas
reconhecimento de gesto de panorâmica no iOS.
Baixar o exemplo
Este específicos da plataforma iOS define a cor de plano de fundo padrão do Cell instâncias. Ele é consumido em
XAML, definindo o Cell.DefaultBackgroundColor propriedade associável a uma Color :
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ListView ItemsSource="{Binding GroupedEmployees}"
IsGroupingEnabled="true">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell ios:Cell.DefaultBackgroundColor="Teal">
<Label Margin="10,10"
Text="{Binding Key}"
FontAttributes="Bold" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O ListView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Cell.SetDefaultBackgroundColor método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, define
a cor de plano de fundo da célula para determinado Color . Além disso, o Cell.DefaultBackgroundColor método
pode ser usado para recuperar a cor de plano de fundo da célula atual.
O resultado é que a cor do plano de fundo em um Cell pode ser definido para um determinado Color :
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Cor do Cursor de entrada no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma define a cor do cursor de um Entry como uma cor especificada. Ele é consumido
em XAML, definindo o Entry.CursorColor propriedade associável a uma Color :
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
<Entry ... ios:Entry.CursorColor="LimeGreen" />
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O Entry.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Entry.SetCursorColor método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, define a cor do
cursor para um especificados Color . Além disso, o Entry.GetCursorColor método pode ser usado para recuperar
a cor atual do cursor.
O resultado é que a cor do cursor em uma Entry pode ser definido para um determinado Color :
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Tamanho da fonte de entrada no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para dimensionar o tamanho da fonte de um Entry para garantir que
o texto de valores se encaixa no controle. Ele é consumido em XAML, definindo o
Entry.AdjustsFontSizeToFitWidth anexado à propriedade um boolean valor:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
<StackLayout Margin="20">
<Entry x:Name="entry"
Placeholder="Enter text here to see the font size change"
FontSize="22"
ios:Entry.AdjustsFontSizeToFitWidth="true" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
entry.On<iOS>().EnableAdjustsFontSizeToFitWidth();
O Entry.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Entry.EnableAdjustsFontSizeToFitWidth método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace,
é usado para dimensionar o tamanho da fonte do texto para garantir que ela se encaixa valores de Entry . Além
disso, o Entry classe o Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace também tem um
DisableAdjustsFontSizeToFitWidth método que desabilita essa específicos da plataforma, e um
SetAdjustsFontSizeToFitWidth método que pode ser usado para ativar/desativar o tamanho da fonte
dimensionamento chamando o AdjustsFontSizeToFitWidth método:
entry.On<iOS>().SetAdjustsFontSizeToFitWidth(!entry.On<iOS>().AdjustsFontSizeToFitWidth());
O resultado é que o tamanho da fonte de Entry é dimensionado para garantir que o texto de valores se encaixa
no controle:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Adicionando formatação específica do iOS
12/04/2019 • 4 minutes to read
Uma maneira de definir específico do iOS formatação é criar uma renderizador personalizado para um controle e
definir estilos de específico da plataforma e cores para cada plataforma.
Outras opções para controlar a aparência do aplicativo iOS xamarin. Forms incluem:
Configurando opções de exibição Info. plist
Definindo estilos de controle por meio de UIAppearance API
Essas alternativas são discutidas abaixo.
O resultado é mostrado no trecho de tela abaixo. Observe que os itens da barra de status são pretos (isso não
pode ser definido dentro do xamarin. Forms porque ele é um recurso específico da plataforma).
O ideal é que a barra de status também seria branca – algo que podemos pode realizar diretamente no projeto do
iOS. Adicione as seguintes entradas para o Info. plist para forçar a barra de status para ser branco:
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
Agora, quando o aplicativo é executado, a barra de navegação é verde e seu texto é branco (devido à formatação
de xamarin. Forms) e o texto da barra de status também é brancas, graças à configuração específica do iOS:
UIAppearance API
O UIAppearance API pode ser usado para definir propriedades visuais em vários controles de iOS sem precisar
criar um renderizador personalizado.
Adição de uma única linha de código para o AppDelegate.cs FinishedLaunching método pode definir o estilo de
todos os controles de um determinado tipo usando seu Appearance propriedade. O código a seguir contém dois
exemplos - globalmente a guia de definição de estilo de barra e alterne o controle:
AppDelegate.cs no projeto iOS
UITabBar
Por padrão, o ícone da barra de guia selecionada em um TabbedPage seria azul:
Usar essa API permite que você personalize a aparência do xamarin. Forms TabbedPage no iOS com muito pouco
código. Consulte a receita Personalizar guias para obter mais detalhes sobre como usar um renderizador
personalizado para definir uma fonte específica para a guia.
UISwitch
O Switch controle é outro exemplo que pode ser estilizado facilmente:
Essas capturas de tela de dois mostram o padrão UISwitch controle à esquerda e a versão personalizada
(configuração Appearance ) à direita na exemplo de tarefas pendentes:
Outros controles
Muitos controles de interface do usuário iOS podem ter suas cores padrão e outros atributos definidos usando o
UIAppearance API.
Links relacionados
UIAppearance
Personalizar guias
Estilo de apresentação de página Modal do iPad
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para definir o estilo de apresentação de uma página modal em um
iPad. Ele é consumido em XAML, definindo o Page.ModalPresentationStyle propriedade associável a uma
UIModalPresentationStyle valor de enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.ModalPresentationStyle="FormSheet">
...
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O Page.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Page.SetModalPresentationStyle método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usado
para definir o estilo de apresentação modal em um Page especificando um dos seguintes
UIModalPresentationStyle enumeração valores:
FullScreen , que define o estilo de apresentação modal para abranger a tela inteira. Por padrão, as páginas
modais são exibidas usando esse estilo de apresentação.
FormSheet , que define o estilo de apresentação modal seja menor do que a tela e centralizada no.
Além disso, o método pode ser usado para recuperar o valor atual do
GetModalPresentationStyle
UIModalPresentationStyle enumeração é aplicada para o Page .
O resultado é que o estilo de apresentação modal em uma Page podem ser definidos:
NOTE
As páginas que usam esse específicos da plataforma para definir o estilo de apresentação modal devem usar a navegação
modal. Para obter mais informações, consulte páginas modais do xamarin. Forms.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Títulos de página grande no iOS
12/04/2019 • 3 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para exibir o título da página como um título grande na barra de
navegação de um NavigationPage , para dispositivos que usam iOS 11 ou superior. Um título grande é alinhado à
esquerda e usa uma fonte maior e faz a transição para um título padrão conforme o usuário começa a rolagem de
conteúdo, para que o espaço na tela é usado com eficiência. No entanto, em orientação paisagem, o título
retornará para o centro da barra de navegação para otimizar o layout do conteúdo. Ele é consumido em XAML,
definindo o NavigationPage.PrefersLargeTitles anexado à propriedade um boolean valor:
<NavigationPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
...
ios:NavigationPage.PrefersLargeTitles="true">
...
</NavigationPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O NavigationPage.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS.
O NavigationPage.SetPrefersLargeTitle método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace,
que controla se os títulos grandes estão habilitados.
Desde que os títulos grandes estão habilitados na NavigationPage , todas as páginas na pilha de navegação serão
exibir títulos grandes. Esse comportamento pode ser substituído nas páginas, definindo o Page.LargeTitleDisplay
propriedade anexada a um valor da LargeTitleDisplayMode enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
Title="Large Title"
ios:Page.LargeTitleDisplay="Never">
...
</ContentPage>
Como alternativa, o comportamento de página pode ser substituído no C# usando a API fluente:
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O Page.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Page.SetLargeTitleDisplay método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, controla o
comportamento de título grande no Page , com o LargeTitleDisplayMode fornecendo três possíveis de
enumeração valores:
Always – forçar a barra de navegação e a fonte tamanho para usar o formato grande.
Automatic – use o mesmo estilo (pequeno ou grande) como o item anterior na pilha de navegação.
Never – forçar o uso da barra de navegação de formato pequeno regular.
Além disso, o SetLargeTitleDisplay método pode ser usado para alternar os valores de enumeração por meio da
chamada a LargeTitleDisplay método, que retorna atual LargeTitleDisplayMode :
switch (On<iOS>().LargeTitleDisplay())
{
case LargeTitleDisplayMode.Always:
On<iOS>().SetLargeTitleDisplay(LargeTitleDisplayMode.Automatic);
break;
case LargeTitleDisplayMode.Automatic:
On<iOS>().SetLargeTitleDisplay(LargeTitleDisplayMode.Never);
break;
case LargeTitleDisplayMode.Never:
On<iOS>().SetLargeTitleDisplay(LargeTitleDisplayMode.Always);
break;
}
O resultado é que o especificado LargeTitleDisplayMode é aplicada para o Page , que controla o comportamento
de título grande:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Estilo do cabeçalho de grupo de ListView no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa controla de específico da plataforma iOS se ListView células de cabeçalho float durante a rolagem. Ele é
consumido em XAML, definindo o ListView.GroupHeaderStyle propriedade associável a um valor da
GroupHeaderStyle enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ListView ... ios:ListView.GroupHeaderStyle="Grouped">
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
listView.On<iOS>().SetGroupHeaderStyle(GroupHeaderStyle.Grouped);
O ListView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
ListView.SetGroupHeaderStyle método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usada
para controlar se ListView células de cabeçalho float durante a rolagem. O GroupHeaderStyle enumeração
fornece dois valores possíveis:
Plain – indica que as células de cabeçalho float quando o ListView é rolado (padrão).
Grouped – indica que as células de cabeçalho não flutuante quando o ListView é rolada.
Além disso, o ListView.GetGroupHeaderStyle método pode ser usado para retornar o GroupHeaderStyle que é
aplicado para o ListView .
O resultado é que a especificada GroupHeaderStyle valor é aplicado para o ListView , que controla se as células de
cabeçalho float durante a rolagem:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Animações de linha de ListView no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa controla de específico da plataforma iOS de linha se as animações são desabilitados quando o ListView
coleção de itens está sendo atualizada. Ele é consumido em XAML, definindo o ListView.RowAnimationsEnabled
para a propriedade associável false :
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ListView ... ios:ListView.RowAnimationsEnabled="false">
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
listView.On<iOS>().SetRowAnimationsEnabled(false);
O ListView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
ListView.SetRowAnimationsEnabled método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é
usada para controlar se as animações de linha são desabilitado quando o ListView coleção de itens está sendo
atualizada. Além disso, o ListView.GetRowAnimationsEnabled método pode ser usado para retornar se animações de
linha estão desabilitadas no ListView .
NOTE
ListView animações de linha são habilitadas por padrão. Portanto, uma animação ocorre quando uma nova linha é
inserida em um ListView .
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Estilo do separador de ListView no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS controla se o separador entre células em uma ListView usa a largura total do
ListView . Ele é consumido em XAML, definindo o ListView.SeparatorStyle propriedade anexada a um valor da
SeparatorStyle enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<ListView ... ios:ListView.SeparatorStyle="FullWidth">
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
listView.On<iOS>().SetSeparatorStyle(SeparatorStyle.FullWidth);
O ListView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
ListView.SetSeparatorStyle método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usada
para controlar se o separador entre células no ListView usa completo largura do ListView , com o
SeparatorStyle enumeração fornecendo dois valores possíveis:
Default – indica o comportamento do separador de iOS padrão. Esse é o comportamento padrão no xamarin.
Forms.
FullWidth – indica que os separadores serão desenhados de uma borda da ListView para outro.
O resultado é que o especificado SeparatorStyle valor é aplicado a ListView , que controla a largura do
separador entre células:
NOTE
Depois que o estilo do separador foi definido como FullWidth , ele não pode ser alterado para Default em tempo de
execução.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Atualizações de controle do Thread principal no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS permite controlar o layout e renderização de atualizações a serem executadas
no thread principal, em vez de que está sendo executada em um thread em segundo plano. Ele deve ser raramente
necessário, mas em alguns casos, pode impedir que falhas. Seu consumido em XAML, definindo o
Application.HandleControlUpdatesOnMainThread para a propriedade associável true :
<Application ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Application.HandleControlUpdatesOnMainThread="true">
...
</Application>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
Xamarin.Forms.Application.Current.On<iOS>().SetHandleControlUpdatesOnMainThread(true);
O Application.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Application.SetHandleControlUpdatesOnMainThread método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, é usada para controlar se o controle de layout e renderização atualizações são executadas no thread
principal, em vez de que está sendo executada em um thread em segundo plano. Além disso, o
Application.GetHandleControlUpdatesOnMainThread método pode ser usado para retornar se o controle de layout e
renderização atualizações estão sendo executadas no thread principal.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Separador de barra NavigationPage no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS oculta a linha separadora e sombra que está na parte inferior da barra de
navegação em um NavigationPage . Ele é consumido em XAML, definindo o
NavigationPage.HideNavigationBarSeparator para a propriedade associável false :
<NavigationPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:NavigationPage.HideNavigationBarSeparator="true">
</NavigationPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
O NavigationPage.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS.
O NavigationPage.SetHideNavigationBarSeparator método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, é usada para controlar se o separador de barra de navegação está oculto. Além disso, o
NavigationPage.HideNavigationBarSeparator método pode ser usado para retornar se o separador de barra de
navegação está oculto.
O resultado é que o separador de barra de navegação em um NavigationPage podem estar ocultos:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Modo de cor de texto NavigationPage barra no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este controles específicos da plataforma se o texto da barra de status de cor em um NavigationPage é ajustado
para coincidir com a luminosidade da barra de navegação. Ele é consumido em XAML, definindo o
NavigationPage.StatusBarTextColorMode propriedade anexada a um valor da StatusBarTextColorMode enumeração:
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
x:Class="PlatformSpecifics.iOSStatusBarTextColorModePage">
<MasterDetailPage.Master>
<ContentPage Title="Master Page Title" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<NavigationPage BarBackgroundColor="Blue" BarTextColor="White"
ios:NavigationPage.StatusBarTextColorMode="MatchNavigationBarTextLuminosity">
<x:Arguments>
<ContentPage>
<Label Text="Slide the master page to see the status bar text color mode change." />
</ContentPage>
</x:Arguments>
</NavigationPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O NavigationPage.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS.
O NavigationPage.SetStatusBarTextColorMode método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, controles se o texto da barra de status de cor no NavigationPage é ajustado para coincidir com o
luminosidade da barra de navegação, com o StatusBarTextColorMode enumeração fornecendo dois valores
possíveis:
DoNotAdjust – indica que a barra de cor do texto de status não devem ser ajustado.
MatchNavigationBarTextLuminosity – indica que a barra de cor do texto de status deve corresponder à
luminosidade da barra de navegação.
Além disso, o método pode ser usado para recuperar o valor atual da
GetStatusBarTextColorMode
StatusBarTextColorMode enumeração é aplicada para o NavigationPage .
O resultado é que o status da barra de cor do texto em uma NavigationPage pode ser ajustado de acordo com a
luminosidade da barra de navegação. Neste exemplo, a barra de alterações de cor do texto de status que o usuário
alterna entre o Master e Detail páginas de um MasterDetailPage :
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
NavigationPage Translucência de barra no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para alterar a transparência da barra de navegação em um
NavigationPage e consumido em XAML, definindo o NavigationPage.IsNavigationBarTranslucent propriedade
anexada a um boolean valor:
<NavigationPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
BackgroundColor="Blue"
ios:NavigationPage.IsNavigationBarTranslucent="true">
...
</NavigationPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O NavigationPage.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS.
O NavigationPage.EnableTranslucentNavigationBar método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, é usado para fazer a barra de navegação translúcido. Além disso, o NavigationPage classe o
Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace também tem um DisableTranslucentNavigationBar
método que restaura a barra de navegação para seu estado padrão, e um SetIsNavigationBarTranslucent método
que pode ser usado para alternar a transparência da barra de navegação, chamando o IsNavigationBarTranslucent
método:
(App.Current.MainPage as Xamarin.Forms.NavigationPage)
.On<iOS>()
.SetIsNavigationBarTranslucent(!(App.Current.MainPage as Xamarin.Forms.NavigationPage).On<iOS>
().IsNavigationBarTranslucent());
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Página de visibilidade da barra de Status no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para definir a visibilidade da barra de status em uma Page , e inclui a
capacidade de controlar como a barra de status entra ou sai de Page . Ele é consumido em XAML, definindo o
Page.PrefersStatusBarHidden propriedade anexada a um valor da StatusBarHiddenMode enumeração e,
opcionalmente, o Page.PreferredStatusBarUpdateAnimation propriedade anexada a um valor da
UIStatusBarAnimation enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Page.PrefersStatusBarHidden="True"
ios:Page.PreferredStatusBarUpdateAnimation="Fade">
...
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
On<iOS>().SetPrefersStatusBarHidden(StatusBarHiddenMode.True)
.SetPreferredStatusBarUpdateAnimation(UIStatusBarAnimation.Fade);
O Page.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Page.SetPrefersStatusBarHidden método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usado
para definir a visibilidade da barra de status em um Page especificando um dos StatusBarHiddenMode valores de
enumeração: Default , True , ou False . O StatusBarHiddenMode.True e StatusBarHiddenMode.False valores
definidos a visibilidade da barra de status, independentemente da orientação do dispositivo e o
StatusBarHiddenMode.Default valor oculta a barra de status em um ambiente compact verticalmente.
O resultado é que a visibilidade da barra de status em uma Page podem ser definidos:
NOTE
Em um TabbedPage , especificado StatusBarHiddenMode valor de enumeração também atualizará a barra de status em
todas as páginas filho. Em todos os outros Page -tipos derivados, especificados StatusBarHiddenMode valor de
enumeração só atualizará a barra de status na página atual.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Seleção de Item de seletor no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS controla quando a seleção de item ocorre em um Picker , permitindo que o
usuário especifique que a seleção de item ocorre ao navegar por itens no controle, ou apenas uma vez a feito
botão é pressionado. Ele é consumido em XAML, definindo o Picker.UpdateMode propriedade anexada a um valor
da UpdateMode enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<Picker ... Title="Select a monkey" ios:Picker.UpdateMode="WhenFinished">
...
</Picker>
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
picker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
O Picker.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Picker.SetUpdateMode método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usado para
controlar quando a seleção de item ocorre, com o UpdateMode enumeração fornecendo dois valores possíveis:
Immediately – seleção de item ocorre conforme o usuário navega por itens na Picker . Esse é o
comportamento padrão no xamarin. Forms.
WhenFinished – seleção de item ocorrerá somente depois que o usuário pressiona o feito botão na Picker .
Além disso, o SetUpdateMode método pode ser usado para alternar os valores de enumeração por meio da
chamada a UpdateMode método, que retorna atual UpdateMode :
switch (picker.On<iOS>().UpdateMode())
{
case UpdateMode.Immediately:
picker.On<iOS>().SetUpdateMode(UpdateMode.WhenFinished);
break;
case UpdateMode.WhenFinished:
picker.On<iOS>().SetUpdateMode(UpdateMode.Immediately);
break;
}
O resultado é que a especificada UpdateMode é aplicada para o Picker , que controla quando ocorre a seleção de
item:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Guia do Layout da área de segurança no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para garantir que o conteúdo da página é posicionado em uma área da
tela que é segura para todos os dispositivos que usam iOS 11 e superior. Especificamente, ele ajudará a garantir
que o conteúdo não é recortado pelo cantos arredondados de dispositivo, o indicador de base ou a estrutura do
sensor em um iPhone X. Ele é consumido em XAML, definindo o Page.UseSafeArea anexado à propriedade um
boolean valor:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
Title="Safe Area"
ios:Page.UseSafeArea="true">
<StackLayout>
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
On<iOS>().SetUseSafeArea(true);
O Page.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Page.SetUseSafeArea método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, que controla se o
guia do layout da área de segurança está habilitado.
O resultado é que o conteúdo da página pode ser posicionado em uma área da tela que é segura para todos os
iPhones:
NOTE
Área de segurança definida pela Apple é usada no xamarin. Forms para definir a Page.Padding propriedade e substituirá
qualquer anteriores valores dessa propriedade que foram definidos.
Área de segurança pode ser personalizada, recuperando seu Thickness de valor com o Page.SafeAreaInsets
método da Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace. Em seguida, pode ser modificado como
necessário e reatribuído à Padding propriedade no construtor da página ou OnAppearing substituir:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
ScrollView toques de conteúdo no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Um temporizador implícito é disparado quando um gesto de toque começa em um ScrollView no iOS e o
ScrollView decide, com base na ação de usuário na extensão de timer, se ele deve tratar o gesto ou passá-lo ao
seu conteúdo. Por padrão, o iOS ScrollView toques de conteúdo de atrasos, mas isso pode causar problemas em
algumas circunstâncias com o ScrollView conteúdo não ganhando o gesto quando deveria. Portanto, esse
controles específicos da plataforma se um ScrollView manipula um gesto de toque ou passá-lo ao seu conteúdo.
Ele é consumido em XAML, definindo o ScrollView.ShouldDelayContentTouches anexado à propriedade um
boolean valor:
<MasterDetailPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<MasterDetailPage.Master>
<ContentPage Title="Menu" BackgroundColor="Blue" />
</MasterDetailPage.Master>
<MasterDetailPage.Detail>
<ContentPage>
<ScrollView x:Name="scrollView" ios:ScrollView.ShouldDelayContentTouches="false">
<StackLayout Margin="0,20">
<Slider />
<Button Text="Toggle ScrollView DelayContentTouches" Clicked="OnButtonClicked" />
</StackLayout>
</ScrollView>
</ContentPage>
</MasterDetailPage.Detail>
</MasterDetailPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
scrollView.On<iOS>().SetShouldDelayContentTouches(false);
O ScrollView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
ScrollView.SetShouldDelayContentTouches método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, é usada para controlar se uma ScrollView manipula um gesto de toque ou passá-lo ao seu conteúdo.
Além disso, o SetShouldDelayContentTouches método pode ser usado para ativar/desativar atrasando o conteúdo
de toques, chamando o ShouldDelayContentTouches método para retornar se o conteúdo de toques estão atrasadas:
scrollView.On<iOS>().SetShouldDelayContentTouches(!scrollView.On<iOS>().ShouldDelayContentTouches());
O resultado é que um ScrollView pode desabilitar atrasando o recebimento de toques de conteúdo, portanto, que
neste cenário o Slider recebe o gesto em vez de Detail página do MasterDetailPage :
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Reconhecimento de gesto de panorâmica
simultâneas no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Quando um PanGestureRecognizer é anexado a um modo de exibição dentro de uma exibição de rolagem, todos a
panorâmica de gestos são capturados pelo PanGestureRecognizer e não serão passados para o modo de exibição
de rolagem. Portanto, o modo de exibição de rolagem não mais será rolada.
Este específicos da plataforma iOS permite que um PanGestureRecognizer em uma exibição de rolagem para
capturar e compartilhar o gesto de panorâmica com o modo de exibição de rolagem. Ele é consumido em XAML,
definindo o Application.PanGestureRecognizerShouldRecognizeSimultaneously anexado à propriedade true :
<Application ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core"
ios:Application.PanGestureRecognizerShouldRecognizeSimultaneously="true">
...
</Application>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
Xamarin.Forms.Application.Current.On<iOS>().SetPanGestureRecognizerShouldRecognizeSimultaneously(true);
O Application.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Application.SetPanGestureRecognizerShouldRecognizeSimultaneously método, no
Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usada para controlar se um reconhecedor de
gestos em uma exibição da rolagem panorâmica capturar o gesto de panorâmica, ou capturar e compartilhar a
panorâmica com o modo de exibição de rolagem do gesto. Além disso, o
Application.GetPanGestureRecognizerShouldRecognizeSimultaneously método pode ser usado para retornar se o
gesto de Panorâmica é compartilhado com o modo de exibição de rolagem que contém o PanGestureRecognizer .
Portanto, com essa específicos da plataforma habilitado, quando um ListView contém um PanGestureRecognizer ,
ambos o ListView e o PanGestureRecognizer receberá o gesto de Panorâmica e processá-lo. No entanto, com essa
específicos da plataforma desabilitado, quando um ListView contém uma PanGestureRecognizer , o
PanGestureRecognizer capturará o gesto de Panorâmica e processá-lo e o ListView não receberá o gesto de
panorâmica.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Controle deslizante Thumb toque no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS permite que o Slider.Value propriedade a ser definido tocando em uma
posição no Slider barra, em vez de precisar arrastar o Slider thumb. Ele é consumido em XAML, definindo o
Slider.UpdateOnTap para a propriedade associável true :
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout ...>
<Slider ... ios:Slider.UpdateOnTap="true" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
O Slider.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
Slider.SetUpdateOnTap método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usada para
controlar se um toque do Slider barra definirá o Slider.Value propriedade. Além disso, o
Slider.GetUpdateOnTap método pode ser usado para retornar se um toque dos Slider barra definirá o
Slider.Value propriedade.
O resultado é que um toque do Slider barra pode mover o Slider thumb e defina o Slider.Value propriedade:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
VisualElement desfoque no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para desfocar o conteúdo em camadas abaixo dela e pode ser aplicado
a qualquer VisualElement . Ele é consumido em XAML, definindo o VisualElement.BlurEffect propriedade
anexada a um valor da BlurEffectStyle enumeração:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
...
<AbsoluteLayout HorizontalOptions="Center">
<Image Source="monkeyface.png" />
<BoxView x:Name="boxView" ios:VisualElement.BlurEffect="ExtraLight" HeightRequest="300"
WidthRequest="300" />
</AbsoluteLayout>
...
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
boxView.On<iOS>().UseBlurEffect(BlurEffectStyle.ExtraLight);
O BoxView.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
VisualElement.UseBlurEffect método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é usado
para aplicar o efeito de desfoque, com o BlurEffectStyle enumeração fornecendo quatro valores: None ,
ExtraLight , Light , e Dark .
O resultado é que o especificado BlurEffectStyle é aplicado ao BoxView da instância, que Desfoca a Image em
camadas abaixo dela:
NOTE
Ao adicionar um efeito de desfoque a uma VisualElement , eventos de toque ainda serão recebidos pelo VisualElement .
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
VisualElement Drop sombras no iOS
12/04/2019 • 3 minutes to read
Baixar o exemplo
Este específicos da plataforma iOS é usado para habilitar uma sombra em um VisualElement . Ele é consumido
em XAML, definindo o VisualElement.IsShadowEnabled anexado à propriedade true , juntamente com um número
de adicionais opcional propriedades que controlam a sombra anexadas:
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout Margin="20">
<BoxView ...
ios:VisualElement.IsShadowEnabled="true"
ios:VisualElement.ShadowColor="Purple"
ios:VisualElement.ShadowOpacity="0.7"
ios:VisualElement.ShadowRadius="12">
<ios:VisualElement.ShadowOffset>
<Size>
<x:Arguments>
<x:Double>10</x:Double>
<x:Double>10</x:Double>
</x:Arguments>
</Size>
</ios:VisualElement.ShadowOffset>
</BoxView>
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
var boxView = new BoxView { Color = Color.Aqua, WidthRequest = 100, HeightRequest = 100 };
boxView.On<iOS>()
.SetIsShadowEnabled(true)
.SetShadowColor(Color.Purple)
.SetShadowOffset(new Size(10,10))
.SetShadowOpacity(0.7)
.SetShadowRadius(12);
O VisualElement.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
VisualElement.SetIsShadowEnabled método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace, é
usada para controlar se uma sombra está habilitada no VisualElement . Além disso, os métodos a seguir podem
ser invocados para controlar a sombra:
SetShadowColor – Define a cor da sombra. A cor padrão é Color.Default .
SetShadowOffset – Define o deslocamento da sombra. O deslocamento altera a direção da sombra é convertida
e é especificada como uma Size valor. O Size valores de estrutura são expressos em unidades
independentes de dispositivo, com o primeiro valor que está sendo a distância para a esquerda (valor negativo)
ou a direita (valor positivo) e o segundo valor sendo a distância acima (valor negativo) ou abaixo (valor
positivo) . O valor padrão dessa propriedade é (0,0, 0,0), que resulta na sombra que está sendo convertido em
torno de cada lado do VisualElement .
SetShadowOpacity – Define a opacidade da sombra, com o valor sendo no intervalo de 0,0 (transparente) para
1,0 (opaco). O valor de opacidade padrão é 0,5.
SetShadowRadius – Define o raio de desfoque usado para renderizar a sombra projetada. O valor de raio padrão
é 10.0.
NOTE
O estado de uma sombra pode ser consultado por meio da chamada a GetIsShadowEnabled , GetShadowColor ,
GetShadowOffset , GetShadowOpacity , e GetShadowRadius métodos.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Modo de cor VisualElement herdado no iOS
12/04/2019 • 2 minutes to read
Baixar o exemplo
Algumas das exibições de xamarin. Forms apresentam um modo de cor herdado. Nesse modo, quando o
IsEnabled propriedade do modo de exibição é definida como false , o modo de exibição substituirá as cores
definidas pelo usuário com os nativo as cores padrão para o estado desabilitado. Para versões anteriores
compatibilidade, esse modo herdado cor permanece o comportamento padrão para modos de exibição com
suporte.
Este específicos da plataforma iOS desabilita esse modo herdado de cor em um VisualElement , de modo que as
cores definidas em uma exibição pelo usuário permanecem até mesmo quando o modo de exibição está
desabilitado. Ele é consumido em XAML, definindo o VisualElement.IsLegacyColorModeEnabled anexado à
propriedade false :
<ContentPage ...
xmlns:ios="clr-
namespace:Xamarin.Forms.PlatformConfiguration.iOSSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
...
<Button Text="Button"
TextColor="Blue"
BackgroundColor="Bisque"
ios:VisualElement.IsLegacyColorModeEnabled="False" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.iOSSpecific;
...
_legacyColorModeDisabledButton.On<iOS>().SetIsLegacyColorModeEnabled(false);
O VisualElement.On<iOS> método Especifica que este específicos da plataforma serão executado apenas no iOS. O
VisualElement.SetIsLegacyColorModeEnabled método, no Xamarin.Forms.PlatformConfiguration.iOSSpecific
namespace, é usada para controlar se o modo de cor herdados é desabilitado. Além disso, o
VisualElement.GetIsLegacyColorModeEnabled método pode ser usado para retornar se o modo de cor herdado está
desabilitado.
O resultado é que o modo herdado de cor pode ser desabilitado, para que as cores definidas em uma exibição pelo
usuário permaneçam até mesmo quando o modo de exibição está desabilitado:
NOTE
Ao definir uma VisualStateGroup em uma exibição, o modo herdado de cor é totalmente ignorado. Para obter mais
informações sobre estados visuais, consulte o Gerenciador de estado Visual xamarin. Forms.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
iOSSpecific API
Xamarin. Forms em projetos do Xamarin nativo
12/04/2019 • 23 minutes to read
baixar o exemplo
Formulários nativos permitem que páginas ContentPage do xamarin. Forms derivado a ser consumido por
projetos nativos do xamarin. IOS, xamarin. Android e plataforma Universal do Windows (UWP ). Projetos nativos
podem consumir páginas com ContentPage derivada que são adicionadas diretamente ao projeto ou de uma
biblioteca .NET Standard, um projeto compartilhado ou uma biblioteca .NET Standard. Este artigo explica como
consumir páginas ContentPage derivadas que são adicionadas diretamente ao projetos nativos e como navegar
entre eles.
Normalmente, um aplicativo xamarin. Forms inclui uma ou mais páginas que derivam de ContentPage , e essas
páginas são compartilhadas por todas as plataformas em um projeto compartilhado ou o projeto de biblioteca
.NET Standard. No entanto, formas nativas permite ContentPage -derivado de páginas a serem adicionados
diretamente a aplicativos nativos do xamarin. IOS, xamarin. Android e UWP. Em comparação com a ter o projeto
nativo consumir ContentPage -páginas derivadas de um projeto de biblioteca .NET Standard ou o projeto
compartilhado, a vantagem de adicionar páginas diretamente em projetos nativos é que as páginas podem ser
estendidas com exibições nativas. Exibições nativas, em seguida, podem ser nomeadas no XAML com x:Name e
referenciada de code-behind. Para obter mais informações sobre exibições nativas, consulte exibições nativas.
O processo para o consumo de um xamarin. Forms ContentPage -página derivada em um projeto nativo é o
seguinte:
1. Adicione o pacote do NuGet xamarin. Forms para o projeto nativo.
2. Adicione a ContentPage -derivado de página e quaisquer dependências, para o projeto nativo.
3. Chame o método Forms.Init .
4. Construir uma instância de ContentPage -página derivada e convertê-lo para o tipo apropriado de nativo
usando um dos seguintes métodos de extensão: CreateViewController para iOS, CreateSupportFragment para o
Android, ou CreateFrameworkElement para UWP.
5. Navegue até a representação de tipo nativo do ContentPage -usando a API nativa de navegação de página
derivada.
Xamarin. Forms deve ser inicializado chamando o Forms.Init método antes de um projeto nativo pode construir
uma ContentPage -página derivada. Escolher quando fazer isso principalmente depende de quando é mais
conveniente em seu fluxo de aplicativo – pode ser executada na inicialização do aplicativo, ou imediatamente antes
do ContentPage -página derivada é construído. Neste artigo, e os aplicativos de exemplo que acompanha este
artigo, o Forms.Init método é chamado na inicialização do aplicativo.
NOTE
O NativeForms solução de aplicativo de exemplo não contém todos os projetos xamarin. Forms. Em vez disso, ele consiste
em um projeto xamarin. IOS, um projeto xamarin. Android e um projeto UWP. Cada projeto é um projeto nativo que usa
formulários nativos para consumir ContentPage -derivado de páginas. No entanto, não há nenhum motivo por que os
projetos nativos não podiam consumir ContentPage -derivado de páginas de um projeto de biblioteca .NET Standard ou o
projeto compartilhado.
Ao usar formulários Native, xamarin. Forms recursos como DependencyService , MessagingCenter e o mecanismo
de associação de dados, todo o trabalho ainda. No entanto, a navegação de página deve ser executada usando a
API nativa de navegação.
iOS
No iOS, o FinishedLaunching substituir no AppDelegate classe geralmente é o lugar para executar o aplicativo de
tarefas relacionadas à inicialização. Ele é chamado depois que o aplicativo foi iniciado e geralmente é substituído
para configurar a janela principal e exibir o controlador. O seguinte exemplo de código mostra o AppDelegate
classe no aplicativo de exemplo:
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
public static AppDelegate Instance;
UIWindow _window;
UINavigationController _navigation;
Instance = this;
_window = new UIWindow(UIScreen.MainScreen.Bounds);
UINavigationBar.Appearance.SetTitleTextAttributes(new UITextAttributes
{
TextColor = UIColor.Black
});
return true;
}
...
}
Uma vez a FinishedLaunching método foi executado, a interface do usuário definido no xamarin. Forms
PhonewordPage classe será exibida, conforme mostrado na seguinte captura de tela:
Interagindo com a interface do usuário, por exemplo, tocando em uma Button , resultará em manipuladores de
eventos no PhonewordPage de lógica de execução. Por exemplo, quando um usuário toca a histórico de
chamadas botão, o manipulador de eventos a seguir é executado:
Android
No Android, o OnCreate substituir no MainActivity classe geralmente é o lugar para executar o aplicativo de
tarefas relacionadas à inicialização. O seguinte exemplo de código mostra o MainActivity classe no aplicativo de
exemplo:
public class MainActivity : AppCompatActivity
{
public static MainActivity Instance;
Forms.Init(this, bundle);
Instance = this;
SetContentView(Resource.Layout.Main);
var toolbar = FindViewById<Toolbar>(Resource.Id.toolbar);
SetSupportActionBar(toolbar);
SupportActionBar.Title = "Phoneword";
Esse manipulador de eventos exibe um botão Voltar na barra de ação, desde que haja um ou mais Fragment
instâncias no fragmento de pilha de volta. A resposta ao tocar no botão Voltar é tratada pelo
OnOptionsItemSelected substituir:
Escolher um arquivo
Ao inserir uma ContentPage -derivado de página que usa um WebView que precisa para dar suporte um HTML
"Escolher arquivo" botão, o Activity precisará substituir o OnActivityResult método:
UWP
Na UWP, nativo App classe geralmente é o lugar para executar o aplicativo de tarefas relacionadas à inicialização.
Xamarin. Forms é geralmente inicializado, em aplicativos da UWP do xamarin. Forms, na OnLaunched substituir
em nativo App classe, para passar o LaunchActivatedEventArgs argumento para o Forms.Init método. Por esse
motivo, os aplicativos nativos de UWP que consomem um xamarin. Forms ContentPage -página derivada pode
chamar mais facilmente os Forms.Init método a partir de App.OnLaunched método.
Por padrão, nativo App classe inicia o MainPage classe como a primeira página do aplicativo. O seguinte exemplo
de código mostra o MainPage classe no aplicativo de exemplo:
public MainPage()
{
this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Enabled;
Instance = this;
this.Content = new Phoneword.UWP.Views.PhonewordPage().CreateFrameworkElement();
}
...
}
Uma vez a MainPage construtor foi executado, a interface do usuário definido no xamarin. Forms PhonewordPage
classe será exibida, conforme mostrado na seguinte captura de tela:
Interagindo com a interface do usuário, por exemplo, tocando em uma Button , resultará em manipuladores de
eventos no PhonewordPage de lógica de execução. Por exemplo, quando um usuário toca a histórico de
chamadas botão, o manipulador de eventos a seguir é executado:
Navegação no UWP normalmente é executada com o Frame.Navigate método, que usa um Page argumento.
Xamarin. Forms define uma Frame.Navigate método de extensão que usa um ContentPage -instância de página
derivada. Portanto, quando o NavigateToCallHistoryPage método é executado, a interface do usuário definido no
xamarin. Forms CallHistoryPage será exibida, conforme mostrado na seguinte captura de tela:
Quando o CallHistoryPage for exibida, tocando o back seta será exibida a FrameworkElement para o
CallHistoryPage da pilha Voltar no aplicativo, retornando o usuário para o FrameworkElement para o
PhonewordPage classe.
Habilitando o suporte de navegação regressiva
Na UWP, aplicativos devem habilitar a navegação para todos os software e hardware back botões, em fatores
forma de dispositivo diferentes. Isso pode ser feito ao registrar um manipulador de eventos para o BackRequested
evento, que pode ser executado em de OnLaunched método nativo App classe:
if (rootFrame == null)
{
...
// Place the frame in the current Window
Window.Current.Content = rootFrame;
SystemNavigationManager.GetForCurrentView().BackRequested += OnBackRequested;
}
...
}
O OnNavigated manipulador de eventos, que é executado em resposta ao Navigated evento disparando, atualiza a
visibilidade do botão Voltar da barra de título quando ocorrer a navegação de página. Isso garante que o botão
Voltar de barra de título é visível se a pilha Voltar no aplicativo não está vazia ou removido da barra de título se a
pilha Voltar no aplicativo está vazia.
Para obter mais informações sobre o suporte de navegação regressiva na UWP, consulte histórico de navegação e
para trás a navegação para aplicativos UWP.
Resumo
Formulários nativos permitem que o xamarin. Forms ContentPage -derivado de páginas a ser consumido por
projetos nativos do xamarin. IOS, xamarin. Android e plataforma Universal do Windows (UWP ). Projetos nativos
podem consumir ContentPage -derivado de páginas que são adicionadas diretamente ao projeto, ou de um projeto
de biblioteca .NET Standard ou o projeto compartilhado. Este artigo explicou como consumir ContentPage -
derivado de páginas que são adicionadas diretamente para projetos nativos e como navegar entre eles.
Links relacionados
NativeForms (amostra)
Exibições nativas
Modos de exibição nativo no xamarin. Forms
12/04/2019 • 2 minutes to read
Exibições nativo do iOS, Android e o Windows UWP (plataforma Universal) podem ser referenciadas
diretamente do xamarin. Forms. Propriedades e manipuladores de eventos podem ser definidos em exibições
nativo, e eles podem interagir com exibições xamarin. Forms.
Exibições nativas em C#
Exibições nativo do iOS, Android e UWP podem ser referenciadas diretamente do xamarin. Forms páginas
criadas usando o c#.
Links relacionados
Formulários nativos
Exibições nativas em XAML
12/04/2019 • 23 minutes to read
baixar o exemplo
Exibições nativas do iOS, Android e plataforma Universal do Windows podem ser referenciadas diretamente de
arquivos XAML de xamarin. Forms. Propriedades e os manipuladores de eventos podem ser definidos em exibições
nativas e eles podem interagir com exibições do xamarin. Forms. Este artigo demonstra como consumir exibições
nativas de arquivos XAML de xamarin. Forms.
Este artigo discute os seguintes tópicos:
Consumindo exibições nativas – o processo para o consumo de um modo de exibição nativo de XAML.
Usando associações nativas – e para as propriedades de exibições nativas de vinculação de dados.
Passando argumentos para exibições nativas – passando argumentos para construtores de modo nativo e
chamar métodos de fábrica de modo nativo.
Referindo-se a exibições nativas do código – recuperar instâncias de modo nativo declarado em um arquivo
XAML, de seu arquivo code-behind.
Exibições nativas da subclasse – subclasses exibições nativas para definir uma API amigável a XAML.
Visão geral
Para inserir uma exibição nativa em um arquivo XAML de xamarin. Forms:
1. Adicionar um xmlns declaração de namespace no arquivo XAML para o namespace que contém o modo
nativo.
2. Crie uma instância do modo nativo no arquivo XAML.
NOTE
XAMLC deve ser desativado para todas as páginas XAML que usam exibições nativas.
Para fazer referência a um modo de exibição nativo de um arquivo code-behind, você deve usar um projeto de
ativo compartilhado (SAP ) e encapsule o código específico da plataforma com diretivas de compilação condicional.
Para obter mais informações, consulte referindo-se a exibições nativas do código.
Bem como especificar o clr-namespace e assembly para um namespace de modo nativo, um targetPlatform
também deve ser especificado. Isso deve ser definido como um dos valores da TargetPlatform enumeração e
normalmente será definido como iOS , Android , ou Windows . Em tempo de execução, o analisador XAML
ignorará quaisquer prefixos de namespace XML que têm um targetPlatform que não coincida com a plataforma
na qual o aplicativo está em execução.
Cada declaração de namespace pode ser usada para fazer referência a qualquer classe ou estrutura de namespace
especificado. Por exemplo, o ios declaração de namespace pode ser usada para fazer referência a qualquer classe
ou estrutura do iOS UIKit namespace. Propriedades do modo nativo podem ser definidas por meio de XAML,
mas os tipos de objeto e propriedade devem coincidir. Por exemplo, o UILabel.TextColor estiver definida como
UIColor.Red usando o x:Static extensão de marcação e o ios namespace.
Propriedades vinculáveis e propriedades vinculáveis anexadas podem também ser definidas em exibições nativas
usando o Class.BindableProperty="value" sintaxe. Cada exibição nativa é encapsulada em uma plataforma
específica NativeViewWrapper instância, que deriva de Xamarin.Forms.View classe. Definir uma propriedade
associável ou a propriedade associável anexada em um modo de exibição nativo transfere o valor da propriedade
para o wrapper. Por exemplo, um layout horizontal centralizado pode ser especificado definindo
View.HorizontalOptions="Center" na exibição nativa.
NOTE
Observe que os estilos não podem ser usados com exibições nativas, porque os estilos somente podem direcionar as
propriedades que têm o respaldo BindableProperty objetos.
Construtores de widget Android geralmente requerem o Android Context objeto como um argumento e isso
podem ser disponibilizado por meio de uma propriedade estática no MainActivity classe. Portanto, ao criar um
widget de Android em XAML, o Context objeto geralmente deve ser passado ao construtor do widget usando o
x:Arguments atributo com um x:Static extensão de marcação. Para obter mais informações, consulte passando
argumentos para exibições nativas.
NOTE
Observe que uma exibição nativa com a nomenclatura x:Name não é possível em um projeto de biblioteca .NET Standard ou
um projeto de ativo compartilhado (SAP). Isso vai gerar uma variável do tipo nativo, o que causará um erro de compilação.
No entanto, podem ser ajustadas exibições nativas em ContentView instâncias e recuperados no arquivo code-behind,
desde que um SAP está sendo usado. Para obter mais informações, consulte referindo-se a uma exibição nativo do código.
Associações nativas
Vinculação de dados é usada para sincronizar uma interface do usuário com sua fonte de dados e simplifica como
um aplicativo xamarin. Forms exibe e interage com seus dados. Desde que o objeto de origem implementa o
INotifyPropertyChanged interface, as alterações na código -fonte objeto são enviadas automaticamente para o
destino objeto pela estrutura de associação e as alterações no alvo objeto opcionalmente pode ser enviado para o
origem objeto.
Propriedades de exibições nativas também podem usar a vinculação de dados. O exemplo de código a seguir
demonstra a associação de dados usando propriedades de exibições nativas:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidLocal="clr-
namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
xmlns:win="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
xmlns:local="clr-namespace:NativeSwitch"
x:Class="NativeSwitch.NativeSwitchPage">
<StackLayout Margin="20">
<Label Text="Native Views Demo" FontAttributes="Bold" HorizontalOptions="Center" />
<Entry Placeholder="This Entry is bound to the native switch" IsEnabled="{Binding IsSwitchOn}" />
<ios:UISwitch On="{Binding Path=IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=ValueChanged}"
OnTintColor="{x:Static ios:UIColor.Red}"
ThumbTintColor="{x:Static ios:UIColor.Blue}" />
<androidWidget:Switch x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
Checked="{Binding Path=IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=CheckedChange}"
Text="Enable Entry?" />
<win:ToggleSwitch Header="Enable Entry?"
OffContent="No"
OnContent="Yes"
IsOn="{Binding IsSwitchOn, Mode=TwoWay, UpdateSourceEventName=Toggled}" />
</StackLayout>
</ContentPage>
O UIFont.FromName método de fábrica é usado para definir a UILabel.Font propriedade para um novo UIFont no
iOS. O UIFont nome e tamanho são especificados pelos argumentos de método que são filhos do x:Arguments
atributo.
O Typeface.Create método de fábrica é usado para definir a TextView.Typeface propriedade para um novo
Typeface no Android. O Typeface nome da família e estilo são especificados pelos argumentos de método que
são filhos do x:Arguments atributo.
O FontFamily construtor é usado para definir a TextBlock.FontFamily propriedade para um novo FontFamily no
Universal Windows Platform (UWP ). O FontFamily nome é especificado pelo argumento do método que é um
filho do x:Arguments atributo.
NOTE
Argumentos devem corresponder aos tipos exigidos pelo método de construtor ou de fábrica.
Para obter mais informações sobre como passar argumentos em XAML, consulte passando argumentos em
XAML.
A API nativa, em seguida, pode ser invocada no modo de nativo para executar as operações desejadas. Essa
abordagem também oferece o benefício que várias exibições nativas do XAML para diferentes plataformas podem
ser filhos dos mesmos ContentView . O exemplo de código a seguir demonstra essa técnica:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
xmlns:androidWidget="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidLocal="clr-
namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
xmlns:winControls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
xmlns:local="clr-namespace:NativeViewInsideContentView"
x:Class="NativeViewInsideContentView.NativeViewInsideContentViewPage">
<StackLayout Margin="20">
<ContentView x:Name="contentViewTextParent" HorizontalOptions="Center"
VerticalOptions="CenterAndExpand">
<ios:UILabel Text="Text in a UILabel" TextColor="{x:Static ios:UIColor.Red}" />
<androidWidget:TextView x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
Text="Text in a TextView" />
<winControls:TextBlock Text="Text in a TextBlock" />
</ContentView>
<ContentView x:Name="contentViewButtonParent" HorizontalOptions="Center"
VerticalOptions="EndAndExpand">
<ios:UIButton TouchUpInside="OnButtonTap" View.HorizontalOptions="Center"
View.VerticalOptions="Center" />
<androidWidget:Button x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
Text="Scale and Rotate Text"
Click="OnButtonTap" />
<winControls:Button Content="Scale and Rotate Text" />
</ContentView>
</StackLayout>
</ContentPage>
No exemplo acima, as exibições de nativas para cada plataforma são filhos de ContentView controles, com o
x:Name valor de atributo que está sendo usado para recuperar o ContentView no code-behind:
public partial class NativeViewInsideContentViewPage : ContentPage
{
public NativeViewInsideContentViewPage()
{
InitializeComponent();
#if __IOS__
var wrapper = (Xamarin.Forms.Platform.iOS.NativeViewWrapper)contentViewButtonParent.Content;
var button = (UIKit.UIButton)wrapper.NativeView;
button.SetTitle("Scale and Rotate Text", UIKit.UIControlState.Normal);
button.SetTitleColor(UIKit.UIColor.Black, UIKit.UIControlState.Normal);
#endif
#if __ANDROID__
var wrapper = (Xamarin.Forms.Platform.Android.NativeViewWrapper)contentViewTextParent.Content;
var textView = (Android.Widget.TextView)wrapper.NativeView;
textView.SetTextColor(Android.Graphics.Color.Red);
#endif
#if WINDOWS_UWP
var textWrapper = (Xamarin.Forms.Platform.UWP.NativeViewWrapper)contentViewTextParent.Content;
var textBlock = (Windows.UI.Xaml.Controls.TextBlock)textWrapper.NativeElement;
textBlock.Foreground = new Windows.UI.Xaml.Media.SolidColorBrush(Windows.UI.Colors.Red);
var buttonWrapper = (Xamarin.Forms.Platform.UWP.NativeViewWrapper)contentViewButtonParent.Content;
var button = (Windows.UI.Xaml.Controls.Button)buttonWrapper.NativeElement;
button.Click += (sender, args) => OnButtonTap(sender, EventArgs.Empty);
#endif
}
O ContentView.Content propriedade é acessada para recuperar o modo de exibição nativo encapsulado como um
específico da plataforma NativeViewWrapper instância. O NativeViewWrapper.NativeElement propriedade é acessada,
em seguida, para recuperar o modo nativo como seu tipo nativo. API nativa do modo de exibição, em seguida, é
chamado para realizar as operações desejadas.
O iOS e Android botões nativo compartilham a mesma OnButtonTap manipulador de eventos, porque cada botão
nativo consome um EventHandler delegar em resposta a um evento de toque. No entanto, a Universal Windows
Platform (UWP ) usa um separado RoutedEventHandler , que por sua vez consome o OnButtonTap manipulador de
eventos neste exemplo. Portanto, quando um botão nativo é clicado, o OnButtonTap manipulador de eventos é
executado, que se dimensiona e gira o controle nativo contido a ContentView chamado contentViewTextParent . As
capturas de tela a seguir demonstram essa que ocorrem em cada plataforma:
Criando subclasses exibições nativas
Muitos iOS e Android exibições nativas não são adequadas para criar uma instância em XAML, porque eles usam
métodos, em vez de propriedades, para configurar o controle. Exibições nativas de subclasse nos wrappers que
definem uma API de XAML compatível com mais do que usa as propriedades para o controle de instalação, e que
usa eventos independente de plataforma é a solução para esse problema. Os modos de exibição encapsulados
nativos podem ser colocados em um projeto de ativo compartilhado (SAP ) e cercados com diretivas de
compilação condicional, ou colocados em projetos específicos da plataforma e referenciados de XAML em um
projeto de biblioteca .NET Standard.
O exemplo de código a seguir demonstra uma página de xamarin. Forms que consome uma subclasse exibições
nativas:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:ios="clr-namespace:UIKit;assembly=Xamarin.iOS;targetPlatform=iOS"
xmlns:iosLocal="clr-
namespace:SubclassedNativeControls.iOS;assembly=SubclassedNativeControls.iOS;targetPlatform=iOS"
xmlns:android="clr-namespace:Android.Widget;assembly=Mono.Android;targetPlatform=Android"
xmlns:androidLocal="clr-
namespace:SimpleColorPicker.Droid;assembly=SimpleColorPicker.Droid;targetPlatform=Android"
xmlns:androidLocal="clr-
namespace:SubclassedNativeControls.Droid;assembly=SubclassedNativeControls.Droid;targetPlatform=Android"
xmlns:winControls="clr-namespace:Windows.UI.Xaml.Controls;assembly=Windows, Version=255.255.255.255,
Culture=neutral, PublicKeyToken=null, ContentType=WindowsRuntime;targetPlatform=Windows"
xmlns:local="clr-namespace:SubclassedNativeControls"
x:Class="SubclassedNativeControls.SubclassedNativeControlsPage">
<StackLayout Margin="20">
<Label Text="Subclassed Native Views Demo" FontAttributes="Bold" HorizontalOptions="Center" />
<StackLayout Orientation="Horizontal">
<Label Text="You have chosen:" />
<Label Text="{Binding SelectedFruit}" />
</StackLayout>
<iosLocal:MyUIPickerView ItemsSource="{Binding Fruits}"
SelectedItem="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=SelectedItemChanged}" />
<androidLocal:MySpinner x:Arguments="{x:Static androidLocal:MainActivity.Instance}"
ItemsSource="{Binding Fruits}"
SelectedObject="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=ItemSelected}" />
<winControls:ComboBox ItemsSource="{Binding Fruits}"
SelectedItem="{Binding SelectedFruit, Mode=TwoWay, UpdateSourceEventName=SelectionChanged}" />
</StackLayout>
</ContentPage>
A página contém um Label que exibe as frutas escolhidas pelo usuário de um controle nativo. O Label está
associado a SubclassedNativeControlsPageViewModel.SelectedFruit propriedade. O BindingContext da página é
definido como uma nova instância dos SubclassedNativeControlsPageViewModel classe no arquivo code-behind, com
a classe ViewModel Implementando o INotifyPropertyChanged interface.
A página também contém um modo de exibição de seletor de nativo para cada plataforma. Cada exibição nativa
exibe a coleção de frutas, associando sua ItemSource propriedade para o
SubclassedNativeControlsPageViewModel.Fruits coleção. Isso permite que o usuário escolha uma frutas, conforme
mostrado nas capturas de tela seguir:
No iOS e Android os seletores nativos usam métodos para configurar os controles. Portanto, esses seletores
devem ser uma subclasse para expor as propriedades para torná-las amigável a XAML. Na Universal Windows
Platform (UWP ), o ComboBox já é compatível com XAML e, portanto, não exige a criação de subclasses.
iOS
As subclasses de implementação do iOS a UIPickerView exibição e expõe propriedades e um evento que pode ser
facilmente consumido de XAML:
public class MyUIPickerView : UIPickerView
{
public event EventHandler<EventArgs> SelectedItemChanged;
public MyUIPickerView()
{
var model = new PickerModel();
model.ItemChanged += (sender, e) =>
{
if (SelectedItemChanged != null)
{
SelectedItemChanged.Invoke(this, e);
}
};
Model = model;
}
O PickerModel classe fornece o armazenamento subjacente para o MyUIPickerView classe, por meio de Items
propriedade. Sempre que o item selecionado na MyUIPickerView alterações, o Selected método é executado, que
atualiza o índice selecionado e aciona o ItemChanged eventos. Isso garante que o SelectedItem propriedade
sempre retornará o último item escolhido pelo usuário. Além disso, o PickerModel classe substitui os métodos que
são usados para configurar o MyUIPickerView instância.
Android
As subclasses de implementação do Android a Spinner exibição e expõe propriedades e um evento que pode ser
facilmente consumido de XAML:
class MySpinner : Spinner
{
ArrayAdapter adapter;
IList<string> items;
Resumo
Este artigo demonstrou como consumir exibições nativas de arquivos XAML de xamarin. Forms. Propriedades e os
manipuladores de eventos podem ser definidos em exibições nativas e eles podem interagir com exibições do
xamarin. Forms.
Links relacionados
NativeSwitch (amostra)
Forms2Native (amostra)
NativeViewInsideContentView (amostra)
SubclassedNativeControls (amostra)
Formulários nativos
Passando argumentos em XAML
Exibições nativas em c#
12/04/2019 • 12 minutes to read
baixar o exemplo
Exibições nativas do iOS, Android e UWP podem ser referenciadas diretamente das páginas do xamarin. Forms
criadas usando a linguagem c#. Este artigo demonstra como adicionar exibições nativas para um layout de
xamarin. Forms criado usando a linguagem c# e como substituir o layout dos modos de exibição personalizados
para corrigir seu uso da API de medição.
Visão geral
Qualquer controle do xamarin. Forms que permite Content deve ser definido, ou que tenha um Children , pode
adicionar modos de exibição específicos da plataforma. Por exemplo, um iOS UILabel podem ser adicionados
diretamente para o ContentView.Content propriedade, ou para o StackLayout.Children coleção. No entanto,
observe que essa funcionalidade requer o uso de #if define em soluções de projeto do xamarin. Forms
compartilhado e não está disponível em soluções do xamarin. Forms .NET Standard library.
As capturas de tela a seguir demonstram específicos da plataforma exibições ter sido adicionado a um xamarin.
Forms StackLayout :
A capacidade de adicionar modos de exibição específicos da plataforma para um layout de xamarin. Forms é
habilitada por dois métodos de extensão em cada plataforma:
Add – Adiciona uma exibição específica da plataforma para o Children coleção de um layout.
ToView – usa uma exibição específica de plataforma e o encapsula como um xamarin. Forms View que pode
ser definido como o Content propriedade de um controle.
Usando esses métodos em um projeto compartilhado do xamarin. Forms requer importando o namespace
apropriado do xamarin. Forms específicos da plataforma:
iOS – Xamarin.Forms.Platform.iOS
Android – Xamarin.Forms.Platform.Android
Plataforma universal do Windows (UWP ) – Xamarin.Forms.Platform.UWP
O exemplo supõe que o stackLayout e contentView instâncias criadas anteriormente no XAML ou c#.
Android
O exemplo de código a seguir demonstra como adicionar um TextView para um StackLayout e um ContentView :
O exemplo supõe que o stackLayout e contentView instâncias criadas anteriormente no XAML ou c#.
Plataforma Universal do Windows
O exemplo de código a seguir demonstra como adicionar um TextBlock para um StackLayout e um ContentView
:
O exemplo supõe que o stackLayout e contentView instâncias criadas anteriormente no XAML ou c#.
Substituindo as medidas da plataforma para modos de exibição
personalizados
Exibições personalizadas em cada plataforma geralmente só corretamente implementam medida para o cenário de
layout para o qual eles foram criados. Por exemplo, uma exibição personalizada pode ter sido projetada para
ocupar apenas metade da largura disponível do dispositivo. No entanto, após o que está sendo compartilhado com
outros usuários, o modo de exibição personalizado pode ser necessário para ocupar a largura total disponível do
dispositivo. Portanto, pode ser necessário substituir uma implementação de medição de modos de exibição
personalizados quando sendo reutilizadas em um layout de xamarin. Forms. Por esse motivo, o Add e ToView
métodos de extensão fornecem substituições que permitem que os representantes de medida seja especificado,
que podem substituir o layout do modo de exibição personalizado quando ele é adicionado a um layout de
xamarin. Forms.
As seções a seguir demonstram como substituir o layout dos modos de exibição personalizados, para corrigir seu
uso da API de medição.
iOS
O seguinte exemplo de código mostra a CustomControl classe, que herda de UILabel :
Uma instância dessa exibição é adicionada a um StackLayout , conforme demonstrado no exemplo de código a
seguir:
No entanto, porque o CustomControl.SizeThatFits substituição sempre retorna uma altura de 150, o modo de
exibição será exibido com um espaço vazio acima e abaixo dele, conforme mostrado na seguinte captura de tela:
Uma solução para esse problema é fornecer um GetDesiredSizeDelegate implementação, conforme demonstrado
no exemplo de código a seguir:
if (uiView == null) {
return null;
}
Esse método usa a largura fornecida pelo CustomControl.SizeThatFits método, mas substitui a altura de 150 de
altura de 70. Quando o CustomControl instância é adicionada ao StackLayout , o FixSize método pode ser
especificado como o GetDesiredSizeDelegate para corrigir a medida incorreta fornecida pelo CustomControl classe:
Isso resulta na exibição personalizada que está sendo exibida corretamente, sem espaço vazio acima e abaixo dele,
conforme mostrado na seguinte captura de tela:
Android
O seguinte exemplo de código mostra a CustomControl classe, que herda de TextView :
public class CustomControl : TextView
{
public CustomControl (Context context) : base (context)
{
}
Uma instância dessa exibição é adicionada a um StackLayout , conforme demonstrado no exemplo de código a
seguir:
Uma solução para esse problema é fornecer um GetDesiredSizeDelegate implementação, conforme demonstrado
no exemplo de código a seguir:
Esse método usa a largura fornecida pelo CustomControl.OnMeasure método, mas o multiplica por dois. Quando o
CustomControl instância é adicionada ao StackLayout , o FixSize método pode ser especificado como o
GetDesiredSizeDelegate para corrigir a medida incorreta fornecida pelo CustomControl classe:
Isso resulta no modo de exibição personalizado que está sendo exibida corretamente, que ocupa a largura do
dispositivo, conforme mostrado na seguinte captura de tela:
public CustomControl()
{
textBlock = new TextBlock
{
MinHeight = 0,
MaxHeight = double.PositiveInfinity,
MinWidth = 0,
MaxWidth = double.PositiveInfinity,
FontSize = 14,
TextWrapping = TextWrapping.Wrap,
VerticalAlignment = VerticalAlignment.Center
};
Children.Add(textBlock);
}
Uma instância dessa exibição é adicionada a um StackLayout , conforme demonstrado no exemplo de código a
seguir:
Esse método usa a largura fornecida pelo CustomControl.ArrangeOverride método, mas o multiplica por dois. Isso
resulta no modo de exibição personalizado que está sendo exibida corretamente, que ocupa a largura do
dispositivo, conforme mostrado na seguinte captura de tela:
Resumo
Este artigo explicou como adicionar exibições nativas para um layout de xamarin. Forms criado usando a
linguagem c# e como substituir o layout dos modos de exibição personalizados para corrigir seu uso da API de
medição.
Links relacionados
NativeEmbedding (amostra)
Formulários nativos
Outras plataformas xamarin. Forms
12/04/2019 • 2 minutes to read
GTK
Xamarin. Forms agora tem suporte para aplicativos do GTK # visualização.
Mac
Xamarin. Forms agora tem suporte para aplicativos macOS visualização.
Tizen
Tizen .NET permite que você crie aplicativos .NET com xamarin. Forms e Tizen .NET Framework.
WPF
Xamarin. Forms agora tem suporte de visualização para aplicativos do Windows Presentation Foundation (WPF ).
Instalação de plataforma do GTK #
12/04/2019 • 10 minutes to read
Xamarin. Forms agora tem suporte para aplicativos do GTK # visualização. O GTK # é um kit de ferramentas de
interface gráfica do usuário que vincula o Kit de ferramentas GTK + e uma variedade de bibliotecas GNOME,
permitindo o desenvolvimento de GNOME totalmente nativo aplicativos de gráficos usando o Mono e .NET. Este
artigo demonstra como adicionar um projeto GTK # a uma solução do xamarin. Forms.
Antes de começar, crie uma nova solução xamarin. Forms ou usar uma solução existente do xamarin. Forms, por
exemplo, GameOfLife.
NOTE
Embora este artigo se concentra na adição de um aplicativo do GTK # a uma solução do xamarin. Forms no VS2017 e o
Visual Studio para Mac, ele também pode ser executado no MonoDevelop para Linux.
namespace GameOfLife.GTK
{
class MainClass
{
[STAThread]
public static void Main(string[] args)
{
Gtk.Application.Init();
Forms.Init();
Gtk.Application.Run();
}
}
}
Esse código inicializa o GTK # e xamarin. Forms, cria uma janela do aplicativo e executa o aplicativo.
11. No Gerenciador de soluções, com o botão direito do mouse no projeto GTK e selecione propriedades.
12. No propriedades janela, selecione a aplicativo guia e altere a tipo de saída lista suspensa para
aplicativo Windows.
13. No Gerenciador de soluções, clique com botão direito no projeto GTK e selecione definir como projeto
de inicialização. Pressione F5 para executar o programa com o depurador do Visual Studio, na área de
trabalho do Windows:
Próximas etapas
Especificidades da plataforma
Você pode determinar em qual plataforma está em execução no seu aplicativo xamarin. Forms de XAML ou
código. Isso permite que você altere as características do programa quando ele é executado em GTK #. No código,
comparar o valor de Device.RuntimePlatform com o Device.GTK constante (que é igual a cadeia de caracteres
"GTK"). Se houver uma correspondência, o aplicativo está em execução em GTK #.
No XAML, você pode usar o OnPlatform marca para selecionar um valor de propriedade específico da plataforma:
<Button.TextColor>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="White" />
<On Platform="macOS" Value="White" />
<On Platform="Android" Value="Black" />
<On Platform="GTK" Value="Blue" />
</OnPlatform>
</Button.TextColor>
Ícone do Aplicativo
Você pode definir o ícone do aplicativo na inicialização:
window.SetApplicationIcon("icon.png");
Temas
Há uma grande variedade de temas disponíveis para GTK #, e eles podem ser usados em um aplicativo xamarin.
Forms:
GtkThemes.Init ();
GtkThemes.LoadCustomTheme ("Themes/gtkrc");
Formulários nativos
Formulários nativos permite que o xamarin. Forms ContentPage -derivado de páginas a ser consumido por
projetos nativos, incluindo projetos GTK #. Isso pode ser feito criando uma instância das ContentPage -derivado de
página e convertê-lo para o nativo GTK # tipo usando o CreateContainer método de extensão:
Para obter mais informações sobre formulários nativos, consulte formulários nativos.
Problemas
Esta é uma visualização, portanto, você deve esperar que nem tudo está pronto para produção. O status atual de
implementação, consulte Statuse para os problemas conhecidos atuais, consulte problemas conhecidos e
pendentes.
Configuração de plataforma do Mac
12/04/2019 • 5 minutes to read
Antes de começar, crie (ou usar uma existente) projeto xamarin. Forms. Você só pode adicionar aplicativos do Mac
usando o Visual Studio para Mac.
5. No projeto do Mac, clique duas vezes em pacotes > Adicionar pacotes... para adicionar o xamarin. Forms
NuGet. Você também deve atualizar os outros projetos para usar a mesma versão do pacote NuGet do
xamarin. Forms.
6. No projeto do Mac, clique duas vezes em referências e adicione uma referência ao projeto xamarin. Forms
(projeto de biblioteca de projeto compartilhado ou .NET Standard).
8. Atualização AppDelegate para inicializar o xamarin. Forms, criar uma janela e carregar o aplicativo xamarin.
Forms (Lembre-se de definir um apropriado Title ). Se você tiver outras dependências que precisam ser
inicializados, fazer isso aqui também.
using Xamarin.Forms;
using Xamarin.Forms.Platform.MacOS;
// also add a using for the Xamarin.Forms project, if the namespace is different to this file
...
[Register("AppDelegate")]
public class AppDelegate : FormsApplicationDelegate
{
NSWindow window;
public AppDelegate()
{
var style = NSWindowStyle.Closable | NSWindowStyle.Resizable | NSWindowStyle.Titled;
Você pode editar o sistema de menus no storyboard para remover os itens indesejados.
10. Por fim, adicione qualquer recurso local (por exemplo. arquivos de imagem) de projetos de plataforma
existentes que são necessários.
11. Projeto do Mac agora deve executar seu código do xamarin. Forms em macOS!
Próximas etapas
Estilo
Com as alterações recentes feitas OnPlatform agora você pode direcionar qualquer número de plataformas. Isso
inclui o macOS.
<Button.TextColor>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="White"/>
<On Platform="macOS" Value="White"/>
<On Platform="Android" Value="Black"/>
</OnPlatform>
</Button.TextColor>
Observe que você também pode dobrar em plataformas como este: <On Platform="iOS, macOS" ...> .
Posição e tamanho da janela
Você pode ajustar o tamanho inicial e o local da janela no AppDelegate :
Problemas Conhecidos
Esta é uma visualização, portanto, você deve esperar que nem tudo está pronto para produção. Abaixo estão
algumas coisas que você pode encontrar conforme você adiciona o macOS para seus projetos:
Nem todos os NuGets estão prontos para o macOS
Você pode achar que algumas das bibliotecas que você usa não ainda dão suporte a macOS. Nesse caso, você
precisará enviar uma solicitação para o mantenedor do projeto para adicioná-lo. Até que tenham suporte, você
precisa procurar alternativas.
Recursos ausentes do xamarin. Forms
Nem todos os recursos do xamarin. Forms forem concluídos nesta visualização. Para obter mais informações,
consulte suporte de plataforma macOS Status na xamarin. Forms repositório do GitHub.
Links relacionados
Xamarin.Mac
Tizen .NET
12/04/2019 • 2 minutes to read
Tizen .NET permite que você desenvolva aplicativos de Tizen sejam executados em dispositivos Samsung,
incluindo TVs, dispositivos portáteis, dispositivos móveis e outros dispositivos de IoT.
Tizen .NET permite que você crie aplicativos .NET com xamarin. Forms e Tizen .NET framework. Xamarin. Forms
permite que você crie com facilidade interfaces do usuário, enquanto a API TizenFX fornece interfaces para o
hardware que se encontra no modo de TV moderno, móvel, dispositivo portátil e dispositivos IoT. Para obter mais
informações sobre o .NET Tizen, consulte Introdução ao aplicativo do .NET Tizen.
Introdução
Antes de poder começar a desenvolver aplicativos .NET Tizen, primeiro você deve configurar seu ambiente de
desenvolvimento. Para obter mais informações, consulte instalar o Visual Studio Tools for Tizen.
Para obter informações sobre como adicionar um projeto .NET Tizen a uma solução existente do xamarin. Forms,
consulte criando seu primeiro aplicativo .NET Tizen.
Documentação
Documentação do xamarin. Forms – como compilar aplicativos de plataforma cruzada com C# e xamarin.
Forms.
Developer.tizen.org – documentação e vídeos para ajudá-lo a criar e implantar aplicativos Tizen.
Exemplos
Samsung mantém uma bifurcação do exemplos de xamarin. Forms com projetos Tizen adicionados, e há um
repositório separado Tizen-Csharp-Samples que contém projetos adicionais, incluindo o dispositivo portátil e
Demonstrações de TV específicos.
Instalação de plataforma do WPF
12/04/2019 • 6 minutes to read
Xamarin. Forms agora tem suporte de visualização para o Windows Presentation Foundation (WPF ). Este artigo
demonstra como adicionar um projeto do WPF para uma solução xamarin. Forms.
Antes de começar, criar uma nova solução xamarin. Forms no Visual Studio de 2019 ou usar uma solução existente
do xamarin. Forms, por exemplo, BoxViewClock. Você só pode adicionar aplicativos do WPF a uma solução do
xamarin. Forms no Windows.
7. No projeto do WPF, clique duas vezes em referências. No Gerenciador de referências caixa de diálogo,
selecione projetos na esquerda e verifique a caixa de seleção adjacente para o BoxViewClock projeto:
8. Editar o MainWindow. XAML arquivo do projeto WPF. No Window marca, adicione uma declaração de
namespace XML para o Xamarin.Forms.Platform.WPF assembly e namespace:
xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF"
Agora, altere a Window marca a wpf:FormsApplicationPage . Alterar o Title definindo como o nome do seu
aplicativo, por exemplo, BoxViewClock. O arquivo XAML concluído deve ter esta aparência:
<wpf:FormsApplicationPage x:Class="BoxViewClock.WPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:wpf="clr-namespace:Xamarin.Forms.Platform.WPF;assembly=Xamarin.Forms.Platform.WPF"
xmlns:local="clr-namespace:BoxViewClock.WPF"
mc:Ignorable="d"
Title="BoxViewClock" Height="450" Width="800">
<Grid>
</Grid>
</wpf:FormsApplicationPage>
9. Editar o MainWindow.xaml.cs arquivo do projeto WPF. Adicione dois novos using diretivas:
using Xamarin.Forms;
using Xamarin.Forms.Platform.WPF;
Forms.Init();
LoadApplication(new BoxViewClock.App());
Exceto para comentários e não utilizadas using diretivas, completo MainWindows.xaml.cs arquivo deve
ter esta aparência:
using Xamarin.Forms;
using Xamarin.Forms.Platform.WPF;
namespace BoxViewClock.WPF
{
public partial class MainWindow : FormsApplicationPage
{
public MainWindow()
{
InitializeComponent();
Forms.Init();
LoadApplication(new BoxViewClock.App());
}
}
}
10. Clique com botão direito no projeto do WPF na Gerenciador de soluções e selecione definir como
projeto de inicialização. Pressione F5 para executar o programa com o depurador do Visual Studio, na
área de trabalho do Windows:
Próximas etapas
Especificidades da plataforma
Você pode determinar em qual plataforma está em execução no seu aplicativo xamarin. Forms de código ou
XAML. Isso permite que você altere as características do programa quando ele está em execução no WPF. No
código, comparar o valor de Device.RuntimePlatform com o Device.WPF constante (que é igual a cadeia de
caracteres "WPF"). Se houver uma correspondência, o aplicativo está em execução no WPF.
No XAML, você pode usar o OnPlatform marca para selecionar um valor de propriedade específico da plataforma:
<Button.TextColor>
<OnPlatform x:TypeArguments="Color">
<On Platform="iOS" Value="White" />
<On Platform="macOS" Value="White" />
<On Platform="Android" Value="Black" />
<On Platform="WPF" Value="Blue" />
</OnPlatform>
</Button.TextColor>
Tamanho da janela
Você pode ajustar o tamanho inicial da janela no WPF MainWindow. XAML arquivo:
Problemas
Esta é uma visualização, portanto, você deve esperar que nem tudo está pronto para produção. Nem todos os
pacotes do NuGet para xamarin. Forms estão prontos para WPF, e alguns recursos talvez não esteja funcionando
totalmente.
Especificidades da plataforma
12/04/2019 • 11 minutes to read
baixar o exemplo
Especificidades da plataforma permitem que você consumir funcionalidade só está disponível em uma plataforma
específica, sem implementar renderizadores personalizados ou efeitos.
O processo para o consumo de um específico da plataforma por meio de XAML, ou por meio do código API
fluente é da seguinte maneira:
1. Adicionar um xmlns declaração ou using diretiva para o Xamarin.Forms.PlatformConfiguration namespace.
2. Adicionar um xmlns declaração ou using diretiva para o namespace que contém a funcionalidade específica
da plataforma:
a. No iOS, essa é a Xamarin.Forms.PlatformConfiguration.iOSSpecific namespace.
b. No Android, essa é a Xamarin.Forms.PlatformConfiguration.AndroidSpecific namespace. Para Android
AppCompat, esse é o Xamarin.Forms.PlatformConfiguration.AndroidSpecific.AppCompat namespace.
c. Na plataforma Universal do Windows, isso é o Xamarin.Forms.PlatformConfiguration.WindowsSpecific
namespace.
3. Aplicar o específicos da plataforma de XAML ou de código com o On<T> API fluente. O valor de T pode ser o
iOS , Android , ou Windows tipos do Xamarin.Forms.PlatformConfiguration namespace.
NOTE
Observe que a tentativa de consumir um específico da plataforma em uma plataforma em que ele não está disponível não
resultará em erro. Em vez disso, o código será executado sem o específicos da plataforma que está sendo aplicado.
Especificidades da plataforma consumidos por meio de On<T> retorno da API de código fluente
IPlatformElementConfiguration objetos. Isso permite que várias especificações de plataforma a ser invocado no
mesmo objeto com método em cascata.
Para obter mais informações sobre as especificidades de plataforma fornecido pelo xamarin. Forms, consulte
especificidades da plataforma do iOS, especificidades da plataforma Android, e Windows-especificidades da
plataforma.
NOTE
É previu que fornecedores usará essa técnica para criar seus próprios-especificidades da plataforma, para facilitar o consumo
por usuários. Embora os usuários podem optar por criar seus próprios especificidades da plataforma, deve-se observar que
ela requer mais código que criar e consumir um efeito.
O aplicativo de exemplo demonstra uma Shadow específicos da plataforma que adiciona uma sombra para o texto
exibido por um Label controle:
O aplicativo de exemplo implementa o Shadow específico da plataforma em cada plataforma, para facilitar a
compreensão. No entanto, além de cada implementação do efeito específico da plataforma, a implementação da
classe sombra é praticamente idêntica para cada plataforma. Portanto, este guia concentra-se na implementação
da classe de sombra e efeito associado em uma única plataforma.
Para obter mais informações sobre os efeitos, consulte personalizar controles com efeitos.
Criando uma classe específica da plataforma
Uma plataforma específica é criada como um public static classe:
namespace MyCompany.Forms.PlatformConfiguration.iOS
{
public static Shadow
{
...
}
}
namespace MyCompany.Forms.PlatformConfiguration.iOS
{
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using FormsElement = Xamarin.Forms.Label;
...
NOTE
Observe que o efeito é resolvido, especificando um valor que é uma concatenação do nome do grupo de resolução e
identificador exclusivo que é especificado na implementação do efeito. Para obter mais informações, consulte criando um
efeito.
Para obter mais informações sobre propriedades anexadas, consulte propriedades anexadas.
Adicionando métodos de extensão
Métodos de extensão devem ser adicionados para o Shadow específicos da plataforma para permitir o consumo
por meio de um API fluente de código:
namespace MyCompany.Forms.PlatformConfiguration.iOS
{
using System.Linq;
using Xamarin.Forms;
using Xamarin.Forms.PlatformConfiguration;
using FormsElement = Xamarin.Forms.Label;
O IsShadowed e SetIsShadowed chamar get de métodos de extensão e definir acessadores para o IsShadowed
anexado a propriedade, respectivamente. Cada método de extensão funciona com o
IPlatformElementConfiguration<iOS, FormsElement> tipo, que especifica que a plataforma específica pode ser
invocada sob Label instâncias do iOS.
Criando o efeito
O Shadow específico da plataforma adiciona a MyCompany.LabelShadowEffect para um Label e a remove. O
seguinte exemplo de código mostra o LabelShadowEffect implementação para o projeto do iOS:
[assembly: ResolutionGroupName("MyCompany")]
[assembly: ExportEffect(typeof(LabelShadowEffect), "LabelShadowEffect")]
namespace ShadowPlatformSpecific.iOS
{
public class LabelShadowEffect : PlatformEffect
{
protected override void OnAttached()
{
UpdateShadow();
}
if (args.PropertyName == Shadow.IsShadowedProperty.PropertyName)
{
UpdateShadow();
}
}
void UpdateShadow()
{
try
{
if (((Label)Element).OnThisPlatform().IsShadowed())
{
Control.Layer.CornerRadius = 5;
Control.Layer.ShadowColor = UIColor.Black.CGColor;
Control.Layer.ShadowOffset = new CGSize(5, 5);
Control.Layer.ShadowOpacity = 1.0f;
}
else if (!((Label)Element).OnThisPlatform().IsShadowed())
{
Control.Layer.ShadowOpacity = 0;
}
}
catch (Exception ex)
{
Console.WriteLine("Cannot set property on attached control. Error: ", ex.Message);
}
}
}
}
O UpdateShadow método define Control.Layer as propriedades para criar a sombra, desde que o IsShadowed
propriedade anexada é definida como true e desde que o Shadow específicos da plataforma foi invocado na
mesma plataforma que o Efeito é implementado para. Essa verificação é realizada com o OnThisPlatform método.
Se o Shadow.IsShadowed anexado alterações de valor de propriedade em tempo de execução, o efeito precisa
responder, removendo a sombra. Portanto, uma versão de substituição de OnElementPropertyChanged método é
usado para responder à alteração de propriedade associável chamando o UpdateShadow método.
Para obter mais informações sobre como criar um efeito, consulte criando um efeito e passando os parâmetros de
efeito como propriedades anexadas.
Consumindo o específicos da plataforma
O Shadow específico da plataforma é consumido em XAML, definindo o Shadow.IsShadowed anexado à
propriedade um boolean valor:
<ContentPage xmlns:ios="clr-namespace:MyCompany.Forms.PlatformConfiguration.iOS" ...>
...
<Label Text="Label Shadow Effect" ios:Shadow.IsShadowed="true" ... />
...
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using MyCompany.Forms.PlatformConfiguration.iOS;
...
shadowLabel.On<iOS>().SetIsShadowed(true);
Links relacionados
PlatformSpecifics (amostra)
ShadowPlatformSpecific (amostra)
Especificidades da plataforma do iOS
Especificidades da plataforma Android
Especificidades da plataforma Windows
Personalizar controles com efeitos
Propriedades anexadas
PlatformConfiguration API
Recursos da plataforma Windows
12/04/2019 • 4 minutes to read
Desenvolvimento de aplicativos xamarin. Forms para plataformas do Windows requer o Visual Studio. O página
de requisitos contém mais informações sobre os pré-requisitos.
Especificidades da plataforma
Especificidades da plataforma permitem que você consumir funcionalidade só está disponível em uma plataforma
específica, sem implementar renderizadores personalizados ou efeitos.
A seguinte funcionalidade específica da plataforma é fornecida para exibições do xamarin. Forms, páginas e
layouts no Universal Windows Platform (UWP ):
Definindo uma tecla de acesso para um VisualElement . Para obter mais informações, consulte VisualElement
chaves de acesso no Windows.
Desabilitar o modo de cor herdados em um com suporte VisualElement . Para obter mais informações,
consulte modo de cor VisualElement herdado no Windows.
A seguinte funcionalidade específica da plataforma é fornecida para modos de exibição do xamarin. Forms na
UWP:
Detectando a ordem de leitura do conteúdo de texto Entry , Editor , e Label instâncias. Para obter mais
informações, consulte InputView a ordem de leitura no Windows.
Habilitando o suporte de gestos de toque em um ListView . Para obter mais informações, consulte ListView
SelectionMode no Windows.
Habilitando um SearchBar para interagir com o mecanismo de verificação ortográfica. Para obter mais
informações, consulte SearchBar de verificação ortográfica no Windows.
Habilitando um WebView para exibir alertas de JavaScript em uma caixa de diálogo de mensagem UWP. Para
obter mais informações, consulte alertas de JavaScript do WebView no Windows.
A seguinte funcionalidade específica da plataforma é fornecida para páginas do xamarin. Forms na UWP:
Recolher o MasterDetailPage barra de navegação. Para obter mais informações, consulte MasterDetailPage
barra de navegação no Windows.
Definindo opções de posicionamento da barra de ferramentas. Para obter mais informações, consulte
posicionamento da barra de ferramentas de página no Windows.
Habilitar ícones de página a ser exibido em uma TabbedPage barra de ferramentas. Para obter mais
informações, consulte TabbedPage ícones no Windows.
Suporte de plataforma
Os modelos do xamarin. Forms disponíveis no Visual Studio contêm um projeto de plataforma Universal do
Windows (UWP ).
NOTE
Suporte de xamarin. Forms 1.x e 2.x Windows Phone 8 Silverlight, Windows Phone 8.1, e Windows 8.1 desenvolvimento de
aplicativos. No entanto, esses tipos de projeto foram preteridos.
Introdução
Vá para arquivo > Novo > projeto no Visual Studio e escolha uma da plataforma cruzada > aplicativo em
branco (xamarin. Forms) modelos para começar.
Soluções antigas do xamarin. Forms, ou aqueles criados no macOS, não terá todos os projetos do Windows
listados acima (mas eles precisam ser adicionados manualmente). Se a plataforma do Windows que você deseja
direcionar ainda não estiver em sua solução, visite o instruções de instalação para adicionar os Windows
desejados tipo/s do projeto.
Exemplos
Todos os exemplos para livro Charles Petzold criação de aplicativos móveis com xamarin. Forms incluir projetos
de plataforma Universal do Windows (para Windows 10).
O aplicativo de demonstração de "Scott Hanselman" está disponível separadamente e também inclui projetos de
Apple Watch e o Android Wear (usando xamarin. IOS e xamarin. Android, respectivamente, xamarin. Forms não é
executado nessas plataformas).
Links relacionados
Projetos de instalação do Windows
Ordem de leitura de InputView no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa plataforma específicas de plataforma Universal do Windows permite que a ordem de leitura (esquerda para a
direita ou à direita para esquerda) do texto bidirecional no Entry , Editor e Label instâncias para ser detectada
dinamicamente. Ele é consumido em XAML, definindo o InputView.DetectReadingOrderFromContent (para Entry e
Editor instâncias) ou Label.DetectReadingOrderFromContent anexado à propriedade um boolean valor:
<ContentPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
<Editor ... windows:InputView.DetectReadingOrderFromContent="true" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
editor.On<Windows>().SetDetectReadingOrderFromContent(true);
O Editor.On<Windows> método Especifica que este específicos da plataforma só serão executado na plataforma
Universal do Windows. O InputView.SetDetectReadingOrderFromContent método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é usada para controlar se a ordem de leitura é
detectada de conteúdo a InputView . Além disso, o InputView.SetDetectReadingOrderFromContent método pode ser
usado para ativar ou desativar a ordem de leitura é detectada do conteúdo por meio da chamada a
InputView.GetDetectReadingOrderFromContent método para retornar o valor atual:
editor.On<Windows>().SetDetectReadingOrderFromContent(!editor.On<Windows>
().GetDetectReadingOrderFromContent());
O resultado é que Entry , Editor , e Label instâncias podem ter a ordem de leitura de seus conteúdos
detectadas dinamicamente:
NOTE
Ao contrário da configuração de FlowDirection propriedade, a lógica para modos de exibição que detectar que a ordem
de leitura do seu conteúdo de texto não afetará o alinhamento do texto dentro da exibição. Em vez disso, ele ajusta a ordem
na qual os blocos de texto bidirecional são apresentados.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
ListView SelectionMode no Windows
12/04/2019 • 3 minutes to read
Baixar o exemplo
Na plataforma Universal do Windows, por padrão, o xamarin. Forms ListView usa nativo ItemClick eventos
para responder à interação, em vez de nativo Tapped eventos. Isso fornece funcionalidades de acessibilidade para
que o Narrador do Windows e o teclado podem interagir com o ListView . No entanto, ele também processa
qualquer gestos de toque dentro a ListView inoperável.
Este controles específicos da plataforma de plataforma Universal do Windows se itens em uma ListView pode
responder para gestos de toque e, portanto, se nativo ListView é acionado o ItemClick ou Tapped eventos. Ele é
consumido em XAML, definindo o ListView.SelectionMode propriedade anexada a um valor da
ListViewSelectionMode enumeração:
<ContentPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
<ListView ... windows:ListView.SelectionMode="Inaccessible">
...
</ListView>
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
listView.On<Windows>().SetSelectionMode(ListViewSelectionMode.Inaccessible);
O ListView.On<Windows> método Especifica que este específicos da plataforma só serão executado na plataforma
Universal do Windows. O ListView.SetSelectionMode método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é usada para controlar se itens em um
ListView pode responder para toque gestos, com o ListViewSelectionMode enumeração fornecendo dois valores
possíveis:
Accessible – indica que o ListView acionarão nativo ItemClick eventos para manipular a interação e,
portanto, fornecer funcionalidades de acessibilidade. Portanto, o Narrador do Windows e o teclado podem
interagir com o ListView . No entanto, os itens no ListView não pode responder para gestos de toque. Esse é
o comportamento padrão para ListView instâncias na plataforma Universal do Windows.
Inaccessible – indica que o ListView acionarão nativo Tapped eventos para manipular a interação. Portanto,
os itens no ListView pode responder para gestos de toque. No entanto, não há nenhuma funcionalidade de
acessibilidade e, portanto, o Narrador do Windows e o teclado não é possível interagir com o ListView .
NOTE
O Accessible e Inaccessible modos de seleção são mutuamente exclusivos, e você precisará escolher entre uma
acessível ListView ou um ListView que pode responder a gestos de toque.
Além disso, o GetSelectionMode método pode ser usado para retornar atual ListViewSelectionMode .
O resultado é que o especificado ListViewSelectionMode é aplicado ao ListView , que controla se itens do
ListView pode responder para gestos de toque e, portanto, se nativo ListView é acionado o ItemClick ou
Tapped eventos.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Barra de navegação MasterDetailPage no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa plataforma específicas de plataforma Universal do Windows é usada para recolher a barra de navegação em
um MasterDetailPage e é consumido em XAML, definindo o MasterDetailPage.CollapseStyle e
MasterDetailPage.CollapsedPaneWidth propriedades anexadas:
<MasterDetailPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core"
windows:MasterDetailPage.CollapseStyle="Partial"
windows:MasterDetailPage.CollapsedPaneWidth="48">
...
</MasterDetailPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
page.On<Windows>().SetCollapseStyle(CollapseStyle.Partial).CollapsedPaneWidth(148);
O MasterDetailPage.On<Windows> método Especifica que este específicos da plataforma serão executado apenas no
Windows. O Page.SetCollapseStyle método, no Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace,
é usado para especificar o estilo de recolher, com o CollapseStyle enumeração fornecendo dois valores: Full e
Partial . O MasterDetailPage.CollapsedPaneWidth método é usado para especificar a largura de uma barra de
navegação colapsada parcialmente.
O resultado é que o especificado CollapseStyle é aplicado para o MasterDetailPage instância, com a largura
também está sendo especificada:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Posicionamento da barra de ferramentas da página
no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Específico da plataforma essa plataforma Universal do Windows é usado para alterar o posicionamento de uma
barra de ferramentas em uma Page e consumido em XAML, definindo o Page.ToolbarPlacement anexado à
propriedade um valor de ToolbarPlacement enumeração:
<TabbedPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core"
windows:Page.ToolbarPlacement="Bottom">
...
</TabbedPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
page.On<Windows>().SetToolbarPlacement(ToolbarPlacement.Bottom);
O Page.On<Windows> método Especifica que este específicos da plataforma serão executado apenas no Windows.
O Page.SetToolbarPlacement método, no Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é
usado para definir o posicionamento da barra de ferramentas, com o ToolbarPlacement fornecendo de
enumeração três valores: Default , Top , e Bottom .
O resultado é que o posicionamento da barra de ferramentas especificada é aplicado para o Page instância:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Projetos de instalação do Windows
12/04/2019 • 6 minutes to read
2 . No novo projeto da plataforma Windows Universal caixa de diálogo, selecione as versões mínima e de
destino do Windows 10 que o aplicativo será executado em:
3 . Clique com botão direito no projeto UWP e selecione gerenciar pacotes NuGet... e adicione o xamarin.
Forms pacote. Certifique-se de que os outros projetos na solução também são atualizados para a mesma versão
do pacote do xamarin. Forms.
4 . Verifique se o novo projeto UWP será compilado na compilar > Configuration Manager janela (isso
provavelmente não ter ocorrido por padrão). Escala de construir e implantar caixas para o projeto Universal:
5 . Clique com botão direito no projeto e selecione Add > referência e criar uma referência ao projeto de
aplicativo xamarin. Forms (.NET Standard ou projeto compartilhado).
6 . No projeto UWP, edite App.xaml.cs para incluir o Init chamada do método dentro de OnLaunched método
perto da linha 52:
7 . No projeto UWP, edite MainPage. XAML removendo a Grid contidos o Page elemento.
8 . Na MainPage. XAML, adicione uma nova xmlns entrada de Xamarin.Forms.Platform.UWP :
xmlns:forms="using:Xamarin.Forms.Platform.UWP"
<forms:WindowsPage
...
xmlns:forms="using:Xamarin.Forms.Platform.UWP"
...
</forms:WindowsPage>
10 . No projeto UWP, edite MainPage.xaml.cs para remover o : Page especificador de herança para o nome
da classe (uma vez que ele agora herda WindowsPage devido à alteração feita na etapa anterior):
12 . Adicione qualquer recurso local (por exemplo. arquivos de imagem) de projetos de plataforma existentes
que são necessários.
Solução de problemas
"Exceção de invocação de destino" ao usar "Compilar com cadeia de ferramentas nativas do .NET"
Se seu aplicativo da UWP está fazendo referência a vários assemblies (por exemplo bibliotecas de controle de
terceiros, ou seu próprio aplicativo é dividido em várias bibliotecas), xamarin. Forms talvez não consiga carregar
objetos desses assemblies (como renderizadores personalizados).
Isso pode ocorrer ao usar o compilar com cadeia de ferramentas .NET Native que é uma opção para
aplicativos UWP na Propriedades > Build > geral janela para o projeto.
Você pode corrigir isso usando uma sobrecarga específica de UWP do Forms.Init chamar App.xaml.cs
conforme mostrado no código a seguir (você deve substituir ClassInOtherAssembly com uma classe real do seu
código faz referência):
Adicione uma entrada para cada assembly que você adicionou como uma referência no Gerenciador de
soluções, por meio de uma referência direta ou um NuGet.
Compilação nativa de serviços de dependência e .NET
Builds de versão usando a compilação do .NET nativo podem fazer para resolver os serviços de dependência
que são definidos fora o executável de aplicativo principal (como em um projeto separado ou biblioteca).
Use o DependencyService.Register<T>() método para registrar manualmente as classes de serviço de
dependência. Com base no exemplo acima, adicione o método register como este:
Xamarin.Forms.Forms.Init(e, assembliesToInclude);
Xamarin.Forms.DependencyService.Register<ClassInOtherAssembly>(); // add this
Verificação ortográfica SearchBar no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa plataforma específicas de plataforma Universal do Windows permite que um SearchBar para interagir com o
mecanismo de verificação ortográfica. Ele é consumido em XAML, definindo o SearchBar.IsSpellCheckEnabled
anexado à propriedade um boolean valor:
<ContentPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
<SearchBar ... windows:SearchBar.IsSpellCheckEnabled="true" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
searchBar.On<Windows>().SetIsSpellCheckEnabled(true);
O SearchBar.On<Windows> método Especifica que este específicos da plataforma só serão executado na plataforma
Universal do Windows. O SearchBar.SetIsSpellCheckEnabled método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific e no namespace, desativa o verificador ortográfico. Além
disso, o SearchBar.SetIsSpellCheckEnabled método pode ser usado para ativar/desativar a verificação ortográfica,
chamando o SearchBar.GetIsSpellCheckEnabled método para retornar se o verificador ortográfico está habilitado:
searchBar.On<Windows>().SetIsSpellCheckEnabled(!searchBar.On<Windows>().GetIsSpellCheckEnabled());
O resultado é inserido no texto a SearchBar pode ser ortografia verificada, com erros de ortografia incorretos
sendo indicados para o usuário:
NOTE
O SearchBar classe de Xamarin.Forms.PlatformConfiguration.WindowsSpecific também tem um namespace
EnableSpellCheck e DisableSpellCheck métodos que podem ser usados para habilitar e desabilitar o verificador
ortográfico no SearchBar , respectivamente.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Ícones de TabbedPage no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Essa plataforma específicas de plataforma Universal do Windows permite que os ícones de página a ser exibido
em uma TabbedPage barra de ferramentas e fornece a capacidade de, opcionalmente, especificar o tamanho do
ícone. Ele é consumido em XAML, definindo o TabbedPage.HeaderIconsEnabled anexado à propriedade true e,
opcionalmente, definindo o TabbedPage.HeaderIconsSize anexado à propriedade um Size valor:
<TabbedPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core"
windows:TabbedPage.HeaderIconsEnabled="true">
<windows:TabbedPage.HeaderIconsSize>
<Size>
<x:Arguments>
<x:Double>24</x:Double>
<x:Double>24</x:Double>
</x:Arguments>
</Size>
</windows:TabbedPage.HeaderIconsSize>
<ContentPage Title="Todo" Icon="todo.png">
...
</ContentPage>
<ContentPage Title="Reminders" Icon="reminders.png">
...
</ContentPage>
<ContentPage Title="Contacts" Icon="contacts.png">
...
</ContentPage>
</TabbedPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
O TabbedPage.On<Windows> método Especifica que este específicos da plataforma só serão executado na plataforma
Universal do Windows. O TabbedPage.SetHeaderIconsEnabled método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é usado para ativar ou desativar os ícones de
cabeçalho. O TabbedPage.SetHeaderIconsSize método, opcionalmente, especifica o tamanho do ícone de cabeçalho
com um Size valor.
Além disso, o TabbedPage classe o Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace também tem
um EnableHeaderIcons método que permite que os ícones de cabeçalho, uma DisableHeaderIcons método que
desabilita os ícones de cabeçalho, e uma IsHeaderIconsEnabled método que retorna um boolean valor que indica
se os ícones de cabeçalho estão habilitados.
O resultado é que essa página ícones podem ser exibidos em uma TabbedPage barra de ferramentas, com o
tamanho do ícone, opcionalmente, que está sendo definido como um tamanho desejado:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Chaves de acesso de VisualElement no Windows
12/04/2019 • 6 minutes to read
Baixar o exemplo
Chaves de acesso são atalhos de teclado que melhoram a usabilidade e a acessibilidade de aplicativos na
plataforma Universal de Windows (UWP ), fornecendo uma maneira intuitiva para os usuários a navegar
rapidamente e interagir com a interface do usuário visível do aplicativo por meio de um teclado em vez de por
meio de toque ou um mouse. Eles são combinações da tecla Alt e uma ou mais chaves alfanuméricas,
normalmente pressionadas em sequência. Atalhos de teclado automaticamente têm suporte para chaves de
acesso que usam um único caractere alfanumérico.
Dicas de tecla de acesso são flutuantes selos exibidos ao lado de controles que incluem as chaves de acesso. Cada
dica de tecla de acesso contém as chaves alfanuméricas que ativam o controle associado. Quando um usuário
pressiona a tecla Alt, as dicas de tecla de acesso são exibidas.
Essa plataforma específica de UWP é usada para especificar uma chave de acesso para um VisualElement . Ele é
consumido em XAML, definindo o VisualElement.AccessKey propriedade anexada para um valor alfanumérico e,
opcionalmente, definindo o VisualElement.AccessKeyPlacement propriedade anexada com o valor de
AccessKeyPlacement enumeração, o VisualElement.AccessKeyHorizontalOffset anexado à propriedade um double e
a VisualElement.AccessKeyVerticalOffset propriedade anexada a um double :
<TabbedPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<ContentPage Title="Page 1"
windows:VisualElement.AccessKey="1">
<StackLayout Margin="20">
...
<Switch windows:VisualElement.AccessKey="A" />
<Entry Placeholder="Enter text here"
windows:VisualElement.AccessKey="B" />
...
<Button Text="Access key F, placement top with offsets"
Margin="20"
Clicked="OnButtonClicked"
windows:VisualElement.AccessKey="F"
windows:VisualElement.AccessKeyPlacement="Top"
windows:VisualElement.AccessKeyHorizontalOffset="20"
windows:VisualElement.AccessKeyVerticalOffset="20" />
...
</StackLayout>
</ContentPage>
...
</TabbedPage>
var button4 = new Button { Text = "Access key F, placement top with offsets", Margin = new Thickness(20) };
button4.Clicked += OnButtonClicked;
button4.On<Windows>()
.SetAccessKey("F")
.SetAccessKeyPlacement(AccessKeyPlacement.Top)
.SetAccessKeyHorizontalOffset(20)
.SetAccessKeyVerticalOffset(20);
...
NOTE
Normalmente, o Auto posicionamento da dica de tecla é suficiente, que inclui suporte para interfaces do usuário adaptável.
NOTE
Deslocamentos de dica de tecla de acesso não podem ser definidos quando o posicionamento de chave de acesso é definido
Auto .
Quando um usuário ativa uma chave de acesso, pressionando a tecla Alt, seguida pelo acesso de chave, a ação
padrão para o VisualElement será executado. Por exemplo, quando um usuário ativa a chave de acesso em uma
Switch , o Switch é alternada. Quando um usuário ativa a chave de acesso em uma Entry , o Entry ganha o
foco. Quando um usuário ativa a chave de acesso em uma Button , o manipulador de eventos para o Clicked
eventos é executado.
Para obter mais informações sobre chaves de acesso, consulte chaves de acesso.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Modo de cor VisualElement herdado no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Algumas das exibições de xamarin. Forms apresentam um modo de cor herdado. Nesse modo, quando o
IsEnabled propriedade do modo de exibição é definida como false , o modo de exibição substituirá as cores
definidas pelo usuário com os nativo as cores padrão para o estado desabilitado. Para versões anteriores
compatibilidade, esse modo herdado cor permanece o comportamento padrão para modos de exibição com
suporte.
Essa plataforma específicas de plataforma Universal do Windows desabilita a esse modo herdado de cor, para que
as cores definidas em uma exibição pelo usuário permanecem mesmo quando o modo de exibição está
desabilitado. Ele é consumido em XAML, definindo o VisualElement.IsLegacyColorModeEnabled anexado à
propriedade false :
<ContentPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
...
<Editor Text="Enter text here"
TextColor="Blue"
BackgroundColor="Bisque"
windows:VisualElement.IsLegacyColorModeEnabled="False" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
_legacyColorModeDisabledEditor.On<Windows>().SetIsLegacyColorModeEnabled(false);
O VisualElement.On<Windows> método Especifica que este específicos da plataforma serão executado apenas no
Windows. O VisualElement.SetIsLegacyColorModeEnabled método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é usada para controlar se o modo de cor
herdados é desabilitado. Além disso, o VisualElement.GetIsLegacyColorModeEnabled método pode ser usado para
retornar se o modo de cor herdado está desabilitado.
O resultado é que o modo herdado de cor pode ser desabilitado, para que as cores definidas em uma exibição pelo
usuário permaneçam até mesmo quando o modo de exibição está desabilitado:
NOTE
Ao definir uma VisualStateGroup em uma exibição, o modo herdado de cor é totalmente ignorado. Para obter mais
informações sobre estados visuais, consulte o Gerenciador de estado Visual xamarin. Forms.
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Alertas do WebView do JavaScript no Windows
12/04/2019 • 2 minutes to read
Baixar o exemplo
Este específicos da plataforma permite que um WebView para exibir alertas de JavaScript em uma caixa de diálogo
de mensagem UWP. Ele é consumido em XAML, definindo o WebView.IsJavaScriptAlertEnabled anexado à
propriedade um boolean valor:
<ContentPage ...
xmlns:windows="clr-
namespace:Xamarin.Forms.PlatformConfiguration.WindowsSpecific;assembly=Xamarin.Forms.Core">
<StackLayout>
<WebView ... windows:WebView.IsJavaScriptAlertEnabled="true" />
...
</StackLayout>
</ContentPage>
using Xamarin.Forms.PlatformConfiguration;
using Xamarin.Forms.PlatformConfiguration.WindowsSpecific;
...
O WebView.On<Windows> método Especifica que este específicos da plataforma só serão executado na plataforma
Universal do Windows. O WebView.SetIsJavaScriptAlertEnabled método, no
Xamarin.Forms.PlatformConfiguration.WindowsSpecific namespace, é usada para controlar se os alertas de
JavaScript estão habilitados. Além disso, o WebView.SetIsJavaScriptAlertEnabled método pode ser usado para
ativar/desativar alertas de JavaScript por meio da chamada a IsJavaScriptAlertEnabled método para retornar se
eles estão habilitados:
_webView.On<Windows>().SetIsJavaScriptAlertEnabled(!_webView.On<Windows>().IsJavaScriptAlertEnabled());
O resultado é que os alertas de JavaScript podem ser exibidas em uma caixa de diálogo de mensagem UWP:
Links relacionados
PlatformSpecifics (amostra)
Criação de itens específicos à plataforma
WindowsSpecific API
Xamarin.Essentials
12/04/2019 • 4 minutes to read • Edit Online
O Xamarin.Essentials fornece desenvolvedores com APIs de plataforma cruzada para seus aplicativos móveis.
O Android, iOS e UWP oferecem APIs de plataforma e sistema operacional exclusivos nos quais os
desenvolvedores podem acessar tudo que estiver no C# aproveitando o Xamarin. O Xamarin.Essentials oferece
uma API única entre plataformas que funciona com qualquer aplicativo Xamarin.Forms, Android, iOS ou UWP e
que pode ser acessado no código compartilhado, independentemente da forma como a interface do usuário é
criada.
Introdução ao Xamarin.Essentials
Siga o guia de introdução para instalar o pacote NuGet do Xamarin.Essentials em seus projetos existentes ou
novos do Xamarin.Forms, Android, iOS ou UWP.
Guias de recursos
Siga os guias para integrar esses recursos Xamarin.Essentials em seus aplicativos:
Acelerômetro – recuperar dados de aceleração do dispositivo no espaço tridimensional.
Informações do aplicativo – localize informações sobre o aplicativo.
Barômetro – monitorar o barômetro em relação a alterações de pressão.
Bateria – facilmente detectar o nível de bateria, o código-fonte e o estado.
Área de transferência – definir ou ler rapidamente e facilmente texto na área de transferência.
Conversores de cor – métodos auxiliares para System.Drawing.Color.
Bússola – monitorar a bússola em relação a alterações.
Conectividade – verificar o estado da conectividade e detectar alterações.
Detectar movimento – detectar um movimento do dispositivo.
Informações sobre a exibição de dispositivos – obter a orientação e as métricas de tela do dispositivo.
Informações do dispositivo – saiba mais sobre o dispositivo com facilidade.
Email – enviar mensagens de email com facilidade.
Auxiliares do sistema de arquivos – salve arquivos em dados de aplicativo com facilidade.
Lanterna – uma maneira simples de ativar a lanterna/desativar.
Geocodificação – geocodificação e geocodificação reversa dos endereços e coordenadas.
Localização geográfica – recuperar a localização do GPS do dispositivo.
Giroscópio – acompanhar a rotação em torno dos três principais eixos do dispositivo.
Inicializador – permite que um aplicativo abra um URI pelo sistema.
Magnetômetro – detectar a orientação do dispositivo em relação ao campo magnético da Terra.
Thread principal – executar código no thread principal do aplicativo.
Mapas – abrir o aplicativo de mapas em um local específico.
Abrir o navegador – abrir um navegador em um site específico com rapidez e facilidade.
Sensor de orientação – recuperar a orientação do dispositivo no espaço tridimensional.
Discagem telefônica – abrir a discagem telefônica.
Extensões da plataforma – métodos auxiliares para converter retângulo, tamanho e ponto.
Preferências – adicionar preferências persistentes com rapidez e facilidade.
Armazenamento seguro – armazenar dados com segurança.
Compartilhar – enviar texto e URIs de site a outros aplicativos.
SMS – criar uma mensagem de texto para enviar.
Conversão de Texto em Fala – vocalizar texto no dispositivo.
Conversores de unidade – métodos auxiliares para converter unidades.
Controle de versão – controlar a versão de aplicativos e os números de build.
Vibrar – fazer o dispositivo vibrar.
Solução de problemas
Encontre ajuda se você estiver tendo problemas.
Documentação da API
Navegue pela documentação da API de todos os recursos Xamarin.Essentials.
Introdução ao Xamarin.Essentials
12/04/2019 • 5 minutes to read • Edit Online
O Xamarin.Essentials oferece uma API única entre plataformas que funciona com qualquer aplicativo
iOS, Android ou UWP e que pode ser acessado no código compartilhado, independentemente da forma
como a interface do usuário é criada.
Suporte de plataforma
O Xamarin.Essentials é compatível com os seguintes sistemas operacionais e plataformas:
PLATAFORMA VERSÃO
Instalação
O Xamarin.Essentials está disponível como um pacote NuGet que pode ser adicionado a qualquer
projeto, novo ou existente, através do Visual Studio.
1. Faça o download e instale o Visual Studio com as Ferramentas do Visual Studio para Xamarin.
2. Abra um projeto existente ou crie um novo projeto usando o modelo Aplicativo em branco no C#
do Visual Studio (Android, iPhone e iPad ou plataforma cruzada). Importante: Se adicionar a
um projeto UWP, verifique se o Build 16299 ou superior está definido nas propriedades do
projeto.
3. Adicione o pacote NuGet do Xamarin.Essentials a cada projeto:
Visual Studio
Visual Studio para Mac
No painel do Gerenciador de Soluções, clique com o botão direito do mouse no nome da solução
e escolha Gerenciar pacotes NuGet. Pesquise Xamarin.Essentials e instale o pacote em
TODOS os projetos, incluindo bibliotecas do Android, iOS, UWP e .NET Standard.
4. Adicione uma referência ao Xamarin.Essentials na classe C# para fazer referência às APIs.
using Xamarin.Essentials;
Para lidar com permissões de tempo de execução no Android, o Xamarin.Essentials deve receber
qualquer OnRequestPermissionsResult . Adicione o seguinte código a todas as classes Activity :
6. Siga os guias do Xamarin.Essentials que permitem copiar e colar os trechos de código para cada
recurso.
Outros recursos
Recomendamos que os novos desenvolvedores do Xamarin confiram a Introdução ao desenvolvimento
do Xamarin.
Visite o Repositório do GitHub do Xamarin.Essentials para ver o código-fonte atual, o que vem a seguir,
colocar exemplos em prática e clonar o repositório. Contribuições da comunidade são bem-vindas!
Navegue pela documentação da API de todos os recursos do Xamarin.Essentials.
Xamarin.Essentials: Acelerômetro
12/04/2019 • 4 minutes to read • Edit Online
A classe Accelerometer permite monitorar o sensor de acelerômetro do dispositivo que indica a aceleração do
dispositivo no espaço tridimensional.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do acelerômetro
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
A funcionalidade do Acelerômetro chama os métodos Start e Stop e escuta as alterações na aceleração. Todas
as alterações são enviadas de volta por meio do evento ReadingChanged . Veja um exemplo de uso:
public class AccelerometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;
public AccelerometerTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Accelerometer.ReadingChanged += Accelerometer_ReadingChanged;
}
As leituras do acelerômetro são registradas em G. A G, uma unidade de força gravitacional equivalente à exercida
pelo campo gravitacional da Terra (9,81 m/s2).
O sistema de coordenadas é definido em relação à tela do telefone na orientação padrão. Os eixos não são
trocados quando a orientação da tela do dispositivo é alterada.
O eixo X é horizontal e aponta para a direita; o eixo Y é vertical e aponta para cima; o eixo Z aponta para a parte
externa da face frontal da tela. Nesse sistema, as coordenadas atrás da tela têm valores de Z negativos.
Exemplos:
Quando o dispositivo estiver em uma superfície plana e for empurrado da esquerda para a direita, o valor
de aceleração x será positivo.
Quando o dispositivo estiver em uma superfície plana, o valor de aceleração será +1,00 G ou (+9,81 m/s2),
o que corresponde à aceleração do dispositivo (0 m/s2) menos a força da gravidade (-9,81 m/s2) e
normalizado em G.
Quando o dispositivo estiver em uma superfície plana e for empurrado para cima com uma aceleração de
A m/s^2, o valor da aceleração será igual a A + 9,81, o que corresponde à aceleração do dispositivo (+A
m/s^2) menos a força da gravidade (-9,81 m/s^2) e normalizado em G.
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
API
Código-fonte do acelerômetro
Documentação da API do acelerômetro
Vídeo relacionados
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
// Application Name
var appName = AppInfo.Name;
Esta página de configurações permite ao usuário alterar permissões do aplicativo e executar outras tarefas
específicas à plataforma.
API
Código-fonte de AppInfo
Documentação da API de AppInfo
Vídeo relacionados
A classe Barometer permite que você monitore o sensor do barômetro do dispositivo. Esse sensor mede a
pressão.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do Barometer
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
A funcionalidade Barometer funciona chamando os métodos Start e Stop para escutar as alterações nas leituras
de pressão do barômetro em hectopascais. Todas as alterações são enviadas de volta por meio do evento
ReadingChanged . Veja um exemplo de uso:
public class BarometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;
public BarometerTest()
{
// Register for reading changes.
Barometer.ReadingChanged += Barometer_ReadingChanged;
}
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
A classe Battery permite que você verifique as informações sobre a bateria do dispositivo e monitore as
alterações, além de fornecer informações sobre o status de economia de energia do dispositivo, o que indica se o
dispositivo está em execução em um modo de baixa energia. Os aplicativos devem evitar o processamento em
segundo plano se o status da economia de energia do dispositivo estiver ativado.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade Battery, a configuração específica da plataforma a seguir é necessária.
Android
iOS
UWP
A permissão Battery é necessária e deve ser configurada no projeto do Android. Ela pode ser usado das
seguintes maneiras:
Abra o arquivo AssemblyInfo.cs na pasta Propriedades e adicione:
[assembly: UsesPermission(Android.Manifest.Permission.BatteryStats)]
Ou clique com o botão direito do mouse no projeto do Android e abra as propriedades do projeto. Em Manifesto
do Android, localize a área Permissões necessárias: e marque a permissão Bateria. Isso atualizará
automaticamente o arquivo AndroidManifest.xml.
using Xamarin.Essentials;
switch (state)
{
case BatteryState.Charging:
// Currently charging
break;
case BatteryState.Full:
// Battery is full
break;
case BatteryState.Discharging:
case BatteryState.NotCharging:
// Currently discharging battery or not being charged
break;
case BatteryState.NotPresent:
// Battery doesn't exist in device (desktop computer)
case BatteryState.Unknown:
// Unable to detect battery state
break;
}
switch (source)
{
case BatteryPowerSource.Battery:
// Being powered by the battery
break;
case BatteryPowerSource.AC:
// Being powered by A/C unit
break;
case BatteryPowerSource.Usb:
// Being powered by USB cable
break;
case BatteryPowerSource.Wireless:
// Powered via wireless charging
break;
case BatteryPowerSource.Unknown:
// Unable to detect power source
break;
}
Sempre que qualquer uma das propriedades da bateria for alterada, um evento será disparado:
Os dispositivos que funcionam com baterias podem ser colocados em um modo de baixo consumo de energia.
Por vezes, os dispositivos passam para este modo automaticamente, por exemplo, quando a bateria fica abaixo dos
20% de capacidade. O sistema operacional responde ao modo de economia de energia reduzindo atividades que
tendem a esgotar a bateria. Os aplicativos podem ajudar evitando o processamento em segundo plano ou outras
atividades que consomem muita energia quando o modo de economia de energia está ativado.
Obtenha o status atual da economia de energia do dispositivo usando a propriedade Battery.EnergySaverStatus
estática:
Se o status da economia de energia for alterado para On , o aplicativo deverá interromper a execução do
processamento em segundo plano. Se o status mudar para Unknown ou Off , o aplicativo poderá retomar o
processamento em segundo plano.
API
Código-fonte de Bateria
Documentação da API de Bateria
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Xamarin.Essentials: Área de Transferência
12/04/2019 • 2 minutes to read • Edit Online
A classe Clipboard permite que você copie e cole o texto para a área de transferência do sistema entre aplicativos.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Para verificar se a Área de Transferência tem algum texto pronto para ser colado:
API
Código-fonte de Área de Transferência
Documentação de API de Área de Transferência
Vídeo relacionados
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Ao trabalhar com System.Drawing.Color , você pode usar os conversores internos do Xamarin.Forms para criar
uma cor de Hsl, Hex ou UInt.
// Back to System.Drawing.Color
var system = platform.ToSystemColor();
API
Código-fonte de conversores de cor
Documentação da API de conversores de cor
Código-fonte de extensões de cor
Documentação da API de extensões de cor
Xamarin.Essentials: Bússola
12/04/2019 • 4 minutes to read • Edit Online
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A funcionalidade de Bússola funciona chamando os métodos Start e e fica atenta às alterações na bússola.
Stop
Todas as alterações são enviadas de volta por meio do evento ReadingChanged . Veja um exemplo:
public CompassTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Compass.ReadingChanged += Compass_ReadingChanged;
}
Isso só é aplicado na plataforma Android, e o parâmetro é ignorado no iOS e UWP. Encontre mais informações
aqui.
API
Código-fonte da Bússola
Documentação da API de Bússola
Xamarin.Essentials: Conectividade
12/04/2019 • 4 minutes to read • Edit Online
A classe Connectivity permite monitorar alterações em condições de rede do dispositivo, verificar o acesso da
rede atual e como ele está conectado no momento.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade Connectivity, a seguinte configuração específica da plataforma é necessária.
Android
iOS
UWP
A permissão AccessNetworkState é necessária e deve ser configurada no projeto do Android. Ela pode ser usado
das seguintes maneiras:
Abra o arquivo AssemblyInfo.cs na pasta Propriedades e adicione:
[assembly: UsesPermission(Android.Manifest.Permission.AccessNetworkState)]
Ou clique com o botão direito do mouse no projeto do Android e abra as propriedades do projeto. Em Manifesto
do Android, localize a área Permissões necessárias: e marque a permissão Acessar estado da rede. Isso
atualizará automaticamente o arquivo AndroidManifest.xml.
Uso de Connectivity
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
if (current == NetworkAccess.Internet)
{
// Connection to internet is available
}
Sempre que o perfil de conexão ou o acesso à rede mudar, você poderá receber um evento quando houver um
acionamento:
Limitações
É importante observar que é possível que Internet seja reportado pelo NetworkAccess . No entanto, o acesso
completo à Web não estará disponível. Devido ao funcionamento da conectividade em cada plataforma, só é
possível garantir que uma conexão disponível. Por exemplo, o dispositivo pode estar conectado a uma rede Wi-Fi,
mas o roteador está desconectado da Internet. Nesta instância, a Internet pode ser reportada, mas uma conexão
ativa não estará disponível.
API
Código-fonte de Connectivity
Documentação da API de Connectivity
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Xamarin.Essentials: Detectar movimento
12/04/2019 • 3 minutes to read • Edit Online
A classe Accelerometer permite monitorar o sensor de acelerômetro do dispositivo, que indica a aceleração do
dispositivo no espaço tridimensional. Além disso, ele permite que você se registre para eventos quando o usuário
sacudir o dispositivo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Para detectar um movimento do dispositivo, você deve usar a funcionalidade do acelerômetro, chamando os
métodos Start e Stop para ouvir alterações na aceleração e detectar um movimento. Sempre que um
movimento for detectado, um evento ShakeDetected será disparado. Recomenda-se usar Game ou mais veloz para
o SensorSpeed . Veja um exemplo de uso:
public class DetectShakeTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.Game;
public DetectShakeTest()
{
// Register for reading changes, be sure to unsubscribe when finished
Accelerometer.ShakeDetected += Accelerometer_ShakeDetected ;
}
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
Detalhes da implementação
A API de detecção de movimento usa leituras brutas do acelerômetro para calcular a aceleração. Ela usa um
mecanismo de fila simples para detectar se 3/4 dos eventos recentes do acelerômetro ocorreram na última
metade do segundo. A aceleração é calculada adicionando o quadrado das leituras de X, Y e Z do acelerômetro e
comparando com um limite específico.
API
Código-fonte do acelerômetro
Documentação da API do acelerômetro
Xamarin.Essentials: Informações sobre DeviceDisplay
12/04/2019 • 2 minutes to read • Edit Online
A classe DeviceDisplay fornece informações sobre as métricas de tela do dispositivo no qual o aplicativo está
sendo executado e pode solicitar para evitar que a tela fique suspensa quando o aplicativo está em execução.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
// Get Metrics
var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
// Screen density
var density = mainDisplayInfo.Density;
A classe DeviceDisplay também expõe um evento que pode ser assinado e que é disparado sempre que ocorre
alterações nas métricas da tela:
public class DisplayInfoTest
{
public DisplayInfoTest()
{
// Subscribe to changes of screen metrics
DeviceDisplay.MainDisplayInfoChanged += OnMainDisplayInfoChanged;
}
A classe DeviceDisplay expõe uma bool propriedade chamada KeepScreenOn que pode ser definida para tentar
evitar o bloqueio ou desligamento da tela do dispositivo.
API
Código-fonte de DeviceDisplay
Documentação da API de DeviceDisplay
Xamarin.Essentials: Informações sobre o dispositivo
12/04/2019 • 2 minutes to read • Edit Online
A classe DeviceInfo fornece informações sobre o dispositivo no qual o aplicativo está em execução.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
// Manufacturer (Samsung)
var manufacturer = DeviceInfo.Manufacturer;
// Platform (Android)
var platform = DeviceInfo.Platform;
// Idiom (Phone)
var idiom = DeviceInfo.Idiom;
Plataformas
DeviceInfo.Platform correlaciona com uma cadeia de caracteres constante que mapeia para o sistema
operacional. Os valores podem ser verificados com a classe DevicePlatform :
DevicePlatform.iOS – iOS
DevicePlatform.Android – Android
DevicePlatform.UWP – UWP
DevicePlatform.Unknown – Desconhecido
Linguagens
DeviceInfo.Idiom correlaciona uma cadeia de caracteres constante que mapeia para o tipo de dispositivo em que
o aplicativo está sendo executado. Os valores podem ser verificados com a classe DeviceIdiom :
DeviceIdiom.Phone – Telefone
DeviceIdiom.Tablet – Tablet
DeviceIdiom.Desktop – Área de trabalho
DeviceIdiom.TV – TV
DeviceIdiom.Watch – Observação
DeviceIdiom.Unknown – Desconhecido
Tipo de dispositivo
DeviceInfo.DeviceType correlaciona uma enumeração para determinar se o aplicativo está em execução em um
dispositivo físico ou virtual. Um dispositivo virtual é um simulador ou emulador.
API
Código-fonte de DeviceInfo
Documentação da API de DeviceInfo
Xamarin.Essentials: Email
12/04/2019 • 2 minutes to read • Edit Online
A classe Email permite que um aplicativo abra o aplicativo de email padrão com uma informação especificada,
incluindo assunto, corpo e destinatários (PARA, CC, CCO ).
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A funcionalidade de Email funciona chamando o método ComposeAsync com um EmailMessage que contém
informações sobre o email:
Anexos de Arquivo
O envio de arquivos por email está disponível como uma versão prévia experimental no Xamarin.Essentials versão
1.1.0. Esse recurso permite que um aplicativo envie arquivos por email em clientes de email no dispositivo. Para
habilitar esse recurso, defina a propriedade a seguir no código de inicialização do aplicativo:
ExperimentalFeatures.Enable(ExperimentalFeatures.EmailAttachments);
Depois de habilitar o recurso, qualquer arquivo poderá ser enviado por email. O Xamarin.Essentials detectará
automaticamente o tipo de arquivo (MIME ) e solicitará que o arquivo seja adicionado como um anexo. Cada
cliente de email é diferente poderá ser compatível somente com extensões de arquivo específicas ou até mesmo
não ser com nenhuma.
Aqui está um exemplo de como gravar texto no disco e adicioná-lo como um anexo de email:
var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
message.Attachments.Add(new EmailAttachment(file));
await Email.ComposeAsync(message);
API
Código-fonte de email
Documentação da API de email
Xamarin.Essentials: Auxiliares de sistema de arquivos
12/04/2019 • 3 minutes to read • Edit Online
A classe FileSystem contém uma série de auxiliares para localizar o cache e os diretórios de dados do aplicativo e
abrir arquivos dentro do pacote de aplicativos.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Para fazer com que o diretório do aplicativo armazene dados de cache. Os dados de cache podem ser usados
para quaisquer dados que precisem permanecer mais tempo do que os dados temporários, mas que não devem
ser dados necessários para uma operação correta.
Para obter o diretório de nível superior do aplicativo para todos os arquivos que não são arquivos de dados do
usuário. O backup desses arquivos ocorre na estrutura de sincronização do sistema operacional. Veja abaixo as
particularidades de implementação da plataforma.
API
Código-fonte de Auxiliares do sistema de arquivos
Documentação da API do Sistema de Arquivos
Xamarin.Essentials: Lanterna
12/04/2019 • 3 minutes to read • Edit Online
A classe Flashlight tem a capacidade de ativar ou desativar o flash da câmera do dispositivo para transformá-lo
em uma lanterna.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade Flashlight, a seguinte configuração específica da plataforma é necessária.
Android
iOS
UWP
As permissões Flashlight e Camera são necessárias e devem ser configuradas no projeto do Android. Ela pode ser
usado das seguintes maneiras:
Abra o arquivo AssemblyInfo.cs na pasta Propriedades e adicione:
[assembly: UsesPermission(Android.Manifest.Permission.Flashlight)]
[assembly: UsesPermission(Android.Manifest.Permission.Camera)]
Ou clique com o botão direito do mouse no projeto do Android e abra as propriedades do projeto. Em Manifesto
do Android, localize a área Permissões necessárias: e marque as permissões FLASHLIGHT e CAMERA. Isso
atualizará automaticamente o arquivo AndroidManifest.xml.
Ao adicionar essas permissões, o Google Play filtrará automaticamente os dispositivos sem um hardware
específico. Você pode contornar isso adicionando o seguinte ao seu arquivo AssemblyInfo.cs em seu projeto do
Android:
using Xamarin.Essentials;
A lanterna pode ser ativada e desativada por meio dos métodos TurnOnAsync e TurnOffAsync :
try
{
// Turn On
await Flashlight.TurnOnAsync();
// Turn Off
await Flashlight.TurnOffAsync();
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to turn on/off flashlight
}
API
Código-fonte de Lanterna
Documentação da API de Lanterna
Xamarin.Essentials: Geocódigo
12/04/2019 • 3 minutes to read • Edit Online
A classe Geocoding fornece APIs para definir o código geográfico de um marcador de local para coordenadas
posicionais e reverter as coordenadas de código geográfico para um marcador de local.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade Geocodificação, a seguinte configuração específica da plataforma é necessária.
Android
iOS
UWP
Não exige mais configurações.
using Xamarin.Essentials;
try
{
var address = "Microsoft Building 25 Redmond WA USA";
var locations = await Geocoding.GetLocationsAsync(address);
A altitude nem sempre está disponível. Se não estiver disponível, a propriedade Altitude poderá ser null ou o
valor poderá ser zero. Se a altitude estiver disponível, o valor estará em metros acima do nível do mar.
try
{
var lat = 47.673988;
var lon = -122.121513;
Console.WriteLine(geocodeAddress);
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Handle exception that may have occurred in geocoding
}
API
Código-fonte de Geocodificação
Documentação da API de Geocodificação
Xamarin.Essentials: Geolocalização
12/04/2019 • 7 minutes to read • Edit Online
A classe Geolocation fornece APIs para recuperar as coordenadas atuais de geolocalização do dispositivo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade de Geolocalização, a seguinte configuração específica da plataforma é necessária:
Android
iOS
UWP
As permissões Coarse Location e Fine Location são necessárias e devem ser configuradas no projeto do Android.
Além disso, se o seu aplicativo for destinado ao Android 5.0 (API nível 21) ou superior, você deverá declarar que
ele usa os recursos de hardware no arquivo de manifesto. Isso pode ser usado das seguintes maneiras:
Abra o arquivo AssemblyInfo.cs na pasta Propriedades e adicione:
[assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
[assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
[assembly: UsesFeature("android.hardware.location", Required = false)]
[assembly: UsesFeature("android.hardware.location.gps", Required = false)]
[assembly: UsesFeature("android.hardware.location.network", Required = false)]
Ou clique com o botão direito no projeto do Android e abra as propriedades do projeto. Em Manifesto do
Android, localize a área Permissões necessárias: e marque as permissões ACCESS_COARSE_LOCATION e
ACCESS_FINE_LOCATION. Isso atualizará automaticamente o arquivo AndroidManifest.xml.
Usar a geolocalização
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get location
}
A altitude nem sempre está disponível. Se não estiver disponível, a propriedade Altitude poderá ser null ou o
valor poderá ser zero. Se a altitude estiver disponível, o valor estará em metros acima do nível do mar.
Para consultar as coordenadas do local atual do dispositivo, use GetLocationAsync . É melhor passar um
GeolocationRequest e CancellationToken completo, pois pode demorar um pouco para obter o local do
dispositivo.
try
{
var request = new GeolocationRequest(GeolocationAccuracy.Medium);
var location = await Geolocation.GetLocationAsync(request);
if (location != null)
{
Console.WriteLine($"Latitude: {location.Latitude}, Longitude: {location.Longitude}, Altitude:
{location.Altitude}");
}
}
catch (FeatureNotSupportedException fnsEx)
{
// Handle not supported on device exception
}
catch (FeatureNotEnabledException fneEx)
{
// Handle not enabled on device exception
}
catch (PermissionException pEx)
{
// Handle permission exception
}
catch (Exception ex)
{
// Unable to get location
}
Precisão da geolocalização
A tabela a seguir descreve a precisão por plataforma:
O menor
PLATAFORMA DISTÂNCIA (EM METROS)
Android 500
iOS 3000
UWP 1.000–5.000
Baixo
PLATAFORMA DISTÂNCIA (EM METROS)
Android 500
iOS 1000
UWP 300–3.000
Médio (padrão )
PLATAFORMA DISTÂNCIA (EM METROS)
Android 100–500
iOS 100
UWP 30–500
Alta
PLATAFORMA DISTÂNCIA (EM METROS)
Android 0–100
iOS 10
UWP <= 10
Melhor
PLATAFORMA DISTÂNCIA (EM METROS)
Android 0–100
iOS ~0
UWP <= 10
Detectando locais fictícios
Alguns dispositivos podem retornar um local fictício do provedor ou por um aplicativo que fornece locais fictícios.
Você pode detectar isso usando o IsFromMockProvider em qualquer Location .
if (location != null)
{
if(location.IsFromMockProvider)
{
// location is from a mock provider
}
}
O construtor Location tem argumentos de latitude e longitude, nessa ordem. Os valores de latitude positiva estão
ao norte do Equador, e os valores de longitude positiva estão a leste do Meridiano primário. Use o argumento
final para CalculateDistance a fim de especificar milhas ou quilômetros. A classe UnitConverters também define
os métodos KilometersToMiles e MilesToKilometers para conversão entre as duas unidades.
API
Código-fonte de geolocalização
Documentação da API de Geolocalização
Xamarin.Essentials: Giroscópio
12/04/2019 • 2 minutes to read • Edit Online
A classe Gyroscope permite que você monitore o sensor de giroscópio do dispositivo, que mede a rotação em
torno dos três eixos principais do dispositivo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A funcionalidade de Giroscópio chama os métodos Start e Stop e fica atenta às alterações no giroscópio. Todas
as alterações são enviadas de volta por meio do evento ReadingChanged em rad/s. Veja um exemplo de uso:
public class GyroscopeTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;
public GyroscopeTest()
{
// Register for reading changes.
Gyroscope.ReadingChanged += Gyroscope_ReadingChanged;
}
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
API
Código-fonte de Giroscópio
Documentação da API de Giroscópio
Xamarin.Essentials: Inicializador
12/04/2019 • 2 minutes to read • Edit Online
A classe Launcher permite que um aplicativo abra um URI pelo sistema. Isso geralmente é utilizado quando a
vinculação profunda é usada em esquemas de URI personalizados de outro aplicativo. Se quiser abrir o navegador
em um site, confira a API do Browser.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do Launcher
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
Para usar a funcionalidade Launcher, chame o método OpenAsync e passe uma string ou Uri para abrir.
Opcionalmente, o método CanOpenAsync pode ser usado para verificar se o esquema de URI pode ser tratado por
um aplicativo no dispositivo.
API
Código-fonte do Inicializador
Documentação da API do Inicializador
Xamarin.Essentials: Magnetômetro
12/04/2019 • 2 minutes to read • Edit Online
A classe Magnetometer permite que você monitore o sensor do magnetômetro do dispositivo, que indica a
orientação do dispositivo em relação ao campo magnético da Terra.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A funcionalidade do Magnetometer chama os métodos Start e Stop para ficar atenta às alterações no
magnetômetro. Todas as alterações são enviadas de volta por meio do evento ReadingChanged . Veja um exemplo
de uso:
public class MagnetometerTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;
public MagnetometerTest()
{
// Register for reading changes.
Magnetometer.ReadingChanged += Magnetometer_ReadingChanged;
}
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
API
Código-fonte de Magnetômetro
Documentação da API de Magnetômetro
Xamarin.Essentials: MainThread
12/04/2019 • 5 minutes to read • Edit Online
A classe MainThread permite que os aplicativos executem o código no thread de execução principal e
determinem se certo bloco de código está sendo executado no thread principal.
Informações preliminares
A maioria dos sistemas operacionais, incluindo iOS, Android e a Plataforma Universal do Windows, usa um
modelo de threading simples para o código que envolve a interface do usuário. Esse modelo é necessário para
serializar adequadamente os eventos da interface do usuário, incluindo pressionamentos de tecla e entrada de
toque. Este thread é frequentemente chamado de thread principal ou o thread da interface do usuário ou,
ainda, o thread da IU. A desvantagem desse modelo é que todo código que acessa os elementos da interface
do usuário deve ser executado no thread principal do aplicativo.
Às vezes, os aplicativos precisam usar eventos que chamam o manipulador de eventos em um thread de
execução secundário. (As classes Accelerometer , Compass , Gyroscope , Magnetometer e OrientationSensor do
Xamarin.Essentials podem todas retornar informações em um thread secundário, quando usadas com
velocidades mais rápidas). Se o manipulador de eventos precisar acessar os elementos da interface do usuário,
ele deverá executar esse código no thread principal. A classe MainThread permite que os aplicativos
executem esse código no thread principal.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a
biblioteca esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
MainThread.BeginInvokeOnMainThread(() =>
{
// Code to run on the main thread
});
Também é possível definir um método separado para o código que deverá ser executado no thread principal:
void MyMainThreadCode()
{
// Code to run on the main thread
}
Você pode executar esse método no thread principal fazendo referência a ele no método
BeginInvokeOnMainThread :
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
NOTE
O Xamarin.Forms tem um método chamado Device.BeginInvokeOnMainThread(Action) , que faz o mesmo que
MainThread.BeginInvokeOnMainThread(Action) . Embora você possa usar qualquer método em um aplicativo
Xamarin.Forms, considere se o código de chamada tem ou não alguma outra necessidade de dependência no
Xamarin.Forms. Caso contrário, é provável que MainThread.BeginInvokeOnMainThread(Action) seja uma opção
melhor.
if (MainThread.IsMainThread)
{
// Code to run if this is the main thread
}
else
{
// Code to run if this is a secondary thread
}
Você pode se perguntar se deve verificar se o código está sendo executado em um thread secundário antes de
chamar BeginInvokeOnMainThread , por exemplo:
if (MainThread.IsMainThread)
{
MyMainThreadCode();
}
else
{
MainThread.BeginInvokeOnMainThread(MyMainThreadCode);
}
Você pode suspeitar que essa verificação possa melhorar o desempenho se o bloco de código já estiver em
execução no thread principal.
No entanto, essa verificação não é necessária. As implementações da plataforma de BeginInvokeOnMainThread
verificam se a chamada é feita no thread principal. A perda de desempenho é pouca se você chamar
BeginInvokeOnMainThread quando não for realmente necessário.
API
Código-fonte do MainThread
Documentação da API do MainThread
Xamarin.Essentials: Mapa
12/04/2019 • 3 minutes to read • Edit Online
A classe Maps permite que um aplicativo abra o aplicativo de mapas instalado em um local ou marcador
específico.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Usando o mapa
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
A funcionalidade Map funciona chamando o método OpenAsync com Location ou Placemark para abrir com
MapLaunchOptions opcional.
Métodos de extensão
Se você já tiver uma referência a uma Location ou Placemark , use o método de extensão interno OpenMapAsync
com MapLaunchOptions opcional:
Modo de direções
Se você chamar OpenMapAsync sem MapLaunchOptions , o mapa será iniciado no local especificado. Se quiser, tenha
uma rota de navegação calculada a partir da posição atual do dispositivo. Isso é feito definindo o NavigationMode
nas MapLaunchOptions :
API
Código-fonte do Mapa
Documentação da API do Mapa
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Xamarin.Essentials: Navegador
12/04/2019 • 2 minutes to read • Edit Online
A classe Browser permite que um aplicativo abra um link da Web no navegador preferido do sistema otimizado
ou no navegador externo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do Browser
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
Esse método retorna depois que o navegador foi iniciado e não necessariamente fechado pelo usuário. O bool
resultado indica se a inicialização foi bem-sucedida ou não.
Personalização
Ao usar o navegador preferencial do sistema, existem várias opções de personalização disponíveis para iOS e
Android. Isso inclui um TitleMode (somente Android) e opções de cores preferenciais para a Toolbar (iOS e
Android) e os Controls (somente iOS ) que são exibidos.
Essas opções são especificadas usando BrowserLaunchOptions ao chamar OpenAsync .
Sistema preferido
As Custom Tabs do Chrome tentarão ser usadas para carregar o Uri e manter o reconhecimento da navegação.
Externo
Uma Intent será usada para solicitar o Uri que será aberto por meio do navegador normal dos sistemas.
API
Código-fonte do Browser
Documentação da API do Browser
Vídeo relacionados
NOTE
Essa classe é usada para determinar a orientação de um dispositivo no espaço tridimensional. Se for necessário determinar
se a exibição de vídeo do dispositivo está no modo retrato ou paisagem, use a propriedade Orientation do objeto
ScreenMetrics disponível na classe DeviceDisplay .
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do OrientationSensor
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
O OrientationSensor é habilitado pela chamada do método Start , para monitorar as alterações da orientação do
dispositivo, e desabilitado chamando o método Stop . Todas as alterações são enviadas de volta por meio do
evento ReadingChanged . Veja um exemplo de uso:
public class OrientationSensorTest
{
// Set speed delay for monitoring changes.
SensorSpeed speed = SensorSpeed.UI;
public OrientationSensorTest()
{
// Register for reading changes, be sure to unsubscribe when finished
OrientationSensor.ReadingChanged += OrientationSensor_ReadingChanged;
}
Estes são sistemas de coordenadas à direita, portanto, com o polegar da mão direita apontado na direção positiva
do eixo de rotação, a curva dos dedos indica a direção da rotação para ângulos positivos.
Exemplos:
Os dois sistemas de coordenadas estarão alinhados quando o dispositivo estiver em uma mesa com a tela
voltada para cima e a parte superior do dispositivo (no modo retrato) estiver apontando para norte. O
valor Quaternion representa o quatérnio da identidade (0, 0, 0, 1). Todas as rotações podem ser analisadas
em relação a essa posição.
O valor Quaternion será (0, 0, 0.707, 0.707) quando dispositivo estiver em uma mesa com a tela voltada
para cima e a parte superior do dispositivo (no modo retrato) estiver apontando para oeste. O dispositivo
girou 90 graus em torno do eixo Z da Terra.
O dispositivo terá girado 90 graus ao redor do eixo X quando for colocado na posição vertical de modo
que a parte superior (no modo retrato) aponte para o céu e a parte de trás do dispositivo fique voltada para
norte. O valor Quaternion é (0.707, 0, 0, 0.707).
O dispositivo terá sido girado –90 graus ao redor do eixo Y (ou 90 graus ao redor do eixo negativo Y ) se
ele estiver posicionado de forma que sua borda esquerda esteja sobre uma mesa e os pontos superiores ao
norte. O valor Quaternion é (0, -0.707, 0, 0.707).
Sensor de velocidade
Mais rápido – obtenha os dados do sensor o mais rápido possível (não é garantido retornar no thread de
interface do usuário).
Jogo – taxa adequada para jogos (não é garantido retornar no thread de interface do usuário).
Normal – taxa padrão adequada para alterações de orientação da tela.
Interface do usuário – taxa adequada para a interface do usuário geral.
Se o manipulador de eventos não tiver a garantia de ser executado no thread da interface do usuário e se precisar
acessar os elementos de interface do usuário, use o método MainThread.BeginInvokeOnMainThread para executar
esse código no thread da interface do usuário.
API
Código-fonte do OrientationSensor
Documentação da API do OrientationSensor
Xamarin.Essentials: Discagem telefônica
12/04/2019 • 2 minutes to read • Edit Online
A classe PhoneDialer permite que um aplicativo abra um número de telefone pelo discador.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A funcionalidade de Discagem telefônica chama o método Open com um número de telefone para abrir o
discador. Quando Open é solicitada, a API automaticamente tenta formatar o número com base no código de país,
caso tenha sido especificado.
API
Código-fonte de Discagem telefônica
Documentação da API de Discagem Telefônica
Xamarin.Essentials: Extensões de plataforma
12/04/2019 • 2 minutes to read • Edit Online
O Xamarin.Essentials fornece vários métodos de extensão de plataforma quando é preciso trabalhar com tipos de
plataforma, como retângulo, tamanho e o ponto. Isso significa que você pode converter entre a versão System
desses tipos para iOS, Android e tipos específicos de UWP.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Todas as extensões de plataforma só podem ser chamadas do iOS, do Android ou do projeto UWP.
Ponto
// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();
Tamanho
// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();
Retângulo
// Back to System.Drawing.Size
var system2 = platform.ToSystemSize();
API
Código-fonte de conversores
Documentação da API de conversores de ponto
Documentação da API de conversores de retângulo
Documentação da API de conversores de tamanho
Xamarin.Essentials: Preferências
12/04/2019 • 4 minutes to read • Edit Online
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Preferences.Set("my_key", "my_value");
Preferences.Remove("my_key");
Preferences.Clear();
Além desses métodos, cada uma pode receber um sharedName opcional que pode ser usado para criar
contêineres adicionais para preferência. Leia a seguir as particularidades de implementação da plataforma.
Persistência
A desinstalação do aplicativo causará a remoção de todas as Preferências. Há uma exceção a isso para aplicativos
destinados ao Android 6.0 (API nível 23) ou posterior que usam Backup Automático. Esse recurso está ativado
por padrão e preserva os dados do aplicativo, incluindo Preferências Compartilhadas, que é o que a API de
Preferências utiliza. É possível desabilitar isso seguindo a documentação do Google.
Limitações
Ao armazenar uma cadeia de caracteres, essa API destina-se a armazenar pequenas quantidades de texto. O
desempenho pode ser abaixo da média se você tentar usá-lo para armazenar grandes quantidades de texto.
API
Código-fonte de Preferências
Documentação da API de Preferências
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Xamarin.Essentials: Armazenamento seguro
18/04/2019 • 7 minutes to read • Edit Online
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade SecureStorage, a seguinte configuração específica da plataforma é necessária:
Android
iOS
UWP
TIP
O Backup Automático para Aplicativos é um recurso do Android 6.0 (nível da API 23) e posterior que faz o backup dos dados
do aplicativo do usuário (preferências compartilhadas, arquivos no armazenamento interno do aplicativo e outros arquivos
específicos). Os dados são restaurados quando um aplicativo é reinstalado ou instalado em um novo dispositivo. Isso pode
afetar a SecureStorage , que utiliza as preferências de compartilhamento do backup e que não podem ser
descriptografadas quando a restauração ocorrer. O Xamarin.Essentials trata automaticamente desse caso removendo a chave
para que ela possa ser redefinida. No entanto, você pode avançar e desabilitar o Backup Automático.
Backup seletivo
O backup automático pode ser configurado para desabilitar o backup de um conteúdo específico. Você pode criar
uma regra personalizada definida para excluir itens do SecureStore de passarem por backup.
1. Defina o atributo android:fullBackupContent em seu AndroidManifest.xml:
<application ...
android:fullBackupContent="@xml/auto_backup_rules">
</application>
using Xamarin.Essentials;
try
{
await SecureStorage.SetAsync("oauth_token", "secret-oauth-token-value");
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
try
{
var oauthToken = await SecureStorage.GetAsync("oauth_token");
}
catch (Exception ex)
{
// Possible that device doesn't support secure storage on device.
}
NOTE
Se não houver valores associados à chave solicitada, GetAsync retornará null .
SecureStorage.Remove("oauth_token");
SecureStorage.RemoveAll();
Limitações
Essa API destina-se a armazenar pequenas quantidades de texto. O desempenho pode ser lento se você tentar usá-
lo para armazenar grandes quantidades de texto.
API
Código-fonte de SecureStorage
Documentação da API de SecureStorage
Vídeo relacionados
A classe Share permite que um aplicativo compartilhe dados, como links de texto e da Web com outros aplicativos
no dispositivo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Usando o compartilhamento
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
A funcionalidade Share funciona chamando o método RequestAsync com um conteúdo de solicitação de dados
que inclui informações para compartilhar com outros aplicativos. É possível combinar texto e Uri, e cada
plataforma tratará a filtragem com base no conteúdo.
Interface do usuário para compartilhar com aplicativo externo exibida quando uma solicitação é feita:
Diferenças entre plataformas
Android
iOS
UWP
Subject a propriedade é usada para o assunto desejado de uma mensagem.
Arquivos
O compartilhamento de arquivos está disponível como uma versão prévia experimental no Xamarin.Essentials
versão 1.1.0. Esse recurso permite que um aplicativo compartilhe arquivos com outros aplicativos no dispositivo.
Para habilitar esse recurso, defina a propriedade a seguir no código de inicialização do aplicativo:
ExperimentalFeatures.Enable(ExperimentalFeatures.ShareFileRequest);
Depois de habilitar o recurso, qualquer arquivo poderá ser compartilhado. O Xamarin.Essentials detectará
automaticamente o tipo de arquivo (MIME ) e solicitará um compartilhamento. Cada plataforma poderá ser
compatível somente com extensões de arquivo específicas.
Veja um exemplo de como gravar texto no disco e compartilhá-lo com outros aplicativos:
var fn = "Attachment.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
API
Compartilhar código-fonte
Compartilhar documentação da API
Vídeo relacionados
Saiba mais sobre o Xamarin Show no Channel 9 e no YouTube.
Xamarin.Essentials: SMS
12/04/2019 • 2 minutes to read • Edit Online
A classe Sms permite que um aplicativo abra o aplicativo de SMS padrão com uma determinada mensagem para
enviar para um destinatário.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Uso do SMS
Adicione uma referência ao Xamarin.Essentials na classe:
using Xamarin.Essentials;
A funcionalidade do SMS funciona chamando o método ComposeAsync de uma SmsMessage que contém o
destinatário da mensagem e o corpo da mensagem, sendo ambos opcionais.
Além disso, você pode passar vários destinatários para uma SmsMessage :
public class SmsTest
{
public async Task SendSms(string messageText, string[] recipients)
{
try
{
var message = new SmsMessage(messageText, recipients);
await Sms.ComposeAsync(message);
}
catch (FeatureNotSupportedException ex)
{
// Sms is not supported on this device.
}
catch (Exception ex)
{
// Other error has occurred.
}
}
}
API
Código-fonte do SMS
Documentação da API do SMS
Xamarin.Essentials: Conversão de texto em fala
12/04/2019 • 3 minutes to read • Edit Online
A classe TextToSpeech permite que um aplicativo utilize os mecanismos internos de conversão de texto em fala
para repetir o texto do dispositivo e, também, consulte os idiomas disponíveis, compatíveis com o mecanismo.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A Conversão de Texto em Fala funciona chamando o método SpeakAsync com texto e parâmetros opcionais e
retorna depois que a expressão é concluída.
}, TaskScheduler.FromCurrentSynchronizationContext());
}
Esse método usa um recurso opcional CancellationToken para interromper a expressão após ela ser iniciada.
CancellationTokenSource cts;
public async Task SpeakNowDefaultSettings()
{
cts = new CancellationTokenSource();
await TextToSpeech.SpeakAsync("Hello World", cancelToken: cts.Token);
cts.Cancel();
}
A Conversão de Texto em Fala automaticamente enfileirará as solicitações de voz do mesmo thread.
Configurações de fala
Para obter mais controle sobre como o áudio é falado com SpeechOptions , que permite definir o volume, o tom e a
localidade.
Densidade 0 2.0
Volume 0 1.0
Localidades de fala
Cada plataforma suporta diferentes localidades, para responder em diferentes idiomas e sotaques. As plataformas
têm diferentes códigos e formas de especificar a localidade e é por isso que o Xamarin.Essentials fornece uma
classe Locale de plataforma cruzada e uma maneira de consultá-los com GetLocalesAsync .
public async Task SpeakNow()
{
var locales = await TextToSpeech.GetLocalesAsync();
Limitações
A fila de expressão não terá garantia se for chamada através de múltiplos threads.
Oficialmente, não há suporte para a reprodução de áudio em segundo plano.
API
Código-fonte TextToSpeech
Documentação da API do TextToSpeech
Xamarin.Essentials: Conversores de unidade
12/04/2019 • 2 minutes to read • Edit Online
A classe UnitConverters fornece vários conversores de unidade para ajudar os desenvolvedores ao usar o
Xamarin.Essentials.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
Todos os conversores de unidade estão disponíveis com o uso da classe UnitConverters estática no
Xamarin.Essentials. Por exemplo, você pode converter facilmente Fahrenheit em Celsius.
API
Código-fonte de conversores de unidade
Documentação da API de conversores de unidade
Xamarin.Essentials: Controle de versão
12/04/2019 • 2 minutes to read • Edit Online
A classe VersionTracking permite que você verifique a versão e os números de build dos aplicativos, junto com
informações adicionais, por exemplo, se é a primeira vez que o aplicativo é iniciado ou, para a versão atual, obter
informações do build anterior e muito mais.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
using Xamarin.Essentials;
A primeira vez que você usar a classe VersionTracking, ela começará a acompanhar a versão atual. Chame
Track antecipadamente em seu aplicativo sempre que ele for carregado, a fim de garantir que as informações da
versão atual sejam rastreadas:
VersionTracking.Track();
API
Código-fonte de Controle de Versão
Documentação da API de Controle de Versão
Xamarin.Essentials: Vibração
12/04/2019 • 2 minutes to read • Edit Online
A classe Vibration permite iniciar e interromper a funcionalidade de vibrar por um tempo desejado.
Introdução
Para começar a usar essa API, leia o guia de Introdução para Xamarin.Essentials a fim de garantir que a biblioteca
esteja corretamente instalada e configurada em seus projetos.
Para acessar a funcionalidade de Vibração, a seguinte configuração específica da plataforma é necessária.
Android
iOS
UWP
A permissão de Vibração é necessária e deve ser configurada no projeto do Android. Isso pode ser usado das
seguintes maneiras:
Abra o arquivo AssemblyInfo.cs na pasta Propriedades e adicione:
[assembly: UsesPermission(Android.Manifest.Permission.Vibrate)]
Ou clique com o botão direito do mouse no projeto do Android e abra as propriedades do projeto. Em Manifesto
do Android, localize a área Permissões necessárias: e marque a permissão VIBRAR. Isso atualizará
automaticamente o arquivo AndroidManifest.xml.
using Xamarin.Essentials;
A funcionalidade de vibração pode ser solicitada por um determinado tempo ou pelo padrão de 500
milissegundos.
try
{
// Use default vibration length
Vibration.Vibrate();
try
{
Vibration.Cancel();
}
catch (FeatureNotSupportedException ex)
{
// Feature not supported on device
}
catch (Exception ex)
{
// Other error has occurred.
}
API
Código-fonte de Vibração
Documentação da API de Vibração
Xamarin.Essentials: Solução de problemas
12/04/2019 • 2 minutes to read • Edit Online
NU1107: Version conflict detected for Xamarin.Android.Support.Compat. Reference the package directly from the
project to resolve this issue.
MyApp -> Xamarin.Essentials 1.1.0 -> Xamarin.Android.Support.CustomTabs 28.0.0.1 ->
Xamarin.Android.Support.Compat (= 28.0.0.1)
MyApp -> Xamarin.Forms 3.1.0.583944 -> Xamarin.Android.Support.v4 25.4.0.2 -> Xamarin.Android.Support.Compat
(= 25.4.0.2).
O problema são dependências sem correspondência para os dois NuGets. Isso pode ser resolvido adicionando
manualmente uma versão específica da dependência (nesse caso, Xamarin.Android.Support.Compat) que
pode ser compatível com ambas.
Para fazer isso, adicione o NuGet que é a origem do conflito manualmente e use a lista Versão para selecionar
uma versão específica. No momento, a versão 28.0.0.1 do NuGet do Xamarin.Android.Support.Compat e do
Xamarin.Android.Support.Core.Util resolverão esse erro.
Confira esta postagem no blog para obter mais informações e um vídeo sobre como resolver o problema.
Se encontrar problemas ou localizar um bug, relate o que ocorreu no repositório GitHub do Xamarin.Essentials
GitHub.
Serviços de dados e de nuvem
12/04/2019 • 5 minutes to read
Aplicativos xamarin. Forms podem consumir serviços da web implementado usando uma ampla variedade de
tecnologias e este guia examinará como fazer isso.
Para obter uma introdução para o consumo do serviço web de plataforma cruzada na plataforma Xamarin,
consulte Introdução aos serviços Web.
baixar o exemplo
Este tópico fornece um passo a passo do aplicativo de exemplo do xamarin. Forms que demonstra como se
comunicar com serviços web diferentes. Enquanto a cada serviço web usa um aplicativo de exemplo separado,
elas são funcionalmente semelhantes e compartilharem classes comuns.
O aplicativo de lista de tarefas pendentes de exemplo descrito abaixo é usado para demonstrar como acessar os
diferentes tipos de back-ends da web de serviço com o xamarin. Forms. Ele fornece funcionalidade para:
Exiba uma lista de tarefas.
Adicionar, editar e excluir tarefas.
Defina o status da tarefa para 'concluído'.
Fale os campos de nome e Observações da tarefa.
Em todos os casos, as tarefas são armazenadas em um back-end que é acessado por meio de um serviço web.
Quando o aplicativo é iniciado, é exibida uma página que lista as tarefas recuperadas do serviço web e permite
que o usuário crie uma nova tarefa. Clicar em uma tarefa navega o aplicativo em uma segunda página em que a
tarefa pode ser editada, salvo, excluída e falada. O aplicativo final é mostrado abaixo:
Cada tópico deste guia fornece um link de download para um diferentes versão do aplicativo que demonstra um
tipo específico de back-end de serviço web. Baixe o código de exemplo relevante na página relacionadas ao estilo
de cada serviço web.
PASTA FINALIDADE
O projeto PCL para cada aplicativo também consiste em um número de arquivos importantes:
ARQUIVO FINALIDADE
Exibindo páginas
A maioria dos aplicativos de exemplo contém pelo menos duas páginas:
TodoListPage – esta página exibe uma lista de TodoItem instâncias e um ícone de tique se o TodoItem.Done é
de propriedade true . Clicar em um item navega para o TodoItemPage . Além disso, novos itens podem ser
criados, clicando na + símbolo.
TodoItemPage – esta página exibe os detalhes para o selecionado TodoItem e permite que ele seja editado,
salvo, excluído e falado.
Além disso, alguns aplicativos de exemplo contêm páginas adicionais que são usadas para gerenciar o processo
de autenticação do usuário.
Modelagem de dados
Cada aplicativo de exemplo usa o TodoItem classe para modelar os dados que são exibidos e enviados para o
serviço web para o armazenamento. O exemplo de código a seguir mostra a classe TodoItem :
O ID propriedade é usada para identificar exclusivamente cada TodoItem instância e são usados por cada
serviço da web para identificar os dados a serem atualizados ou excluídos.
Invocar operações de serviço Web
Operações de serviço Web são acessadas por meio de TodoItemManager classe e uma instância da classe podem
ser acessados por meio do App.TodoManager propriedade. O TodoItemManager classe fornece os seguintes
métodos para chamar operações de serviço web:
GetTasksAsync – esse método é usado para preencher a ListView control na TodoListPage com o TodoItem
instâncias recuperadas do serviço web.
SaveTaskAsync – esse método é usado para criar ou atualizar um TodoItem instância no serviço web.
DeleteTaskAsync – esse método é usado para excluir um TodoItem instância no serviço web.
Além disso, alguns aplicativos de exemplo contêm métodos adicionais no TodoItemManager classe, que são usados
para gerenciar o processo de autenticação do usuário.
Em vez de invocar as operações de serviço web diretamente, o TodoItemManager métodos de invocam métodos
em uma classe dependente que é injetado no TodoItemManager construtor. Por exemplo, um aplicativo de exemplo
injeta a RestService de classe para o TodoItemManager construtor para fornecer a implementação que usa APIs
REST para acessar os dados.
Converter texto em fala
A maioria dos aplicativos de exemplo contêm funcionalidade de texto em fala (TTS ) falar os valores de
TodoItem.Name e TodoItem.Notes propriedades. Isso é feito usando o OnSpeakActivated manipulador de eventos
no TodoItemPage de classe, conforme mostrado no exemplo de código a seguir:
Esse método simplesmente chama o Speak método é implementado por uma plataforma específica Speech
classe. Cada Speech classe implementa o ITextToSpeech interface, e código de inicialização específica da
plataforma cria uma instância da Speech classe que pode ser acessado por meio do App.Speech propriedade.
Resumo
Este tópico forneceu um passo a passo do aplicativo de exemplo de xamarin. Forms é usado para demonstrar
como se comunicar com serviços web diferentes. Enquanto a cada serviço web usa um aplicativo de exemplo
separados, eles se baseiam na mesma lógica de negócios e de interface do usuário conforme descrito acima -
apenas o mecanismo de armazenamento do web service dados é diferente.
Links relacionados
Versão ASMX (amostra)
Versão do WCF (amostra)
Versão REST (amostra)
Versão do Azure (exemplo)
Consumir serviços da Web
12/04/2019 • 3 minutes to read
Es_te guia demonstra como se comunicar com serviços web diferentes para fornecer criar, ler, atualizar e excluir
(CRUD ) funcionalidade a um aplicativo xamarin. Forms. Os tópicos abordados incluem a se comunicar com
serviços ASMX, os serviços WCF, serviços REST e aplicativos móveis do Azure.
Links relacionados
Introdução aos serviços Web
Visão geral do suporte assíncrono
Consumir um serviço Web ASP.NET (ASMX)
18/04/2019 • 12 minutes to read
baixar o exemplo
ASMX fornece a capacidade de criar serviços web que enviam mensagens usando o SOAP Simple Object Access
Protocol (). SOAP é um protocolo independente de plataforma e linguagem para criar e acessar serviços web. Os
consumidores de um serviço ASMX não precisam saber nada sobre a plataforma, um modelo de objeto ou uma
linguagem de programação usada para implementar o serviço. Eles só precisam entender como enviar e receber
mensagens SOAP. Este artigo demonstra como consumir um serviço ASMX SOAP de um aplicativo xamarin.
Forms.
Uma mensagem SOAP é um documento XML que contém os seguintes elementos:
Um elemento raiz chamado Envelope que identifica o documento XML como uma mensagem SOAP.
Um recurso opcional cabeçalho elemento que contém informações específicas do aplicativo, como dados de
autenticação. Se o cabeçalho elemento está presente ele deve ser o primeiro elemento filho do Envelope
elemento.
Obrigatória corpo elemento que contém a mensagem SOAP para o destinatário.
Um recurso opcional falha elemento que é usado para indicar as mensagens de erro. Se o falhas elemento
estiver presente, ele deve ser um elemento filho do corpo elemento.
SOAP pode operar em vários protocolos de transporte, incluindo HTTP, SMTP, TCP e UDP. No entanto, um
serviço ASMX só pode operar sobre HTTP. A plataforma Xamarin dá suporte a implementações padrão de SOAP
1.1 via HTTP, e isso inclui suporte para muitas das configurações de serviço padrão do ASMX.
Este exemplo inclui os aplicativos móveis que são executados em dispositivos físicos ou emulados e um serviço
ASMX que fornece métodos para obter, adicionar, editar e excluir dados. Quando os aplicativos móveis são
executados, eles se conectam ao serviço ASMX hospedado localmente conforme mostrado na seguinte captura de
tela:
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos
de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção. ATS poderá ser aceito de se
ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da internet. Isso pode ser feito
atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de transporte de aplicativo.
Para obter mais informações sobre o modelo de dados usado no aplicativo, consulte modelagem de dados.
O exemplo SoapService :
1. Cria uma instância de TodoService como uma instância de nível de classe
2. Cria uma coleção chamada Items para armazenar TodoItem objetos
3. Especifica um ponto de extremidade personalizado para opcional Url propriedade sobre a TodoService
public SoapService ()
{
todoService = new ASMXService.TodoService ();
todoService.Url = Constants.SoapUrl;
...
}
}
Esse método cria uma nova ASMService.TodoItem da instância e define cada propriedade para a propriedade
idêntica do TodoItem instância.
Da mesma forma, quando os dados são recuperados do serviço da web, ele deve ser convertido do proxy gerado
TodoItem de tipo para um TodoItem instância. Isso é feito com o FromASMXServiceTodoItem método, conforme
mostrado no exemplo de código a seguir:
static TodoItem FromASMXServiceTodoItem (ASMXService.TodoItem item)
{
return new TodoItem {
ID = item.ID,
Name = item.Name,
Notes = item.Notes,
Done = item.Done
};
}
Esse método recupera os dados do proxy gerado TodoItem de tipo e define-a no recém-criado TodoItem instância.
Recuperar dados
O ISoapService interface espera que o RefreshDataAsync método retorne um Task com a coleção de itens. No
entanto, o TodoService.GetTodoItemsAsync método retorna void. Para satisfazer o padrão de interface, você deve
chamar GetTodoItemsAsync , aguarde até que o GetTodoItemsCompleted evento seja acionado e popular a coleção.
Isso permite que você retorne uma coleção válida para a interface do usuário.
O exemplo a seguir cria um novo TaskCompletionSource , inicia a chamada assíncrona na RefreshDataAsync método
e aguarda o Task fornecidos pelo TaskCompletionSource . Quando o TodoService_GetTodoItemsCompleted
manipulador de eventos é invocado ele preenche os Items coleção e atualizações a TaskCompletionSource :
public class SoapService : ISoapService
{
TaskCompletionSource<bool> getRequestComplete = null;
...
public SoapService()
{
...
todoService.GetTodoItemsCompleted += TodoService_GetTodoItemsCompleted;
}
...
}
Para obter mais informações, consulte modelo de programação assíncrona e .NET Framework programação
assíncrona tradicional e TPL.
Criar ou editar dados
Quando você cria ou edita dados, você deve implementar o ISoapService.SaveTodoItemAsync método. Este método
detecta se o TodoItem é um item novo ou atualizado e chama o método apropriado no todoService objeto. O
CreateTodoItemCompleted e EditTodoItemCompleted manipuladores de eventos devem ser implementados para que
você saiba quando o todoService recebeu uma resposta do serviço ASMX (eles podem ser combinados em um
único manipulador porque elas executam a mesma operação). O exemplo a seguir demonstra as implementações
de manipulador de interface e eventos, bem como o TaskCompletionSource objeto usado para operar de maneira
assíncrona:
public class SoapService : ISoapService
{
TaskCompletionSource<bool> saveRequestComplete = null;
...
public SoapService()
{
...
todoService.CreateTodoItemCompleted += TodoService_SaveTodoItemCompleted;
todoService.EditTodoItemCompleted += TodoService_SaveTodoItemCompleted;
}
...
}
Excluir dados
A exclusão de dados requer uma implementação semelhante. Definir um TaskCompletionSource , implemente um
manipulador de eventos e o ISoapService.DeleteTodoItemAsync método:
public class SoapService : ISoapService
{
TaskCompletionSource<bool> deleteRequestComplete = null;
...
public SoapService()
{
...
todoService.DeleteTodoItemCompleted += TodoService_DeleteTodoItemCompleted;
}
...
}
Links relacionados
TodoASMX (amostra)
IAsyncResult
Consumir um serviço Web do Windows
Communication Foundation (WCF)
12/04/2019 • 24 minutes to read
IMPORTANT
O suporte de plataforma do Xamarin para o WCF é limitado a texto codificado mensagens SOAP sobre HTTP/HTTPS usando
o BasicHttpBinding classe.
Suporte do WCF requer o uso das ferramentas disponíveis somente em um ambiente do Windows para gerar o proxy e
hospedar o TodoWCFService. Compilar e testar o aplicativo iOS exigirá a implantação de TodoWCFService em um
computador Windows ou como um serviço web do Azure.
Aplicativos nativos do Xamarin. Forms normalmente compartilham código com uma biblioteca de classes .NET Standard. No
entanto, .NET Core não suporta no momento WCF para que o projeto compartilhado deve ser uma biblioteca de classes
portátil herdado. Para obter informações sobre o suporte do WCF no .NET Core, consulte escolhendo entre o .NET Core e
.NET Framework para aplicativos de servidor.
A solução de aplicativo de exemplo inclui um serviço WCF que pode ser executado localmente e é mostrado na
seguinte captura de tela:
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos de
segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção.
ATS poderá ser aceito de se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da
internet. Isso pode ser feito atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de
transporte de aplicativo.
Para obter mais informações sobre o modelo de dados usado no aplicativo, consulte modelagem de dados.
Um proxy deve ser gerado para consumir um serviço WCF, que permite que o aplicativo para se conectar ao
serviço. O proxy é construído por consumo metadados de serviço que definem os métodos e a configuração de
serviço associado. Esses metadados são expostos na forma de um documento de descrição linguagem WSDL
(Web Services) que é gerado pelo serviço web. O proxy pode ser compilado usando o Microsoft WCF Web Service
Reference Provider no Visual Studio 2017 para adicionar uma referência de serviço para o serviço web a uma
biblioteca .NET Standard. Uma alternativa para criar o proxy usando o Microsoft WCF Web Service Reference
Provider no Visual Studio 2017 é usar a ferramenta Utilitário de metadados de ServiceModel (svcutil.exe). Para
obter mais informações, consulte ferramenta de utilitário de metadados ServiceModel (Svcutil.exe).
As classes de proxy geradas fornecem métodos para consumir os serviços web que usam o padrão de design do
modelo de programação assíncrona (APM ). Nesse padrão, uma operação assíncrona é implementada como dois
métodos chamados BeginOperationName e EndOperationName, que começam e terminam a operação
assíncrona.
O BeginOperationName método inicia a operação assíncrona e retorna um objeto que implementa o
IAsyncResult interface. Depois de chamar BeginOperationName, um aplicativo pode continuar a executar as
instruções no thread de chamada, enquanto a operação assíncrona ocorre em um pool de threads.
Para cada chamada para BeginOperationName, o aplicativo também deve chamar EndOperationName para obter
os resultados da operação. O valor de retorno EndOperationName é do mesmo tipo retornado pelo método de
serviço da web síncronas. Por exemplo, o EndGetTodoItems método retorna uma coleção de TodoItem instâncias. O
EndOperationName método também inclui um IAsyncResult parâmetro deve ser definido como a instância
retornada pela chamada correspondente para o BeginOperationName método.
A tarefa paralela TPL (biblioteca) pode simplificar o processo de consumir um par de métodos de início/término
do APM, encapsulando as operações assíncronas no mesmo Task objeto. Esse encapsulamento é fornecido pelas
várias sobrecargas do TaskFactory.FromAsync método.
Para obter mais informações sobre o APM, consulte modelo de programação assíncrona e .NET Framework
programação assíncrona tradicional e TPL no MSDN.
Criar o objeto TodoServiceClient
Fornece a classe proxy gerada a TodoServiceClient classe, que é usado para se comunicar com o serviço WCF por
meio de HTTP. Ele fornece funcionalidade para invocar métodos de serviço web, como operações assíncronas de
um URI identificado a instância de serviço. Para obter mais informações sobre as operações assíncronas, consulte
visão geral do suporte assíncrono.
O TodoServiceClient instância é declarada no nível de classe, de modo que o objeto reside para desde que o
aplicativo precisa consumir o serviço WCF, conforme mostrado no exemplo de código a seguir:
public SoapService ()
{
todoService = new TodoServiceClient (
new BasicHttpBinding (),
new EndpointAddress (Constants.SoapUrl));
}
...
}
Esse método simplesmente cria um novo TodoWCFService.TodoItem da instância e define cada propriedade para a
propriedade idêntica do TodoItem instância.
Da mesma forma, quando os dados são recuperados do serviço da web, ele deve ser convertido do proxy gerado
TodoItem de tipo para um TodoItem instância. Isso é feito com o FromWCFServiceTodoItem método, conforme
mostrado no exemplo de código a seguir:
Esse método simplesmente recupera os dados do proxy gerado TodoItem de tipo e define-a no recém-criado
TodoItem instância.
Recuperar dados
O TodoServiceClient.BeginGetTodoItems e TodoServiceClient.EndGetTodoItems métodos são usados para chamar o
GetTodoItems operação fornecidos pelo serviço web. Esses métodos assíncronos são encapsulados em um Task
do objeto, conforme mostrado no exemplo de código a seguir:
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var todoItems = await Task.Factory.FromAsync <ObservableCollection<TodoWCFService.TodoItem>> (
todoService.BeginGetTodoItems,
todoService.EndGetTodoItems,
null,
TaskCreationOptions.None);
O Task.Factory.FromAsync método cria uma Task que executa o TodoServiceClient.EndGetTodoItems método uma
vez o TodoServiceClient.BeginGetTodoItems método é concluído, com o null parâmetro que indica que nenhum
dado está sendo passado para o BeginGetTodoItems delegar. Por fim, o valor da TaskCreationOptions enumeração
que especifica que o comportamento padrão para a criação e execução de tarefas deve ser usado.
O TodoServiceClient.EndGetTodoItems método retorna um ObservableCollection de TodoWCFService.TodoItem
instâncias, que, em seguida, é convertido em um List de TodoItem instâncias para exibição.
Criar dados
O TodoServiceClient.BeginCreateTodoItem e TodoServiceClient.EndCreateTodoItem métodos são usados para
chamar o CreateTodoItem operação fornecidos pelo serviço web. Esses métodos assíncronos são encapsulados em
um Task do objeto, conforme mostrado no exemplo de código a seguir:
O Task.Factory.FromAsync método cria uma Task que executa o TodoServiceClient.EndEditTodoItem método uma
vez o TodoServiceClient.BeginCreateTodoItem método é concluído, com o todoItem parâmetro sendo os dados que
são passados para o BeginEditTodoItem delegado para especificar o TodoItem a ser atualizado pelo serviço web.
Por fim, o valor da TaskCreationOptions enumeração que especifica que o comportamento padrão para a criação e
execução de tarefas deve ser usado.
A web service lança um FaultException se ele não conseguir localizar ou atualizar o TodoItem , que é tratada pelo
aplicativo.
Excluir dados
O TodoServiceClient.BeginDeleteTodoItem e TodoServiceClient.EndDeleteTodoItem métodos são usados para
chamar o DeleteTodoItem operação fornecidos pelo serviço web. Esses métodos assíncronos são encapsulados em
um Task do objeto, conforme mostrado no exemplo de código a seguir:
2. Configurar o IIS Express para conexões remotas aceitar. Você pode configurar o IIS Express editando
o arquivo de configuração para o IIS Express na [diretório da
solução].vs\config\applicationhost.config. Localizar o site elemento com o nome TodoWCFService .
Ele deve ser semelhante ao seguinte XML:
Você precisará adicionar dois binding elementos para abrir a porta 49393 para o tráfego externo e o
emulador do Android. A associação usa um [IP address]:[port]:[hostname] formato que especifica como o
IIS Express irão responder às solicitações. As solicitações externas terão nomes de host que devem ser
especificado como um binding . Adicione o seguinte XML para o bindings elemento, substituindo o
endereço IP com seu próprio endereço IP:
IMPORTANT
Por padrão, o IIS Express não aceita conexões de fontes externas, por motivos de segurança. Para habilitar conexões
de dispositivos remotos você deve executar o IIS Express com permissões administrativas. A maneira mais fácil de
fazer isso é executar o Visual Studio 2017 com permissões administrativas. Isso inicializará o IIS Express com
permissões administrativas ao executar o TodoWCFService.
Com essas etapas concluídas, você deve ser capaz de executar o TodoWCFService e conecte-se com outros
dispositivos na sua sub-rede. Você pode testar isso executando seu aplicativo e visitar
http://localhost:49393/TodoService.svc . Se você receber um solicitação incorreta erros ao visitar essa
URL e sua bindings pode estar incorreto na configuração IIS Express (a solicitação está alcançando o IIS
Express, mas está sendo rejeitada). Se você receber um erro diferente pode ser que seu aplicativo não está
em execução ou seu firewall está configurado incorretamente.
Para permitir que o IIS Express manter em execução e que atende o serviço, desative o editar e continuar
opção propriedades do projeto > Web > depuradores.
3. Personalizar o ponto de extremidade dispositivos usam para acessar o serviço. Esta etapa envolve a
configuração do aplicativo cliente, em execução em um dispositivo físico ou emulado, para acessar o serviço
do WCF.
O emulador do Android utiliza um proxy interno que impede que o emulador acessem diretamente da
máquina host localhost endereço. Em vez disso, o endereço 10.0.2.2 o emulador é roteado para
localhost no computador host por meio de um proxy interno. Essas solicitações com proxy terá 127.0.0.1
como o nome do host no cabeçalho da solicitação, que é por isso que você criou a associação do IIS Express
para esse nome de host nas etapas acima.
O iOS Simulator é executado em um Mac build host, mesmo se você estiver usando o remoto de iOS
Simulator para Windows. Solicitações de rede pelo simulador terá o IP de estação de trabalho na rede local
como o nome do host (neste exemplo tem 192.168.1.143 , mas seu endereço IP real provavelmente será
diferente). Isso é por isso que você criou a associação do IIS Express para esse nome de host nas etapas
acima.
Verifique se o SoapUrl propriedade no Constants.cs arquivo no projeto TodoWCF (portátil) têm valores
que estão corretos para sua rede:
if (Device.RuntimePlatform == Device.Android)
{
defaultUrl = "http://10.0.2.2:49393/TodoService.svc";
}
else if (Device.RuntimePlatform == Device.iOS)
{
defaultUrl = "http://192.168.1.143:49393/TodoService.svc";
}
return defaultUrl;
}
}
Depois de configurar o Constants.cs com pontos de extremidade apropriados, você deve ser capaz de
conectar-se para o TodoWCFService em execução em sua estação de trabalho do Windows 10 de
dispositivos físicos ou virtuais.
Links relacionados
TodoWCF (amostra)
Como: Criar um cliente do Windows Communication Foundation
Ferramenta de utilitário de metadados ServiceModel (svcutil.exe)
Consumir um serviço Web RESTful
12/04/2019 • 15 minutes to read
baixar o exemplo
Integrar um serviço web em um aplicativo é um cenário comum. Este artigo demonstra como consumir um
serviço web RESTful em um aplicativo xamarin. Forms.
REST Representational State Transfer () é um estilo de arquitetura para a criação de serviços da web. Solicitações
REST são feitas por HTTP, usando os mesmos verbos HTTP que navegadores da web usam para recuperar as
páginas da web e para enviar dados para servidores. Os verbos são:
OBTER – esta operação é usada para recuperar dados do serviço web.
POST – esta operação é usada para criar um novo item de dados no serviço web.
COLOCAR – esta operação é usada para atualizar um item de dados no serviço web.
PATCH – esta operação é usada para atualizar um item de dados no serviço web, descrevendo um conjunto de
instruções sobre como o item deve ser modificado. Esse verbo não é usado no aplicativo de exemplo.
Excluir – esta operação é usada para excluir um item de dados no serviço web.
APIs que aderem ao restante do serviço da Web são chamados de APIs RESTful e são definidos usando:
Um URI de base.
Métodos HTTP, como GET, POST, PUT, PATCH ou DELETE.
Um tipo de mídia para os dados, como o objeto notação JSON (JavaScript).
Serviços web rESTful normalmente usam mensagens JSON para retornar dados ao cliente. JSON é um formato
de troca de dados baseado em texto que gera conteúdos de compact, que resulta em reduzida requisitos de
largura de banda ao enviar dados. O aplicativo de exemplo usa o software livre biblioteca NewtonSoft JSON.NET
para serializar e desserializar mensagens.
A simplicidade do REST ajudou a torná-lo o principal método para acessar os serviços da web em aplicativos
móveis.
Quando o aplicativo de exemplo é executado, ele se conecte a um serviço REST hospedado localmente, conforme
mostrado na seguinte captura de tela:
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos
de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção.
ATS poderá ser aceito de se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da
internet. Isso pode ser feito atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de
transporte de aplicativo.
A maioria dos URIs inclui o ID no caminho. Por exemplo, para excluir o TodoItem cuja ID é
TodoItem
6bb8a868-dba1-4f1a-93b7-24ebce87e243 , o cliente envia uma solicitação de exclusão
http://hostname/api/todoitems/6bb8a868-dba1-4f1a-93b7-24ebce87e243 . Para obter mais informações sobre o
modelo de dados usado no aplicativo de exemplo, consulte modelagem de dados.
Quando a estrutura da API Web recebe uma solicitação, ele encaminha a solicitação para uma ação. Essas ações
são simplesmente público em métodos de TodoItemsController classe. A estrutura usa uma tabela de roteamento
para determinar qual ação a ser invocada em resposta a uma solicitação, que é mostrada no exemplo de código a
seguir:
config.Routes.MapHttpRoute(
name: "TodoItemsApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { controller="todoitems", id = RouteParameter.Optional }
);
A tabela de roteamento contém um modelo de rota e quando a estrutura da API Web recebe uma solicitação
HTTP, ele tenta corresponder o URI em relação ao modelo de rota na tabela de roteamento. Se uma
correspondência de rota não foi encontrada que o cliente recebe um erro de 404 (não encontrado). Se uma rota
correspondente for encontrada, API da Web selecionará o controlador e a ação da seguinte maneira:
Para localizar o controlador, API da Web adiciona "controller" como o valor da {controlador } variável.
Para localizar a ação, a API Web examina o método HTTP e examina a ações do controlador são decoradas
com o mesmo método HTTP como um atributo.
O {id } variável de espaço reservado é mapeado para um parâmetro de ação.
O serviço REST usa autenticação básica. Para obter mais informações, consulte autenticar um serviço web
RESTful. Para obter mais informações sobre o roteamento do ASP.NET Web API, consulte roteamento na API
Web ASP.NET no site do ASP.NET. Para obter mais informações sobre como criar o serviço REST usando o
ASP.NET Core, consulte criação de serviços de back-end para aplicativos móveis nativos.
O HttpClient classe é usada para enviar e receber solicitações via HTTP. Ele fornece funcionalidade para enviar
solicitações HTTP e receber respostas HTTP de um URI identificou o recurso. Cada solicitação é enviada como
uma operação assíncrona. Para obter mais informações sobre as operações assíncronas, consulte visão geral do
suporte assíncrono.
O HttpResponseMessage classe representa uma mensagem de resposta HTTP recebida do serviço da web depois
que foi feita uma solicitação HTTP. Ele contém informações sobre a resposta, incluindo o código de status,
cabeçalhos e qualquer corpo. O HttpContent classe representa o corpo de HTTP e cabeçalhos de conteúdo, como
Content-Type e Content-Encoding . O conteúdo pode ser lido usando qualquer um dos ReadAs métodos, tais
como ReadAsStringAsync e ReadAsByteArrayAsync , dependendo do formato dos dados.
Criando o objeto HTTPClient
O HttpClient instância é declarada no nível de classe, de modo que o objeto reside para desde que o aplicativo
precisa fazer solicitações HTTP, conforme mostrado no exemplo de código a seguir:
public RestService ()
{
_client = new HttpClient ();
}
...
}
Recuperando dados
O HttpClient.GetAsync método é usado para enviar a solicitação GET para o serviço web especificado pelo URI e,
em seguida, receber a resposta do serviço da web, conforme mostrado no exemplo de código a seguir:
public async Task<List<TodoItem>> RefreshDataAsync ()
{
...
var uri = new Uri (string.Format (Constants.TodoItemsUrl, string.Empty));
...
var response = await _client.GetAsync (uri);
if (response.IsSuccessStatusCode)
{
var content = await response.Content.ReadAsStringAsync ();
Items = JsonConvert.DeserializeObject <List<TodoItem>> (content);
}
...
}
...
var json = JsonConvert.SerializeObject (item);
var content = new StringContent (json, Encoding.UTF8, "application/json");
if (response.IsSuccessStatusCode)
{
Debug.WriteLine (@"\tTodoItem successfully saved.");
}
...
}
O TodoItem instância é convertida em uma carga JSON para enviar para o serviço web. Essa carga, em seguida, é
inserida no corpo do conteúdo HTTP que será enviado ao serviço web antes que a solicitação é feita com o
PostAsync método.
A operação do PutAsync método é idêntico de PostAsync método que é usado para a criação de dados no serviço
web. No entanto, as respostas possíveis enviadas do serviço web são diferentes.
O serviço REST envia um código de status HTTP no HttpResponseMessage.IsSuccessStatusCode propriedade para
indicar se a solicitação HTTP foi bem-sucedida ou falhou. As respostas comuns para essa operação são:
204 (sem conteúdo) – a solicitação foi processada com êxito e a resposta está intencionalmente em branco.
400 (solicitação incorreta) – a solicitação não é entendida pelo servidor.
404 (não encontrado) – o recurso solicitado não existe no servidor.
Excluindo dados
O HttpClient.DeleteAsync método é usado para enviar a solicitação de exclusão para o serviço web especificado
pelo URI e, em seguida, receber a resposta do serviço da web, conforme mostrado no exemplo de código a seguir:
Links relacionados
Criando Serviços de Back-end para Aplicativos Móveis Nativos
TodoREST (amostra)
HttpClient
Consumir um aplicativo móvel do Azure
12/04/2019 • 10 minutes to read
baixar o exemplo
Aplicativos móveis do Azure permitem que você desenvolva aplicativos com back-ends dimensionável
hospedado no serviço de aplicativo do Azure com suporte para autenticação móvel, sincronização offline e
notificações por push. Neste artigo, que só é aplicável aos aplicativos móveis do Azure que usam um back-end
do Node. js, explica como consultar, inserir, atualizar e excluir os dados armazenados em uma tabela em uma
instância de aplicativos móveis do Azure.
NOTE
Iniciando em 30 de junho, todos os novos aplicativos de móveis do Azure serão criados com o TLS 1.2 por padrão. Além
disso, também é recomendado que os aplicativos móveis do Azure ser reconfigurados para usar o TLS 1.2. Para obter
informações sobre como impor o TLS 1.2 no aplicativo móvel do Azure, consulte versões impor o TLS. Para obter
informações sobre como configurar projetos do Xamarin para usar TLS 1.2, consulte Transport Layer Security (TLS) 1.2.
Para obter informações sobre como criar uma instância de aplicativos móveis do Azure que pode ser consumida
por xamarin. Forms, consulte criar um aplicativo xamarin. Forms. Depois de seguir essas instruções, o aplicativo
de exemplo para download pode ser configurado para consumir a instância de aplicativos móveis do Azure,
definindo o Constants.ApplicationURL para a URL da instância de aplicativos móveis do Azure. Em seguida,
quando o aplicativo de exemplo for executado ele se conecte à instância de aplicativos móveis do Azure,
conforme mostrado na seguinte captura de tela:
Acesso a aplicativos móveis do Azure é por meio de SDK do Azure Mobile Client, e todas as conexões do
aplicativo de exemplo do xamarin. Forms para o Azure são feitas por HTTPS.
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet
(como o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações
confidenciais. Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão
sujeitos a requisitos de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção. ATS
poderá ser aceito de se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da internet.
Isso pode ser feito atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de
transporte de aplicativo.
IMobileServiceTable<TodoItem> todoTable;
MobileServiceClient client;
public TodoItemManager ()
{
client = new MobileServiceClient (Constants.ApplicationURL);
todoTable = client.GetTable<TodoItem> ();
}
Quando o MobileServiceClient instância é criada, uma URL de aplicativo deve ser especificada para identificar a
instância de aplicativos móveis do Azure. Esse valor pode ser obtido a partir do painel para o aplicativo móvel na
Portal do Microsoft Azure.
Uma referência para o TodoItem tabela armazenada na instância de aplicativos móveis do Azure deve ser obtida
antes de operações podem ser executadas nessa tabela. Isso é feito chamando o GetTable método em de
MobileServiceClient da instância, que retorna um IMobileServiceTable<TodoItem> referência.
Consultar Dados
O conteúdo de uma tabela pode ser recuperado chamando o IMobileServiceTable.ToEnumerableAsync método que
avalia a consulta e retorna os resultados de forma assíncrona. Dados também podem ser filtradas do lado do
servidor, incluindo um Where cláusula na consulta. O Where cláusula aplica um predicado à consulta na tabela, a
filtragem de linha conforme mostrado no exemplo de código a seguir:
Esta consulta retorna todos os itens do TodoItem tabela cujos Done propriedade é igual a false . Os resultados
da consulta, em seguida, são colocados em um ObservableCollection para exibição.
Inserindo dados
Ao inserir dados na instância de aplicativos móveis do Azure, novas colunas serão geradas automaticamente na
tabela conforme necessário, fornecido o esquema dinâmico está habilitado na instância de aplicativos móveis do
Azure. O IMobileServiceTable.InsertAsync método é usado para inserir uma nova linha de dados na tabela
especificada, conforme mostrado no exemplo de código a seguir:
Quando você faz uma solicitação de inserção, uma ID não deve ser especificada nos dados que está sendo
passados para a instância de aplicativos móveis do Azure. Se a solicitação de inserção contém uma ID de um
MobileServiceInvalidOperationException será lançada.
Após o InsertAsync método for concluído, a ID dos dados na instância de aplicativos móveis do Azure será
preenchida na TodoItem instância no aplicativo xamarin. Forms.
Atualizando dados
Ao atualizar dados na instância de aplicativos móveis do Azure, novas colunas serão geradas automaticamente
na tabela conforme necessário, fornecido o esquema dinâmico está habilitado na instância de aplicativos móveis
do Azure. O IMobileServiceTable.UpdateAsync método é usado para atualizar os dados existentes com novas
informações, conforme mostrado no exemplo de código a seguir:
Quando você faz uma solicitação de atualização, uma ID deve ser especificada para que a instância de aplicativos
móveis do Azure possa identificar os dados a serem atualizados. Esse valor de ID é armazenado no TodoItem.ID
propriedade. Se a solicitação de atualização não contém uma ID não é possível para a instância de aplicativos
móveis do Azure determinar os dados a ser atualizado e, portanto, um MobileServiceInvalidOperationException
será lançada.
Excluindo dados
O IMobileServiceTable.DeleteAsync método é usado para excluir dados de uma tabela de aplicativos móveis do
Azure, conforme mostrado no exemplo de código a seguir:
Quando você faz uma solicitação de exclusão, uma ID deve ser especificada para que o aplicativo móvel do Azure
sinstance possa identificar os dados a ser excluído. Esse valor de ID é armazenado no TodoItem.ID propriedade.
Se a solicitação de exclusão não contém uma ID, não há nenhuma maneira para a instância de aplicativos móveis
do Azure determinar os dados a serem excluídos e, portanto, um MobileServiceInvalidOperationException será
lançada.
Resumo
Este artigo explicou como usar o SDK do Azure Mobile Client para consultar, inserir, atualizar e excluir os dados
armazenados em uma tabela em uma instância de aplicativos móveis do Azure. O SDK fornece o
MobileServiceClient classe que é usado por um aplicativo xamarin. Forms para acessar a instância de aplicativos
móveis do Azure.
Links relacionados
TodoAzure (amostra)
Criar um aplicativo xamarin. Forms
SDK de cliente móvel do Azure
MobileServiceClient
Autenticando o acesso a serviços Web
12/04/2019 • 3 minutes to read
Este guia explica como integrar serviços de autenticação em um aplicativo xamarin. Forms para permitir que os
usuários compartilham um back-end tendo apenas o acesso a seus próprios dados. Os tópicos abordados incluem
o uso de autenticação básica com um serviço REST usando o componente Xamarin.Auth para autenticar em
relação a provedores de identidade OAuth, e usar os mecanismos de autenticação internos oferecidos pelos
provedores diferentes.
Links relacionados
Introdução aos serviços Web
Visão geral do suporte assíncrono
Autenticar um serviço Web RESTful
12/04/2019 • 6 minutes to read
HTTP oferece suporte ao uso de vários mecanismos de autenticação para controlar o acesso aos recursos.
Autenticação básica oferece acesso a recursos somente a clientes que possuem as credenciais corretas. Este artigo
demonstra como usar a autenticação básica para proteger o acesso aos recursos do serviço web RESTful.
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos
de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção. ATS poderá ser aceito de
se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da internet. Isso pode ser feito
atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de transporte de aplicativo.
Se um serviço web recebe uma solicitação para um recurso protegido, com o Authorization cabeçalho
definido corretamente, o web serviço responde com um código de status HTTP 200, que indica se a solicitação
foi bem-sucedida e que as informações solicitadas estão na resposta. Este cenário é mostrado no diagrama a
seguir:
NOTE
Autenticação básica deve ser usada apenas ao longo de uma conexão HTTPS. Quando usado em uma conexão HTTP, o
Authorization cabeçalho pode ser decodificado com facilidade se o tráfego HTTP é capturado por um invasor.
Especificar a autenticação básica em uma solicitação da Web
Uso da autenticação básica é especificado da seguinte maneira:
1. A cadeia de caracteres "Básico" é adicionado para o Authorization cabeçalho da solicitação.
2. O nome de usuário e senha são combinados em uma cadeia de caracteres com o formato "nomedeusuario:
senha", que é, em seguida, na Base 64 codificados e adicionado ao Authorization cabeçalho da solicitação.
Portanto, com um nome de usuário de 'XamarinUser' e uma senha de 'XamarinPassword', o cabeçalho se torna:
public RestService ()
{
var authData = string.Format ("{0}:{1}", Constants.Username, Constants.Password);
var authHeaderValue = Convert.ToBase64String (Encoding.UTF8.GetBytes (authData));
Em seguida, quando é feita uma solicitação para uma operação de serviço da web a solicitação é assinada com o
Authorization cabeçalho, que indica se o usuário tem permissão para invocar a operação.
NOTE
Embora esse código armazena as credenciais como constantes, eles não devem ser armazenados em um formato inseguro
em um aplicativo publicado. O Xamarith.Auth NuGet fornece funcionalidade para armazenar com segurança as credenciais.
Para obter mais informações, consulte armazenando e recuperando informações da conta em dispositivos.
Links relacionados
Consumir um serviço web RESTful
HttpClient
Autenticar usuários com um provedor de identidade
12/04/2019 • 25 minutes to read
baixar o exemplo
AUTH é um SDK de plataforma cruzada para autenticar usuários e armazenar suas contas. Ele inclui os
autenticadores de OAuth que oferecem suporte para o consumo de provedores de identidade, como Google,
Microsoft, Facebook e Twitter. Este artigo explica como usar auth para gerenciar o processo de autenticação em
um aplicativo xamarin. Forms.
OAuth é um padrão aberto para autenticação e permite que o proprietário do recurso notificar um provedor de
recursos que a permissão deve ser concedida a um terceiro para acessar suas informações sem compartilhar a
identidade de proprietários de recurso. Um exemplo disso seria ser habilitação de um usuário notificar um
provedor de identidade (por exemplo, Google, Microsoft, Facebook ou Twitter) que deve ser concedida permissão
a um aplicativo para acessar seus dados, sem compartilhar a identidade do usuário. Normalmente, ele é usado
como uma abordagem para que os usuários para entrar para sites e aplicativos usando um provedor de
identidade, mas sem expor sua senha para o site ou aplicativo.
Uma visão geral do fluxo de autenticação durante o consumo de um provedor de identidade OAuth é da seguinte
maneira:
1. O aplicativo navega de um navegador para uma URL do provedor de identidade.
2. O provedor de identidade lida com a autenticação de usuário e retorna um código de autorização para o
aplicativo.
3. O aplicativo troca o código de autorização para um token de acesso do provedor de identidade.
4. O aplicativo usa o token de acesso para acessar as APIs no provedor de identidade, como uma API para
solicitar dados básicos do usuário.
O aplicativo de exemplo demonstra como usar auth para implementar um fluxo de autenticação nativa no Google.
Enquanto o Google é usado como o provedor de identidade neste tópico, a abordagem é igualmente aplicável a
outros provedores de identidade. Para obter mais informações sobre autenticação usando o ponto de extremidade
do Google OAuth 2.0, consulte OAuth2.0 usando APIs do Google acesso no site do Google.
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos
de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção. ATS poderá ser aceito de
se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da internet. Isso pode ser feito
atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de transporte de aplicativo.
O aplicativo faz uma solicitação de autenticação usando o Google o OAuth2Authenticator classe. Uma resposta de
autenticação é retornada, depois que o usuário foi autenticado com êxito com o Google por meio de sua página
de entrada, que inclui um token de acesso. O aplicativo, em seguida, faz uma solicitação para o Google para dados
de usuário básico, usando o OAuth2Request classe, com o token de acesso que está sendo incluído na solicitação.
Configuração
Um projeto de Console de API do Google deve ser criado para integrar o logon do Google com um aplicativo
xamarin. Forms. Isso pode ser feito da seguinte maneira:
1. Vá para o Console de API do Google site e entre com as credenciais de conta do Google.
2. Do projeto lista suspensa, selecione um projeto existente ou crie um novo.
3. Na barra lateral em "Gerenciador de API", selecione credenciais, em seguida, selecione o guia de tela de
consentimento de OAuth. Escolha uma endereço de Email, especifique um nome do produto mostrado
aos usuáriose pressione salvar.
4. No credenciais guia, selecione o criar credenciais lista suspensa lista e escolha ID do cliente OAuth.
5. Sob tipo de aplicativo, selecione a plataforma que serão executados no aplicativo móvel (iOS ou Android).
6. Preencha os detalhes necessários e selecione o criar botão.
NOTE
Uma ID de cliente permite que um aplicativo acessar Google APIs habilitadas e para aplicativos móveis é exclusiva para uma
única plataforma. Portanto, uma ID do cliente OAuth deve ser criado para cada plataforma que usarão logon do Google.
Depois de executar essas etapas, AUTH pode ser usado para iniciar um fluxo de autenticação OAuth2 com o
Google.
Criando e configurando um autenticador
Do AUTH OAuth2Authenticator classe é responsável por gerenciar o fluxo de autenticação OAuth. O exemplo de
código a seguir mostra a instanciação do OAuth2Authenticator classe ao executar a autenticação usando o
navegador da web do dispositivo:
authenticator.Completed += OnAuthCompleted;
Esse evento será acionado quando o usuário é autenticado com êxito ou cancela na entrada.
Opcionalmente, um manipulador de eventos para o OAuth2Authenticator.Error eventos também podem ser
registrados.
Apresentando a Interface do usuário de entrada
A interface do usuário de entrada pode ser apresentada ao usuário por meio de um apresentador de logon AUTH,
que deve ser inicializado em cada projeto de plataforma. O exemplo de código a seguir mostra como inicializar
um apresentador de logon na AppDelegate classe no projeto do iOS:
global::Xamarin.Auth.Presenters.XamarinIOS.AuthenticationConfiguration.Init();
O exemplo de código a seguir mostra como inicializar um apresentador de logon na MainActivity classe no
projeto do Android:
global::Xamarin.Auth.Presenters.XamarinAndroid.AuthenticationConfiguration.Init(this, bundle);
O projeto de biblioteca .NET Standard pode, em seguida, invoque o apresentador de logon da seguinte maneira:
Quando o navegador da web recebe uma resposta do provedor de identidade que contém um esquema de URL
personalizado, ele tenta carregar a URL, que falhará. Em vez disso, o esquema de URL personalizado é relatado
para o sistema operacional, gerando um evento. O sistema operacional, em seguida, verifica para esquemas
registradas e, caso seja encontrado, o sistema operacional inicie o aplicativo que registrou o esquema e enviá-lo a
URL de redirecionamento.
O mecanismo para registrar um esquema de URL personalizado com o sistema operacional e lidar com o
esquema é específico para cada plataforma.
iOS
No iOS, um esquema de URL personalizado é registrado no Info. plist, conforme mostrado na seguinte captura
de tela:
O identificador valor pode ser qualquer coisa e o função valor deve ser definido como visualizador. O
esquemas de Url valor, que começa com com.googleusercontent.apps , pode ser obtido da id do cliente iOS para o
projeto no Console de API do Google.
Quando o provedor de identidade conclui a solicitação de autorização, ele redireciona para a URL de
redirecionamento do aplicativo. Como a URL usa um esquema personalizado, ele resulta na inicialização do
aplicativo do iOS, passando a URL como um parâmetro de inicialização, onde ela é processada pelo OpenUrl
substituir da caixa de diálogo AppDelegate classe, que é mostrado no exemplo de código a seguir:
return true;
}
O OpenUrl método converte a URL recebida de um NSUrl para um .NET Uri , antes de processar a URL de
redirecionamento com o OnPageLoading método de um público OAuth2Authenticator objeto. Isso faz com que
auth para fechar a guia do navegador da web e analisar os dados recebidos do OAuth.
Android
No Android, um esquema de URL personalizado está registrado com a especificação de um IntentFilter
atributo o Activity que irá manipular o esquema. Quando o provedor de identidade conclui a solicitação de
autorização, ele redireciona para a URL de redirecionamento do aplicativo. Como a URL usa um esquema
personalizado, ele resulta na inicialização do aplicativo do Android, passando a URL como um parâmetro de
inicialização, onde ela é processada pelo OnCreate método da Activity registrado para manipular o esquema de
URL personalizado. O exemplo de código a seguir mostra a classe do aplicativo de exemplo que manipula o
esquema de URL personalizado:
Finish();
}
}
O DataSchemes propriedade do IntentFilter deve ser definido como o identificador de cliente invertido é obtido
da id do cliente Android para o projeto no Console de API do Google.
O OnCreate método converte a URL recebida de um Android.Net.Url para um .NET Uri , antes de processar a
URL de redirecionamento com o OnPageLoading método de um público OAuth2Authenticator objeto. Isso faz com
que AUTH fechar a guia do navegador da web e analisar os dados recebidos do OAuth.
IMPORTANT
No Android, AUTH usa a CustomTabs API para se comunicar com o navegador da web e o sistema operacional. No
entanto, ele terá assegurado que não um CustomTabs navegador compatível será instalado no dispositivo do usuário.
// UserInfoUrl = https://www.googleapis.com/oauth2/v2/userinfo
var request = new OAuth2Request ("GET", new Uri (Constants.UserInfoUrl), null, e.Account);
var response = await request.GetResponseAsync ();
if (response != null)
{
string userJson = response.GetResponseText ();
var user = JsonConvert.DeserializeObject<User> (userJson);
}
Bem como o método HTTP e a URL da API, o OAuth2Request também especifica uma instância de um Account
instância que contém o token de acesso que faz a solicitação para a URL especificada pelo Constants.UserInfoUrl
propriedade. O provedor de identidade, em seguida, retorna dados básicos do usuário como uma resposta JSON,
incluindo o nome dos usuários e o endereço de email, desde que ele reconhece o token de acesso como válido. A
resposta JSON, em seguida, é lida e desserializada para o user variável.
Para obter mais informações, consulte chamar uma API do Google no portal de desenvolvedores do Google.
Armazenar e recuperar informações de conta em dispositivos
AUTH armazena com segurança Account objetos em uma conta de repositório para que os aplicativos nem
sempre têm a autenticar novamente os usuários. O AccountStore classe é responsável por armazenar
informações de conta e é apoiada por serviços de conjunto de chaves no iOS e o KeyStore classe no Android.
O seguinte exemplo de código mostra como um Account objeto é salvo com segurança:
Contas salvas são identificadas exclusivamente usando uma chave composta da conta de Username propriedade e
uma ID de serviço, que é uma cadeia de caracteres que é usada ao buscar contas do repositório de conta. Se um
Account foi salvo anteriormente, chamar o Save método novamente irá substituí-la.
Account objetos para um serviço pode ser recuperado chamando o FindAccountsForService método, conforme
mostrado no exemplo de código a seguir:
Resumo
Este artigo explicou como usar auth para gerenciar o processo de autenticação em um aplicativo xamarin. Forms.
AUTH fornece o OAuth2Authenticator e OAuth2Request classes que são usadas por aplicativos do xamarin. Forms
para consumir provedores de identidade, como Google, Microsoft, Facebook e Twitter.
Links relacionados
OAuthNativeFlow (amostra)
OAuth 2.0 para aplicativos nativos
Usando o OAuth 2.0 para acessar as APIs do Google
AUTH (NuGet)
AUTH (GitHub)
Autenticar usuários com aplicativos móveis do Azure
12/04/2019 • 12 minutes to read
baixar o exemplo
Aplicativos móveis do Azure usam uma variedade de provedores de identidade externos para dar suporte à
autenticação e autorização de usuários do aplicativo, incluindo o Facebook, Google, Microsoft, Twitter e Active
Directory do Azure. Permissões podem ser definidas em tabelas para restringir o acesso somente aos usuários
autenticados. Este artigo explica como usar aplicativos móveis do Azure para gerenciar o processo de
autenticação em um aplicativo xamarin. Forms.
Visão geral
O processo de ter os aplicativos móveis do Azure a gerenciar o processo de autenticação em um aplicativo
xamarin. Forms é da seguinte maneira:
1. Registrar seu aplicativo móvel do Azure no site do provedor de identidade e, em seguida, defina as credenciais
geradas pelo provedor no back-end dos aplicativos móveis. Para obter mais informações, consulte registrar
seu aplicativo para autenticação e configurar serviços de aplicativos.
2. Defina um novo esquema de URL para seu aplicativo xamarin. Forms, que permite que o sistema de
autenticação redirecionar de volta para o aplicativo xamarin. Forms depois que o processo de autenticação for
concluído. Para obter mais informações, consulte adicionar seu aplicativo para a permissão URLs de
redirecionamento externo.
3. Restringir o acesso para o back-end de aplicativos móveis do Azure para somente aos clientes autenticados.
Para obter mais informações, consulte restringir permissões a usuários autenticados.
4. Invocar a autenticação do aplicativo xamarin. Forms. Para obter mais informações, consulte adicionar
autenticação à biblioteca de classes portátil, adicionar autenticação ao aplicativo do iOS, adicionar autenticação
ao aplicativo do Androide Adicionar autenticação a projetos de aplicativo do Windows 10.
NOTE
No iOS 9 e superior, a segurança de transporte de aplicativo (ATS) impõe conexões seguras entre recursos da internet (como
o servidor de back-end do aplicativo) e o aplicativo, impedindo assim a divulgação acidental de informações confidenciais.
Desde que o ATS é habilitado por padrão em aplicativos criados para o iOS 9, todas as conexões serão sujeitos a requisitos
de segurança ATS. Se as conexões não atender a esses requisitos, eles falharão com uma exceção. ATS poderá ser aceito de
se ele não é possível usar o HTTPS de protocolo e proteger a comunicação para recursos da internet. Isso pode ser feito
atualizando o aplicativo Info. plist arquivo. Para obter mais informações, consulte segurança de transporte de aplicativo.
Historicamente, os aplicativos móveis usou modos de exibição da web incorporadas para realizar a autenticação
com o provedor de identidade. Isso não é mais recomendável pelos seguintes motivos:
O aplicativo que hospeda a exibição da web pode acessar a credencial do usuário autenticação completa, não
apenas a concessão de autorização foi destinada para o aplicativo. Isso viola o princípio de privilégios
mínimos, que o aplicativo tenha acesso a credenciais mais poderosas do que o necessário, possivelmente,
aumentando a superfície de ataque do aplicativo.
O aplicativo host pode capturar os nomes de usuário e senhas, automaticamente enviar formulários e ignorar
o consentimento do usuário e copiar os cookies de sessão e usá-los para executar ações autenticadas como o
usuário.
Modos de exibição da web incorporadas não compartilham o estado de autenticação com outros aplicativos
ou navegador da web do dispositivo, exigir que o usuário entrar para cada solicitação de autorização que é
considerada uma experiência de usuário de qualidade inferior.
Alguns pontos de extremidade de autorização tomar medidas para detectar e bloquear solicitações de
autorização que vêm de exibições da web.
A alternativa é usar o navegador da web do dispositivo para realizar a autenticação, que é a abordagem usada
pela versão mais recente do SDK do Azure Mobile Client. Usando o navegador do dispositivo para as solicitações
de autenticação melhora a usabilidade de um aplicativo, como os usuários precisam apenas entrar para o
provedor de identidade uma vez por dispositivo, melhorando as taxas de conversão de fluxos de entrada e
autorização no aplicativo. O navegador do dispositivo também fornece segurança aprimorada como os
aplicativos capazes de inspecionar e modificar o conteúdo em uma exibição da web, mas não os conteúdo exibido
no navegador.
Enquanto o Google é usado como o provedor de identidade, uma variedade de outros provedores de identidade
pode ser usada, incluindo a Microsoft, Facebook, Twitter e Active Directory do Azure.
O exemplo de código a seguir mostra como o processo de logon é invocado:
O seguinte exemplo de código mostra o LoginAsync método para a plataforma Universal do Windows:
if (App.Authenticator != null)
{
loggedOut = await App.Authenticator.LogoutAsync ();
}
...
}
O seguinte exemplo de código mostra o LogoutAsync método para a plataforma Universal do Windows:
Resumo
Este artigo explicou como usar aplicativos móveis do Azure para gerenciar o processo de autenticação em um
aplicativo xamarin. Forms. Aplicativos móveis do Azure usam uma variedade de provedores de identidade
externos para dar suporte à autenticação e autorização de usuários do aplicativo, incluindo o Facebook, Google,
Microsoft, Twitter e Active Directory do Azure. O MobileServiceClient classe é usada pelo aplicativo xamarin.
Forms para controlar o acesso à instância de aplicativos móveis do Azure.
Links relacionados
TodoAzureAuth (amostra)
Consumir um aplicativo móvel do Azure
Adicionar autenticação ao aplicativo xamarin. Forms
SDK de cliente móvel do Azure
MobileServiceClient
Autenticar usuários com o Azure Active Directory
B2C
12/04/2019 • 16 minutes to read
baixar o exemplo
Azure Active Directory B2C do diretório é uma solução de gerenciamento de identidade de nuvem para
aplicativos móveis e web voltados ao consumidor. Este artigo demonstra como usar a biblioteca de autenticação
da Microsoft e o Azure Active Directory B2C para integrar o gerenciamento de identidade do consumidor em um
aplicativo móvel.
NOTE
O biblioteca de autenticação da Microsoft ainda está em visualização, mas é adequado para uso em um ambiente de
produção. No entanto, há podem ser alterações significativas para a API, formato de cache interno e outros mecanismos
para a biblioteca, que podem afetar seu aplicativo.
Visão geral
Azure Active Directory B2C do diretório é um serviço de gerenciamento de identidade para aplicativos voltados
ao consumidor, que permite que os consumidores entrar no seu aplicativo por:
Usando suas contas sociais existentes (Microsoft, Google, Facebook, Amazon, LinkedIn).
Criando novas credenciais (endereço de email e senha, ou nome de usuário e senha). Essas credenciais são
denominadas local contas.
O processo para integrar o serviço de gerenciamento de identidade do Azure Active Directory B2C em um
aplicativo móvel é da seguinte maneira:
1. Crie um locatário do Azure Active Directory B2C. Para obter mais informações, consulte criar um locatário do
Azure Active Directory B2C no portal do Azure.
2. Registre seu aplicativo móvel com o locatário do Azure Active Directory B2C. O processo de registro atribui
uma ID do aplicativo que identifica exclusivamente o seu aplicativo e um URL de redirecionamento que
pode ser usado para direcionar as respostas de volta ao seu aplicativo. Para obter mais informações, consulte
Azure Active Directory B2C: registrar seu aplicativo.
3. Crie uma política de inscrição e entrada. Essa política definirá as experiências pelas quais os consumidores
passarão durante a inscrição e entrada e também especifica o conteúdo dos tokens que o aplicativo receberá
bem-sucedido inscrever-se ou entrar. Para obter mais informações, consulte Azure Active Directory B2C:
políticas internas.
4. Use o biblioteca de autenticação da Microsoft (MSAL ) em seu aplicativo móvel para iniciar um fluxo de
trabalho de autenticação com seu locatário do Azure Active Directory B2C.
NOTE
Bem como integrar o gerenciamento de identidades do Azure Active Directory B2C em aplicativos móveis, a MSAL também
pode ser usada para integrar o gerenciamento de identidade do Active Directory do Azure em aplicativos móveis. Isso pode
ser feito ao registrar um aplicativo móvel com o Azure Active Directory na Portal de registro de aplicativo. O processo de
registro atribui uma ID do aplicativo que identifica exclusivamente o seu aplicativo, que deve ser especificado ao usar a
MSAL. Para obter mais informações, consulte como registrar um aplicativo com o ponto de extremidade v 2.0, e autenticar
seu Mobile Apps usando biblioteca de autenticação Microsoft no blog do Xamarin.
MSAL usa um navegador da web do dispositivo para realizar a autenticação. Isso melhora a usabilidade de um
aplicativo, como os usuários precisam apenas entrar depois por dispositivo, melhorar as taxas de conversão de
entrada e autorização fluxos no aplicativo. O navegador do dispositivo também fornece segurança aprimorada.
Depois que o usuário concluir o processo de autenticação, controle retornará para o aplicativo da guia do
navegador da web. Isso é feito registrando um esquema de URL personalizado para a URL de redirecionamento
que é retornada para o processo de autenticação e, em seguida, detectar e manipular a URL personalizada
quando ele é enviado. Para obter mais informações sobre como escolher um esquema de URL personalizado,
consulte escolhendo um URI de redirecionamento do aplicativo nativo.
NOTE
O mecanismo para registrar um esquema de URL personalizado com o sistema operacional e lidar com o esquema é
específico para cada plataforma.
Cada solicitação é enviada a um locatário do Azure Active Directory B2C Especifica uma diretiva. As políticas
descrevem experiências de identidade do consumidor, como inscrição ou entrada. Por exemplo, uma política de
inscrição permite que o comportamento do locatário do Azure Active Directory B2C para ser configurado por
meio das seguintes configurações:
Tipos de conta que os consumidores podem usar para entrar no aplicativo.
Dados a serem coletados junto ao consumidor durante a inscrição.
A autenticação multifator.
Conteúdo da página de inscrição.
Declarações de token que o aplicativo móvel recebe quando a política foi executada.
Um locatário do Azure Active Directory pode conter várias políticas de tipos diferentes, que podem ser usados
em seu aplicativo conforme necessário. Além disso, as políticas podem ser reutilizadas em aplicativos, permitindo
que você definir e modificar experiências de identidade do consumidor sem alterar seu código. Para obter mais
informações sobre políticas, consulte Azure Active Directory B2C: políticas internas.
Configuração
A biblioteca do NuGet da biblioteca de autenticação da Microsoft (MSAL ) deve ser adicionada ao projeto de
biblioteca de classe portátil (PCL ) e projetos de plataforma em uma solução do xamarin. Forms. As seções a
seguir fornecem instruções de configuração adicionais para usar MSAL para se comunicar com um locatário do
Azure Active Directory B2C em um aplicativo móvel.
Biblioteca de Classes Portátil
PCLs que consomem MSAL precisará ser redirecionados para usar Profile7. Para obter mais informações sobre
PCLs, consulte Introduction to Portable Class Libraries (Introdução às bibliotecas de classes portáteis).
iOS
No iOS, o esquema de URL personalizado que foi registrado com o Azure Active Directory B2C deve ser
registrado no Info. plist, conforme mostrado na seguinte captura de tela:
Quando o Azure Active Directory B2C conclui a solicitação de autorização, ele redireciona para a URL de
redirecionamento registrado. Como a URL usa um esquema personalizado, ele resulta na inicialização do
aplicativo móvel do iOS, passando a URL como um parâmetro de inicialização, onde ela é processada pelo
OpenUrl substituir da caixa de diálogo AppDelegate classe, que é mostrado no código a seguir exemplo:
using Microsoft.Identity.Client;
namespace TodoAzure.iOS
{
[Register("AppDelegate")]
public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate
{
...
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options)
{
AuthenticationContinuationHelper.SetAuthenticationContinuationEventArgs(url);
return true;
}
}
}
O código a OpenURL método garante que o controle retorna para a MSAL depois que a parte interativa do fluxo
de trabalho de autenticação terminou.
Android
No Android, o esquema de URL personalizado que foi registrado com o Azure Active Directory B2C deve ser
registrado no androidmanifest. XML, com a adição de uma <activity> elemento dentro de existente
<application> elemento. O <activity> elemento Especifica a IntentFilter sobre o Activity que lida com o
esquema e é mostrado no exemplo a seguir:
<application ...>
<activity android:name="microsoft.identity.client.BrowserTabActivity">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="INSERT_URL_SCHEME_HERE" android:host="auth" />
</intent-filter>
</activity>
</application>
Quando o Azure Active Directory B2C conclui a solicitação de autorização, ele redireciona para a URL de
redirecionamento registrado. Como a URL usa um esquema personalizado, ele resulta na inicialização do
aplicativo móvel do Android, passando a URL como um parâmetro de inicialização, onde ela é processada pelo
microsoft.identity.client.BrowserTabActivity . Observe que o data android:scheme propriedade deve ser
definida para o esquema de URL personalizado que está registrado com o aplicativo do Azure Active Directory
B2C.
Além disso, o MainActivity classe deve ser modificada, conforme mostrado no exemplo de código a seguir:
using Microsoft.Identity.Client;
namespace TodoAzure.Droid
{
...
public class MainActivity : FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
LoadApplication(new App());
App.UiParent = new UIParent(this);
}
O OnCreate método é modificado, atribuindo um UIParent da instância para o App.UiParent propriedade. Isso
garante que o fluxo de autenticação ocorre no contexto da atividade atual.
O código a OnActivityResult método garante que o controle retorna para a MSAL depois que a parte interativa
do fluxo de trabalho de autenticação terminou.
Plataforma Universal do Windows
Na plataforma Universal do Windows, nenhuma configuração adicional é necessário para usar a MSAL.
Inicialização
A biblioteca de autenticação da Microsoft usa os membros de PublicClientApplication classe iniciar um fluxo de
trabalho de autenticação. O aplicativo de exemplo declara e inicializa um public propriedade desse tipo,
chamado ADB2CClient , no AuthenticationProvider classe. O exemplo de código a seguir mostra como essa
propriedade é inicializada:
Quando o aplicativo móvel foi registrado com o locatário do Azure Active Directory B2C, o processo de registro é
atribuído um ID do aplicativo. Essa ID deve ser especificada na PublicClientApplication construtor, junto com
um Authority constante que consiste em uma URL base e a política do Azure Active Directory B2C para ser
executado.
Entrar
A tela de entrada no aplicativo de exemplo é mostrada nas capturas de tela seguir:
Entrar com provedores de identidade social, ou com uma conta local, são permitidos. Embora a Microsoft, Google
e Facebook, como mostrado acima, são usados como provedores de identidade social, outros provedores de
identidade também podem ser usados.
O exemplo de código a seguir mostra como o processo de logon é invocado:
using Microsoft.Identity.Client;
if (useSilent)
{
authenticationResult = await ADB2CClient.AcquireTokenSilentAsync(
Constants.Scopes,
GetUserByPolicy(ADB2CClient.Users, Constants.PolicySignUpSignIn),
Constants.Authority,
false);
}
...
}
O AcquireTokenSilentAsync método tenta recuperar um token de usuário do cache, sem exigir que o usuário
entrar. Ele lida com o cenário em que um token adequado pode já estar presente no cache de sessões anteriores.
Se a tentativa de obter um token for bem-sucedida, o TodoList página é navegada. Se a tentativa de obter um
token não for bem-sucedida, nada acontece e o usuário terá a opção para iniciar um novo fluxo de trabalho de
autenticação.
Sair
O exemplo de código a seguir mostra como o processo de saída é invocado:
Resumo
Este artigo demonstrou como usar a biblioteca de autenticação da Microsoft (MSAL ) e o Azure Active Directory
B2C para integrar o gerenciamento de identidade do consumidor em um aplicativo móvel. Azure Active Directory
B2C do diretório é uma solução de gerenciamento de identidade de nuvem para aplicativos móveis e web
voltados ao consumidor.
Links relacionados
AzureADB2CAuth (amostra)
Azure Active Directory B2C
Biblioteca de autenticação da Microsoft
A integração do Azure Active Directory B2C com
aplicativos móveis do Azure
12/04/2019 • 19 minutes to read
baixar o exemplo
Azure Active Directory B2C do diretório é uma solução de gerenciamento de identidade de nuvem para
aplicativos móveis e web voltados ao consumidor. Este artigo demonstra como usar o Azure Active Directory B2C
para fornecer autenticação e autorização para uma instância de aplicativos móveis do Azure com o xamarin.
Forms.
NOTE
O biblioteca de autenticação da Microsoft ainda está em visualização, mas é adequado para uso em um ambiente de
produção. No entanto, há podem ser alterações significativas para a API, formato de cache interno e outros mecanismos para
a biblioteca, que podem afetar seu aplicativo.
Visão geral
Aplicativos móveis do Azure permitem que você desenvolva aplicativos com o back-ends dimensionável
hospedado no serviço de aplicativo do Azure com suporte para autenticação móvel, sincronização offline e
notificações por push. Para obter mais informações sobre aplicativos móveis do Azure, consulte consumir o
aplicativo móvel do Azure, e autenticando usuários com aplicativos móveis do Azure.
Azure Active Directory B2C do diretório é um serviço de gerenciamento de identidade para aplicativos voltados ao
consumidor, que permite que os consumidores entrar no seu aplicativo por:
Usando suas contas sociais existentes (Microsoft, Google, Facebook, Amazon, LinkedIn).
Criando novas credenciais (endereço de email e senha, ou nome de usuário e senha). Essas credenciais são
denominadas local contas.
Para obter mais informações sobre o Azure Active Directory B2C, consulte autenticando usuários com o Azure
Active Directory B2C.
Azure Active Directory B2C do diretório pode ser usado para gerenciar o fluxo de trabalho de autenticação para o
aplicativo móvel do Azure. Com essa abordagem, a experiência de gerenciamento de identidade está totalmente
definida na nuvem e pode ser modificada sem alterar o código do aplicativo móvel.
Há dois fluxos de trabalho de autenticação que podem ser adotados ao integrar um locatário do Azure Active
Directory B2C com uma instância de aplicativos móveis do Azure:
Cliente gerenciado – desta abordagem o iniciará o aplicativo móvel do xamarin. Forms o processo de
autenticação com o locatário do Azure Active Directory B2C e passa o token de autenticação recebidas para a
instância de aplicativos móveis do Azure.
Servidor gerenciado – nessa abordagem, os aplicativos móveis do Azure a instância usa o locatário do Azure
Active Directory B2C para iniciar o processo de autenticação por meio de um fluxo de trabalho baseado na web.
Em ambos os casos, a experiência de autenticação é fornecida pelo locatário do Azure Active Directory B2C. No
aplicativo de exemplo, isso resulta na tela de logon mostrada nas capturas de tela seguir:
Entrar com provedores de identidade social, ou com uma conta local, são permitidos. Embora o Facebook, Google
e Microsoft são usados como provedores de identidade social, neste exemplo, outros provedores de identidade
também podem ser usados.
Configuração
Independentemente do fluxo de trabalho de autenticação usado, o processo inicial para a integração de um
locatário do Azure Active Directory B2C com uma instância de aplicativos móveis do Azure é o seguinte:
1. Crie uma instância de aplicativos móveis do Azure. Para obter mais informações, consulte consumir o aplicativo
móvel do Azure.
2. Habilite a autenticação na instância de aplicativos móveis do Azure e o aplicativo xamarin. Forms. Para obter
mais informações, consulte autenticando usuários com aplicativos móveis do Azure.
3. Crie um locatário do Azure Active Directory B2C. Para obter mais informações, consulte autenticando usuários
com o Azure Active Directory B2C.
Observe que a biblioteca de autenticação Microsoft (MSAL ) é necessária ao usar um fluxo de trabalho de
autenticação gerenciada pelo cliente. MSAL usa um navegador da web do dispositivo para realizar a autenticação.
Isso melhora a usabilidade de um aplicativo, como os usuários precisam apenas entrar depois por dispositivo,
melhorar as taxas de conversão de entrada e autorização fluxos no aplicativo. O navegador do dispositivo também
fornece segurança aprimorada. Depois que o usuário concluir o processo de autenticação, controle retornará para
o aplicativo da guia do navegador da web. Isso é feito registrando um esquema de URL personalizado para a URL
de redirecionamento que é retornada para o processo de autenticação e, em seguida, detectar e manipular a URL
personalizada quando ele é enviado. Para obter mais informações sobre como usar MSAL para se comunicar com
um locatário do Azure Active Directory B2C, consulte autenticando usuários com o Azure Active Directory B2C.
Autenticação gerenciada pelo cliente
Na autenticação gerenciada pelo cliente, um aplicativo móvel do xamarin. Forms entra em contato com um
locatário do Azure Active Directory B2C para iniciar um fluxo de autenticação. Após o logon bem-sucedido o B2C
do Azure Active Directory locatário retorna um token de identidade que é fornecido durante a entrada para a
instância de aplicativos móveis do Azure. Isso permite que o aplicativo xamarin. Forms executar ações na instância
de aplicativos móveis do Azure que requer permissões de usuário autenticado.
Configuração de locatário do Azure Active Directory B2C
Um fluxo de trabalho de autenticação gerenciada pelo cliente, o locatário B2C do Azure Active Directory deve ser
configurado da seguinte maneira:
Inclua um cliente nativo.
Defina o URI de redirecionamento personalizado a um esquema de URL que identifica exclusivamente o
aplicativo móvel, seguido por ://auth/ . Para obter mais informações sobre como escolher um esquema de
URL personalizado, consulte escolhendo um URI de redirecionamento do aplicativo nativo.
Captura de tela a seguir demonstra essa configuração:
A política usada no Azure Active Directory B2C locatário também deve ser configurado para que a URL de
resposta é definida como o mesmo esquema de URL personalizado, seguido por ://auth/ . Captura de tela a
seguir demonstra essa configuração:
Configuração de aplicativo móvel do Azure
Um fluxo de trabalho de autenticação gerenciada pelo cliente, a instância de aplicativos móveis do Azure deve ser
configurada da seguinte maneira:
Autenticação do serviço de aplicativo deve ser ativada.
A ação a ser tomada quando uma solicitação for autenticada não deve ser definida como faça logon com o
Azure Active Directory.
Captura de tela a seguir demonstra essa configuração:
A instância de aplicativos móveis do Azure também deve ser configurada para se comunicar com o locatário do
Azure Active Directory B2C. Isso pode ser feito habilitando Advanced modo para o provedor de autenticação do
Active Directory do Azure, com o ID do cliente sendo o ID do aplicativo do Azure Locatário do Active Directory
B2C e o Url do emissor sendo o ponto de extremidade de metadados para a política do Azure Active Directory
B2C. Captura de tela a seguir demonstra essa configuração:
Entrar
O exemplo de código a seguir mostra como iniciar um fluxo de trabalho de autenticação gerenciada pelo cliente:
...
var payload = new JObject();
payload["access_token"] = authenticationResult.IdToken;
A biblioteca de autenticação Microsoft (MSAL ) é usado para iniciar um fluxo de trabalho de autenticação com o
locatário do Azure Active Directory B2C. O AcquireTokenAsync método inicia o navegador da web do dispositivo e
exibe as opções de autenticação definidas na política do Azure Active Directory B2C é especificada pela política
referenciada por meio de Constants.Authority constante. Essa política define as experiências pelas quais os
consumidores passarão durante a inscrição e entrar e as declarações que o aplicativo receberá bem-sucedido
inscrever-se ou entrar.
O resultado do AcquireTokenAsync chamada de método é um AuthenticationResult instância. Se a autenticação
for bem-sucedida, o AuthenticationResult instância conterá um token de identidade, que será armazenado
localmente. Se a autenticação for bem-sucedida, o AuthenticationResult instância conterá os dados que indicam
por que a autenticação falhou. Para obter informações sobre como usar MSAL para se comunicar com um
locatário do Azure Active Directory B2C, consulte autenticando usuários com o Azure Active Directory B2C.
Quando o MobileServiceClient.LoginAsync método é invocado, a instância de aplicativos móveis do Azure recebe o
token de identidade encapsulado em um JObject . A presença de um meio de token válido que a instância de
aplicativos móveis do Azure não precisa iniciar seu próprio fluxo de autenticação OAuth 2.0. Em vez disso, o
MobileServiceClient.LoginAsync método retorna um MobileServiceUser que será armazenada na instância a
MobileServiceClient.CurrentUser propriedade. Esta propriedade fornece UserId e
MobileServiceAuthenticationToken propriedades. Elas representam o usuário autenticado e um token de
autenticação para o usuário, que pode ser usado até que ela expire. O token de autenticação será incluído em todas
as solicitações feitas para a instância de aplicativos móveis do Azure, permitindo que o aplicativo xamarin. Forms
executar ações na instância de aplicativos móveis do Azure que exigem permissões de usuário autenticado.
Sair
O exemplo de código a seguir mostra como o processo de saída gerenciada pelo cliente é invocado:
Entrar
O exemplo de código a seguir mostra como iniciar um fluxo de trabalho de autenticação gerenciada pelo servidor:
Resumo
Este artigo demonstrou como usar o Azure Active Directory B2C para fornecer autenticação e autorização para
uma instância de aplicativos móveis do Azure com o xamarin. Forms. Azure Active Directory B2C do diretório é
uma solução de gerenciamento de identidade de nuvem para aplicativos móveis e web voltados ao consumidor.
Links relacionados
TodoAzureAuth ServerFlow (amostra)
TodoAzureAuth ClientFlow (amostra)
Consumir um aplicativo móvel do Azure
Autenticar usuários com aplicativos móveis do Azure
Autenticar usuários com o Azure Active Directory B2C
Biblioteca de autenticação da Microsoft
Sincronização de dados com serviços Web
12/04/2019 • 2 minutes to read
Sincronização offline permite que os usuários interagem com um aplicativo móvel, exibir, adicionar ou modificar
dados, mesmo que não tem uma conexão de rede. As alterações são armazenadas em um banco de dados local e,
depois que o dispositivo estiver online, as alterações podem ser sincronizadas com o serviço web.
Links relacionados
Introdução aos serviços Web
Visão geral do suporte assíncrono
Sincronizar dados Offline com aplicativos móveis do
Azure
12/04/2019 • 14 minutes to read
baixar o exemplo
Sincronização offline permite que os usuários interajam com um aplicativo móvel, exibindo, adicionando ou
modificando dados, mesmo que não tem uma conexão de rede. As alterações são armazenadas em um banco de
dados local e, depois que o dispositivo estiver online, as alterações podem ser sincronizadas com a instância de
aplicativos móveis do Azure. Este artigo explica como adicionar funcionalidade de sincronização offline para um
aplicativo xamarin. Forms.
Visão geral
O SDK do Azure Mobile Client fornece o IMobileServiceTable interface, que representa as operações que podem
ser executadas em tabelas armazenadas na instância de aplicativos móveis do Azure. Essas operações conectam
diretamente à instância de aplicativos móveis do Azure e falharão se o dispositivo móvel não tiver uma conexão de
rede.
Para dar suporte à sincronização offline, o SDK do Azure Mobile Client oferece suporte a tabelas de sincronização,
que são fornecidas pelo IMobileServiceSyncTable interface. Essa interface fornece o mesmo Create, Read, Update,
operações de exclusão (CRUD ) como o IMobileServiceTable interface, mas as operações de ler ou gravar em um
repositório local. O armazenamento local não é preenchido com novos dados da instância de aplicativos móveis do
Azure até que haja uma chamada para pull dados. Da mesma forma, os dados não serão enviados para a instância
de aplicativos móveis do Azure até que haja uma chamada para push alterações locais.
Sincronização offline também inclui suporte para detectar conflitos quando o mesmo registro é alterado no
repositório local e na instância de aplicativos móveis do Azure e a resolução de conflitos personalizado. Conflitos
podem ser manuseados no armazenamento local ou na instância de aplicativos móveis do Azure.
Para obter mais informações sobre a sincronização offline, consulte sincronização de dados Offline nos aplicativos
móveis do Azure e habilitar sincronização offline para seu aplicativo móvel do xamarin. Forms.
Configuração
O processo para a integração de sincronização offline entre um aplicativo xamarin. Forms e uma instância de
aplicativos móveis do Azure é da seguinte maneira:
1. Crie uma instância de aplicativos móveis do Azure. Para obter mais informações, consulte consumir o aplicativo
móvel do Azure.
2. Adicione a sqlitestore pacote do NuGet para todos os projetos na solução xamarin. Forms.
3. (Opcional) Habilite a autenticação na instância de aplicativos móveis do Azure e o aplicativo xamarin. Forms.
Para obter mais informações, consulte autenticando usuários com aplicativos móveis do Azure.
A seção a seguir fornece instruções de configuração adicionais para configurar projetos de plataforma Universal
do Windows (UWP ) para usar o pacote NuGet do sqlitestore. Nenhuma configuração adicional é necessária para
usar o pacote NuGet do sqlitestore no iOS e Android.
Plataforma Universal do Windows
Para usar o SQLite no Universal Windows Platform (UWP ), siga estas etapas:
1. Instalar o SQLite para plataforma Universal do Windows extensão do Visual Studio em seu ambiente de
desenvolvimento.
2. No projeto UWP no Visual Studio, clique com botão direito referências > Adicionar referência, navegue até
extensões e adicione o SQLite para plataforma Universal do Windows e Visual C++ 2015 Runtime para
aplicativos da plataforma Windows Universal extensões para o projeto UWP.
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using Microsoft.WindowsAzure.MobileServices.Sync;
namespace TodoAzure
{
public partial class TodoItemManager
{
static TodoItemManager defaultInstance = new TodoItemManager();
IMobileServiceClient client;
IMobileServiceSyncTable<TodoItem> todoTable;
private TodoItemManager()
{
this.client = new MobileServiceClient(Constants.ApplicationURL);
var store = new MobileServiceSQLiteStore("localstore.db");
store.DefineTable<TodoItem>();
this.client.SyncContext.InitializeAsync(store);
this.todoTable = client.GetSyncTable<TodoItem>();
}
...
}
}
Novo banco de dados SQLite local é criado pelo MobileServiceSQLiteStore de classe, desde que ele ainda não
existir. Em seguida, o DefineTable<T> método cria uma tabela no repositório local que corresponde aos campos no
TodoItem de tipo, desde que ele ainda não existir.
Um contexto de sincronização está associado com um MobileServiceClient instância e rastreia as alterações são
feitas com tabelas de sincronização. O contexto de sincronização mantém uma fila que mantém uma lista
ordenada de operações criar, atualizar e excluir (CUD ) que será enviada para a instância de aplicativos móveis do
Azure mais tarde. O IMobileServiceSyncContext.InitializeAsync() método é usado para associar o repositório local
com o contexto de sincronização.
O todoTable campo é um IMobileServiceSyncTable , e, portanto, todas as operações de CRUD usam o
armazenamento local.
Execução da sincronização
O armazenamento local é sincronizado com o Azure Mobile Apps instância quando o SyncAsync método é
invocado:
public async Task SyncAsync()
{
ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
try
{
await this.client.SyncContext.PushAsync();
// The first parameter is a query name that is used internally by the client SDK to implement incremental
sync.
// Use a different query name for each unique query in your program.
await this.todoTable.PullAsync("allTodoItems", this.todoTable.CreateQuery());
}
catch (MobileServicePushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
NOTE
Se um pull é executado em uma tabela que tenha atualizações locais pendentes, o pull primeiro executará um envio por push
no contexto de sincronização. Isso minimiza os conflitos entre as alterações que já estão na fila e novos dados da instância de
aplicativos móveis do Azure.
O SyncAsync método também inclui uma implementação básica para lidar com conflitos quando o mesmo
registro é alterado no repositório local e na instância de aplicativos móveis do Azure. Quando o conflito é que os
dados tiverem sido atualizados no repositório local e na instância de aplicativos móveis do Azure, o SyncAsync
método atualiza os dados no repositório local dos dados armazenados na instância de aplicativos móveis do Azure.
Quando ocorre qualquer conflito de outro, o SyncAsync método descarta a alteração local. Ele lida com o cenário
em que uma alteração local existe para os dados que foi excluídos da instância de aplicativos móveis do Azure.
Em um aplicativo de produção, os desenvolvedores devem escrever um personalizado IMobileServiceSyncHandler
implementação de manipulação de conflitos que é adequada ao seu caso de uso. Para obter mais informações,
consulte usar concorrência otimista para resolução de conflitos no portal do Azure, e aprofundando-se sobre o
suporte offline no SDK do cliente gerenciado em blogs do MSDN.
Limpando dados
Tabelas no armazenamento local podem ser apagadas de dados com o IMobileServiceSyncTable.PurgeAsync
método. Esse método dá suporte a cenários, como remover dados obsoletos que não exige um aplicativo. Por
exemplo, o aplicativo de exemplo exibe apenas TodoItem instâncias que não são concluídas. Portanto, itens
concluídos não precisam mais ser armazenados localmente. Limpar itens concluídos do repositório local pode ser
feito da seguinte maneira:
Uma chamada para PurgeAsync também dispara uma operação de push. Portanto, todos os itens que são
marcados como concluídos localmente serão enviados para a instância de aplicativos móveis do Azure antes de
serem removidos do repositório local. No entanto, se houver operações pendentes de sincronização com a
instância de aplicativos móveis do Azure, a limpeza lançará uma InvalidOperationException , a menos que o
force parâmetro for definido como true . Uma estratégia alternativa é examinar o
IMobileServiceSyncContext.PendingOperations propriedade, que retorna o número de operações que ainda não foi
enviado para a instância de aplicativos móveis do Azure e executar a limpeza apenas se a propriedade é zero
pendentes.
NOTE
Invocando PurgeAsync com o force parâmetro definido como true perderá todas as alterações pendentes.
Iniciando sincronização
No aplicativo de exemplo, o SyncAsync método é invocado por meio de TodoList.OnAppearing método:
// Set syncItems to true to synchronize the data on startup when running in offline mode
await RefreshItems(true, syncItems: true);
}
Isso significa que o aplicativo tentará sincronizar com a instância de aplicativos móveis do Azure quando ele é
iniciado.
Além disso, sincronização poderá ser iniciada no iOS e Android usando o pull para atualizar a lista de dados e nas
plataformas Windows usando o sincronização botão na interface do usuário. Para obter mais informações,
consulte efetue Pull para atualizar.
Resumo
Este artigo explicou como adicionar funcionalidade de sincronização offline para um aplicativo xamarin. Forms.
Sincronização offline permite que os usuários interajam com um aplicativo móvel, exibindo, adicionando ou
modificando dados, mesmo que não tem uma conexão de rede. As alterações são armazenadas em um banco de
dados local e, depois que o dispositivo estiver online, as alterações podem ser sincronizadas com a instância de
aplicativos móveis do Azure.
Links relacionados
TodoAzureAuthOfflineSync (sample)
Consumir um aplicativo móvel do Azure
Autenticar usuários com aplicativos móveis do Azure
SDK de cliente móvel do Azure
MobileServiceClient
Enviar notificações por Push
12/04/2019 • 2 minutes to read
Uma notificação por push é usada para fornecer informações, como uma mensagem de um sistema de back-end a
um aplicativo em um dispositivo móvel para aumentar o uso e o compromisso do aplicativo. A notificação pode
ser enviada em qualquer momento, mesmo quando o usuário não está usando ativamente o aplicativo de destino.
baixar o exemplo
Os Hubs de notificação do Azure fornecem uma infraestrutura de envio por push escalonável para enviar
notificações por push de qualquer back-end para qualquer plataforma móvel, enquanto elimina a complexidade
de um back-end precisar se comunicar com sistemas de notificação de plataforma diferente. Este artigo explica
como usar os Hubs de notificação do Azure para enviar notificações por push de uma instância de aplicativos
móveis do Azure para um aplicativo xamarin. Forms.
Para enviar uma notificação por push, o sistema de back-end contata o PNS específico da plataforma para enviar
uma notificação para uma instância do aplicativo cliente. Isso aumenta significativamente a complexidade de back-
end quando as notificações por push de plataforma cruzada forem necessárias, como o back-end deve usar cada
PNS API e um protocolo específico da plataforma.
Os Hubs de notificação do Azure eliminar essa complexidade, abstraindo os detalhes dos sistemas de notificação
de plataforma diferente, permitindo que uma notificação de plataforma cruzada ser enviada com uma única
chamada de API, conforme mostrado no diagrama a seguir:
Para enviar uma notificação por push, os back-end sistema apenas os contatos Azure Hub de notificação, que por
sua vez se comunica com os sistemas de notificação de plataforma diferente, portanto, diminuir a complexidade de
back-end que as notificações por push de envios de código.
Aplicativos móveis do Azure têm suporte interno para notificações por push usando hubs de notificação. O
processo para enviar uma notificação por push de uma instância de aplicativos móveis do Azure para um
aplicativo xamarin. Forms é da seguinte maneira:
1. Registra o aplicativo xamarin. Forms com o PNS, que retorna um identificador.
2. A instância de aplicativos móveis do Azure envia uma notificação ao seu Hub de notificação do Azure,
especificando o identificador do dispositivo para ser direcionado.
3. O Hub de notificação do Azure envia a notificação para o PNS apropriado para o dispositivo.
4. O PNS envia a notificação ao dispositivo especificado.
5. O aplicativo xamarin. Forms processa a notificação e o exibe.
O aplicativo de exemplo demonstra um aplicativo de lista de tarefas cujos dados são armazenados em uma
instância de aplicativos móveis do Azure. Sempre que um novo item é adicionado à instância de aplicativos móveis
do Azure, uma notificação por push seja enviada ao aplicativo xamarin. Forms. As capturas de tela a seguir
mostram a cada plataforma exibindo a notificação por push recebida:
Para obter mais informações sobre os Hubs de notificação do Azure, consulte os Hubs de notificação do Azure e
adicionar notificações de envio por push ao aplicativo xamarin. Forms.
UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
UIApplication.SharedApplication.RegisterForRemoteNotifications();
...
}
Quando um aplicativo do iOS registra com o APNS, ele deve especificar os tipos de notificações por push que ele
gostaria de receber. O RegisterUserNotificationSettings método registra os tipos de notificações que o aplicativo
pode receber, com o RegisterForRemoteNotifications método registrar para receber notificações por push do
APNS.
NOTE
Falha ao chamar o RegisterUserNotificationSettings método resultará em notificações por push silenciosamente que
está sendo recebidas pelo aplicativo.
Esse método cria um modelo de mensagem de notificação simples como JSON e registra o dispositivo para
receber notificações de modelo do hub de notificação.
NOTE
O FailedToRegisterForRemoteNotifications substituição deve ser implementada para lidar com situações como
nenhuma conexão de rede. Isso é importante porque os usuários podem iniciar o aplicativo enquanto offline.
// Show alert
if (!string.IsNullOrEmpty(alert))
{
var notificationAlert = UIAlertController.Create("Notification", alert, UIAlertControllerStyle.Alert);
notificationAlert.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Cancel, null));
UIApplication.SharedApplication.KeyWindow.RootViewController.PresentViewController(notificationAlert,
true, null);
}
}
O userInfo dicionário contém o aps chave, cujo valor é o alert dicionário com os dados restantes de
notificação. Esse dicionário é recuperado, com o string que está sendo exibida em uma caixa de diálogo de
mensagem de notificação.
NOTE
Se um aplicativo não está em execução quando chega uma notificação por push, o aplicativo será iniciado, mas o
DidReceiveRemoteNotification método não processará a notificação. Em vez disso, obtenha a carga de notificação e
responder adequadamente a partir de WillFinishLaunching ou FinishedLaunching substitui.
Para obter mais informações sobre o APNS, consulte notificações por Push no iOS.
Android
O processo para implementar o suporte à notificação por push em um aplicativo Android é da seguinte maneira:
1. Adicione a firebase NuGet do pacote ao projeto do Android e defina a versão de destino do aplicativo para
Android 7.0 ou superior.
2. Adicione a google-services.json arquivo, baixado do console do Firebase, para a raiz do projeto do Android e
defina sua ação de compilação como GoogleServicesJson. Para obter mais informações, consulte adicionar o
arquivo de JSON de serviços do Google.
3. Registre-se com o Firebase Cloud Messaging (FCM ) declarando um receptor no manifesto do Android de
arquivo e por implementar a FirebaseRegistrationService.OnTokenRefresh método. Para obter mais
informações, consulte Registrando com o Firebase Cloud Messaging.
4. Registrar com o Hub de notificação do Azure na AzureNotificationHubService.RegisterAsync método. Para obter
mais informações, consulte Registrando com o Hub de notificação do Azure.
5. Implementar o FirebaseNotificationService.OnMessageReceived método para processar as notificações por push
recebidas. Para obter mais informações, consulte exibindo o conteúdo de uma notificação por Push.
Para obter mais informações sobre o Firebase Cloud Messaging, consulte Firebase Cloud Messaging e
notificações remotas com o Firebase Cloud Messaging.
Registrando com o Firebase Cloud Messaging
Antes de um aplicativo do Android pode receber notificações por push, deve ser registrado com o FCM, que vai
gerar um token de registro e retorná-lo para o aplicativo. Para obter mais informações sobre tokens do registro,
consulte registro com FCM.
Isso é feito:
Declarando um receptor no manifesto do Android. Para obter mais informações, consulte declarando o
receptor no manifesto do Android.
Implementando o serviço de ID de instância do Firebase. Para obter mais informações, consulte
Implementando o serviço de ID de instância do Firebase.
D e c l a r a n d o o r e c e p t o r n o m a n i fe st o d o A n d r o i d
Registrar o aplicativo com o FCM é feito derivando uma classe a partir de FirebaseInstanceIdService classe. Essa
classe é responsável por gerar tokens de segurança que autorizam o aplicativo cliente para acessar o FCM. No
aplicativo de exemplo o FirebaseRegistrationService classe deriva de FirebaseInstanceIdService classe e é
mostrado no exemplo de código a seguir:
[Service]
[IntentFilter(new[] { "com.google.firebase.INSTANCE_ID_EVENT" })]
public class FirebaseRegistrationService : FirebaseInstanceIdService
{
const string TAG = "FirebaseRegistrationService";
O OnTokenRefresh método é invocado quando o aplicativo recebe um token de registro do FCM. O método
recupera o token a partir de FirebaseInstanceId.Instance.Token propriedade, que é atualizada de forma assíncrona
pelo FCM. O OnTokenRefresh método é invocado com pouca frequência, porque o token é atualizado somente
quando o aplicativo é instalado ou desinstalado, quando o usuário exclui dados de aplicativos, quando o aplicativo
apaga a ID da instância, ou quando a segurança do token tiver sido comprometido. Além disso, o serviço de ID de
instância do FCM solicita que o aplicativo atualize seu token periodicamente, normalmente a cada 6 meses.
O OnTokenRefresh também invoca um método de SendRegistrationTokenToAzureNotificationHub método, que é
usado para associar o token de registro do usuário com o Hub de notificação do Azure.
Registrando com o Hub de notificação do Azure
O AzureNotificationHubService classe fornece o RegisterAsync método, que associa o token de registro do
usuário com o Hub de notificação do Azure. O seguinte exemplo de código mostra a RegisterAsync método, que é
invocado pelo FirebaseRegistrationService classe quando o token de registro do usuário é alterado:
Esse método cria um modelo de mensagem de notificação simples como JSON e se registra para receber
notificações de modelo do hub de notificação, usando o token de registro do Firebase. Isso garante que todas as
notificações enviadas do Hub de notificação do Azure serão o representado pelo token de registro de dispositivo
de destino.
Exibindo o conteúdo de uma notificação por Push
Exibir o conteúdo de uma notificação por push é obtido, derivando uma classe a partir de
FirebaseMessagingService classe. Essa classe inclui o substituível OnMessageReceived fornecido de método, que é
invocado quando o aplicativo recebe uma notificação do FCM, se o aplicativo está em execução em primeiro plano.
No aplicativo de exemplo do FirebaseNotificationService classe deriva o FirebaseMessagingService de classe e é
mostrado no exemplo de código a seguir:
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
public class FirebaseNotificationService : FirebaseMessagingService
{
const string TAG = "FirebaseNotificationService";
Quando o aplicativo recebe uma notificação do FCM, o OnMessageReceived método extrai o conteúdo da
mensagem e chama o SendNotification método. Este método converte o conteúdo da mensagem em uma
notificação de local que é iniciada enquanto o aplicativo é executado, com a notificação que aparece na área de
notificação.
M a n i p u l a ç ã o d e t e n t a t i v a s d e n o t i fi c a ç ã o
Quando um usuário toca uma notificação, todos os dados que acompanha a mensagem de notificação foi
disponibilizados no Intent extras. Esses dados podem ser extraídos com o código a seguir:
if (Intent.Extras != null)
{
foreach (var key in Intent.Extras.KeySet())
{
var value = Intent.Extras.GetString(key);
Log.Debug(TAG, "Key: {0} Value: {1}", key, value);
}
}
Iniciador do aplicativo Intent é acionado quando o usuário toca em sua mensagem de notificação, portanto, esse
código registrará em log todos os dados que acompanha este artigo no Intent à janela de saída.
Plataforma Universal do Windows
Antes de um Universal Windows Platform (UWP ) o aplicativo pode receber notificações por push que deve ser
registrado com o Windows serviço WNS (notificação), que retornará um canal de notificação. Registro é invocado
com o InitNotificationsAsync método no App classe:
await TodoItemManager.DefaultManager.CurrentClient.GetPush()
.RegisterAsync(channel.Uri, templates);
}
Esse método obtém o canal de notificação por push, cria um modelo de mensagem de notificação como JSON e
registra o dispositivo para receber notificações de modelo do hub de notificação.
O InitNotificationsAsync método é chamado do OnLaunched substituir no App classe:
Isso garante que o registro de notificação por push é criado ou atualizado sempre que o aplicativo é iniciado,
garantindo assim que o canal de push do WNS está sempre ativo.
Quando é recebida uma notificação por push ele será automaticamente exibido como uma toast – uma janela não
restrita que contém a mensagem.
Resumo
Este artigo demonstrou como usar os Hubs de notificação do Azure para enviar notificações por push de uma
instância de aplicativos móveis do Azure para um aplicativo xamarin. Forms. Os Hubs de notificação do Azure
fornecem uma infraestrutura de envio por push escalonável para enviar notificações por push de qualquer back-
end para qualquer plataforma móvel, enquanto elimina a complexidade de um back-end precisar se comunicar
com sistemas de notificação de plataforma diferente.
Links relacionados
Consumir um aplicativo móvel do Azure
Hubs de notificação do Azure
Adicionar notificações por push ao seu aplicativo xamarin. Forms
Notificações por push no iOS
Mensagens na nuvem do Firebase
TodoAzurePush (amostra)
SDK de cliente móvel do Azure
Armazenando arquivos na nuvem
12/04/2019 • 2 minutes to read
Armazenamento do Azure é uma solução de armazenamento de nuvem escalonáveis que pode ser usada para
armazenar dados estruturados e não estruturados.
baixar o exemplo
Armazenamento do Azure é uma solução de armazenamento de nuvem escalonável que pode ser usada para
armazenar dados não estruturados e estruturados. Este artigo demonstra como usar o xamarin. Forms para
armazenar texto e dados binários no armazenamento do Azure e como acessar os dados.
O armazenamento do Azure fornece quatro serviços de armazenamento:
Armazenamento de BLOBs. Um blob pode ser texto ou dados binários, como backups, máquinas virtuais,
arquivos de mídia ou documentos.
Armazenamento de tabela é um repositório de atributos de chave NoSQL.
Armazenamento de filas é um serviço de mensagens para processamento de fluxo de trabalho e comunicação
entre serviços de nuvem.
O armazenamento de arquivos oferece armazenamento compartilhado usando o protocolo SMB.
Há dois tipos de contas de armazenamento:
Contas de armazenamento de uso geral fornece acesso aos serviços de armazenamento do Azure de uma única
conta.
Uma conta de armazenamento de BLOBs é uma conta de armazenamento especializada para armazenamento
de blobs. Esse tipo de conta é recomendado quando você só precisa armazenar dados blob.
Neste artigo e que acompanha o aplicativo de exemplo demonstra a carregar arquivos de imagem e texto para o
armazenamento de blob e baixá-los. Além disso, ele também demonstra recuperando uma lista de arquivos do
armazenamento de BLOBs e excluir arquivos.
Para obter mais informações sobre o armazenamento do Azure, consulte Introdução ao armazenamento.
NOTE
Observe que as contas de armazenamento de BLOBs têm suporte para bloquear e acrescentar blobs, mas não os blobs de
página.
Configuração
O processo para integrar uma conta de armazenamento do Azure em um aplicativo xamarin. Forms é da seguinte
maneira:
1. Crie uma conta de armazenamento. Para obter mais informações, consulte criar uma conta de armazenamento.
2. Adicione a biblioteca de cliente de armazenamento do Azure ao aplicativo xamarin. Forms.
3. Configure a cadeia de caracteres de conexão de armazenamento. Para obter mais informações, consulte
conectar-se ao armazenamento do Azure.
4. Adicione using diretivas para o Microsoft.WindowsAzure.Storage e Microsoft.WindowsAzure.Storage.Blob
namespaces para classes que vai acessar o armazenamento do Azure.
NOTE
O armazenamento do Azure dá suporte a HTTP e HTTPS em uma cadeia de conexão. No entanto, é recomendável usar
HTTPS.
UseDevelopmentStorage=true
Para obter mais informações sobre o emulador de armazenamento do Azure, consulte usar o emulador de
armazenamento do Azure para desenvolvimento e teste.
Conectar-se ao armazenamento do Azure usando uma chave compartilhada
O seguinte formato de cadeia de caracteres de conexão deve ser usado para se conectar ao armazenamento do
Azure com uma chave compartilhada:
DefaultEndpointsProtocol=[http|https];AccountName=myAccountName;AccountKey=myAccountKey
myAccountName deve ser substituído pelo nome da sua conta de armazenamento e myAccountKey deve ser
substituído por uma das suas duas chaves de acesso de conta.
NOTE
Ao usar compartilhada autenticação de chave, o nome da conta e chave de conta será distribuída para cada pessoa que usa
seu aplicativo, que fornece acesso completo de leitura/gravação à conta de armazenamento. Portanto, usar a autenticação de
chave compartilhada somente para testes e nunca distribuir chaves para outros usuários.
myBlobEndpoint deve ser substituído pela URL do seu ponto de extremidade do blob e mySharedAccessSignature
deve ser substituído com a SAS. A SAS fornece o protocolo, o ponto de extremidade de serviço e as credenciais
para acessar o recurso.
NOTE
Autenticação de SAS é recomendada para aplicativos de produção. No entanto, em um aplicativo de produção as SAS devem
ser recuperadas de um back-end serviço sob demanda, em vez de ser agrupado com o aplicativo.
Para obter mais informações sobre assinaturas de acesso compartilhado, consulte usando acesso assinaturas
compartilhado (SAS ).
Criar um contêiner
O GetContainer método é usado para recuperar uma referência a um contêiner nomeado, o que, em seguida,
pode ser usado para recuperar os blobs do contêiner ou adicionar blobs no contêiner. O seguinte exemplo de
código mostra o GetContainer método:
NOTE
Os nomes de contêiner devem estar em minúsculos e devem começar com uma letra ou número. Além disso, eles podem
conter apenas letras, números e o caractere de traço e devem ter entre 3 e 63 caracteres.
O CloudBlobContainer instância, em seguida, pode ser usada para criar um contêiner se ele ainda não existir:
await container.CreateIfNotExistsAsync();
Por padrão, um contêiner recém-criado é privado. Isso significa que uma chave de acesso de armazenamento deve
ser especificada para recuperar os blobs do contêiner. Para obter informações sobre como fazer os blobs dentro de
um contêiner público, consulte criar um contêiner.
return name;
}
Depois de recuperar uma referência de contêiner, o método cria o contêiner se ele ainda não existir.Uma nova
Guid , em seguida, é criado para atuar como um nome exclusivo de blob, e uma referência de blob de blocos é
recuperada como um CloudBlockBlob instância. O fluxo de dados é então carregado para o blob usando o
UploadFromStreamAsync método, que cria o blob se ele ainda não existe ou substitui, se ele existir.
Antes de um arquivo pode ser carregado usando esse método de armazenamento de BLOBs, primeiro ele deve ser
convertido para um fluxo de bytes. Isso é demonstrado no exemplo de código a seguir:
O textdados são convertidos em uma matriz de bytes, que é empacotada como um fluxo que é passado para o
UploadFileAsync método.
Depois de recuperar uma referência de contêiner, o método recupera uma referência de blob para os dados
armazenados. Se o blob existir, suas propriedades são recuperadas pelo FetchAttributesAsync método. Uma
matriz de bytes do tamanho correto é criada e o blob é baixado como uma matriz de bytes que é retornada para o
método de chamada.
Depois de baixar os dados de bytes de blob, ele deve ser convertido em sua representação original. Isso é
demonstrado no exemplo de código a seguir:
var byteData = await AzureStorage.GetFileAsync(ContainerType.Text, uploadedFilename);
string text = Encoding.UTF8.GetString(byteData);
do
{
var result = await container.ListBlobsSegmentedAsync(token);
if (result.Results.Count() > 0)
{
var blobs = result.Results.Cast<CloudBlockBlob>().Select(b => b.Name);
allBlobsList.AddRange(blobs);
}
token = result.ContinuationToken;
} while (token != null);
return allBlobsList;
}
Depois de recuperar uma referência de contêiner, o método usa o contêiner ListBlobsSegmentedAsync método para
recuperar as referências para os blobs dentro do contêiner. Os resultados retornados pela ListBlobsSegmentedAsync
método são enumerados enquanto a BlobContinuationToken instância não é null . Cada blob é convertido de
retornado IListBlobItem para um CloudBlockBlob no acesso de ordem de Name propriedade do blob, antes que
seja o valor é adicionada ao allBlobsList coleção. Uma vez a BlobContinuationToken instância é null , o último
nome de blob retornou e execução sai do loop.
Depois de recuperar uma referência de contêiner, o método recupera uma referência de blob para o blob
especificado. O blob é excluído com o DeleteIfExistsAsync método.
Links relacionados
Armazenamento do Azure (exemplo)
Introdução ao armazenamento
Como usar o armazenamento de BLOBs do Xamarin
Usando assinaturas de acesso compartilhado (SAS )
Windows (NuGet) de armazenamento do Azure
Pesquisando dados na nuvem
12/04/2019 • 2 minutes to read
Pesquisa do Azure é um serviço de nuvem que fornece a indexação e consulta de recursos para os dados
carregados. Isso remove os requisitos de infraestrutura e as complexidades de algoritmo de pesquisa normalmente
associadas ao implementar a funcionalidade de pesquisa em um aplicativo.
baixar o exemplo
O Azure Search é um serviço de nuvem que fornece a indexação e consulta recursos para os dados carregados.
Isso remove as complexidades do algoritmo de pesquisa tradicionalmente associadas ao implementar a
funcionalidade de pesquisa em um aplicativo e requisitos de infraestrutura. Este artigo demonstra como usar a
biblioteca do Microsoft Azure Search para integrar o Azure Search em um aplicativo xamarin. Forms.
Visão geral
Dados são armazenados no Azure Search, como índices e documentos. Uma índice é um repositório de dados que
podem ser pesquisados pelo serviço de Azure Search e é conceitualmente semelhante a uma tabela de banco de
dados. Um documento é uma única unidade de dados pesquisáveis em um índice e é conceitualmente semelhante
a uma linha do banco de dados. Quando carregar documentos e enviar consultas de pesquisa para o Azure Search,
as solicitações são feitas em um índice específico no serviço de pesquisa.
Cada solicitação feita ao Azure Search deve incluir o nome do serviço e uma chave de API. Há dois tipos de chave
de API:
Chaves de administração conceder direitos totais para todas as operações. Isso inclui o serviço de
gerenciamento, a criação e a exclusão de índices e fontes de dados.
Chaves de consulta conceder acesso somente leitura a índices e documentos e deve ser usado por aplicativos
que emitem solicitações de pesquisa.
A solicitação mais comum para o Azure Search é executar uma consulta. Há dois tipos de consulta que pode ser
enviado:
Um pesquisa consulta procura por um ou mais itens em todos os campos pesquisáveis em um índice.
Consultas de pesquisa são criadas usando a sintaxe simplificada, ou a sintaxe de consulta Lucene. Para obter
mais informações, consulte sintaxe de consulta simples no Azure Search, e sintaxe de consulta Lucene no Azure
Search.
Um filtro consulta avalia uma expressão booliana em todos os campos que podem ser filtrados em um índice.
Consultas de filtro são criadas usando um subconjunto da linguagem de filtro OData. Para obter mais
informações, consulte sintaxe de expressão do OData para o Azure Search.
Consultas de pesquisa e consultas de filtro podem ser usadas separadamente ou em conjunto. Quando usados
juntos, a consulta de filtro é aplicada primeiro ao índice inteiro e, em seguida, a consulta de pesquisa é realizada
nos resultados da consulta de filtro.
O Azure Search também dá suporte ao recuperar sugestões com base na entrada de pesquisa. Para obter mais
informações, consulte consultas de sugestão.
Configuração
O processo para a integração do Azure Search em um aplicativo xamarin. Forms é da seguinte maneira:
1. Crie um serviço Azure Search. Para obter mais informações, consulte criar um serviço de Azure Search usando
o Portal do Azure.
2. Remova o Silverlight como uma estrutura de destino da biblioteca de classe portátil (PCL ) da solução do
xamarin. Forms. Isso pode ser feito alterando o perfil PCL para qualquer perfil que dá suporte ao
desenvolvimento de plataforma cruzada, mas não oferece suporte a Silverlight, como perfil 151 ou 92.
3. Adicione a biblioteca do Microsoft Azure Search pacote NuGet ao projeto PCL na solução xamarin. Forms.
Depois de executar essas etapas, a API de biblioteca do Microsoft Search pode ser usada para gerenciar fontes de
dados e índices de pesquisa, carregar e gerenciar documentos e executar consultas.
var searchClient =
new SearchServiceClient(Constants.SearchServiceName, new SearchCredentials(Constants.AdminApiKey));
NOTE
Um único SearchServiceClient instância deve ser usada em um aplicativo para evitar abrir um número excessivo de
conexões para o Azure Search.
Um índice é definido pelo Index do objeto, conforme demonstrado no exemplo de código a seguir:
searchClient.Indexes.Create(index);
}
O Index.Name propriedade deve ser definida como o nome do índice e o Index.Fields propriedade deve ser
definida como uma matriz de Field objetos. Cada Field instância Especifica um nome, um tipo e quaisquer
propriedades que especificam como o campo é usado. Essas propriedades incluem:
IsKey – Indica se o campo é a chave do índice. Apenas um campo no índice, do tipo DataType.String , deve ser
designado como o campo de chave.
IsFacetable – Indica se é possível executar a navegação facetada nesse campo. O valor padrão é false .
IsFilterable – Indica se o campo pode ser usado em consultas de filtro. O valor padrão é false .
IsRetrievable – Indica se o campo pode ser recuperado nos resultados da pesquisa. O valor padrão é true .
IsSearchable – Indica se o campo está incluído em pesquisas de texto completo. O valor padrão é false .
IsSortable – Indica se o campo pode ser usado em OrderBy expressões. O valor padrão é false .
NOTE
Alterar um índice após sua implantação envolve a recriação e recarregar os dados.
Uma Index objeto pode especificar opcionalmente um Suggesters propriedade, que define os campos no índice a
ser usado para dar suporte a preenchimento automático ou consultas de sugestão de pesquisa. O Suggesters
propriedade deve ser definida como uma matriz de Suggester objetos que definem os campos que são usados
para criar resultados de sugestão de pesquisa.
Depois de criar o Index do objeto, o índice é criado chamando Indexes.Create sobre o SearchServiceClient
instância.
NOTE
Ao criar um índice de um aplicativo que deve ser mantido responsivo, use o Indexes.CreateAsync método.
Para obter mais informações, consulte criar um índice de Azure Search usando o SDK do .NET.
searchClient.Indexes.Delete(Constants.Index);
Dados a serem importados para o índice são empacotados como um IndexBatch objeto que encapsula uma
coleção de IndexAction objetos. Cada IndexAction instância contém um documento e uma propriedade que
informam ao Azure Search qual ação executar no documento. No exemplo de código acima, o IndexAction.Upload
ação for especificada, o que resulta no documento que está sendo inserida no índice, se for novo, ou substituída se
ele já existe. O IndexBatch objeto, em seguida, é enviado para o índice chamando o Documents.Index método o
SearchIndexClient objeto. Para obter informações sobre outras ações de indexação, consulte decidir qual ação de
indexação para usar.
NOTE
Apenas 1000 documentos podem ser incluídos em uma única solicitação de indexação.
Observe que no exemplo de código acima, o monkeyList coleção é criada como um objeto anônimo de uma
coleção de Monkey objetos. Isso cria os dados para o id campo e resolve o mapeamento de Pascal case Monkey
nomes de campo de índice de pesquisa de nomes de propriedade para concatenação com maiusculas. Como
alternativa, esse mapeamento também pode ser feito adicionando o [SerializePropertyNamesAsCamelCase] de
atributo para o Monkey classe.
Para obter mais informações, consulte carregar dados no Azure Search usando o SDK do .NET.
O SearchAsync método usa um argumento de texto de pesquisa e um opcional SearchParameters objeto que pode
ser usado para refinar ainda mais a consulta. Uma consulta de pesquisa é especificada como o argumento de texto
de pesquisa, enquanto uma consulta de filtro pode ser especificada definindo a Filter propriedade do
SearchParameters argumento. O exemplo de código a seguir demonstra que os dois tipos de consulta:
Essa consulta de filtro é aplicada a todo o índice e remove documentos nos resultados em que o location campo
não é igual a China e não é igual a Vietnã. Após a filtragem, a consulta de pesquisa é executada nos resultados da
consulta de filtro.
NOTE
Para filtrar sem pesquisar, passar * como o argumento de texto de pesquisa.
O SearchAsync método retorna um DocumentSearchResult objeto que contém os resultados da consulta. Esse
objeto é enumerado, com cada Document do objeto que está sendo criado como um Monkey do objeto e
adicionado à Monkeys ObservableCollection para exibição. Os seguir capturas de tela mostrar consulta resultados
da pesquisa retornados do Azure Search:
Para obter mais informações sobre pesquisa e filtragem, consulte consultar seu índice de Azure Search usando o
SDK do .NET.
Consultas de sugestão
O Azure Search permite sugestões para ser solicitado com base em uma consulta de pesquisa, chamando o
Documents.SuggestAsync método no SearchIndexClient instância. Isso é demonstrado no exemplo de código a
seguir:
async Task AzureSuggestions(string text)
{
Suggestions.Clear();
var suggestionResults =
await indexClient.Documents.SuggestAsync<Monkey>(text, "nameSuggester", parameters);
O SuggestAsync método aceita um argumento de texto de pesquisa, o nome do sugestor usar (que é definido no
índice), e um opcional SuggestParameters objeto que pode ser usado para refinar ainda mais a consulta. O
SuggestParameters instância define as propriedades a seguir:
UseFuzzyMatching – Quando definido como true , Azure Search encontrará sugestões mesmo que haja um
caractere ausente ou substituído no texto de pesquisa.
HighlightPreTag – a marcação que é anexada à sugestão de ocorrências.
HighlightPostTag – a marcação que é acrescentada à sugestão de ocorrências.
MinimumCoverage – representa a porcentagem do índice que deve ser coberto por uma consulta de sugestão
para a consulta a ser relatado um sucesso. O padrão é 80.
Top – o número de sugestões a serem recuperadas. Ele deve ser um inteiro entre 1 e 100, com um valor
padrão de 5.
O efeito geral é que os 10 primeiros resultados do índice serão retornados com realce de ocorrências e os
resultados incluirão os documentos que incluem os termos de pesquisa a ortografia da mesma forma.
O SuggestAsync método retorna um DocumentSuggestResult objeto que contém os resultados da consulta. Esse
objeto é enumerado, com cada Document do objeto que está sendo criado como um Monkey do objeto e
adicionado à Monkeys ObservableCollection para exibição. As capturas de tela a seguir mostram os resultados de
sugestão retornados do Azure Search:
Observe que o aplicativo de exemplo, o SuggestAsync método é chamado somente quando o usuário termina de
inserir um termo de pesquisa. No entanto, ele também pode ser usado para dar suporte a consultas de pesquisa
de preenchimento automático executando em cada pressionamento de tecla.
Resumo
Este artigo demonstrou como usar a biblioteca do Microsoft Azure Search para integrar o Azure Search em um
aplicativo xamarin. Forms. O Azure Search é um serviço de nuvem que fornece a indexação e consulta recursos
para os dados carregados. Isso remove as complexidades do algoritmo de pesquisa tradicionalmente associadas
ao implementar a funcionalidade de pesquisa em um aplicativo e requisitos de infraestrutura.
Links relacionados
O Azure Search (amostra)
Documentação do Azure Search
Biblioteca do Microsoft Azure Search
Sem servidor de computação com o xamarin. Forms
12/04/2019 • 2 minutes to read
Compile aplicativos com a poderosa funcionalidade de back-end, sem a complexidade de configurar e gerenciar
um servidor.
Azure Functions
Comece criando seu primeiro Azure Function que interage com o xamarin. Forms.
Introdução ao Azure Functions
12/04/2019 • 2 minutes to read
Links relacionados
Documentos de funções do Azure
Implementando uma função do Azure simples com um cliente do xamarin. Forms (amostra)
Armazenamento de dados em um banco de dados
de documento
12/04/2019 • 2 minutes to read
Um banco de dados de documento de banco de dados do Azure Cosmos é um banco de dados NoSQL que
fornece acesso de baixa latência para documentos JSON, oferecendo um serviço de banco de dados rápida,
altamente disponível e dimensionável para aplicativos que necessitam de replicação global e escala contínua.
baixar o exemplo
Um banco de dados de documentos do Azure Cosmos DB é um banco de dados NoSQL que fornece acesso de
baixa latência para documentos JSON, oferecendo um serviço de banco de dados rápida, altamente disponível e
escalonável para aplicativos que exigem dimensionamento perfeito e replicação global. Este artigo explica como
usar a biblioteca de cliente .NET Standard do Azure Cosmos DB para integrar um banco de dados de documentos
do Azure Cosmos DB em um aplicativo xamarin. Forms.
Configuração
O processo para a integração de um banco de dados de documentos do Azure Cosmos DB em um aplicativo
xamarin. Forms é da seguinte maneira:
1. Crie uma conta do Cosmos DB. Para obter mais informações, consulte criar uma conta do Azure Cosmos DB.
2. Adicione a biblioteca de cliente do .NET Standard do Azure Cosmos DB pacote do NuGet para os projetos de
plataforma da solução do xamarin. Forms.
3. Adicione using diretivas para o Microsoft.Azure.Documents , Microsoft.Azure.Documents.Client , e
Microsoft.Azure.Documents.Linq namespaces para classes que acessarão a conta do Cosmos DB.
Depois de executar essas etapas, a biblioteca de cliente .NET Standard do Azure Cosmos DB pode ser usada para
configurar e executar solicitações no banco de dados de documentos.
NOTE
A biblioteca de cliente .NET Standard do Azure Cosmos DB só pode ser instalada em projetos de plataforma e não em um
projeto de biblioteca de classe portátil (PCL). Portanto, o aplicativo de exemplo é um projeto de acesso compartilhado (SAP)
para evitar a duplicação de código. No entanto, o DependencyService classe pode ser usada em um projeto PCL para
invocar o código da biblioteca cliente .NET Standard do Azure Cosmos DB contido em projetos específicos da plataforma.
O Uri do Cosmos DB e a chave primária devem ser fornecidas para o DocumentClient construtor. Eles podem ser
obtidos do Portal do Azure. Para obter mais informações, consulte conectar-se a uma conta do Azure Cosmos DB.
Criando um banco de dados
Um banco de dados do documento é um contêiner lógico para os usuários e coleções de documento e pode ser
criado no Portal do Azure ou programaticamente usando o DocumentClient.CreateDatabaseIfNotExistsAsync
método:
NOTE
O CreateDatabaseIfNotExistsAsync método retorna um Task<ResourceResponse<Database>> objeto e o código de
status da resposta podem ser verificada para determinar se um banco de dados foi criado ou um banco de dados foi
retornado.
NOTE
O CreateDocumentCollectionIfNotExistsAsync método retorna um Task<ResourceResponse<DocumentCollection>>
objeto e o código de status da resposta podem ser verificada para determinar se uma coleção de documentos foi criada ou
uma coleção de documento existente foi retornada.
IMPORTANT
Observe que o CreateDocumentCollectionIfNotExistsAsync método criará uma nova coleção com uma taxa de
transferência reservada, que tem implicações de preço.
Essa consulta assíncrona recupera todos os documentos da coleção especificada e coloca os documentos em um
List<TodoItem> coleção para exibição.
O CreateDocumentQuery<T> método Especifica um Uri argumento que representa a coleção que deve ser
consultada para documentos. Neste exemplo, o collectionLink variável é um campo de nível de classe que
especifica o Uri que representa a coleção de documentos para recuperar os documentos a partir de:
O CreateDocumentQuery<T> método cria uma consulta que é executada de forma síncrona e retorna um
IQueryable<T> objeto. No entanto, o AsDocumentQuery método converte os IQueryable<T> do objeto para um
IDocumentQuery<T> objeto que pode ser executado de forma assíncrona. A consulta assíncrona é executada com o
IDocumentQuery<T>.ExecuteNextAsync método, que recupera a próxima página de resultados de banco de dados de
documento, com o IDocumentQuery<T>.HasMoreResults propriedade que indica se há resultados adicionais a serem
retornados da consulta.
Os documentos podem ser filtradas do lado do servidor, incluindo um Where cláusula na consulta, que aplica um
predicado de filtragem à consulta na coleção de documentos:
Essa consulta recupera todos os documentos da coleção cuja Done propriedade é igual a false .
Inserindo um documento em uma coleção de documentos
Documentos são conteúdo JSON de definidas pelo usuário e podem ser inseridos em uma coleção de
documentos com o DocumentClient.CreateDocumentAsync método:
O CreateDocumentAsync método Especifica um Uri argumento que representa a coleção em que o documento
deve ser inserido no, e um object argumento que representa o documento a ser inserido.
Substituição de um documento em uma coleção de documentos
Documentos podem ser substituídos em uma coleção de documentos com o DocumentClient.ReplaceDocumentAsync
método:
public async Task SaveTodoItemAsync(TodoItem item, bool isNewItem = false)
{
...
await client.ReplaceDocumentAsync(UriFactory.CreateDocumentUri(Constants.DatabaseName,
Constants.CollectionName, item.Id), item);
...
}
O ReplaceDocumentAsync método Especifica um Uri argumento que representa o documento na coleção que deve
ser substituído, e um object argumento que representa os dados de documento atualizado.
Excluir um documento de uma coleção de documentos
Um documento pode ser excluído de uma coleção de documentos com o DocumentClient.DeleteDocumentAsync
método:
O DeleteDocumentAsync método Especifica um Uri argumento que representa o documento na coleção que deve
ser excluído.
Excluindo uma coleção de documentos
Uma coleção de documentos pode ser excluída do banco de dados com o
DocumentClient.DeleteDocumentCollectionAsync método:
await client.DeleteDocumentCollectionAsync(collectionLink);
await client.DeleteDatabaseAsync(UriFactory.CreateDatabaseUri(Constants.DatabaseName));
O DeleteDatabaseAsync método Especifica um Uri argumento que representa o banco de dados a ser excluído.
Observe que invocar esse método também excluirá as coleções de documentos armazenadas no banco de dados e
os documentos armazenados nas coleções de documento.
Resumo
Este artigo explicou como usar a biblioteca de cliente .NET Standard do Azure Cosmos DB para integrar um banco
de dados de documentos do Azure Cosmos DB em um aplicativo xamarin. Forms. Um banco de dados de
documentos do Azure Cosmos DB é um banco de dados NoSQL que fornece acesso de baixa latência para
documentos JSON, oferecendo um serviço de banco de dados rápida, altamente disponível e escalonável para
aplicativos que exigem dimensionamento perfeito e replicação global.
Links relacionados
Todo Azure Cosmos DB (amostra)
Documentação do Azure Cosmos DB
Biblioteca de cliente do Azure Cosmos DB .NET Standard
API do Azure Cosmos DB
Autenticar usuários com um banco de dados de
documentos do Azure Cosmos DB
12/04/2019 • 22 minutes to read
baixar o exemplo
Bancos de dados de documento do Cosmos DB do Azure dão suporte a coleções particionadas, o que podem
abranger vários servidores e partições, e dar suporte a armazenamento ilimitado e taxa de transferência. Este
artigo explica como combinar o controle de acesso com coleções particionadas, para que um usuário só pode
acessar seus próprios documentos em um aplicativo xamarin. Forms.
Visão geral
Uma chave de partição deve ser especificada durante a criação de uma coleção particionada e documentos com a
mesma chave de partição serão armazenados na mesma partição. Portanto, especificando a identidade do usuário
como uma chave de partição resultará em uma coleção particionada que só irá armazenar documentos para que o
usuário. Isso também garante que o banco de dados de documentos do Azure Cosmos DB serão dimensionadas
conforme o número de usuários e aumentam de itens.
Acesso deve ser concedido a qualquer coleção e o modelo de controle de acesso de API do SQL define dois tipos
de construções de acesso:
Chaves mestras habilitam acesso administrativo total a todos os recursos dentro de uma conta do Cosmos DB
e são criadas quando uma conta do Cosmos DB é criada.
Tokens de recurso capturam a relação entre o usuário de um banco de dados e a permissão que o usuário tem
para um recurso específico do Cosmos DB, como uma coleção ou um documento.
Expor uma chave mestra é aberto em uma conta do Cosmos DB para a possibilidade de uso mal-intencionado ou
negligente. No entanto, os tokens de recurso do Azure Cosmos DB fornecem um mecanismo de seguro que
permita aos clientes ler, gravar e excluir recursos específicos em uma conta do Azure Cosmos DB de acordo com
as permissões concedidas.
Uma abordagem típica para solicitar, gerar e fornecer tokens de recurso para um aplicativo móvel é usar um
agente de token de recurso. O diagrama a seguir mostra uma visão geral de como o aplicativo de exemplo usa um
agente de token de recurso para gerenciar o acesso aos dados do banco de dados de documento:
O recurso Agente de token é um serviço de API da Web de camada intermediária, hospedado no serviço de
aplicativo do Azure, que tem a chave mestra da conta do Cosmos DB. O aplicativo de exemplo usa o agente de
token de recurso para gerenciar o acesso aos dados do banco de dados de documento da seguinte maneira:
1. Em logon, o aplicativo xamarin. Forms contata o serviço de aplicativo do Azure para iniciar um fluxo de
autenticação.
2. O serviço de aplicativo do Azure executa um fluxo de autenticação OAuth com o Facebook. Depois que o fluxo
de autenticação for concluída, o aplicativo xamarin. Forms recebe um token de acesso.
3. O aplicativo xamarin. Forms usa o token de acesso para solicitar um token de recurso do recurso Agente de
token.
4. O recurso Agente de token usa o token de acesso para solicitar a identidade do usuário do Facebook. A
identidade do usuário, em seguida, é usada para solicitar um token de recurso do Cosmos DB, que é usado para
conceder acesso de leitura/gravação para coleção particionada do usuário autenticado.
5. O aplicativo xamarin. Forms usa o token de recurso para acessar diretamente recursos do Cosmos DB com as
permissões definidas pelo token de recurso.
NOTE
Quando o token de recurso expira, solicitações de banco de dados de documento subsequente receberá uma exceção 401 de
não autorizado. Neste ponto, os aplicativos xamarin. Forms devem restabelecer a identidade e solicitar um novo token de
recurso.
Para obter mais informações sobre o particionamento do Cosmos DB, consulte como particionar e dimensionar
no Azure Cosmos DB. Para obter mais informações sobre o controle de acesso do Cosmos DB, consulte proteger o
acesso aos dados do Cosmos DB e controle de acesso no API do SQL.
Configuração
O processo para integrar o agente de token de recurso em um aplicativo xamarin. Forms é da seguinte maneira:
1. Crie uma conta do Cosmos DB que usará o controle de acesso. Para obter mais informações, consulte
configuração do BD Cosmos.
2. Crie um serviço de aplicativo do Azure para hospedar o agente de token de recurso. Para obter mais
informações, consulte configuração do serviço de aplicativo do Azure.
3. Crie um aplicativo do Facebook para realizar a autenticação. Para obter mais informações, consulte Facebook
App Configuration.
4. Configure o serviço de aplicativo do Azure para realizar a autenticação fácil com o Facebook. Para obter mais
informações, consulte configuração de autenticação de serviço de aplicativo do Azure.
5. Configure o aplicativo de exemplo do xamarin. Forms para se comunicar com o serviço de aplicativo do Azure e
o Cosmos DB. Para obter mais informações, consulte configuração do aplicativo xamarin. Forms.
Configuração do Azure Cosmos DB
O processo para criar uma conta do Cosmos DB que usará o controle de acesso é da seguinte maneira:
1. Crie uma conta do Cosmos DB. Para obter mais informações, consulte criar uma conta do Azure Cosmos DB.
2. Na conta do Cosmos DB, crie uma nova coleção chamada UserItems , especificando uma chave de partição de
/userid .
3. Publica a solução de agente de token de recurso para o aplicativo de web do serviço de aplicativo do Azure.
Configuração de aplicativo do Facebook
O processo para criar um aplicativo do Facebook para realizar a autenticação é o seguinte:
1. Crie um aplicativo do Facebook. Para obter mais informações, consulte registrar e configurar um aplicativo no
Centro de desenvolvedores do Facebook.
2. Adicione o produto de logon do Facebook para o aplicativo. Para obter mais informações, consulte adicionar o
logon do Facebook ao seu aplicativo ou site no Centro de desenvolvedores do Facebook.
3. Configure o logon do Facebook da seguinte maneira:
Habilite o logon do cliente OAuth.
Habilite o logon do OAuth da Web.
Defina o URI para o URI do aplicativo web do serviço de aplicativo, de redirecionamento OAuth válidos com
/.auth/login/facebook/callback acrescentado.
O serviço de aplicativo também deve ser configurado para se comunicar com o aplicativo do Facebook para
habilitar o fluxo de autenticação. Isso pode ser feito selecionando o provedor de identidade do Facebook e
inserindo os ID do aplicativo e segredo do aplicativo valores das configurações de aplicativo de Facebook no
Centro de desenvolvedores do Facebook. Para obter mais informações, consulte Facebook adicionar informações
ao seu aplicativo.
Configuração do aplicativo xamarin. Forms
O processo para configurar o aplicativo de exemplo do xamarin. Forms é da seguinte maneira:
1. Abra a solução do xamarin. Forms.
2. Abra Constants.cs e atualize os valores das constantes a seguir:
EndpointUri – o valor deve ser a URL da conta do Cosmos DB na folha chaves de conta do Cosmos DB.
DatabaseName – o valor deve ser o nome do banco de dados do documento.
CollectionName – o valor deve ser o nome da coleção de banco de dados de documentos (nesse caso,
UserItems ).
ResourceTokenBrokerUrl – o valor deve ser a URL do aplicativo web de agente de token de recurso da folha de
visão geral da conta de serviço de aplicativo.
Iniciando o logon
O aplicativo de exemplo inicia o processo de logon usando auth para redirecionar um navegador para uma URL
do provedor de identidade, conforme demonstrado no código de exemplo a seguir:
Isso faz com que um fluxo de autenticação OAuth ser iniciada entre o serviço de aplicativo do Azure e o Facebook,
que exibe a página de logon do Facebook:
O logon pode ser cancelado, pressionando a cancele botão no iOS ou pressionando a volta botão no Android,
caso em que o usuário permanece não autenticado e a interface de usuário do provedor de identidade é removido
da tela.
Para obter mais informações sobre AUTH, consulte autenticando usuários com um provedor de identidade.
if (!string.IsNullOrWhiteSpace(resourceToken))
{
client = new DocumentClient(new Uri(Constants.EndpointUri), resourceToken);
...
}
...
}
}
};
NOTE
Um usuário de banco de dados de documento é um recurso associado a um banco de dados de documento, e cada banco
de dados pode conter zero ou mais usuários. Uma permissão de banco de dados de documento é um recurso associado a
um usuário de banco de dados de documento, e cada usuário pode conter zero ou mais permissões. Um recurso de
permissão fornece acesso a um token de segurança que exige que o usuário durante a tentativa de acessar um recurso,
como um documento.
Se o resourcetoken API for concluída com êxito, ele enviará o código de status HTTP 200 (Okey) na resposta,
juntamente com um documento JSON que contém o token de recurso. Os dados JSON a seguir mostram uma
mensagem de resposta bem-sucedida típico:
{
"id": "John Smithpermission",
"token":
"type=resource&ver=1&sig=zx6k2zzxqktzvuzuku4b7y==;a74aukk99qtwk8v5rxfrfz7ay7zzqfkbfkremrwtaapvavw2mrvia4umbi/7
iiwkrrq+buqqrzkaq4pp15y6bki1u//zf7p9x/aefbvqvq3tjjqiffurfx+vexa1xarxkkv9rbua9ypfzr47xpp5vmxuvzbekkwq6txme0xxxb
jhzaxbkvzaji+iru3xqjp05amvq1r1q2k+qrarurhmjzah/ha0evixazkve2xk1zu9u/jpyf1xrwbkxqpzebvqwma+hyyaazemr6qx9uz9be==
;",
"expires": 4035948,
"userid": "John Smith"
}
Recuperar documentos
Recuperar documentos que só pertencem ao usuário autenticado pode ser obtido com a criação de uma consulta
de documento que inclui a id do usuário como uma chave de partição e, em seguida, é demonstrada no exemplo
de código a seguir:
A consulta de forma assíncrona recupera todos os documentos pertencentes ao usuário autenticado, da coleção
especificada e as colocará em um List<TodoItem> coleção para exibição.
O CreateDocumentQuery<T> método Especifica um Uri argumento que representa a coleção que deve ser
consultada para documentos, e um FeedOptions objeto. O FeedOptions objeto Especifica que um número
ilimitado de itens pode ser retornado pela consulta e a id do usuário como uma chave de partição. Isso garante
que apenas os documentos na coleção particionada do usuário são retornados no resultado.
NOTE
Observe que os documentos de permissão, que são criados pelo recurso Agente de token, são armazenados na coleção de
documentos como os documentos criados pelo aplicativo xamarin. Forms. Portanto, a consulta de documento contém um
Where cláusula que aplica um predicado de filtragem à consulta na coleção de documentos. Essa cláusula garante que os
documentos de permissão não são retornados da coleção de documentos.
Para obter mais informações sobre como recuperar os documentos de uma coleção de documentos, consulte
Recuperando documentos da coleção do documento.
Inserir documentos
Antes de inserir um documento em uma coleção de documentos, o TodoItem.UserId propriedade deve ser
atualizada com o valor que está sendo usado como a chave de partição, conforme demonstrado no exemplo de
código a seguir:
item.UserId = UserId;
await client.CreateDocumentAsync(collectionLink, item);
Exclusão de documentos
O valor de chave de partição deve ser especificado quando a exclusão de um documento de uma coleção
particionada, como demonstrado no exemplo de código a seguir:
await client.DeleteDocumentAsync(UriFactory.CreateDocumentUri(Constants.DatabaseName,
Constants.CollectionName, id),
new RequestOptions
{
PartitionKey = new PartitionKey(UserId)
});
Isso garante que o Cosmos DB sabe qual particionados coleção para excluir o documento da.
Para obter mais informações sobre como excluir um documento de uma coleção de documentos, consulte exclusão
de um documento de uma coleção de documentos.
Resumo
Este artigo explicou como combinar o controle de acesso com coleções particionadas, para que um usuário só
pode acessar seus próprios documentos do banco de dados de documento em um aplicativo xamarin. Forms.
Especificando a identidade do usuário como uma chave de partição garante que uma coleção particionada só pode
armazenar documentos para que o usuário.
Links relacionados
Todo o Azure Cosmos DB Auth (amostra)
Consumo de um banco de dados de documento do Azure Cosmos DB
Protegendo o acesso a dados do Azure Cosmos DB
Controle de acesso no API do SQL.
Como particionar e dimensionar no Azure Cosmos DB
Biblioteca de cliente do Azure Cosmos DB
API do Azure Cosmos DB
Adicionando inteligência com os serviços Cognitivos
12/04/2019 • 10 minutes to read
baixar o exemplo
Serviços Cognitivos da Microsoft são um conjunto de APIs, SDKs e serviços disponíveis para desenvolvedores para
tornar seus aplicativos mais inteligentes com a adição de recursos, como reconhecimento facial, reconhecimento
de fala e reconhecimento vocal. Este artigo fornece uma introdução ao aplicativo de exemplo que demonstra
como invocar algumas das APIs de serviços Cognitivos da Microsoft.
Visão geral
O exemplo que acompanha este artigo é um aplicativo de lista de tarefas que fornece funcionalidade para:
Exiba uma lista de tarefas.
Adicionar e editar tarefas por meio do teclado virtual, ou realizando o reconhecimento de fala com a API de fala
da Microsoft. Para obter mais informações sobre como executar o reconhecimento de fala, consulte
reconhecimento de fala usando a API de fala da Microsoft.
Usando a API de verificação de ortografia do Bing de tarefas de verificação de ortografia. Para obter mais
informações, consulte ortográfica usando a API de verificação de ortografia do Bing.
Converter tarefas do inglês para o alemão usando a API de tradução. Para obter mais informações, consulte
tradução de texto usando a API do Translator.
Exclua tarefas.
Defina o status da tarefa para 'concluído'.
Avalie o aplicativo com reconhecimento de emoções, usando a API de detecção facial. Para obter mais
informações, consulte reconhecimento de emoções usando a API de detecção facial.
Tarefas são armazenadas em um banco de dados SQLite local. Para obter mais informações sobre como usar um
banco de dados SQLite local, consulte trabalhando com um banco de dados Local.
O TodoListPage é exibida quando o aplicativo é iniciado. Esta página exibe uma lista de quaisquer tarefas
armazenados no banco de dados local e permite que o usuário para criar uma nova tarefa ou para avaliar o
aplicativo:
Novos itens podem ser criados, clicando na + botão, que navega para o TodoItemPage . Esta página também pode
ser navegada, selecionando uma tarefa:
O TodoItemPage permite que as tarefas a serem criados, editados, uma verificação ortográfica, traduzida, salva e
excluída. Reconhecimento de fala pode ser usado para criar ou editar uma tarefa. Isso é obtido pressionando o
botão de microfone para iniciar a gravação e pressionando o botão mesmo uma segunda vez para parar a
gravação, que envia a gravação para a API de reconhecimento de fala do Bing.
Clicar no botão smilies na TodoListPage navega para o RateAppPage , que é usado para realizar o reconhecimento
de emoções em uma imagem de uma expressão facial:
O RateAppPage permite que o usuário tirar uma foto do seu face, que é enviado à API de detecção facial com a
detecção de emoções retornada que está sendo exibida.
PASTA FINALIDADE
ARQUIVO FINALIDADE
Pacotes NuGet
O aplicativo de exemplo usa os seguintes pacotes NuGet:
Newtonsoft.Json – Fornece uma estrutura JSON para .NET.
PCLStorage – Fornece um conjunto de arquivos local de plataforma cruzada APIs de e/s.
sqlite-net-pcl – Fornece armazenamento de banco de dados SQLite.
Xam.Plugin.Media – Fornece levando de foto de plataforma cruzada e APIs de separação.
Além disso, esses pacotes do NuGet também instalam suas próprias dependências.
Modelagem de dados
O aplicativo de exemplo usa o TodoItem classe para modelar os dados que são exibidos e armazenados no banco
de dados SQLite local. O exemplo de código a seguir mostra a classe TodoItem :
O ID propriedade é usada para identificar exclusivamente cada TodoItem da instância e é decorado com atributos
de SQLite que tornam a propriedade de uma chave primária de incremento automático no banco de dados.
Chamando as operações de banco de dados
O TodoItemRepository classe implementa as operações de banco de dados e uma instância da classe pode ser
acessada por meio de App.TodoManager propriedade. O TodoItemRepository classe fornece os seguintes métodos
para chamar operações de banco de dados:
GetAllItemsAsync – recupera todos os itens do banco de dados SQLite local.
GetItemAsync – recupera um item especificado do banco de dados SQLite local.
SaveItemAsync – cria ou atualiza um item no banco de dados SQLite local.
DeleteItemAsync – exclui o item especificado do banco de dados SQLite local.
Implementações de projeto de plataforma
O Services pasta no projeto PCL contém o IFileHelper e IAudioRecorderService interfaces que são usadas pelo
DependencyService classe para localizar as classes que implementam as interfaces em projetos de plataforma.
O IFileHelper interface é implementada pelo FileHelper classe em cada projeto da plataforma. Essa classe
consiste em um único método, GetLocalFilePath , que retorna um caminho de arquivo local para armazenar o
banco de dados SQLite.
O IAudioRecorderService interface é implementada pelo AudioRecorderService classe em cada projeto da
plataforma. Essa classe consiste StartRecording , StopRecording e que dão suporte a métodos, que usam as APIs
da plataforma para gravar áudio do microfone do dispositivo e armazená-lo como um arquivo wav. No iOS, o
AudioRecorderService usa o AVFoundation API gravar áudio. No Android, o AudioRecordService usa o AudioRecord
API gravar áudio. Na Universal Windows Platform (UWP ), o AudioRecorderService usa o AudioGraph API gravar
áudio.
Invocando serviços Cognitivos
O aplicativo de exemplo invoca os seguintes serviços Cognitivos da Microsoft:
API de fala do Microsoft. Para obter mais informações, consulte reconhecimento de fala usando a API de fala da
Microsoft.
API de verificação de ortografia de Bing. Para obter mais informações, consulte ortográfica usando a API de
verificação de ortografia do Bing.
Converter API. Para obter mais informações, consulte tradução de texto usando a API do Translator.
API de detecção facial. Para obter mais informações, consulte reconhecimento de emoções usando a API de
detecção facial.
Links relacionados
Documentação dos serviços Cognitivos da Microsoft
Serviços Cognitivos de tarefas pendentes (amostra)
Reconhecimento de fala usando a API de fala da
Microsoft
12/04/2019 • 8 minutes to read
baixar o exemplo
A API de fala da Microsoft é uma API baseada em nuvem que fornece algoritmos para processar a linguagem
falada. Este artigo explica como usar a API de REST de reconhecimento de fala Microsoft para converter áudio
em texto em um aplicativo xamarin. Forms.
Visão geral
A API de fala da Microsoft tem dois componentes:
Um reconhecimento de fala API para a conversão de palavras faladas em texto. Reconhecimento de fala pode
ser executado por meio de uma API REST, a biblioteca de cliente ou a biblioteca de serviço.
Um texto em fala API para converter texto em palavras faladas. Conversão de texto em fala é realizada por
meio da API REST.
Este artigo se concentra em fazer o reconhecimento de fala por meio da API REST. Embora as bibliotecas de
cliente e serviço de suporte ao retorno de resultados parciais, a API REST só pode retornar um resultado de
reconhecimento única, sem quaisquer resultados parciais.
Uma chave de API deve ser obtida para usar a API de fala da Microsoft. Isso pode ser obtido do Azure portal.
Para obter mais informações, consulte criar uma conta de serviços Cognitivos no portal do Azure.
Para obter mais informações sobre a API de fala da Microsoft, consulte documentação de API de fala do
Microsoft.
Autenticação
Todas as solicitações feitas para a API de REST de fala da Microsoft exigem um token de acesso do JSON Web
Token (JWT), que pode ser obtido do serviço de token dos serviços cognitivos
https://api.cognitive.microsoft.com/sts/v1.0/issueToken . Um token pode ser obtido, fazendo uma solicitação
POST para o serviço de token, especificando um Ocp-Apim-Subscription-Key cabeçalho que contém a chave de
API como seu valor.
O exemplo de código a seguir mostra como solicitar um acesso de token do serviço de token:
public AuthenticationService(string apiKey)
{
subscriptionKey = apiKey;
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", apiKey);
}
...
async Task<string> FetchTokenAsync(string fetchUri)
{
UriBuilder uriBuilder = new UriBuilder(fetchUri);
uriBuilder.Path += "/issueToken";
var result = await httpClient.PostAsync(uriBuilder.Uri.AbsoluteUri, null);
return await result.Content.ReadAsStringAsync();
}
O token de acesso retornado, o que é um texto Base64, tem uma hora de expiração de 10 minutos. Portanto, o
aplicativo de exemplo renova o token de acesso a cada 9 minutos.
O token de acesso deve ser especificado em cada API de REST de fala da Microsoft chamada como um
Authorization cabeçalho prefixado com a cadeia de caracteres Bearer , conforme mostrado no exemplo de
código a seguir:
Falha ao passar um token de acesso válido para a API de REST de fala da Microsoft resultará em um erro de 403
resposta.
fileStream.Dispose();
return speechResult;
}
Áudio é gravado em cada projeto específico da plataforma, como dados de wav do PCM e o
RecognizeSpeechAsync usa o PCLStorage pacote do NuGet para abrir o arquivo como um fluxo de áudio. A
solicitação de reconhecimento de fala URI é gerado e um token de acesso é recuperado do serviço de token. A
solicitação de reconhecimento de fala é postada para o recognition API, que retorna uma resposta JSON que
contém o resultado. A resposta JSON é desserializada, com o resultado retornado para o método de chamada
para exibição.
Configurando o reconhecimento de fala
O processo de reconhecimento de fala pode ser configurado especificando parâmetros de consulta HTTP:
A principal configuração executada pelo GenerateRequestUri método é definir a localidade do conteúdo de áudio.
Para obter uma lista de localidades com suporte, consulte idiomas com suporte .
Enviar a solicitação
O SendRequestAsync método faz a solicitação POST para a API de REST de fala da Microsoft e retorna a resposta:
async Task<string> SendRequestAsync(Stream fileStream, string url, string bearerToken, string contentType)
{
if (httpClient == null)
{
httpClient = new HttpClient();
}
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
A solicitação POST é enviada para recognition API. A resposta é, em seguida, ler e retornada para o método de
chamada.
O recognition API enviará o código de status HTTP 200 (Okey) em resposta, fornecida que a solicitação é válida,
que indica que a solicitação foi bem-sucedida e que as informações solicitadas estão na resposta. Para obter uma
lista de possíveis respostas de erro, consulte solução de problemas.
Processar a resposta
A resposta da API é retornada no formato JSON, com o texto reconhecido sendo contido no name marca. Os
dados JSON a seguir mostram uma mensagem de resposta bem-sucedida típico:
{
"RecognitionStatus":"Success",
"DisplayText":"Go shopping tomorrow.",
"Offset":16000000,
"Duration":17100000
}
Resumo
Este artigo explicou como usar a API de REST de fala da Microsoft para converter áudio em texto em um
aplicativo xamarin. Forms. Além de realizar o reconhecimento de fala, API de fala da Microsoft também pode
converter o texto em palavras faladas.
Links relacionados
Documentação da API de fala da Microsoft.
Consumir um serviço Web RESTful
Serviços Cognitivos de tarefas pendentes (amostra)
Verificação ortográfica usando a API de verificação
ortográfica do Bing
12/04/2019 • 9 minutes to read
baixar o exemplo
Verificação ortográfica do Bing executa ortográfica contextual para texto, fornecendo sugestões embutido para
palavras incorretas. Este artigo explica como usar a API de REST de verificação ortográfica de Bing para corrigir
erros de ortografia em um aplicativo xamarin. Forms.
Visão geral
A API de REST de verificação ortográfica de Bing tem dois modos de operação e um modo deve ser especificado
ao fazer uma solicitação para a API:
Spell corrige o texto curto (palavras até 9) sem quaisquer alterações de maiusculas e minúsculas.
Proof corrige o texto longo, fornece correções de maiusculas e minúsculas e pontuação básica e suprime
correções agressivas.
Uma chave de API deve ser obtida para usar a API de verificação de ortografia do Bing. Isso pode ser obtido no
Experimente os serviços Cognitivos
Para obter uma lista dos idiomas com suporte a API de verificação de ortografia do Bing, consulte idiomas com
suporte. Para obter mais informações sobre a API de verificação de ortografia do Bing, consulte documentação de
verificação ortográfica de Bing.
Autenticação
Todas as solicitações feitas para a API de verificação de ortografia do Bing requer uma chave de API que deve ser
especificada como o valor da Ocp-Apim-Subscription-Key cabeçalho. O exemplo de código a seguir mostra como
adicionar a chave de API para o Ocp-Apim-Subscription-Key cabeçalho de uma solicitação:
public BingSpellCheckService()
{
httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", Constants.BingSpellCheckApiKey);
}
Falha ao passar uma chave de API válida para a API de verificação de ortografia do Bing resultará em um erro de
401 resposta.
O SpellCheckTextAsync método gera um URI de solicitação e, em seguida, envia a solicitação para o SpellCheck
API, que retorna uma resposta JSON que contém o resultado. A resposta JSON é desserializada, com o resultado
retornado para o método de chamada para exibição.
Configurar a verificação ortográfica
O processo de verificação ortográfica pode ser configurado especificando parâmetros de consulta HTTP:
Esse método define o texto a ser ortografia verificada e o modo de verificação ortográfica.
Para obter mais informações sobre a API de REST de verificação ortográfica de Bing, consulte referência do API
de verificação ortográfica v7.
Enviar a solicitação
O SendRequestAsync método faz a solicitação GET para a API de REST de verificação ortográfica de Bing e retorna
a resposta:
Esse método envia a solicitação GET para o SpellCheck API, com a URL da solicitação especifica o texto a ser
traduzido e o modo de verificação ortográfica. A resposta é, em seguida, ler e retornada para o método de
chamada.
O SpellCheck API enviará o código de status HTTP 200 (Okey) em resposta, fornecida que a solicitação é válida,
que indica que a solicitação foi bem-sucedida e que as informações solicitadas estão na resposta. Para obter uma
lista de objetos de resposta, consulte os objetos de resposta.
Processar a resposta
A resposta da API é retornada em formato JSON. Os dados JSON a seguir mostram a mensagem de resposta
para o texto digitado incorretamente Go shappin tommorow :
{
"_type":"SpellCheck",
"flaggedTokens":[
{
"offset":3,
"token":"shappin",
"type":"UnknownToken",
"suggestions":[
{
"suggestion":"shopping",
"score":1
}
]
},
{
"offset":11,
"token":"tommorow",
"type":"UnknownToken",
"suggestions":[
{
"suggestion":"tomorrow",
"score":1
}
]
}
],
"correctionType":"High"
}
O flaggedTokens matriz contém uma matriz de palavras no texto que foram marcados como não sendo escrito
corretamente ou são gramaticalmente incorreto. A matriz será vazia se nenhum ortografia ou erros gramaticais
forem encontrados. As marcas dentro da matriz são:
offset – um deslocamento de base zero desde o início da cadeia de caracteres de texto para a palavra que foi
marcado.
token – a palavra na cadeia de texto que não está escrita corretamente ou está gramaticalmente incorreto.
type – o tipo de erro que causou a palavra a ser sinalizado. Há dois valores possíveis – RepeatedToken e
UnknownToken .
suggestions – uma matriz de palavras que corrigirá o erro de ortografia ou gramática. A matriz é composta de
um suggestion e um score , que indica o nível de confiança de que a correção sugerida é correta.
Esse código itera por meio de FlaggedTokens coleta e substitui qualquer incorretas ou gramaticalmente incorretas
palavras no texto de origem com a primeira sugestão. As capturas de tela a seguir mostram antes e após a
verificação ortográfica:
NOTE
O exemplo acima usa Replace para manter a simplicidade, mas em uma grande quantidade de texto ele poderia substituir
o token errado. A API fornece a offset valor que deve ser usado em aplicativos de produção para identificar o local
correto no texto de origem para executar uma atualização.
Resumo
Este artigo explicou como usar a API de REST de verificação ortográfica de Bing para corrigir erros de ortografia
em um aplicativo xamarin. Forms. Verificação ortográfica do Bing executa ortográfica contextual para texto,
fornecendo sugestões embutido para palavras incorretas.
Links relacionados
Documentação de verificação ortográfica do Bing
Consumir um serviço Web RESTful
Serviços Cognitivos de tarefas pendentes (amostra)
Referência do API de verificação ortográfica do Bing v7
Tradução de texto usando a API do Translator
12/04/2019 • 8 minutes to read
baixar o exemplo
API do Microsoft Translator pode ser usado para converter fala e texto por meio de uma API REST. Este artigo
explica como usar a API de texto do Microsoft Translator para traduzir o texto de um idioma para outro em um
aplicativo xamarin. Forms.
Visão geral
A API de tradução tem dois componentes:
Uma tradução de texto da API REST para traduzir o texto de um idioma para o texto de outro idioma. A API
automaticamente detecta o idioma do texto que foi enviado antes de converter.
Uma tradução de fala a API REST para transcrição de fala de um idioma no texto de outro idioma. A API
também integra os recursos de texto em fala para falar o texto traduzido novamente.
Este artigo se concentra na tradução de texto de um idioma para outro usando a API de tradução de texto.
Uma chave de API deve ser obtida para usar a API de tradução de texto. Isso pode ser obtido no como se
inscrever para a API do Microsoft Translator texto.
Para obter mais informações sobre a API de texto do Microsoft Translator, consulte documentação da API do
Translator texto.
Autenticação
Todas as solicitações feitas para a API de tradução de texto requer um token de acesso do JSON Web Token
(JWT), que pode ser obtido do serviço de token dos serviços cognitivos
https://api.cognitive.microsoft.com/sts/v1.0/issueToken . Um token pode ser obtido, fazendo uma solicitação
POST para o serviço de token, especificando um Ocp-Apim-Subscription-Key cabeçalho que contém a chave de
API como seu valor.
O exemplo de código a seguir mostra como solicitar um acesso de token do serviço de token:
O token de acesso retornado, o que é um texto Base64, tem uma hora de expiração de 10 minutos. Portanto, o
aplicativo de exemplo renova o token de acesso a cada 9 minutos.
O token de acesso deve ser especificado em cada API de tradução de texto chamada como um Authorization
cabeçalho prefixado com a cadeia de caracteres Bearer , conforme mostrado no exemplo de código a seguir:
Para obter mais informações sobre o serviço de token de serviços cognitivos, consulte API de Token de
autenticação.
O TranslateTextAsync método gera um URI de solicitação e recupera um token de acesso ao serviço de token. A
solicitação de tradução de texto é enviada para o translate API, que retorna uma resposta em XML que contém
o resultado. A resposta XML é analisada, e o resultado da conversão é retornado para o método de chamada para
exibição.
Para obter mais informações sobre as APIs de REST de tradução de texto, consulte API do Microsoft Translator
texto.
Configurando a tradução de texto
O processo de tradução de texto pode ser configurado especificando parâmetros de consulta HTTP:
Esse método define o texto a ser convertido e o idioma para traduzir o texto a ser. Para obter uma lista dos
idiomas com suporte pelo Microsoft Translator, consulte idiomas com suporte na API do Microsoft Translator
texto.
NOTE
Se um aplicativo precisa saber qual idioma o texto é, o Detect API pode ser chamada para detectar o idioma da cadeia de
caracteres de texto.
Enviar a solicitação
O SendRequestAsync método faz a solicitação GET para a API de REST de tradução de texto e retorna a resposta:
async Task<string> SendRequestAsync(string url, string bearerToken)
{
if (httpClient == null)
{
httpClient = new HttpClient();
}
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", bearerToken);
Esse método cria a solicitação GET, adicionando o token de acesso para o Authorization cabeçalho, prefixado
com a cadeia de caracteres Bearer . A solicitação GET é enviada para o translate API, com a URL da solicitação
especifica o texto a ser traduzido e o idioma para traduzir o texto a ser. A resposta é, em seguida, ler e retornada
para o método de chamada.
O translate API enviará o código de status HTTP 200 (Okey) em resposta, fornecida que a solicitação é válida,
que indica que a solicitação foi bem-sucedida e que as informações solicitadas estão na resposta. Para obter uma
lista de possíveis respostas de erro, consulte as mensagens de resposta em obter traduzir.
Processar a resposta
A resposta da API é retornada em formato XML. Os dados XML a seguir mostram uma mensagem de resposta
bem-sucedida típico:
No aplicativo de exemplo, a resposta XML é analisada em um XDocument instância, com o valor de raiz XML que
está sendo retornado para o método de chamada para exibição, conforme mostrado nas capturas de tela seguir:
Resumo
Este artigo explicou como usar a API de texto do Microsoft Translator para traduzir o texto de um idioma para o
texto de outro idioma em um aplicativo xamarin. Forms. Além de traduzir o texto, API do Microsoft Translator
pode transcrever também fala de um idioma no texto de outro idioma.
Links relacionados
Documentação de API de texto do tradutor.
Consumir um serviço Web RESTful
Serviços Cognitivos de tarefas pendentes (amostra)
API de texto do Microsoft Translator.
Reconhecimento de emoções usando a API de
detecção facial
12/04/2019 • 10 minutes to read
baixar o exemplo
API de detecção facial usa uma expressão facial em uma imagem como uma entrada e retorna dados que
incluem os níveis de confiança entre um conjunto de emoções para cada face na imagem. Este artigo explica
como usar a API de detecção facial para reconhecer emoções, a taxa de um aplicativo xamarin. Forms.
Visão geral
API de detecção facial pode executar a detecção de emoções para detectar raiva, desdém, aversão, medo,
felicidade, indiferença, tristeza e surpresa, em uma expressão facial. Essas emoções são universalmente e entre
culturas comunicadas por meio das mesmas expressões faciais básicas. Bem como retornar um resultado de
emoções para uma expressão facial, API de detecção facial pode também retorna uma caixa delimitadora para
faces detectadas. Observe que uma chave de API deve ser obtida para usar a API de detecção facial. Isso pode ser
obtido no Experimente os serviços Cognitivos.
Reconhecimento de emoções pode ser executado por meio de uma biblioteca de cliente e por meio da API REST.
Este artigo se concentra em fazer o reconhecimento de emoção por meio da API REST. Para obter mais
informações sobre a API REST, consulte API REST de detecção facial.
API de detecção facial também pode ser usada para reconhecer as expressões faciais das pessoas em vídeo e
pode retornar um resumo de suas emoções. Para obter mais informações, consulte como analisar vídeos em
tempo real.
Para obter mais informações sobre a API de detecção facial, consulte API de detecção facial.
Autenticação
Todas as solicitações feitas para a API de detecção facial requer uma chave de API que deve ser especificada como
o valor da Ocp-Apim-Subscription-Key cabeçalho. O exemplo de código a seguir mostra como adicionar a chave de
API para o Ocp-Apim-Subscription-Key cabeçalho de uma solicitação:
public FaceRecognitionService()
{
_client = new HttpClient();
_client.DefaultRequestHeaders.Add("ocp-apim-subscription-key", Constants.FaceApiKey);
}
Falha ao passar uma chave de API válida para a API de detecção facial resultará em um erro de 401 resposta.
NOTE
Formatos de arquivo de imagem com suporte são PNG, JPEG, GIF e BMP, e o tamanho de arquivo permitido é de 1KB a
4MB.
Esta chamada de método Especifica o fluxo que contém os dados da imagem, que devem ser retornadas faceIds,
que não devem ser retornados marcos faciais e que a emoção da imagem deve ser analisada. Ela também
especifica que os resultados serão retornados como uma matriz de Face objetos. Por sua vez, o DetectAsync
método invoca o detect API REST que executa o reconhecimento de emoções:
Esse método gera um URI de solicitação e, em seguida, envia a solicitação para o detect API por meio de
SendRequestAsync método.
NOTE
Você deve usar a mesma região em suas chamadas de API de detecção facial que você usou para obter as chaves de
assinatura. Por exemplo, se você adquiriu suas chaves de assinatura do westus região, o ponto de extremidade de
detecção de face será https://westus.api.cognitive.microsoft.com/face/v1.0/detect .
Enviar a solicitação
O SendRequestAsync método faz a solicitação POST para a API de detecção facial e retorna o resultado como um
Face matriz:
async Task<TResponse> SendRequestAsync<TRequest, TResponse>(HttpMethod httpMethod, string requestUrl, TRequest
requestBody)
{
var request = new HttpRequestMessage(httpMethod, Constants.FaceEndpoint);
request.RequestUri = new Uri(requestUrl);
if (requestBody != null)
{
if (requestBody is Stream)
{
request.Content = new StreamContent(requestBody as Stream);
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
}
else
{
// If the image is supplied via a URL
request.Content = new StringContent(JsonConvert.SerializeObject(requestBody, s_settings), Encoding.UTF8,
"application/json");
}
}
Se a imagem é fornecida por meio de um fluxo, o método compila a solicitação de POSTAGEM envolvendo o
fluxo de imagem em um StreamContent instância, que fornece conteúdo HTTP com base em um fluxo. Como
alternativa, se a imagem é fornecida por meio de uma URL, o método se baseia a solicitação de POSTAGEM
envolvendo a URL em um StringContent instância, que fornece conteúdo HTTP com base em uma cadeia de
caracteres.
A solicitação POST é enviada para detect API. A resposta é ler, desserializada e retornada para o método de
chamada.
O detect API enviará o código de status HTTP 200 (Okey) em resposta, fornecida que a solicitação é válida, que
indica que a solicitação foi bem-sucedida e que as informações solicitadas estão na resposta. Para obter uma lista
de possíveis respostas de erro, consulte API REST de detecção facial.
Processar a resposta
A resposta da API é retornada em formato JSON. Os dados JSON a seguir mostram uma mensagem de resposta
bem-sucedida típico que fornece os dados solicitados pelo aplicativo de exemplo:
[
{
"faceId":"8a1a80fe-1027-48cf-a7f0-e61c0f005051",
"faceRectangle":{
"top":192,
"left":164,
"width":339,
"height":339
},
"faceAttributes":{
"emotion":{
"anger":0.0,
"contempt":0.0,
"disgust":0.0,
"fear":0.0,
"happiness":1.0,
"neutral":0.0,
"sadness":0.0,
"surprise":0.0
}
}
}
]
Uma mensagem de resposta bem-sucedida consiste em uma matriz de entradas de face, classificados pelo
tamanho do retângulo facial em ordem decrescente, enquanto uma resposta vazia não indica que nenhuma face
detectada. Cada reconhecido face inclui uma série de atributos de face opcional, que são especificados pelo
returnFaceAttributes argumento para o DetectAsync método.
No aplicativo de exemplo, a resposta JSON é desserializada em uma matriz de Face objetos. Ao interpretar os
resultados da API de detecção facial, a emoção detectada deve ser interpretada como a emoção com a pontuação
mais alta, como as pontuações são normalizadas para soma a um. Portanto, o aplicativo de exemplo exibe a
emoção reconhecida com a pontuação mais alta para o rosto detectado maior na imagem. Isso é obtido com o
código a seguir:
emotionResultLabel.Text = faces.FirstOrDefault().FaceAttributes.Emotion.ToRankedList().FirstOrDefault().Key;
Links relacionados
API de detecção facial.
Serviços Cognitivos de tarefas pendentes (amostra)
REST API de detecção facial
Teste e implantação do Xamarin.Forms
12/04/2019 • 2 minutes to read • Edit Online
Desempenho
Há muitas técnicas para aumentar o desempenho de aplicativos Xamarin.Forms. Coletivamente, essas técnicas
podem reduzir de forma considerável a quantidade de trabalho que está sendo executado por uma CPU e a
quantidade de memória consumida por um aplicativo.
Este documento fornece uma visão geral das técnicas de distribuição disponíveis para aplicativos Xamarin.iOS e
funciona como um ponteiro para documentos mais detalhados sobre o tópico.
Depois que um aplicativo Xamarin.iOS for desenvolvido, a próxima etapa no ciclo de vida de desenvolvimento do
software é distribuir o aplicativo para os usuários, conforme mostrado na seção destacada do diagrama abaixo:
Apple fornece as seguintes maneiras de distribuir um aplicativo iOS, que tem suporte com Xamarin.iOS:
1. App Store
2. Interno (Enterprise)
3. Ad Hoc
Todos esses cenários exigem que os aplicativos sejam provisionados usando o perfil de provisionamento
apropriado. Perfis de provisionamento são arquivos que contêm informações de assinatura de código, bem como a
identidade do aplicativo e o mecanismo de distribuição desejado. Para a distribuição fora da App Store, também há
informações sobre em quais dispositivos o aplicativo pode ser implantado.
Essa é a maneira principal que aplicativos iOS são distribuídos para consumidores em dispositivos iOS. Todos os
aplicativos enviados à App Store exigem aprovação da Apple.
Os aplicativos são enviados à App Store por meio de um portal chamado iTunes Connect. O guia Configurar seu
Aplicativo no iTunes Connect fornece mais informações sobre como configurar e usar este portal para preparar
um aplicativo Xamarin.iOS para publicação na App Store.
É importante observar que somente os desenvolvedores que pertencem ao Programa de Desenvolvedores da
Apple têm acesso ao iTunes Connect. Membros do Programa de Desenvolvedores Corporativos da Apple
não tem acesso.
Para obter mais informações, acesse o guia de Distribuição da App Store.
Distribuição Interna
Às vezes chamada de Distribuição Corporativa, a distribuição interna permite que membros do Programa de
Desenvolvedores Corporativos da Apple distribuam aplicativos internamente para outros membros da mesma
organização. A distribuição interna tem as vantagens de não exigir uma análise da App Store e não ter nenhum
limite de número de dispositivos nos quais um aplicativo pode ser instalado. No entanto, é importante observar
que membros do Programa de Desenvolvedor Corporativo da Apple não têm acesso ao iTunes Connect e,
portanto, o licenciado é responsável por distribuir o aplicativo.
Para obter mais informações sobre como configurar e distribuir um aplicativo internamente, consulte o guia de
Distribuição Interna.
Distribuição Ad Hoc
Aplicativos Xamarin.iOS podem ser testados pelo usuário por meio da distribuição ad-hoc, que está disponível no
Programa de Desenvolvedores da Apple e pelo Programa de Desenvolvedor Corporativo da Apple,
permitindo que até 100 dispositivos iOS sejam testados. O melhor caso de uso para a distribuição ad hoc é
distribuição dentro de uma empresa quando iTunes Connect não for uma opção.
Para obter mais informações sobre como configurar e distribuir um aplicativo internamente, consulte o Guia de
Distribuição Ad Hoc.
Resumo
Este artigo forneceu uma breve visão geral dos mecanismos de distribuição que estão disponíveis para aplicativos
Xamarin.iOS. Ele introduziu a iTunes App Store, implantação Ad Hoc e Interna, além de ter fornecido links para
obter informações mais detalhadas.
Links relacionados
Distribuição da App Store
Como configurar um aplicativo no iTunes Connect
Publicando na App Store
Distribuição interna
Distribuição Ad Hoc
O arquivo iTunesMetadata.plist
Suporte a IPA
Solução de problemas
Publicando um aplicativo
12/04/2019 • 6 minutes to read • Edit Online
Quando um bom aplicativo é criado, as pessoas querem usá-lo. Esta seção aborda as etapas envolvidas com a
distribuição pública de um aplicativo criado com o Xamarin.Android por meio de canais, como email, um servidor
Web particular, Google Play ou a Amazon App Store para Android.
Visão geral
A etapa final no desenvolvimento de um aplicativo Xamarin.Android é publicar o aplicativo. A publicação é o
processo de compilação de um aplicativo Xamarin.Android para que ele esteja pronto para que os usuários
instalem em seus dispositivos e envolve duas tarefas essenciais:
Preparação para publicação – Uma versão de lançamento do aplicativo é criada que pode ser implantada
em dispositivos Android (consulte Preparar um Aplicativo para a Lançamento para obter mais informações
sobre a preparação do lançamento).
Distribuição – A versão de um aplicativo é disponibilizada por meio de um ou mais dos vários canais de
distribuição.
O diagrama a seguir ilustra as etapas envolvidas na publicação de um aplicativo Xamarin.Android:
Como pode ser visto no diagrama acima, a preparação é a mesma, independentemente do método de distribuição
usado. Há várias maneiras que um aplicativo Android pode ser liberado para usuários:
Por meio de um site – Um aplicativo Xamarin.Android pode ser disponibilidade para download em um site,
do qual os usuários podem, em seguida, instalar o aplicativo ao clicar em um link.
Por email – É possível que os usuários instalem um aplicativo Xamarin.Android pelo email. O aplicativo será
instalado quando o anexo for aberto com um dispositivo Android.
Por meio de um mercado – Há vários mercados de aplicativos que existem para distribuição, como Google
Play ou Amazon App Store for Android.
Usar um marketplace estabelecido é a maneira mais comum para publicar um aplicativo, pois ele fornece um
alcance mais amplo do mercado e maior controle sobre a distribuição. No entanto, a publicação de um aplicativo
por meio de um marketplace requer esforço adicional.
Vários canais podem distribuir um aplicativo Xamarin.Android simultaneamente. Por exemplo, um aplicativo pode
ser publicado no Google Play, Amazon App Store para o Android e também ser baixado de um servidor Web.
Os outros dois métodos de distribuição (download ou email) são mais úteis para um subconjunto controlado de
usuários, como um ambiente corporativo ou um aplicativo destina-se apenas um conjunto bem específico ou
pequeno de usuários. Distribuição de email e de servidor também são modelos mais simples de publicação,
exigindo menos preparativos para publicar um aplicativo.
O Programa de Distribuição de Aplicativos Móveis da Amazon permite que desenvolvedores de aplicativos
móveis distribuam e vendam seus aplicativos no Amazon. Os usuários podem descobrir e comprar aplicativos em
seus dispositivos com Android ao usar o aplicativo Amazon App Store. Uma captura de tela do Amazon App Store
em execução em um dispositivo Android aparece abaixo:
O Google Play é indiscutivelmente o marketplace mais abrangente e popular para aplicativos Android. O Google
Play permite aos usuários descobrir, baixar, classificar e comprar aplicativos ao clicar em um único ícone no
dispositivo ou no computador. O Google Play também fornece ferramentas para auxiliar na análise de vendas e
tendências do mercado e para controlar quais dispositivos e usuários podem baixar um aplicativo. Uma captura de
tela do Google Play em execução em um dispositivo Android aparece abaixo:
Esta seção mostrou como carregar o aplicativo em lojas como o Google Play, junto com o material promocional
apropriado. Arquivos de expansão APK foram explicados, fornecendo uma visão geral conceitual sobre o que são e
como funcionam. Os serviços de licenciamento do Google também foram descritos. Finalmente, meios
alternativos de distribuição foram apresentados, incluindo o uso de um servidor Web HTTP, distribuição de email
simples e a Amazon App Store para Android.
Links relacionados
HelloWorldPublishing (amostra)
Processo de Compilação
Vinculação
Obter uma chave de API do Google Maps
Assinatura de aplicativos
Como publicar no Google Play
Licenciamento de aplicativos do Google
Android.Play.ExpansionLibrary
Portal de Distribuição de Aplicativo Móvel
Perguntas Frequentes da Distribuição de Aplicativo Móvel da Amazon
Publicando aplicativos Xamarin.Mac na Mac App
Store
12/04/2019 • 3 minutes to read • Edit Online
Visão geral
Os aplicativos Xamarin.Mac podem ser distribuídos de duas maneiras diferentes:
ID de Desenvolvedor – Os aplicativos assinados com uma de ID de Desenvolvedor podem ser distribuídos
fora da App Store, mas são reconhecidos pelo GateKeeper e têm instalação permitida.
Mac App Store – Os aplicativos devem ter um pacote de instalação e o aplicativo e o instalador devem ser
assinados, para o envio para a Mac App Store.
Este documento explica como usar o Visual Studio para Mac e o Xcode para configurar uma conta de
Desenvolvedor da Apple e configurar um projeto Xamarin.Mac para cada tipo de implantação.
NOTE
As escolhas feitas aqui afetarão a forma como algumas telas aparecem ao configurar uma conta de desenvolvedor. As
descrições e capturas de tela neste documento são feitas da perspectiva de uma conta de desenvolvedor de Pessoa Física.
Em uma Empresa, algumas opções só estarão disponíveis para usuários Administradores de Equipe.
Certificados e Identificadores
Esse guia o orienta durante a criação dos Certificados e Identificadores que serão necessários para publicar um
aplicativo Xamarin.Mac.
Criar Perfil de Provisionamento
Esse guia o orienta na criação dos Perfis de Provisionamento que serão necessários para publicar um aplicativo
Xamarin.Mac.
Configuração do aplicativo Mac
Este guia explica como configurar um aplicativo Xamarin.Mac para publicação.
Entrar com a ID de desenvolvedor
Este guia explica como assinar um aplicativo Xamarin.Mac com a ID de Desenvolvedor para publicação.
Pacote para Mac App Store
Este guia ensina como agrupar um aplicativo Xamarin.Mac para publicação na Mac App Store.
Carregar na Mac App Store
Este guia ensina como fazer upload de aplicativos Xamarin.Mac para publicação na Mac App Store.
Links relacionados
Instalação
Amostra do Hello, Mac
ID de Desenvolvedor e GateKeeper
Desempenho do Xamarin.Forms
12/04/2019 • 19 minutes to read • Edit Online
Há muitas técnicas para aumentar o desempenho de aplicativos Xamarin.Forms. Coletivamente, essas técnicas
podem reduzir de forma considerável a quantidade de trabalho que está sendo executado por uma CPU e a
quantidade de memória consumida por um aplicativo. Esse artigo descreve e aborda essas técnicas.
Visão geral
O baixo desempenho de aplicativo se apresenta de várias maneiras. Ele pode fazer com que o aplicativo pareça
não responder, deixar a rolagem lenta ou reduzir a vida útil da bateria. No entanto, a otimização do desempenho
engloba mais do que apenas a implementação de um código eficiente. A experiência do usuário quanto ao
desempenho do aplicativo também deve ser considerada. Por exemplo, garantir que as operações sejam
executadas sem impedir o usuário de realizar outras atividades pode ajudar a melhorar a experiência do usuário.
Há várias técnicas para aumentar o desempenho, bem como o desempenho percebido, de um aplicativo
Xamarin.Forms. Entre elas estão:
Habilitar o compilador de XAML
Escolher o layout correto
Habilitar a Compactação de Layout
Usar os Renderizadores Rápidos
Reduzir associações desnecessárias
Otimizar o desempenho do layout
Otimizar o desempenho da ListView
Otimizar os recursos de imagem
Reduzir o tamanho da árvore visual
Reduzir o tamanho do dicionário de recursos do aplicativo
Uso do padrão de renderizador personalizado
NOTE
Antes de ler esse artigo, você deve primeiro ler Desempenho de plataforma cruzada, que discute técnicas que não são
específicas a uma plataforma para melhorar o uso de memória e o desempenho de aplicativos criados usando a plataforma
Xamarin.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DisplayImage.HomePage">
<ContentPage.Content>
<StackLayout>
<Image Source="waterfront.jpg" />
</StackLayout>
</ContentPage.Content>
</ContentPage>
Isso é um desperdício e o elemento StackLayout deve ser removido, conforme mostrado no exemplo de código a
seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DisplayImage.HomePage">
<ContentPage.Content>
<Image Source="waterfront.jpg" />
</ContentPage.Content>
</ContentPage>
Além disso, não tente reproduzir a aparência de um layout específico usando combinações de outros layouts, pois
isso resulta na execução de cálculos de layout desnecessários. Por exemplo, não tente reproduzir um layout Grid
usando uma combinação de instâncias StackLayout . O código a seguir mostra um exemplo dessa má prática:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Details.HomePage"
Padding="0,20,0,0">
<ContentPage.Content>
<StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Name:" />
<Entry Placeholder="Enter your name" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Age:" />
<Entry Placeholder="Enter your age" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Occupation:" />
<Entry Placeholder="Enter your occupation" />
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Address:" />
<Entry Placeholder="Enter your address" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
Isso é um desperdício porque cálculos de layout desnecessário são executados. Em vez disso, o layout desejado
pode ser melhor obtido usando um Grid , conforme mostra o exemplo de código a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Details.HomePage"
Padding="0,20,0,0">
<ContentPage.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label Text="Name:" />
<Entry Grid.Column="1" Placeholder="Enter your name" />
<Label Grid.Row="1" Text="Age:" />
<Entry Grid.Row="1" Grid.Column="1" Placeholder="Enter your age" />
<Label Grid.Row="2" Text="Occupation:" />
<Entry Grid.Row="2" Grid.Column="1" Placeholder="Enter your occupation" />
<Label Grid.Row="3" Text="Address:" />
<Entry Grid.Row="3" Grid.Column="1" Placeholder="Enter your address" />
</Grid>
</ContentPage.Content>
</ContentPage>
<ContentPage.Content>
<StackLayout>
<StackLayout Padding="20,20,0,0">
<Label Text="Hello" />
</StackLayout>
<StackLayout Padding="20,20,0,0">
<Label Text="Welcome to the App!" />
</StackLayout>
<StackLayout Padding="20,20,0,0">
<Label Text="Downloading Data..." />
</StackLayout>
</StackLayout>
</ContentPage.Content>
O mesmo layout da página poderá ser mantido com uma contagem de elementos reduzida, conforme mostrado
no exemplo de código a seguir:
<ContentPage.Content>
<StackLayout Padding="20,20,0,0" Spacing="25">
<Label Text="Hello" />
<Label Text="Welcome to the App!" />
<Label Text="Downloading Data..." />
</StackLayout>
</ContentPage.Content>
<Application xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Resources.App">
<Application.Resources>
<ResourceDictionary>
<Style x:Key="HeadingLabelStyle" TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Red" />
</Style>
</ResourceDictionary>
</Application.Resources>
</Application>
No entanto, XAML específico de uma página não deve ser incluído no dicionário de recursos do aplicativo, uma
vez que os recursos então serão analisados na inicialização do aplicativo, em vez de quando exigido por uma
página. Se um recurso for usado por uma página que não seja a página de inicialização, ele deverá ser colocado
no dicionário de recursos para essa página, ajudando, assim, a reduzir o XAML analisado quando o aplicativo é
iniciado. O seguinte exemplo de código mostra o recurso HeadingLabelStyle , que está em apenas uma única
página e então é definido no dicionário de recursos da página:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Test.HomePage"
Padding="0,20,0,0">
<ContentPage.Resources>
<ResourceDictionary>
<Style x:Key="HeadingLabelStyle" TargetType="Label">
<Setter Property="HorizontalOptions" Value="Center" />
<Setter Property="FontSize" Value="Large" />
<Setter Property="TextColor" Value="Red" />
</Style>
</ResourceDictionary>
</ContentPage.Resources>
<ContentPage.Content>
...
</ContentPage.Content>
</ContentPage>
Para saber mais sobre os recursos de aplicativo, consulte Working with Styles .
if (Control == null) {
// Instantiate the native control
}
if (e.OldElement != null) {
// Unsubscribe from event handlers and cleanup any resources
}
if (e.NewElement != null) {
// Configure the control and subscribe to event handlers
}
}
Um novo controle nativo deve ser instanciado apenas uma vez, quando a propriedade Control é null . O
controle deve ser configurado e os manipuladores de eventos devem ser inscritos apenas quando o renderizador
personalizado for anexado a um novo elemento Xamarin.Forms. Da mesma forma, a inscrição de quaisquer
manipuladores de evento inscritos só deverá ser cancelada quando o elemento ao qual o renderizador está
anexado for alterado. Adotar essa abordagem ajudará a criar um renderizador personalizado de desempenho
eficiente que não sofra perdas de memória.
Para obter mais informações sobre renderizadores personalizados, consulte Como personalizar controles em cada
plataforma.
Resumo
Esse artigo descreveu e discutiu técnicas para aumentar o desempenho dos aplicativos criados Xamarin.Forms.
Coletivamente, essas técnicas podem reduzir de forma considerável a quantidade de trabalho que está sendo
executado por uma CPU e a quantidade de memória consumida por um aplicativo.
Links relacionados
Desempenho de plataforma cruzada
Desempenho de ListView
Renderizadores Rápidos
Compactação de Layout
XamlCompilation
XamlCompilationOptions
Conceitos avançados e recursos internos
12/04/2019 • 2 minutes to read • Edit Online
Resolução de dependência
Este artigo explica como injetar um método de resolução de dependência em xamarin. Forms para que o contêiner
de injeção de dependência do aplicativo tem controle sobre a criação e o tempo de vida de renderizadores
personalizados, efeitos, e DependencyService implementações.
Renderizadores Rápidos
Este artigo apresenta os renderizadores rápidos, o que reduz os custos de renderização de um controle xamarin.
Forms no Android e inflação nivelando a hierarquia de controle nativo resultante.
.NET Standard
Este artigo explica como converter um aplicativo xamarin. Forms para usar o .NET Standard 2.0.
Resolução de dependência no xamarin. Forms
12/04/2019 • 18 minutes to read • Edit Online
baixar o exemplo
Este artigo explica como injetar um método de resolução de dependência no xamarin. Forms para que o
contêiner de injeção de dependência do aplicativo tem controle sobre a criação e o tempo de vida de
renderizadores personalizados, efeitos e implementações de DependencyService. Os exemplos de código neste
artigo são tirados o resolução de dependência usando contêineres exemplo.
No contexto de um aplicativo xamarin. Forms que usa o padrão Model-View -ViewModel (MVVM ), um contêiner
de injeção de dependência pode ser usado para registrar e resolver os modelos de exibição e para registrar os
serviços e injetando-as nos modelos de exibição. Durante a criação do modelo de exibição, o contêiner injeta
quaisquer dependências que são necessárias. Se essas dependências não tem sido criadas, o contêiner cria e
resolve as dependências primeiro. Para obter mais informações sobre injeção de dependência, incluindo exemplos
de injetar dependências nos modelos de exibição, consulte injeção de dependência.
Controle sobre a criação e o tempo de vida dos tipos de projetos de plataforma é feito tradicionalmente por
xamarin. Forms, que usa o Activator.CreateInstance método para criar instâncias de renderizadores
personalizados, efeitos, e DependencyService implementações. Infelizmente, isso limita o controle do
desenvolvedor sobre a criação e o tempo de vida desses tipos, e a capacidade de injetar dependências neles. Esse
comportamento pode ser alterado por injetando um método de resolução de dependência no xamarin. Forms que
controla como tipos serão criados – pelo contêiner de injeção de dependência do aplicativo, ou xamarin. Forms.
No entanto, observe que não há nenhum requisito para injetar um método de resolução de dependência no
xamarin. Forms. Xamarin. Forms continuarão criar e gerenciar o tempo de vida dos tipos de projetos de
plataforma, se um método de resolução de dependência não é inserido.
NOTE
Embora este artigo se concentra em injetando um método de resolução de dependência no xamarin. Forms que resolve
tipos registrados usando um contêiner de injeção de dependência, também é possível inserir um método de resolução de
dependência que usa métodos de fábrica para resolver tipos registrados. Para obter mais informações, consulte o resolução
de dependência usando métodos de fábrica exemplo.
public App()
{
...
DependencyResolver.ResolveUsing(type => container.IsRegistered(type) ? container.Resolve(type) :
null);
...
}
...
}
Neste exemplo, o método de resolução de dependência é definido como uma expressão lambda que usa o
contêiner de injeção de dependência do Autofac para resolver quaisquer tipos que foram registrados com o
contêiner. Caso contrário, null será retornado, que resultará na tentativa de resolver o tipo de xamarin. Forms.
NOTE
A API usada por um contêiner de injeção de dependência é específica para o contêiner. Os exemplos de código neste artigo
usam o Autofac como um contêiner de injeção de dependência, que fornece o IContainer e ContainerBuilder tipos.
Contêineres de injeção de dependência alternativo igualmente poderia ser usados, mas usam APIs diferentes que são
apresentados aqui.
Observe que não há nenhum requisito para definir o método de resolução de dependência durante a inicialização
do aplicativo. Ele pode ser definido a qualquer momento. A única restrição é que o xamarin. Forms precisa saber
sobre o método de resolução de dependência no momento em que o aplicativo tentar consumir tipos
armazenados no contêiner de injeção de dependência. Portanto, se houver serviços no contêiner de injeção de
dependência que o aplicativo exigirá durante a inicialização, o método de resolução de dependência precisará ser
definido no início do ciclo de vida do aplicativo. Da mesma forma, se o contêiner de injeção de dependência
gerencia a criação e o tempo de vida de um determinado Effect , xamarin. Forms precisará saber sobre o
método de resolução de dependência, antes de tentar criar uma exibição que usa que Effect .
WARNING
Registrar e resolver os tipos com um contêiner de injeção de dependência tem um custo devido ao uso do contêiner de
reflexão para a criação de cada tipo, especialmente se as dependências estão sendo reconstruídas para cada navegação de
página no aplicativo de desempenho. Se houver muitos ou profundas dependências, o custo de criação pode aumentar
significativamente.
Registrando tipos
Tipos devem ser registrados com o contêiner de injeção de dependência, antes que ele possa resolvê-los por meio
do método de resolução de dependência. O exemplo de código a seguir mostra os métodos de registro que o
aplicativo de exemplo expõe no App classe, para o contêiner Autofac:
using Autofac;
using Autofac.Core;
...
public static void RegisterType<TInterface, T>() where TInterface : class where T : class, TInterface
{
builder.RegisterType<T>().As<TInterface>();
}
Quando um aplicativo usa um método de resolução de dependência para resolver os tipos de um contêiner, os
registros do tipo normalmente são executados de projetos de plataforma. Isso permite que projetos de plataforma
ao registrar tipos de renderizadores personalizados, efeitos, e DependencyService implementações.
Após o registro de tipo de um projeto de plataforma, o IContainer objeto deve ser criado, o que é realizado
chamando o BuildContainer método. Este método invoca do Autofac Build método no ContainerBuilder
instância, que cria um novo contêiner de injeção de dependência que contém os registros que foram feitos.
Nas seções a seguirem, uma Logger classe que implementa o ILogger interface é injetado em construtores de
classe. O Logger classe implementa o log simples funcionalidade usando o Debug.WriteLine método e é usado
para demonstrar como os serviços possam ser injetados em renderizadores personalizados, efeitos, e
DependencyService implementações.
Registrando renderizadores personalizados
O aplicativo de exemplo inclui uma página que desempenha vídeos da web, cujo código-fonte XAML é mostrado
no exemplo a seguir:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:video="clr-namespace:FormsVideoLibrary"
...>
<video:VideoPlayer Source="https://archive.org/download/BigBuckBunny_328/BigBuckBunny_512kb.mp4" />
</ContentPage>
O VideoPlayer exibição é implementada em cada plataforma por um VideoPlayerRenderer classe, que fornece a
funcionalidade para reproduzir o vídeo. Para obter mais informações sobre essas classes de renderizador
personalizado, consulte implementando um player de vídeo.
No iOS e Universal Windows Platform (UWP ), o VideoPlayerRenderer classes têm o seguinte construtor, que
exige um ILogger argumento:
Em todas as plataformas, o tipo de registro com o contêiner de injeção de dependência é executado pela
RegisterTypes método, que é invocado antes da plataforma de carregar o aplicativo com o
LoadApplication(new App()) método. A exemplo a seguir mostra o RegisterTypes método na plataforma iOS:
void RegisterTypes()
{
App.RegisterType<ILogger, Logger>();
App.RegisterType<FormsVideoLibrary.iOS.VideoPlayerRenderer>();
App.BuildContainer();
}
Neste exemplo, o Logger tipo concreto é registrado por meio de um mapeamento em relação a seu tipo de
interface e o VideoPlayerRenderer tipo é registrado diretamente sem um mapeamento de interface. Quando o
usuário navega até a página que contém o VideoPlayer modo de exibição, o método de resolução de dependência
será invocado para resolver o VideoPlayerRenderer tipo de contêiner de injeção de dependência, que também
resolver e injetar o Logger digitar em o VideoPlayerRenderer construtor.
O VideoPlayerRenderer construtor na plataforma Android é um pouco mais complicado, pois exige uma Context
argumento além de ILogger argumento:
Registrando efeitos
O aplicativo de exemplo inclui uma página que usa um efeito de controle de toque para arrastar BoxView
instâncias em torno da página. O Effect é adicionado para o BoxView usando o seguinte código:
O TouchEffect classe é um RoutingEffect que é implementada em cada plataforma por um TouchEffect classe
que tem um PlatformEffect . A plataforma TouchEffect classe fornece a funcionalidade de arrastar o BoxView em
torno da página. Para obter mais informações sobre essas classes de efeito, consulte invocação de eventos de
efeitos.
Em todas as plataformas, o TouchEffect classe tem o seguinte construtor, que exige um ILogger argumento:
Em todas as plataformas, o tipo de registro com o contêiner de injeção de dependência é executado pela
RegisterTypes método, que é invocado antes da plataforma de carregar o aplicativo com o
LoadApplication(new App()) método. A exemplo a seguir mostra o RegisterTypes método na plataforma Android:
void RegisterTypes()
{
App.RegisterType<ILogger, Logger>();
App.RegisterType<TouchTracking.Droid.TouchEffect>();
App.BuildContainer();
}
Neste exemplo, o Logger tipo concreto é registrado por meio de um mapeamento em relação a seu tipo de
interface e o TouchEffect tipo é registrado diretamente sem um mapeamento de interface. Quando o usuário
navega até a página que contém um BoxView instância que tem o TouchEffect anexado a ele, o método de
resolução de dependência será invocado para resolver a plataforma TouchEffect tipo de dependência contêiner
de injeção, que também resolver e injetar o Logger digitar no TouchEffect construtor.
Registrando as implementações do DependencyService
O aplicativo de exemplo inclui uma página que usa DependencyService implementações em cada plataforma para
permitir que o usuário escolha uma foto da biblioteca de imagens do dispositivo. O IPhotoPicker interface define
a funcionalidade que é implementada pelo DependencyService implementações e é mostrado no exemplo a seguir:
public interface IPhotoPicker
{
Task<Stream> GetImageStreamAsync();
}
Em cada projeto de plataforma, o PhotoPicker classe implementa o IPhotoPicker interface usando as APIs da
plataforma. Para obter mais informações sobre esses serviços de dependência, consulte escolhendo uma foto na
biblioteca de imagens.
No iOS e UWP, o PhotoPicker classes têm o seguinte construtor, que exige um ILogger argumento:
Em todas as plataformas, o tipo de registro com o contêiner de injeção de dependência é executado pela
RegisterTypes método, que é invocado antes da plataforma de carregar o aplicativo com o
LoadApplication(new App()) método. A exemplo a seguir mostra o RegisterTypes método na UWP:
void RegisterTypes()
{
DIContainerDemo.App.RegisterType<ILogger, Logger>();
DIContainerDemo.App.RegisterType<IPhotoPicker, Services.UWP.PhotoPicker>();
DIContainerDemo.App.BuildContainer();
}
Neste exemplo, o Logger tipo concreto é registrado por meio de um mapeamento em relação a seu tipo de
interface e o PhotoPicker tipo também é registrado por meio de um mapeamento de interface.
O PhotoPicker construtor na plataforma Android é um pouco mais complicado, pois exige uma Context
argumento além de ILogger argumento:
void RegisterTypes()
{
App.RegisterType<ILogger, Logger>();
App.RegisterTypeWithParameters<IPhotoPicker, Services.Droid.PhotoPicker>(typeof(Android.Content.Context),
this, typeof(ILogger), "logger");
App.BuildContainer();
}
NOTE
O Resolve<T> método deve ser usado durante a resolução de um tipo de contêiner de injeção de dependência do
aplicativo por meio de DependencyService .
Links relacionados
Resolução de dependência usando contêineres (amostra)
Injeção de dependência
Implementar um player de vídeo
Invocação de eventos de efeitos
Escolhendo uma foto na biblioteca de imagens
Renderizadores de xamarin. Forms Fast
12/04/2019 • 3 minutes to read • Edit Online
Este artigo apresenta os renderizadores rápidos (adicionados no xamarin. Forms 2.4 ), que reduz os custos de
renderização de um controle xamarin. Forms no Android e inflação nivelando a hierarquia de controle nativo
resultante.
Tradicionalmente, a maioria dos renderizadores de controle original no Android é compostas de dois modos de
exibição:
Controlar um nativo, como uma Button ou TextView .
Um contêiner ViewGroup que lida com algumas das outras tarefas, tratamento de gesto e o trabalho de layout.
No entanto, essa abordagem tem uma implicação de desempenho que dois modos de exibição são criados para
cada controle lógico, o que resulta em uma árvore visual mais complexa que exige mais memória e mais
processamento para renderizar na tela.
Os renderizadores rápidos reduzem os custos de renderização de um controle xamarin. Forms e inflação em uma
única exibição. Portanto, em vez de criar dois modos de exibição e adicioná-los à árvore de exibição, somente um
é criado. Isso melhora o desempenho criando menos objetos, que por sua vez, significa que uma árvore de
exibição menos complexa, e menos uso de memória (que também resulta em menos pausas na coleta de lixo).
Os renderizadores rápidos estão disponíveis para os seguintes controles no xamarin. Forms 2.4 no Android:
Button
Image
Label
Frame
Funcionalmente, esses renderizadores rápidos não são diferentes para os renderizadores originais. No entanto,
eles atualmente são experimentais e só pode ser usados, adicionando a seguinte linha de código para seus
MainActivity classe antes de chamar Forms.Init :
Forms.SetFlags("FastRenderers_Experimental");
NOTE
Os renderizadores rápidos só são aplicáveis para o aplicativo compat Android back-end, portanto, essa configuração será
ignorada em atividades de compatibilidade de aplicativo pré.
Melhorias de desempenho irá variar para cada aplicativo, dependendo da complexidade do layout. Por exemplo,
melhorias de desempenho de x2 são possíveis ao rolar por um ListView que contém milhares de linhas de
dados, em que as células em cada linha são compostas de controles que usam os renderizadores rápidos, o que
resulta em visivelmente rolagem mais suave.
Links relacionados
Renderizadores personalizados
2.0 suporte ao .NET standard no xamarin. Forms
12/04/2019 • 2 minutes to read • Edit Online
Este artigo explica como converter um aplicativo xamarin. Forms para usar o .NET Standard 2.0.
.NET standard é uma especificação de APIs .NET que devem estar disponíveis em todas as implementações do
.NET. Ele torna mais fácil de compartilhar código entre aplicativos da área de trabalho, aplicativos móveis e jogos e
serviços de nuvem, reunindo APIs idêntico para as plataformas diferentes. Para obter informações sobre as
plataformas com suporte pelo .NET Standard, consulte suporte à implementação do .NET.
Bibliotecas do .NET standard são a substituição para Portable Class Libraries (PCL ). No entanto, uma biblioteca
direcionada ao .NET Standard ainda é uma PCL e é conhecida como uma PCL baseada no .NET Standard.
Determinados perfis de PCL são mapeados para versões do .NET Standard e para os perfis que têm um
mapeamento, os tipos de dois biblioteca poderão fazer referência uns aos outros. Para obter mais informações,
consulte compatibilidade com PCL.
2.4 de xamarin. Forms permite que os aplicativos xamarin. Forms destino .NET Standard 2.0, substituindo o PCL
com uma biblioteca .NET Standard 2.0. Isso pode ser feito da seguinte maneira:
Certifique-se .NET Core 2.0 está instalado.
Atualize a solução do xamarin. Forms para usar o xamarin. Forms 2.4 ou superior.
Adicione uma biblioteca .NET Standard à solução, que tem como alvo o .NET Standard 2.0.
Exclua a classe que é adicionada à biblioteca do .NET Standard.
Adicione o pacote do NuGet xamarin. Forms 2,4 (ou superior) para a biblioteca .NET Standard.
Em projetos da plataforma, adicione uma referência à biblioteca do .NET Standard e remova a referência ao
projeto da PCL que contém a lógica de interface de usuário do xamarin. Forms.
Copie os arquivos do projeto PCL para a biblioteca .NET Standard.
Remova o projeto PCL que contém a lógica de interface de usuário do xamarin. Forms.
Links relacionados
.NET Standard
Opções de compartilhamento de código
Solução de problemas
12/04/2019 • 3 minutes to read
Por que o designer XAML do Visual Studio não funciona para arquivos
XAML do Xamarin.Forms?
Xamarin. Forms atualmente não dá suporte a designers visuais para arquivos XAML.
Este guia usa o modelo de biblioteca xamarin. Forms .NET Standard como um exemplo, mas o mesmo método
geral também funcionarão para o modelo de projeto compartilhado do xamarin. Forms. Este guia foi escrito com o
exemplo de atualização do xamarin. Forms 1.5.1.6471 para 2.1.0.6529, mas as mesmas etapas são possíveis definir
outras versões como o padrão em vez disso.
1. Copie o modelo original .zip de:
7. Copie a nova pasta zipada modelo para o novo diretório de "Aplicativos móveis".
8. Baixe o pacote do NuGet que corresponde à versão da etapa 3. Por exemplo,
http://nuget.org/api/v2/package/Xamarin.Forms/2.1.0.6529 (Consulte também
https://stackoverflow.com/questions/8597375/how -to-get-the-url-of-a-nupkg-file ) e copie-o para a
subpasta apropriada da pasta de extensões do Xamarin para Visual Studio:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\Extensions\Xamarin\Xamarin\[Xamarin
Version]\Packages
Por que o designer XAML do Visual Studio não
funciona para arquivos XAML xamarin. Forms?
12/04/2019 • 2 minutes to read
Xamarin. Forms atualmente não dá suporte a designers visuais para arquivos XAML. Por isso, ao tentar abrir um
arquivo XAML de formulários no Visual Studio Designer de interface do usuário XAML ou Designer de interface
do usuário XAML com codificação, a seguinte mensagem de erro é gerada:
"Não é possível abrir o arquivo com o editor selecionado. Escolha outro editor."
Essa limitação é descrita no visão geral seção o xamarin. Forms Noções básicas de XAML guia:
"Não há ainda um designer visual para gerar o XAML em aplicativos xamarin. Forms, XAML para que todos os
deve ser manual".
No entanto, o Visualizador de XAML xamarin. Forms pode ser exibido selecionando a exibição > outras janelas
> Visualizador xamarin. Forms opção de menu.
Erro de build do Android – tarefa o LinkAssemblies
falhou inesperadamente
12/04/2019 • 2 minutes to read
Você poderá ver uma mensagem de erro The "LinkAssemblies" task failed unexpectedly quando a criação de um
projeto xamarin. Android que usa formulários. Isso acontece quando o vinculador está ativo (normalmente em um
versão build para reduzir o tamanho do pacote do aplicativo); e isso ocorre porque os destinos Android não são
atualizados para o framework mais recente. (Mais informações: Xamarin. Forms para Android requisitos)
A resolução para esse problema é certificar-se de ter as versões do SDK do Android mais recente com suporte e
defina as estrutura de destino para a plataforma mais recente instalada. Também é recomendável que você
defina as versão destino Android para a plataforma instalada mais recente e o versão mínima do Android
para API 19 ou superior. Isso é considerado a configuração com suporte.
Esse erro pode ser visto no painel de erro do Visual Studio para Mac ou na janela de saída de compilação do
Visual Studio; em projetos Android usando Xamarin.Forms.Maps.
Isso geralmente é resolvido, aumentando o tamanho do Heap do Java para o seu projeto xamarin. Siga estas
etapas para aumentar o tamanho do heap:
Visual Studio
1. Clique com botão direito do Android & Abrir as opções de projeto.
2. Vá para Android opções -> Avançado
3. Na caixa de texto de tamanho do heap de Java insira 1G.
4. Recompile o projeto.
baixar o exemplo
O livro criação de aplicativos móveis com xamarin. Forms , de Charles Petzold, é um guia
para aprender a escrever aplicativos xamarin. Forms. O único pré-requisito é conhecimento
sobre o C# linguagem de programação. O livro oferece uma exploração extensiva na interface
do usuário do xamarin. Forms e também aborda a animação, MVVM, gatilhos,
comportamentos, layouts personalizados, renderizadores personalizados e muito mais.
O livro foi publicado na primavera de 2016 e não tiver sido atualizado desde então. Há muito
o no livro valioso que permanece, mas alguns dos material está desatualizado, e alguns tópicos não são
totalmente correto ou foi concluído.
Exemplos
Os exemplos estão disponível no githube incluem projetos para iOS, Android e Universal Windows Platform
(UWP ). (Xamarin. Forms não é compatível com Windows 10 Mobile, mas os aplicativos xamarin. Forms serão
executado na área de trabalho do Windows 10.)
Resumos de capítulo
Resumos de capítulo estão disponíveis na tabela de capítulo mostrados abaixo. Esses resumos descrevem o
conteúdo de cada capítulo e incluem vários tipos de links:
Links para os reais capítulos do livro (na parte inferior da página) e artigos relacionados
Links para todos os exemplos de xamarin-forms-samples livro repositório do GitHub
Links para a documentação da API para obter descrições mais detalhadas de classes xamarin. Forms,
estruturas, propriedades, enumerações e assim por diante
Esses resumos também indicam quando pode ser o material no capítulo um pouco desatualizada.
NOTE
Observações sobre cada página indicam onde o xamarin. Forms foi bifurcado do material apresentado no livro.
Exemplos
No xamarin-forms-samples livro repositório do GitHub, o código original do livro branch contém
exemplos de programa consistentes com o catálogo. O mestre branch contém projetos que foram atualizados
para remover APIs preteridas e refletir APIs aprimoradas. Além disso, o Android projetos na mestre branch
foram atualizados para o Android Design de Material via AppCompat e geralmente exibirá texto preto em um
plano de fundo branco.
Links relacionados
Blog do MS Press
Código de exemplo do livro
Padrões de aplicativo empresarial usando o livro
eletrônico do xamarin. Forms
12/04/2019 • 9 minutes to read
Este livro eletrônico fornece orientação sobre como implementar o padrão Model-View -ViewModel (MVVM ), a
injeção de dependência, a navegação, a validação e o gerenciamento de configuração, mantendo um acoplamento
flexível. Além disso, há também orientações sobre como executar autenticação e autorização com IdentityServer,
acessando dados através de microsserviços em contêineres e testes de unidade.
Prefácio
Este capítulo explica a finalidade e o escopo do guia e que ele é destinado.
Introdução
Os desenvolvedores de aplicativos empresariais enfrentam vários desafios que podem alterar a arquitetura do
aplicativo durante o desenvolvimento. Portanto, é importante compilar um aplicativo para que possa ser
modificado ou estendido ao longo do tempo. A criação de tal adaptabilidade pode ser difícil, mas geralmente
envolve o particionamento de um aplicativo em componentes discretos e flexíveis que podem ser facilmente
integrados juntos em um aplicativo.
MVVM
O padrão Model-View -ViewModel (MVVM ) ajuda a separar a lógica de negócios e apresentação de um aplicativo
de sua interface do usuário (UI) de forma precisa. Mantendo uma separação clara entre a lógica do aplicativo e a
interface do usuário ajuda a resolver vários problemas de desenvolvimento e pode tornar mais fácil de testar um
aplicativo, manter e evoluem. Ele pode também melhoram muito a oportunidades de reutilização de código e
permite que os desenvolvedores e designers de interface do usuário mais facilmente colaboram durante o
desenvolvimento de suas respectivas partes de um aplicativo.
Injeção de dependência
Injeção de dependência permite desassociação de tipos concretos do código que depende desses tipos.
Normalmente, ele usa um contêiner que mantém uma lista de registros e mapeamentos entre as interfaces e tipos
abstratos e os tipos concretos que implementam ou estendem a esses tipos.
Contêineres de injeção de dependência reduzem o acoplamento entre objetos fornecendo um recurso para
instanciar instâncias de classe e gerenciar seu tempo de vida com base na configuração do contêiner. Durante a
criação de objetos, o contêiner injeta quaisquer dependências que exige que o objeto nele. Se essas dependências
ainda não tem sido criadas, o contêiner cria e resolve as dependências entre primeiro.
Navegação
Xamarin. Forms inclui suporte para navegação de página, que geralmente resulta da interação do usuário com a
interface do usuário ou do aplicativo em si, como resultado das alterações de estado interno controlado por lógica.
No entanto, a navegação pode ser complexa para implementar em aplicativos que usam o padrão MVVM.
Este capítulo apresenta um NavigationService classe, que é usado para executar a navegação de model first de
modo de exibição de modelos de exibição. Colocar a lógica de navegação no modo de exibição classes de modelo
significa que a lógica pode ser exercida por meio de testes automatizados. Além disso, o modelo de exibição, em
seguida, pode implementar a lógica para controlar a navegação para assegurar que determinadas regras de
negócio são aplicadas.
Validação
Qualquer aplicativo que aceita entrada de usuários deve garantir que a entrada é válida. Sem validação, um usuário
pode fornecer dados que faz com que o aplicativo falhe. Validação impõe regras de negócio e impede que um
invasor injetando dados mal-intencionados.
No contexto do Model-View -ViewModel (MVVM ) padrão, um modelo de exibição ou modelo geralmente
precisará executar a validação de dados e sinalizar erros de validação para o modo de exibição para que o usuário
possa corrigi-los.
Gerenciamento de configurações
As configurações permitem a separação dos dados que configura o comportamento de um aplicativo do código,
permitindo que o comportamento a ser alterado sem recompilar o aplicativo. Configurações do aplicativo são
dados que um aplicativo cria e gerencia e configurações de usuário são as configurações personalizáveis de um
aplicativo que afetam o comportamento do aplicativo e não exigem o ajuste re frequente.
Microservices em contêineres
Os Microsserviços oferecem uma abordagem ao desenvolvimento de aplicativos e implantação que é adequada
para os requisitos de agilidade, escala e confiabilidade de aplicativos de nuvem modernos. Uma das principais
vantagens de microsserviços é que eles podem ser escalados horizontalmente de forma independente, o que
significa que uma área funcional específica pode ser dimensionada que que requer mais processamento de rede ou
energia largura de banda para dar suporte à demanda, sem dimensionamento desnecessariamente áreas do o
aplicativo que não estejam enfrentando o aumento na demanda.
Autenticação e autorização
Há muitas abordagens para integrar a autenticação e autorização em um aplicativo xamarin. Forms que se
comunica com um aplicativo web ASP.NET MVC. Aqui, autenticação e autorização são executadas com um
microsserviço de identidade em contêineres que usa 4 IdentityServer. IdentityServer é uma estrutura de OAuth 2.0
e OpenID Connect do código-fonte aberto para o ASP.NET Core se integra ao ASP.NET Core Identity para realizar
a autenticação de token de portador.
Testes de Unidade
Teste de modelos e modelos de exibição de aplicativos MVVM é idêntico ao teste de outras classes e as mesmas
ferramentas e técnicas podem ser usadas. No entanto, há alguns padrões que são comuns ao modelo e classes de
modelo de exibição, que podem se beneficiar das técnicas de teste de unidade específica.
Comentários
Este projeto tem um site da comunidade, no qual você pode postar perguntas e fornecer comentários. O site da
comunidade está localizado em GitHub. Como alternativa, comentários sobre o livro eletrônico podem ser
enviados por email para dotnet-architecture-ebooks-feedback@service.microsoft.com .
Links relacionados
Baixe o livro eletrônico (PDF de 2Mb)
eShopOnContainers (GitHub) (amostra)
Elementos gráficos de SkiaSharp em Xamarin.Forms
12/04/2019 • 5 minutes to read
baixar o exemplo
Usar SkiaSharp para gráficos 2D em seus aplicativos xamarin. Forms
SkiaSharp é um sistema de gráficos em 2D para .NET e c# com o engine gráficos Skia de código-fonte aberto
que é amplamente usado em produtos do Google. Você pode usar SkiaSharp em seus aplicativos xamarin.
Forms para desenhar o texto, bitmaps e gráficos vetoriais 2D. Consulte a desenho 2D guia para obter mais
informações gerais sobre a biblioteca de SkiaSharp e alguns outros tutoriais.
Este guia pressupõe que você esteja familiarizado com a programação do xamarin. Forms.
IMPORTANT
O SkiaSharp.Views.Forms namespace também contém um SKGLView classe que deriva de View mas utiliza o
OpenGL para renderização de gráficos. Para fins de simplicidade, este guia restringe-se ao SKCanvasView , mas o uso
SKGLView em vez disso, é bastante semelhante.
Transformações de SkiaSharp
As transformações permitem que os objetos gráficos ser uniformemente traduzido, dimensionado, girados ou
inclinados. Este artigo também mostra como você pode usar uma matriz de transformação de 3 por 3 padrão
para criar transformações não afins e aplicar transformações aos caminhos.
Bitmaps do SkiaSharp
Os bitmaps são matrizes retangulares de bits que correspondem aos pixels de um dispositivo de vídeo. Esta
série de artigos mostra como carregar, salvar, exibir, criar, desenhar em, animar e acessar os bits de SkiaSharp
bitmaps.
Efeitos de SkiaSharp
Os efeitos são propriedades que alteram a exibição normal de elementos gráficos, incluindo gradientes linear e
circulares, lado a lado de bitmap, misturar modos de desfoque e outras pessoas.
Links relacionados
APIs de SkiaSharp
SkiaSharpFormsDemos (amostra)
SkiaSharp com xamarin. Forms Webinar (vídeo)