Xamarin.Forms Slider
Use um controle deslizante para selecionar a partir de um intervalo de valores contínuos.
O 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 vinculação padrão de BindingMode.TwoWay
, o que significa que ela é adequada como uma fonte de vinculação em um aplicativo que usa a arquitetura MVVM (Model-View-ViewModel).
Aviso
Internamente, a Slider
garantia é menor que Minimum
Maximum
. Se Minimum
ou Maximum
alguma vez forem definidos de modo que Minimum
não seja inferior a , uma exceção é levantada Maximum
. Consulte a seção Precauções abaixo para obter mais informações sobre como definir as Minimum
propriedades e Maximum
.
O Slider
coage o Value
imóvel para que ele fique entre Minimum
e Maximum
, inclusive. Se a Minimum
propriedade for definida como um valor maior que a Value
propriedade, a Slider
propriedade será definida Value
como Minimum
. Da mesma forma, se Maximum
for definido como um valor menor que Value
, defina Slider
a Value
propriedade como Maximum
.
Slider
Define um ValueChanged
evento que é acionado quando as Value
alterações, por meio da manipulação do Slider
usuário do ou quando o programa define a Value
propriedade diretamente. Um ValueChanged
evento também é disparado 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 é acionado, 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 através 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
. Tanto no Android quanto na UWP, a Slider
barra é reduzida para 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 estiverem definidas, a ThumbImageSource
propriedade terá precedência.
Código e marcação básicos do Slider
O exemplo SliderDemos 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 vinculação de dados no arquivo XAML.
Criando um controle deslizante no código
A página Código Deslizante Básico no exemplo SliderDemos mostra a criação de 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 slider
Value
propriedade do objeto para definir a Rotation
propriedade do primeiro Label
e usa o String.Format
método com a NewValue
propriedade dos 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 em dispositivos iOS e Android:
O segundo Label
exibe o texto "(não inicializado)" até que o seja manipulado, o Slider
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 e são discutidas posteriormente neste artigo na seção Diferenças de implementação de Slider
plataforma.
Criando um controle deslizante em XAML
A página XAML do Controle Deslizante Básico é funcionalmente igual ao Código 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 para o ValueChanged
evento:
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 recebeu um nome no arquivo XAML com um x:Name
atributo (por exemplo, "slider"), o manipulador de eventos poderia fazer referência a esse objeto diretamente:
double value = slider.Value;
Vinculação de dados ao controle deslizante
A página Ligações Deslizantes Básicas mostra como escrever um programa quase equivalente que elimina o manipulador de eventos usando a Value
Vinculaçã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á vinculada à Value
propriedade do Slider
, assim como a Text
propriedade do segundo Label
com uma StringFormat
especificação. A página Basic Slider Bindings funciona de forma um pouco diferente das duas páginas anteriores: quando a página aparece pela primeira vez, a segunda Label
exibe a cadeia de texto com o valor. Esse é um benefício do uso da vinculação de dados. Para exibir texto sem associação de dados, você precisaria inicializar especificamente a Text
propriedade do Label
ou simular um disparo do ValueChanged
evento chamando o manipulador de eventos do construtor de classe.
Precauções
O valor do Minimum
imóvel deve ser sempre menor que o valor do Maximum
imóvel. O trecho 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 do que o valor padrão Minimum
de 0. Quando Minimum
é definido, o valor é menor que o Maximum
valor de 20.
O mesmo problema existe em 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
para números negativos, mas somente em uma ordem em que Minimum
é 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á coagido a ficar dentro do intervalo, mas nenhuma exceção será gerada. Por exemplo, esse código não gerará uma exceção:
Slider slider = new Slider
{
Value = 10
};
Em vez disso, a Value
propriedade é coagida 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, em seguida Value
, também é definido como 10.
Se um ValueChanged
manipulador de eventos tiver sido anexado no momento em que a Value
propriedade for coagida a algo diferente de seu valor padrão de 0, um ValueChanged
evento será acionado. 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
valores de outros elementos na página. Ou, você pode definir o ValueChanged
manipulador de eventos depois que os Slider
valores foram inicializados.
Diferenças de implementação da plataforma
As capturas de tela mostradas anteriormente exibem o valor do Slider
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
para ter um Minimum
de 0 e um Maximum
de 5000, então como o Slider
é manipulado, a Value
propriedade tem valores de 0, 5, 10, 15 e assim por diante.
A implementação da UWP
A implementação da UWP é Slider
baseada no controle UWP Slider
. A StepFrequency
propriedade da UWP Slider
é definida como a diferença das Maximum
propriedades e Minimum
divididas 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. Como 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. (Isso fica evidente na última página do Exemplo de SliderDemos .) Quando a diferença entre as Maximum
propriedades e Minimum
é 10 ou maior, então StepFrequency
é definido como 1 e a Value
propriedade tem valores integrais.
A solução StepSlider
Um mais versátil StepSlider
é discutido no capítulo 27. Renderizadores personalizados do livro Criando aplicativos móveis com Xamarin.Formso . O StepSlider
é semelhante a Slider
, 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 no exemplo SliderDemos usam três Slider
instâncias para seleção de cores. A primeira página manipula todas as interações no arquivo code-behind, enquanto a segunda página mostra como usar a vinculação de dados com um ViewModel.
Manipulando controles deslizantes no arquivo code-behind
A página Controles Deslizantes de Cores RGB instancia um 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 Style
dá a 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
ocorrências como uma cadeia de caracteres de texto curto indicando o valor do Slider
hexadecimal 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 Controles deslizantes de cores HSL 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 INotifyPropertyChanged
interface são discutidos no artigo Vinculaçã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 se associem às 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 são Label
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. Isso é um resultado direto da implementação da UWP Slider
, conforme descrito acima na seção Diferenças de implementação da plataforma.