Xamarin.Forms Slider
Use um controle deslizante para selecionar entre um intervalo de valores contínuos.
A Xamarin.FormsSlider
é uma barra horizontal que pode ser manipulada pelo usuário para selecionar um double
valor de um intervalo contínuo.
O Slider
define três propriedades do tipo double
:
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 1.Value
é o valor do controle deslizante, que pode variar entreMinimum
eMaximum
e tem um valor padrão de 0.
Todas as três propriedades são apoiadas por BindableProperty
objetos. A Value
propriedade tem um modo de associação padrão de , o que significa que ela é adequada como uma fonte de BindingMode.TwoWay
associação em um aplicativo que usa a arquitetura MVVM (Model-View-ViewModel).
Aviso
Internamente, o Slider
garante que Minimum
é menor que Maximum
. Se Minimum
ou Maximum
forem definidos de forma que Minimum
não seja inferior Maximum
a , uma exceção será gerada. Consulte a seção Precauções abaixo para obter mais informações sobre como definir as Minimum
propriedades e Maximum
.
O Slider
coage a Value
propriedade para que fique entre Minimum
e Maximum
, inclusive. Se a Minimum
propriedade for definida como um valor maior que a Value
propriedade, o Slider
definirá a Value
propriedade como Minimum
. Da mesma forma, if Maximum
é definido como um valor menor que Value
, define Slider
a Value
propriedade como Maximum
.
Slider
define um ValueChanged
evento que é acionado quando as Value
alterações, seja por meio da manipulação do Slider
usuário do ou quando o programa define a Value
propriedade diretamente. Um ValueChanged
evento também é acionado quando a Value
propriedade é coagida, conforme descrito no parágrafo anterior.
O ValueChangedEventArgs
objeto que acompanha o ValueChanged
evento tem duas propriedades, ambas do tipo double
: OldValue
e NewValue
. No momento em que o evento é disparado, o valor de NewValue
é o mesmo que a Value
propriedade do Slider
objeto.
Slider
também define DragStarted
e DragCompleted
eventos, que são disparados no início e no final da ação de arrastar. Ao contrário do ValueChanged
evento, os DragStarted
eventos e DragCompleted
só são disparados por meio da manipulação do 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.
Aviso
Não use opções de layout horizontal irrestrito de Center
, Start
, ou End
com Slider
. No Android e na UWP, o Slider
colapso é uma barra de comprimento zero e, no iOS, a barra é muito curta. Mantenha a configuração padrão HorizontalOptions
de Fill
e não use uma largura de Auto
ao colocar Slider
um Grid
layout.
O Slider
também define várias propriedades que afetam sua aparência:
MinimumTrackColor
é a cor da barra no lado esquerdo do polegar.MaximumTrackColor
é a cor da barra no lado direito do polegar.ThumbColor
é a cor do polegar.ThumbImageSource
é a imagem a ser usada para o polegar, do tipoImageSource
.
Observação
As ThumbColor
propriedades e ThumbImageSource
são mutuamente exclusivas. Se ambas as propriedades forem definidas, a ThumbImageSource
propriedade terá precedência.
Código básico do controle deslizante e marcação
O exemplo começa com três páginas que são funcionalmente idênticas, mas são implementadas de maneiras diferentes. A primeira página usa apenas código C#, a segunda usa XAML com um manipulador de eventos no código e a terceira é capaz de evitar o manipulador de eventos usando a associação de dados no arquivo XAML.
Criando um Slider no código
A página Código do controle deslizante básico mostra show para criar um Slider
e dois Label
objetos no código:
public class BasicSliderCodePage : ContentPage
{
public BasicSliderCodePage()
{
Label rotationLabel = new Label
{
Text = "ROTATING TEXT",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Label displayLabel = new Label
{
Text = "(uninitialized)",
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.CenterAndExpand
};
Slider slider = new Slider
{
Maximum = 360
};
slider.ValueChanged += (sender, args) =>
{
rotationLabel.Rotation = slider.Value;
displayLabel.Text = String.Format("The Slider value is {0}", args.NewValue);
};
Title = "Basic Slider Code";
Padding = new Thickness(10, 0);
Content = new StackLayout
{
Children =
{
rotationLabel,
slider,
displayLabel
}
};
}
}
O Slider
é inicializado para ter uma Maximum
propriedade de 360. O ValueChanged
manipulador do Slider
usa a Value
propriedade do slider
objeto para definir a Rotation
propriedade do primeiro Label
e usa o String.Format
método com a NewValue
propriedade dos argumentos do 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 em dispositivos iOS e Android:
O segundo Label
exibe o texto "(não inicializado)" até que o Slider
seja manipulado, o que faz com que o primeiro ValueChanged
evento seja disparado. Observe que o número de casas decimais exibidas é diferente para cada plataforma. Essas diferenças estão relacionadas às implementações de plataforma do Slider
e são discutidas posteriormente neste artigo na seção Diferenças de implementação da plataforma.
Criando um controle deslizante em XAML
A página XAML do Controle Deslizante Básico é funcionalmente a mesma que o Código do Controle Deslizante Básico, mas implementada principalmente em 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>
O arquivo code-behind contém o manipulador do evento ValueChanged
:
public partial class BasicSliderXamlPage : ContentPage
{
public BasicSliderXamlPage()
{
InitializeComponent();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
double value = args.NewValue;
rotatingLabel.Rotation = value;
displayLabel.Text = String.Format("The Slider value is {0}", value);
}
}
Também é possível que o manipulador de eventos obtenha o Slider
que está disparando o evento por meio do sender
argumento. A Value
propriedade contém o valor atual:
double value = ((Slider)sender).Value;
Se o Slider
objeto receber um nome no arquivo XAML com um x:Name
atributo (por exemplo, "slider"), o manipulador de eventos poderá fazer referência a esse objeto diretamente:
double value = slider.Value;
Vinculação de dados do controle deslizante
A página Associações Básicas de Controle Deslizante mostra como escrever um programa quase equivalente que elimina o manipulador de eventos usando a Value
Associação de Dados:
<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>
A Rotation
propriedade do primeiro Label
está ligada à Value
propriedade do Slider
, assim como a Text
propriedade do segundo Label
com uma StringFormat
especificação. A página Associações Básicas do Controle Deslizante funciona de maneira um pouco diferente das duas páginas anteriores: quando a página aparece pela primeira vez, a segunda Label
exibe a cadeia de caracteres de texto com o valor. Esse é um benefício do uso da associação de dados. Para exibir texto sem associação de dados, você precisaria inicializar especificamente a Text
propriedade do Label
ou simular um disparo ValueChanged
do evento chamando o manipulador de eventos do construtor de classe.
Precauções
O valor da Minimum
propriedade deve ser sempre menor que o Maximum
valor da propriedade. O snippet de código a seguir faz com que o Slider
gere 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 a Minimum
propriedade é definida como 10, ela é maior que o valor padrão Maximum
de 1. Você pode evitar a exceção nesse caso definindo a Maximum
propriedade primeiro:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Definir Maximum
como 20 não é um problema porque é maior que o valor padrão Minimum
de 0. Quando Minimum
é definido, o valor é menor que o Maximum
valor de 20.
O mesmo problema existe no XAML. Defina as propriedades em uma ordem que garanta que Maximum
seja sempre maior que Minimum
:
<Slider Maximum="20"
Minimum="10" ... />
Você pode definir os Minimum
valores e Maximum
como números negativos, mas apenas em uma ordem em Minimum
que é sempre menor que Maximum
:
<Slider Minimum="-20"
Maximum="-10" ... />
A Value
propriedade é sempre maior ou igual ao Minimum
valor e menor ou igual a Maximum
. Se Value
for definido como um valor fora desse intervalo, o valor será forçado a estar dentro do intervalo, mas nenhuma exceção será gerada. Por exemplo, este código não gerará uma exceção:
Slider slider = new Slider
{
Value = 10
};
Em vez disso, a Value
propriedade é forçada ao Maximum
valor de 1.
Aqui está um trecho de código mostrado acima:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Quando Minimum
é definido como 10, então Value
também é definido como 10.
Se um ValueChanged
manipulador de eventos tiver sido anexado no momento em que a Value
propriedade for forçada a algo diferente de seu valor padrão de 0, um ValueChanged
evento será 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 tenha sido construído e o manipulador pode tentar fazer referência a outros elementos na página que ainda não foram criados. Talvez você queira adicionar algum código ao ValueChanged
manipulador que verifica null
os valores de outros elementos na página. Ou você pode definir o manipulador de ValueChanged
eventos depois que os Slider
valores forem inicializados.
Diferenças de implementação da plataforma
As capturas de tela mostradas anteriormente exibem o Slider
valor do com um número diferente de pontos decimais. Isso está relacionado a como o Slider
é implementado nas plataformas Android e UWP.
A implementação do Android
A implementação do Slider
Android é baseada no Android SeekBar
e sempre define a Max
propriedade como 1000. Isso significa que o Slider
no Android tem apenas 1.001 valores discretos. Se você definir o Slider
como tendo um Minimum
de 0 e um Maximum
de 5000, à medida que o Slider
for manipulado, a Value
propriedade terá valores de 0, 5, 10, 15 e assim por diante.
A implementação da UWP
A implementação UWP de Slider
é baseada no controle UWP Slider
. A StepFrequency
propriedade da UWP Slider
é definida como a diferença das Maximum
propriedades and Minimum
dividida por 10, mas não maior que 1.
Por exemplo, para o intervalo padrão de 0 a 1, a StepFrequency
propriedade é definida como 0,1. À medida que o Slider
é manipulado, a Value
propriedade é restrita a 0, 0,1, 0,2, 0,3, 0,4, 0,5, 0,6, 0,7, 0,8, 0,9 e 1,0. Quando a diferença entre as Maximum
propriedades e Minimum
for 10 ou maior, então StepFrequency
é definido como 1 e a Value
propriedade tem valores integrais.
A solução StepSlider
Uma mais versátil StepSlider
é discutida no Capítulo 27. Renderizadores personalizados do livro Criando aplicativos móveis com Xamarin.Forms. O é semelhante aSlider
, StepSlider
mas adiciona uma Steps
propriedade para especificar o número de valores entre Minimum
e Maximum
.
Controles deslizantes para seleção de cores
As duas páginas finais do exemplo usam três Slider
instâncias para seleção de cores. A primeira página lida com todas as interações no arquivo code-behind, enquanto a segunda página mostra como usar a associação de dados com um ViewModel.
Manipulando controles deslizantes no arquivo code-behind
A página Controles deslizantes de cores RGB instancia a BoxView
para exibir uma cor, três Slider
instâncias para selecionar os componentes vermelho, verde e azul da cor e três Label
elementos para exibir esses valores de cor:
<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" />
<Label x:Name="redLabel" />
<Slider x:Name="greenSlider"
ValueChanged="OnSliderValueChanged" />
<Label x:Name="greenLabel" />
<Slider x:Name="blueSlider"
ValueChanged="OnSliderValueChanged" />
<Label x:Name="blueLabel" />
</StackLayout>
</ContentPage>
A dá a Style
todos os três Slider
elementos um intervalo de 0 a 255. Os Slider
elementos compartilham o mesmo ValueChanged
manipulador, que é implementado no arquivo code-behind:
public partial class RgbColorSlidersPage : ContentPage
{
public RgbColorSlidersPage()
{
InitializeComponent();
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
if (sender == redSlider)
{
redLabel.Text = String.Format("Red = {0:X2}", (int)args.NewValue);
}
else if (sender == greenSlider)
{
greenLabel.Text = String.Format("Green = {0:X2}", (int)args.NewValue);
}
else if (sender == blueSlider)
{
blueLabel.Text = String.Format("Blue = {0:X2}", (int)args.NewValue);
}
boxView.Color = Color.FromRgb((int)redSlider.Value,
(int)greenSlider.Value,
(int)blueSlider.Value);
}
}
A primeira seção define a Text
propriedade de uma das Label
instâncias como uma cadeia de caracteres de texto curta indicando o valor do Slider
hexadecimal em in. Em seguida, todas as três Slider
instâncias são acessadas para criar um Color
valor a partir dos componentes RGB:
Vinculando o controle deslizante a um ViewModel
A página HSL Color Sliders mostra como usar um ViewModel para executar os cálculos usados para criar um Color
valor a partir de valores de matiz, saturação e luminosidade. Como todos os ViewModels, a classe implementa HSLColorViewModel
a INotifyPropertyChanged
interface e dispara um PropertyChanged
evento sempre que uma das propriedades é alterada:
public class HslColorViewModel : INotifyPropertyChanged
{
Color color;
public event PropertyChangedEventHandler PropertyChanged;
public double Hue
{
set
{
if (color.Hue != value)
{
Color = Color.FromHsla(value, color.Saturation, color.Luminosity);
}
}
get
{
return color.Hue;
}
}
public double Saturation
{
set
{
if (color.Saturation != value)
{
Color = Color.FromHsla(color.Hue, value, color.Luminosity);
}
}
get
{
return color.Saturation;
}
}
public double Luminosity
{
set
{
if (color.Luminosity != value)
{
Color = Color.FromHsla(color.Hue, color.Saturation, value);
}
}
get
{
return color.Luminosity;
}
}
public Color Color
{
set
{
if (color != value)
{
color = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Hue"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Saturation"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Luminosity"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Color"));
}
}
get
{
return color;
}
}
}
ViewModels e a interface são discutidos INotifyPropertyChanged
no artigo Associação de dados.
O arquivo HslColorSlidersPage.xaml instancia o HslColorViewModel
e o define como a propriedade da BindingContext
página. Isso permite que todos os elementos no arquivo XAML sejam associados a propriedades no ViewModel:
<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" />
<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>
</ContentPage>
À medida que os Slider
elementos são manipulados, os BoxView
elementos e Label
são atualizados a partir do ViewModel:
O StringFormat
componente da extensão de Binding
marcação é definido para um formato de "F2" para exibir duas casas decimais. (A formatação de cadeia de caracteres em associações de dados é discutida no artigo Formatação de cadeia de caracteres.) No entanto, a versão UWP do programa é limitada a valores de 0, 0.1, 0.2, ... 0,9 e 1,0. Esse é um resultado direto da implementação da UWP Slider
, conforme descrito acima na seção Diferenças de implementação da plataforma.