Adicionando indicadores no CarouselView – Xamarin.Forms

Hoje irei falar novamente sobre o CarouselView. Após o meu post  CarouselView – Xamarin.Forms, algumas pessoas me procuraram perguntando como adicionar indicadores.

Indicadores são ícones de índice, com a finalidade de informar ao usuário que aquele elemento é uma lista, independente de qual conteúdo for, e a posição na qual ele se encontra.

Porém, no momento em que escrevo este post o componente do CarouselView não possui uma propriedade de indicadores, então você precisará implementá-la.

Para este exemplo, partirei do principio que você já criou o seu CarouselView, caso possua alguma dúvida sobre isso, recomendo ler o post  CarouselView – Xamarin.Forms .

Ícones

Para este exemplo usei 2 ícones com círculos para utilizar de indicadores, sendo um deles preenchido na parte interior para informar o elemento corrente, e um círculo sem preenchimento para informar os demais elementos do CarouselView.

Selecionado

selecionado

Não Selecionado

naoSelecionado

Adicione esses ícones nas pastas designadas para as imagens de acordo com cada plataforma, caso possua alguma dúvida na plataforma Android, recomendo ler o post Adicionando imagens em projeto Android – Xamarin.

Classe IndicadoresCarousel

Em seguida crie uma classe com o nome “IndicadoresCarousel.cs” para realizar o controle dos indicadores. Adicione o código a seguir na classe.

using System;
using System.Collections;
using System.Linq;
using Xamarin.Forms;
namespace DemoCarouselView
{
public class IndicadoresCarousel : Grid
{
private ImageSource UnselectedImageSource = null;
private ImageSource SelectedImageSource = null;
private readonly StackLayout _indicators = new StackLayout() { Orientation = StackOrientation.Horizontal, HorizontalOptions = LayoutOptions.CenterAndExpand };
public IndicadoresCarousel()
{
this.HorizontalOptions = LayoutOptions.CenterAndExpand;
this.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Auto });
this.Children.Add(_indicators);
}
public static readonly BindableProperty PositionProperty = BindableProperty.Create(nameof(Position), typeof(int), typeof(IndicadoresCarousel), 0, BindingMode.TwoWay, propertyChanging: PositionChanging);
public static readonly BindableProperty ItemsSourceProperty = BindableProperty.Create(nameof(ItemsSource), typeof(IEnumerable), typeof(IndicadoresCarousel), Enumerable.Empty<object>(), BindingMode.OneWay, propertyChanged: ItemsChanged);
public static readonly BindableProperty SelectedIndicatorProperty = BindableProperty.Create(nameof(SelectedIndicator), typeof(string), typeof(IndicadoresCarousel), "", BindingMode.OneWay);
public static readonly BindableProperty UnselectedIndicatorProperty = BindableProperty.Create(nameof(UnselectedIndicator), typeof(string), typeof(IndicadoresCarousel), "", BindingMode.OneWay);
public static readonly BindableProperty IndicatorWidthProperty = BindableProperty.Create(nameof(IndicatorWidth), typeof(double), typeof(IndicadoresCarousel), 0.0, BindingMode.OneWay);
public static readonly BindableProperty IndicatorHeightProperty = BindableProperty.Create(nameof(IndicatorHeight), typeof(double), typeof(IndicadoresCarousel), 0.0, BindingMode.OneWay);
public string SelectedIndicator
{
get { return (string)this.GetValue(SelectedIndicatorProperty); }
set { this.SetValue(SelectedIndicatorProperty, value); }
}
public string UnselectedIndicator
{
get { return (string)this.GetValue(UnselectedIndicatorProperty); }
set { this.SetValue(UnselectedIndicatorProperty, value); }
}
public double IndicatorWidth
{
get { return (double)this.GetValue(IndicatorWidthProperty); }
set { this.SetValue(IndicatorWidthProperty, value); }
}
public double IndicatorHeight
{
get { return (double)this.GetValue(IndicatorHeightProperty); }
set { this.SetValue(IndicatorHeightProperty, value); }
}
public int Position
{
get { return (int)this.GetValue(PositionProperty); }
set { this.SetValue(PositionProperty, value); }
}
public IEnumerable ItemsSource
{
get { return (IEnumerable)this.GetValue(ItemsSourceProperty); }
set { this.SetValue(ItemsSourceProperty, (object)value); }
}
private void Clear()
{
_indicators.Children.Clear();
}
private void Init(int position)
{
if (UnselectedImageSource == null)
UnselectedImageSource = ImageSource.FromFile(UnselectedIndicator);
if (SelectedImageSource == null)
SelectedImageSource = ImageSource.FromFile(SelectedIndicator);
if (_indicators.Children.Count > 0)
{
for (int i = 0; i < _indicators.Children.Count; i++)
{
if (((Image)_indicators.Children[i]).ClassId == nameof(State.Selected) && i != position)
_indicators.Children[i] = BuildImage(State.Unselected, i);
else if (((Image)_indicators.Children[i]).ClassId == nameof(State.Unselected) && i == position)
_indicators.Children[i] = BuildImage(State.Selected, i);
}
}
else
{
var enumerator = ItemsSource.GetEnumerator();
int count = 0;
while (enumerator.MoveNext())
{
Image image = null;
if (position == count)
image = BuildImage(State.Selected, count);
else
image = BuildImage(State.Unselected, count);
_indicators.Children.Add(image);
count++;
}
}
}
private Image BuildImage(State state, int position)
{
var image = new Image()
{
WidthRequest = IndicatorWidth,
HeightRequest = IndicatorHeight,
ClassId = state.ToString()
};
switch (state)
{
case State.Selected:
image.Source = SelectedImageSource;
break;
case State.Unselected:
image.Source = UnselectedImageSource;
break;
default:
throw new Exception("Invalid state selected");
}
image.GestureRecognizers.Add(new TapGestureRecognizer() { Command = new Command(() => { Position = position; }) });
return image;
}
private static void PositionChanging(object bindable, object oldValue, object newValue)
{
var carouselIndicators = bindable as IndicadoresCarousel;
carouselIndicators.Init(Convert.ToInt32(newValue));
}
private static void ItemsChanged(object bindable, object oldValue, object newValue)
{
var carouselIndicators = bindable as IndicadoresCarousel;
carouselIndicators.Clear();
carouselIndicators.Init(0);
}
public enum State
{
Selected,
Unselected
}
}
}

https://gist.github.com/juucustodio/36b34a49c33301aae07e83a818a69221

C# Realizado no Code-Behind

Aproveitando o exemplo do post anterior, realizei o Binding no próprio Code-Behind para fins de demonstração dos indicadores, para isso no método construtor atribua “this” para o BindingContext, como demonstrado no exemplo a seguir:

using System.Collections.Generic;
using System.ComponentModel;
using Xamarin.Forms;
namespace DemoCarouselView
{
public partial class IndicadoresPage : ContentPage, INotifyPropertyChanged
{
public IndicadoresPage()
{
InitializeComponent();
ListaImagens = new List<string>
{
"foto1.jpg",
"foto2.jpg",
"foto3.jpg"
};
BindingContext = this;
}
public List<string> ListaImagens { get; set; }
private int _position;
public int Position { get { return _position; } set { _position = value; OnPropertyChanged(); } }
}
}

Xaml

Na sua view, levando em consideração que você já adicionou o componente CarouselView conforme exemplificado no post anterior, adicione os indicadores como demonstrado a seguir:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:local="clr-namespace:DemoCarouselView"
xmlns:forms="clr-namespace:Xamarin.Forms;assembly=Xamarin.Forms.CarouselView"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="DemoCarouselView.IndicadoresPage">
<StackLayout>
<forms:CarouselView x:Name="ImageCarouselView" Position="{Binding Position, Mode=TwoWay}"
ItemsSource="{Binding ListaImagens}" >
<forms:CarouselView.ItemTemplate>
<DataTemplate>
<Image Source="{Binding .}"/>
</DataTemplate>
</forms:CarouselView.ItemTemplate>
</forms:CarouselView>
<local:IndicadoresCarousel x:Name="Indicadores" IndicatorHeight="16" IndicatorWidth="16"
UnselectedIndicator="naoSelecionado.png" SelectedIndicator="selecionado.png"
Position="{Binding Position}" ItemsSource="{Binding ListaImagens}" />
</StackLayout>
</ContentPage>

view raw
IndicadoresPage.xaml
hosted with ❤ by GitHub

 

Resultado

ezgif.com-gif-maker (1)

 

Esse e todos os exemplos deste blog encontram-se disponíveis no GitHub.

icongithub

2 comentários em “Adicionando indicadores no CarouselView – Xamarin.Forms

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair /  Alterar )

Foto do Google

Você está comentando utilizando sua conta Google. Sair /  Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair /  Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair /  Alterar )

Conectando a %s