Xamarin.Forms Suwak
Użyj suwaka do wybierania z zakresu wartości ciągłych.
Jest Xamarin.FormsSlider
to poziomy pasek, który może być manipulowany przez użytkownika w celu wybrania double
wartości z zakresu ciągłego.
Definiuje Slider
trzy właściwości typu double
:
Minimum
jest minimalną wartością zakresu z wartością domyślną 0.Maximum
jest maksymalną wartością zakresu z wartością domyślną 1.Value
jest wartością suwaka, która może zawierać zakres między wartościamiMinimum
iMaximum
i ma wartość domyślną 0.
Wszystkie trzy właściwości są wspierane przez BindableProperty
obiekty. Właściwość Value
ma domyślny tryb BindingMode.TwoWay
powiązania , co oznacza, że jest odpowiedni jako źródło powiązania w aplikacji korzystającej z architektury Model-View-ViewModel (MVVM).
Ostrzeżenie
Wewnętrznie zapewnia Slider
, że Minimum
wartość jest mniejsza niż Maximum
. Jeśli wartość Minimum
lub Maximum
kiedykolwiek jest ustawiona tak, że Minimum
nie jest mniejsza niż Maximum
, zgłaszany jest wyjątek. Aby uzyskać więcej informacji na temat ustawiania właściwości iMaximum
, zobacz sekcję Środki ostrożności poniżej.Minimum
Właściwość Slider
jest przekształcana Value
w taki sposób, aby mieściła się między Minimum
i Maximum
, włącznie. Minimum
Jeśli właściwość jest ustawiona na wartość większą niż Value
właściwość, Slider
właściwość ustawia Value
wartość Minimum
. Podobnie, jeśli Maximum
ustawiono wartość mniejszą niż Value
, Slider
właściwość ustawia Value
wartość na Maximum
.
Slider
ValueChanged
Definiuje zdarzenie, które jest wyzwalane, gdy Value
zmiany są uruchamiane za pomocą manipulowania Slider
przez użytkownika lub, gdy program ustawia Value
właściwość bezpośrednio. Zdarzenie ValueChanged
jest również wyzwalane, gdy Value
właściwość jest coerced zgodnie z opisem w poprzednim akapicie.
Obiekt ValueChangedEventArgs
, który towarzyszy ValueChanged
zdarzeniu ma dwie właściwości: double
i OldValue
NewValue
. W momencie uruchomienia zdarzenia wartość NewValue
jest taka sama jak Value
właściwość Slider
obiektu.
Slider
definiuje DragStarted
również zdarzenia, DragCompleted
które są uruchamiane na początku i na końcu akcji przeciągania. ValueChanged
W przeciwieństwie do zdarzenia zdarzenia zdarzenia DragStarted
i DragCompleted
są wyzwalane tylko za pomocą manipulacji użytkownikami .Slider
Gdy zdarzenie DragStarted
jest uruchamiane, DragStartedCommand
jest wykonywany typ ICommand
, . Podobnie, gdy DragCompleted
zdarzenie jest uruchamiane, DragCompletedCommand
jest wykonywany typ , ICommand
.
Ostrzeżenie
Nie należy używać nieobsługiwanych opcji układu poziomego , Center
Start
lub End
za pomocą polecenia Slider
. Zarówno w systemie Android, jak i uwP, Slider
zwija się na słupek o zerowej długości, a w systemie iOS pasek jest bardzo krótki. Zachowaj ustawienie domyślne HorizontalOptions
elementu Fill
i nie używaj szerokości Auto
podczas umieszczania Slider
Grid
w układzie.
Definiuje Slider
również kilka właściwości, które wpływają na jej wygląd:
MinimumTrackColor
to kolor paska po lewej stronie kciuka.MaximumTrackColor
to kolor paska po prawej stronie kciuka.ThumbColor
jest kolorem kciuka.ThumbImageSource
to obraz używany dla kciuka typuImageSource
.
Uwaga
Właściwości ThumbColor
i ThumbImageSource
wzajemnie się wykluczają. Jeśli obie właściwości są ustawione, ThumbImageSource
właściwość będzie mieć pierwszeństwo.
Kod i znaczniki suwaka podstawowego
Przykład zaczyna się od trzech stron, które są funkcjonalnie identyczne, ale są implementowane na różne sposoby. Pierwsza strona używa tylko kodu C#, drugi używa języka XAML z procedurą obsługi zdarzeń w kodzie, a trzecia jest w stanie uniknąć obsługi zdarzeń przy użyciu powiązania danych w pliku XAML.
Tworzenie suwaka w kodzie
Na stronie Kod suwaka podstawowego pokazano, jak utworzyć i Slider
dwa Label
obiekty w kodzie:
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
}
};
}
}
Właściwość Slider
jest inicjowana jako Maximum
właściwość 360. Procedura obsługi używa właściwości obiektu do ustawienia Rotation
właściwości pierwszego Label
i używa String.Format
metody z właściwością NewValue
argumentów zdarzeń, aby ustawić Text
właściwość drugiego Label
obiektu .slider
Value
Slider
ValueChanged
Te dwa podejścia do uzyskania bieżącej Slider
wartości są zamienne.
Oto program uruchomiony na urządzeniach z systemami iOS i Android:
Drugi Label
wyświetla tekst "(niezainicjowany)", dopóki Slider
nie zostanie zmanipulowany, co powoduje wyzwolenie pierwszego ValueChanged
zdarzenia. Zwróć uwagę, że liczba wyświetlanych miejsc dziesiętnych jest inna dla każdej platformy. Te różnice są związane z implementacjami Slider
platformy programu i zostały omówione w dalszej części tego artykułu w sekcji Różnice implementacji platformy.
Tworzenie suwaka w języku XAML
Strona XAML suwaka podstawowego jest funkcjonalnie taka sama jak podstawowy kod suwaka, ale zaimplementowana głównie w języku 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>
Plik związany z kodem zawiera procedurę obsługi zdarzenia 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);
}
}
Program obsługi zdarzeń może również uzyskać Slider
wyzwalanie zdarzenia za pomocą argumentu sender
. Właściwość Value
zawiera bieżącą wartość:
double value = ((Slider)sender).Value;
Slider
Jeśli obiekt otrzymał nazwę w pliku XAML z atrybutem x:Name
(na przykład "slider"), program obsługi zdarzeń może odwoływać się bezpośrednio do tego obiektu:
double value = slider.Value;
Powiązanie danych suwaka
Na stronie Podstawowe powiązania suwaka pokazano, jak napisać niemal równoważny program eliminujący Value
procedurę obsługi zdarzeń przy użyciu powiązania danych:
<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>
Właściwość Rotation
pierwszego Label
jest powiązana Value
z właściwością Slider
, podobnie jak Text
właściwość drugiego ze specyfikacjąStringFormat
.Label
Strona Podstawowe powiązania suwaka działa nieco inaczej niż na dwóch poprzednich stronach: Po pierwszym wyświetleniu strony drugi Label
wyświetla ciąg tekstowy z wartością . Jest to korzyść z używania powiązania danych. Aby wyświetlić tekst bez powiązania danych, należy w szczególności zainicjować Text
właściwość Label
obiektu lub zasymulować wyzwalanie ValueChanged
zdarzenia przez wywołanie procedury obsługi zdarzeń z konstruktora klasy.
Środki ostrożności
Wartość Minimum
właściwości musi być zawsze mniejsza niż wartość Maximum
właściwości. Poniższy fragment kodu powoduje wystąpienie wyjątku Slider
:
// Throws an exception!
Slider slider = new Slider
{
Minimum = 10,
Maximum = 20
};
Kompilator języka C# generuje kod, który ustawia te dwie właściwości w sekwencji, a gdy Minimum
właściwość jest ustawiona na 10, jest większa niż wartość domyślna Maximum
1. Można uniknąć wyjątku w tym przypadku, ustawiając Maximum
najpierw właściwość:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Ustawienie Maximum
wartości 20 nie jest problemem, ponieważ jest większe niż wartość domyślna Minimum
0. Po Minimum
ustawieniu wartość jest mniejsza niż Maximum
wartość 20.
Ten sam problem występuje w języku XAML. Ustaw właściwości w kolejności, która gwarantuje, że Maximum
wartość jest zawsze większa niż Minimum
:
<Slider Maximum="20"
Minimum="10" ... />
Wartości i można ustawić Minimum
na liczby ujemne, ale tylko w kolejności, w której Minimum
wartość jest zawsze mniejsza niż Maximum
:Maximum
<Slider Minimum="-20"
Maximum="-10" ... />
Właściwość Value
jest zawsze większa lub równa Minimum
wartości i mniejsza niż lub równa Maximum
. Jeśli Value
zostanie ustawiona wartość poza tym zakresem, wartość będzie zmuszana do leżenia w zakresie, ale nie zostanie zgłoszony żaden wyjątek. Na przykład ten kod nie zgłosi wyjątku:
Slider slider = new Slider
{
Value = 10
};
Value
Zamiast tego właściwość jest coerced na Maximum
wartość 1.
Poniżej przedstawiono fragment kodu:
Slider slider = new Slider
{
Maximum = 20,
Minimum = 10
};
Gdy Minimum
jest ustawiona wartość 10, wartość Value
jest również ustawiona na 10.
ValueChanged
Jeśli program obsługi zdarzeń został dołączony w momencie, Value
gdy właściwość jest coerced do czegoś innego niż jego domyślna wartość 0, ValueChanged
zdarzenie zostanie wyzwolone. Oto fragment kodu XAML:
<Slider ValueChanged="OnSliderValueChanged"
Maximum="20"
Minimum="10" />
Gdy Minimum
wartość jest ustawiona na 10, Value
jest również ustawiona na 10, a ValueChanged
zdarzenie zostanie wyzwolone. Może się to zdarzyć przed utworzeniem pozostałej części strony, a program obsługi może próbować odwołać się do innych elementów na stronie, które nie zostały jeszcze utworzone. Możesz dodać kod do ValueChanged
programu obsługi, który sprawdza null
wartości innych elementów na stronie. Można też ustawić procedurę ValueChanged
obsługi zdarzeń po Slider
zainicjowaniu wartości.
Różnice implementacji platformy
Pokazane wcześniej zrzuty ekranu przedstawiają wartość Slider
z inną liczbą punktów dziesiętnych. Dotyczy to sposobu implementacji na Slider
platformach Android i UWP.
Implementacja systemu Android
Implementacja Slider
systemu Android jest oparta na systemie Android SeekBar
i zawsze ustawia Max
właściwość na 1000. Oznacza to, że Slider
w systemie Android jest tylko 1001 wartości dyskretnych. Jeśli dla właściwości ustawiono Slider
Minimum
wartość 0 i Maximum
5000, właściwość Slider
Value
ma wartości 0, 10, 15 itd.
Implementacja platformy UWP
Implementacja platformy UNIWERSALNEJ systemu Slider
Windows jest oparta na kontrolce platformy UWP Slider
. Właściwość StepFrequency
platformy UWP Slider
jest ustawiona na różnicę Maximum
właściwości i Minimum
podzieloną przez 10, ale nie większą niż 1.
Na przykład dla domyślnego zakresu od 0 do 1 StepFrequency
właściwość jest ustawiona na 0,1. W miarę Slider
manipulowania Value
właściwość jest ograniczona do wartości 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 i 1.0. Gdy różnica między właściwościami Maximum
i Minimum
wynosi 10 lub większa, StepFrequency
jest ustawiona na 1, a Value
właściwość ma wartości całkowite.
Rozwiązanie StepSlider
Bardziej wszechstronny jest omówiony w rozdziale StepSlider
27. Niestandardowe programy renderowania książki Creating Mobile Apps with Xamarin.Forms. Właściwość jest podobna StepSlider
do Slider
, ale dodaje Steps
właściwość , aby określić liczbę wartości między Minimum
i Maximum
.
Suwaki wyboru kolorów
Obie ostatnie dwie strony w przykładzie używają trzech Slider
wystąpień do wyboru kolorów. Pierwsza strona obsługuje wszystkie interakcje w pliku za pomocą kodu, a druga strona pokazuje, jak używać powiązania danych z modelem ViewModel.
Obsługa suwaków w pliku za pomocą kodu
Strona Suwaki kolorów RGB tworzy wystąpienie elementu w BoxView
celu wyświetlenia koloru, trzech Slider
wystąpień do wybrania czerwonych, zielonych i niebieskich składników koloru oraz trzech Label
elementów do wyświetlania tych wartości kolorów:
<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>
Element A Style
daje wszystkie trzy Slider
elementy z zakresu od 0 do 255. Slider
Elementy współużytkuje tę samą ValueChanged
procedurę obsługi, która jest implementowana w pliku za kodem:
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);
}
}
Pierwsza sekcja ustawia Text
właściwość jednego z Label
wystąpień na krótki ciąg tekstowy wskazujący wartość Slider
w szesnastkowym. Następnie dostęp do wszystkich trzech Slider
wystąpień jest uzyskiwany w celu utworzenia Color
wartości na podstawie składników RGB:
Wiązanie suwaka z modelem ViewModel
Na stronie Suwaki kolorów HSL pokazano, jak używać modelu ViewModel do wykonywania obliczeń używanych do tworzenia Color
wartości na podstawie odcieni, nasycenia i jasności. Podobnie jak w przypadku wszystkich modeli ViewModel, klasa implementuje INotifyPropertyChanged
PropertyChanged
interfejs i uruchamia zdarzenie za każdym razem, HSLColorViewModel
gdy jedna z właściwości ulegnie zmianie:
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;
}
}
}
Modele widoków i INotifyPropertyChanged
interfejs zostały omówione w artykule Powiązanie danych.
Plik HslColorSlidersPage.xaml tworzy wystąpienie HslColorViewModel
obiektu i ustawia go na właściwość strony BindingContext
. Dzięki temu wszystkie elementy w pliku XAML mogą być powiązane z właściwościami w modelu 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>
Slider
Gdy elementy są manipulowane, BoxView
elementy i Label
są aktualizowane z modelu ViewModel:
Składnik StringFormat
Binding
rozszerzenia znaczników jest ustawiony dla formatu "F2", aby wyświetlić dwa miejsca dziesiętne. (Formatowanie ciągu w powiązaniach danych zostało omówione w artykule Formatowanie ciągu). Jednak wersja platformy UWP programu jest ograniczona do wartości 0, 0,1, 0,2, ... 0.9 i 1.0. Jest to bezpośredni wynik implementacji platformy UWP Slider
, jak opisano powyżej w sekcji Różnice implementacji platformy.