Xamarin.Forms Control deslizante
Use un control deslizante para seleccionar entre un intervalo de valores continuos.
Xamarin.FormsSlider
es una barra horizontal que el usuario puede manipular para seleccionar un double
valor de un intervalo continuo.
Slider
Define tres propiedades de tipo double
:
Minimum
es el valor mínimo del rango, con un valor predeterminado de 0.Maximum
es el máximo del intervalo, con un valor predeterminado de 1.Value
es el valor del control deslizante, que puede oscilar entreMinimum
yMaximum
y tiene un valor predeterminado de 0.
Los objetos respaldan BindableProperty
las tres propiedades. La Value
propiedad tiene un modo de enlace predeterminado de BindingMode.TwoWay
, lo que significa que es adecuado como origen de enlace en una aplicación que usa la arquitectura Model-View-ViewModel (MVVM).
Advertencia
Internamente, Slider
garantiza que Maximum
sea menor que Minimum
. Si Minimum
o Maximum
se establecen alguna vez para que Maximum
no sea menor que Minimum
, se genera una excepción. Consulte la sección Precauciones a continuación para obtener más información sobre cómo establecer las Minimum
propiedades y Maximum
.
El Slider
reprime la propiedad Value
para que esté entre Minimum
y Maximum
, ambos inclusive. Si la propiedad Minimum
se establece en un valor mayor que la propiedad Value
, Slider
establece la propiedad Value
en Minimum
. Del mismo modo, si Maximum
se establece en un valor menor que Value
, Slider
establece la propiedad Value
en Maximum
.
Slider
define un ValueChanged
evento que se desencadena cuando cambia Value
, ya sea a través de la manipulación del usuario de Slider
o cuando el programa establece la Value
propiedad directamente. También se desencadena un ValueChanged
evento cuando la Value
propiedad se coercite como se describe en el párrafo anterior.
El ValueChangedEventArgs
objeto que acompaña al ValueChanged
evento tiene dos propiedades, de tipo double
: OldValue
y NewValue
. En el momento en que se desencadena el evento, el valor de es el mismo que NewValue
la Value
propiedad del Slider
objeto .
Slider
también define y DragStarted
DragCompleted
eventos, que se activan al principio y al final de la acción de arrastrar. A diferencia del ValueChanged
evento , los DragStarted
eventos y DragCompleted
solo se desencadenan a través de la Slider
manipulación del usuario de . Cuando se desencadena el evento DragStarted
, se ejecuta DragStartedCommand
de tipo ICommand
. Del mismo modo, cuando se desencadena el evento DragCompleted
, se ejecuta DragCompletedCommand
de tipo ICommand
.
Advertencia
No uses opciones de diseño horizontal sin restricciones de Center
, Start
o End
con Slider
. Tanto en Android como en UWP, el Slider
se contrae a una barra de longitud cero y, en iOS, la barra es muy corta. Mantén la configuración predeterminada HorizontalOptions
de Fill
y no uses un ancho de Auto
al colocar Slider
en un diseño Grid
.
También Slider
define varias propiedades que afectan a su apariencia:
MinimumTrackColor
es el color de la barra en el lado izquierdo del pulgar.MaximumTrackColor
es el color de la barra en el lado derecho del pulgar.ThumbColor
es el color del pulgar.ThumbImageSource
es la imagen que se va a usar para el control pulgar, de tipoImageSource
.
Nota:
Las propiedades ThumbColor
y ThumbImageSource
se excluyen mutuamente. Si se establecen ambas propiedades, la propiedad ThumbImageSource
tendrá precedencia.
Código y marcado básicos del control deslizante
El ejemplo SliderDemos comienza con tres páginas que son funcionalmente idénticas, pero se implementan de maneras diferentes. La primera página usa solo código de C#, el segundo usa XAML con un controlador de eventos en el código y el tercero puede evitar el controlador de eventos mediante el enlace de datos en el archivo XAML.
Creación de un control deslizante en el código
La página Código de control deslizante básico del ejemplo SliderDemos muestra mostrar para crear un Slider
objeto y dos Label
objetos en el 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
}
};
}
}
Slider
se inicializa para tener una Maximum
propiedad de 360. El ValueChanged
controlador de Slider
utiliza la Value
propiedad del slider
objeto para establecer la Rotation
propiedad del primero Label
y usa el String.Format
método con la NewValue
propiedad de los argumentos de evento para establecer la Text
propiedad del segundo Label
. Estos dos enfoques para obtener el valor actual de Slider
son intercambiables.
Este es el programa que se ejecuta en dispositivos iOS y Android:
El segundo Label
muestra el texto "(sin inicializar)" hasta Slider
que se manipula , lo que hace que se desencadene el primer ValueChanged
evento. Observe que el número de posiciones decimales que se muestran es diferente para cada plataforma. Estas diferencias están relacionadas con las implementaciones de la plataforma de Slider
y se describen más adelante en este artículo en la sección Diferencias de implementación de la plataforma.
Crear un control deslizante en XAML
La página XAML de control deslizante básico es funcionalmente la misma que el código deslizante básico, pero se implementa principalmente en 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>
El archivo de código subyacente contiene el controlador para el 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);
}
}
También es posible que el controlador de eventos obtenga el Slider
que desencadena el evento a través del argumento sender
. La propiedad Value
contiene el valor actual:
double value = ((Slider)sender).Value;
Si el objeto Slider
recibió un nombre en el archivo XAML con un atributo x:Name
(por ejemplo, "slider"), el controlador de eventos podría hacer referencia directamente a ese objeto:
double value = slider.Value;
Enlace de datos al control deslizante
En la página Enlaces deslizantes básicos se muestra cómo escribir un programa casi equivalente que elimina el controlador de eventos mediante el Value
enlace de datos:
<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>
La Rotation
propiedad del primero Label
está enlazada a la Value
propiedad de Slider
, tal como es la Text
propiedad del segundo Label
con una StringFormat
especificación . La página Enlaces deslizantes básicos funciona de forma ligeramente diferente de las dos páginas anteriores: cuando aparece la página por primera vez, la segunda Label
muestra la cadena de texto con el valor . Esta es una ventaja de usar el enlace de datos. Para mostrar texto sin enlace de datos, tendrías que inicializar específicamente la propiedad Text
de Label
o simular una activación del evento ValueChanged
mediante una llamada al controlador de eventos desde el constructor de clase.
Precauciones
El valor de la propiedad Minimum
debe ser siempre inferior que el valor de la propiedad Maximum
. El siguiente fragmento de código hace que Slider
genere una excepción:
// Throws an exception!
Slider slider = new Slider
{
Minimum = 10,
Maximum = 20
};
El compilador de C# genera código que establece estas dos propiedades en secuencia y, cuando la propiedad Minimum
se establece en 10, es mayor que el valor predeterminado Maximum
de 1. Puedes evitar la excepción en este caso estableciendo primero la propiedad Maximum
:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Establecer Maximum
en 20 no es un problema porque es mayor que el valor predeterminado Minimum
de 0. Cuando Minimum
se establece, el valor es menor que el valor Maximum
de 20.
El mismo problema existe en XAML. Establece las propiedades en un orden que garantice que Maximum
siempre sea mayor que Minimum
:
<Slider Maximum="20"
Minimum="10" ... />
Luego, puedes establecer los valores Minimum
y Maximum
en números negativos, pero solo en un orden donde Minimum
siempre sea menor que Maximum
:
<Slider Minimum="-20"
Maximum="-10" ... />
La propiedad Value
siempre es mayor o igual que el valor Minimum
y menor o igual que Maximum
. Si Value
se establece en un valor fuera de ese intervalo, el valor se reprimirá para que se encuentre dentro del intervalo, pero no se genera ninguna excepción. Por ejemplo, este código no generará una excepción:
Slider slider = new Slider
{
Value = 10
};
En su lugar, la propiedad Value
se convierte en el valor Maximum
de 1.
Este es un fragmento de código que se muestra anteriormente:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Cuando Minimum
se establece en 10, Value
también se establece en 10.
Si un ValueChanged
controlador de eventos se ha adjuntado en el momento en que la Value
propiedad está coercedida a algo distinto de su valor predeterminado de 0, se desencadena un ValueChanged
evento. Este es un fragmento de código XAML:
<Slider ValueChanged="OnSliderValueChanged"
Maximum="20"
Minimum="10" />
Cuando Minimum
se establece en 10, Value
también se establece en 10 y el ValueChanged
evento se desencadena. Esto puede ocurrir antes de que se haya construido el resto de la página y el controlador podría intentar hacer referencia a otros elementos de la página que aún no se han creado. Es posible que desees agregar código al controlador ValueChanged
que comprueba si hay valores null
de otros elementos en la página. O bien, puedes establecer el controlador de eventos ValueChanged
después de inicializar los valores Slider
.
Diferencias de implementación de la plataforma
Las capturas de pantalla mostradas anteriormente muestran el valor de Slider
con un número diferente de puntos decimales. Esto se relaciona con cómo se implementa en Slider
las plataformas Android y UWP.
Implementación de Android
La implementación de Android de Slider
se basa en Android SeekBar
y siempre establece la Max
propiedad en 1000. Esto significa que en Slider
Android solo tiene 1001 valores discretos. Si establece que Slider
tiene un Minimum
de 0 y un Maximum
de 5000, a Slider
medida que se manipula, la Value
propiedad tiene valores de 0, 5, 10, 15, etc.
Implementación de UWP
La implementación de UWP de Slider
se basa en el control de UWP Slider
. La StepFrequency
propiedad de UWP Slider
se establece en la diferencia de las Maximum
propiedades y Minimum
divididas por 10, pero no mayores que 1.
Por ejemplo, para el intervalo predeterminado de 0 a 1, la StepFrequency
propiedad se establece en 0,1. Slider
A medida que se manipula, la Value
propiedad está restringida a 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 y 1.0. (Esto es evidente en la última página del Ejemplo SliderDemos ). Cuando la diferencia entre las Maximum
propiedades y Minimum
es 10 o superior, StepFrequency
se establece en 1 y la Value
propiedad tiene valores enteros.
La solución StepSlider
Se analiza un elemento más versátil StepSlider
en el capítulo 27. Representadores personalizados del libro Creación de aplicaciones móviles con Xamarin.Forms. StepSlider
es similar a Slider
pero agrega una Steps
propiedad para especificar el número de valores entre Minimum
y Maximum
.
Controles deslizantes para la selección de colores
Las dos páginas finales del ejemplo SliderDemos usan tres Slider
instancias para la selección de colores. La primera página controla todas las interacciones del archivo de código subyacente, mientras que la segunda página muestra cómo usar el enlace de datos con un ViewModel.
Control de controles deslizantes en el archivo de código subyacente
La página Controles deslizantes de color RGB crea una instancia BoxView
de para mostrar un color, tres Slider
instancias para seleccionar los componentes rojo, verde y azul del color, y tres Label
elementos para mostrar esos valores de color:
<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>
Un Style
proporciona a los tres Slider
elementos un intervalo de 0 a 255. Los Slider
elementos comparten el mismo ValueChanged
controlador, que se implementa en el archivo de código subyacente:
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);
}
}
La primera sección establece la Text
propiedad de una de las Label
instancias en una cadena de texto corta que indica el valor de Slider
en hexadecimal. A continuación, se accede a las tres Slider
instancias para crear un Color
valor a partir de los componentes RGB:
Enlazar el control deslizante a un ViewModel
En la página Controles deslizantes de color HSL se muestra cómo usar un ViewModel para realizar los cálculos utilizados para crear un Color
valor a partir de valores de tono, saturación y luminosidad. Al igual que todos los ViewModels, la HSLColorViewModel
clase implementa la INotifyPropertyChanged
interfaz y desencadena un PropertyChanged
evento cada vez que una de las propiedades cambia:
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 y la INotifyPropertyChanged
interfaz se describen en el artículo Enlace de datos.
El archivo HslColorSlidersPage.xaml crea una instancia de HslColorViewModel
y lo establece en la propiedad de BindingContext
la página. Esto permite que todos los elementos del archivo XAML se enlacen a las propiedades de 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>
A medida que se manipulan los Slider
elementos , los BoxView
elementos y Label
se actualizan desde viewModel:
El StringFormat
componente de la Binding
extensión de marcado se establece para un formato de "F2" para mostrar dos posiciones decimales. (El formato de cadena en los enlaces de datos se describe en el artículo Formato de cadena). Sin embargo, la versión de UWP del programa se limita a los valores de 0, 0.1, 0.2, ... 0.9 y 1.0. Este es un resultado directo de la implementación de la UWP Slider
como se ha descrito anteriormente en la sección Diferencias de implementación de la plataforma.