Xamarin.Forms Controllo Slider

Download Sample Scaricare l'esempio

Usare un dispositivo di scorrimento per la selezione da un intervallo di valori continui.

Xamarin.FormsSlider è una barra orizzontale che può essere modificata dall'utente per selezionare un double valore da un intervallo continuo.

Definisce Slider tre proprietà di tipo double:

  • Minimum è il valore minimo dell'intervallo, con un valore predefinito pari a 0.
  • Maximum è il valore massimo dell'intervallo, con un valore predefinito pari a 1.
  • Value è il valore del dispositivo di scorrimento, che può variare tra Minimum e Maximum e ha un valore predefinito pari a 0.

Tutte e tre le proprietà sono supportate da BindableProperty oggetti . La Value proprietà ha una modalità di associazione predefinita di BindingMode.TwoWay, il che significa che è adatto come origine di associazione in un'applicazione che usa l'architettura Model-View-ViewModel (MVVM).

Avviso

Internamente, garantisce Slider che Minimum sia minore di Maximum. Se Minimum o Maximum sono mai impostati in modo che Minimum non sia minore di Maximum, viene generata un'eccezione. Per altre informazioni sull'impostazione delle proprietà eMaximum, vedere la sezione Precauzioni di seguito.Minimum

La Slider proprietà viene impostata Value in modo che sia compresa tra Minimum e Maximum, inclusiva. Se la Minimum proprietà è impostata su un valore maggiore della Value proprietà , la SliderValue proprietà viene impostata su Minimum. Analogamente, se Maximum è impostato su un valore minore di Value, Slider la Value proprietà viene impostata su Maximum.

Slider definisce un ValueChanged evento generato quando cambia Value , tramite la manipolazione dell'utente di Slider o quando il programma imposta direttamente la Value proprietà. Un ValueChanged evento viene generato anche quando la Value proprietà è forzata come descritto nel paragrafo precedente.

L'oggetto ValueChangedEventArgs che accompagna l'evento ValueChanged ha due proprietà, entrambe di tipo double: OldValue e NewValue. Al momento della generazione dell'evento, il valore di NewValue è uguale alla Value proprietà dell'oggetto Slider .

Slider definisce DragStarted inoltre gli eventi e DragCompleted generati all'inizio e alla fine dell'azione di trascinamento. A differenza dell'evento ValueChanged , gli DragStarted eventi e DragCompleted vengono generati solo tramite la Slidermanipolazione dell'utente di . Quando viene generato l'evento DragStarted , DragStartedCommanddi tipo ICommand, viene eseguito . Analogamente, quando viene generato l'evento DragCompleted , DragCompletedCommanddi tipo ICommand, viene eseguito .

Avviso

Non usare opzioni di layout orizzontale senza vincoli di Center, Starto End con Slider. Sia in Android che nella piattaforma UWP, il Slider comprime su una barra di lunghezza zero e su iOS la barra è molto breve. Mantenere l'impostazione predefinita HorizontalOptions di Fille non usare una larghezza di Auto quando si inserisce Slider un Grid layout.

Definisce Slider anche diverse proprietà che ne influiscono sull'aspetto:

Nota

Le ThumbColor proprietà e ThumbImageSource si escludono a vicenda. Se vengono impostate entrambe le proprietà, la proprietà avrà la ThumbImageSource precedenza.

Codice e markup di base del dispositivo di scorrimento

L'esempio SliderDemos inizia con tre pagine identiche a livello funzionale, ma implementate in modi diversi. La prima pagina usa solo il codice C#, il secondo usa XAML con un gestore eventi nel codice e il terzo è in grado di evitare il gestore eventi usando il data binding nel file XAML.

Creazione di un dispositivo di scorrimento nel codice

La pagina Codice dispositivo di scorrimento di base nell'esempio SliderDemos mostra come creare un Slider oggetto e due Label oggetti nel codice:

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
            }
        };
    }
}

L'oggetto Slider viene inizializzato per avere una Maximum proprietà di 360. Il ValueChanged gestore dell'oggetto Slider utilizza la Value proprietà dell'oggetto slider per impostare la Rotation proprietà del primo Label oggetto e utilizza il String.Format metodo con la NewValue proprietà degli argomenti dell'evento per impostare la Text proprietà del secondo Label. Questi due approcci per ottenere il valore corrente di Slider sono intercambiabili.

Ecco il programma in esecuzione nei dispositivi iOS e Android:

Basic Slider Code

Il secondo Label visualizza il testo "(non inizializzato)" fino a quando l'oggetto Slider non viene modificato, causando la generazione del primo ValueChanged evento. Si noti che il numero di posizioni decimali visualizzate è diverso per ogni piattaforma. Queste differenze sono correlate alle implementazioni della piattaforma di Slider e sono descritte più avanti in questo articolo nella sezione Differenze di implementazione della piattaforma.

Creazione di un dispositivo di scorrimento in XAML

La pagina XAML Del dispositivo di scorrimento di base è funzionalmente identica a Quella del dispositivo di scorrimento di base, ma implementata principalmente in 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>

Il file code-behind contiene il gestore per l'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);
    }
}

È anche possibile che il gestore eventi ottenga l'oggetto Slider che genera l'evento tramite l'argomento sender . La Value proprietà contiene il valore corrente:

double value = ((Slider)sender).Value;

Se all'oggetto Slider è stato assegnato un nome nel file XAML con un x:Name attributo ,ad esempio "slider", il gestore eventi potrebbe fare riferimento direttamente a tale oggetto:

double value = slider.Value;

Data binding del dispositivo di scorrimento

Nella pagina Binding di dispositivo di scorrimento di base viene illustrato come scrivere un programma quasi equivalente che elimina il Value gestore eventi tramite data binding:

<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 proprietà del primo Label è associata alla Value proprietà di Slider, così come è la Text proprietà del secondo Label con una StringFormat specifica. La pagina Basic Slider Bindings funziona in modo leggermente diverso dalle due pagine precedenti: quando viene visualizzata la prima pagina, la seconda Label visualizza la stringa di testo con il valore . Questo è un vantaggio dell'uso del data binding. Per visualizzare testo senza data binding, è necessario inizializzare in modo specifico la Text proprietà dell'oggetto Label o simulare una generazione dell'evento ValueChanged chiamando il gestore eventi dal costruttore della classe.

Precauzioni

Il valore della Minimum proprietà deve essere sempre minore del valore della Maximum proprietà. Il frammento di codice seguente fa sì che generi un'eccezione Slider :

// Throws an exception!
Slider slider = new Slider
{
    Minimum = 10,
    Maximum = 20
};

Il compilatore C# genera codice che imposta queste due proprietà in sequenza e quando la Minimum proprietà è impostata su 10, è maggiore del valore predefinito Maximum 1. È possibile evitare l'eccezione in questo caso impostando prima la Maximum proprietà :

Slider slider = new Slider
{
    Maximum = 20,
    Minimum = 10
};

L'impostazione Maximum su 20 non è un problema perché è maggiore del valore predefinito Minimum 0. Quando Minimum è impostato, il valore è minore del Maximum valore di 20.

Lo stesso problema esiste in XAML. Impostare le proprietà in un ordine che garantisce che Maximum sia sempre maggiore di Minimum:

<Slider Maximum="20"
        Minimum="10" ... />

È possibile impostare i Minimum valori e Maximum su numeri negativi, ma solo in un ordine in cui Minimum è sempre minore di Maximum:

<Slider Minimum="-20"
        Maximum="-10" ... />

La Value proprietà è sempre maggiore o uguale al Minimum valore e minore o uguale a Maximum. Se Value è impostato su un valore esterno a tale intervallo, il valore verrà costretto a trovarsi all'interno dell'intervallo, ma non viene generata alcuna eccezione. Ad esempio, questo codice non genererà un'eccezione:

Slider slider = new Slider
{
    Value = 10
};

La proprietà viene invece Value associata al Maximum valore 1.

Ecco un frammento di codice illustrato sopra:

Slider slider = new Slider
{
    Maximum = 20,
    Minimum = 10
};

Quando Minimum è impostato su 10, Value viene impostato anche su 10.

Se un ValueChanged gestore eventi è stato associato al momento in cui la Value proprietà è associata a un valore diverso dal valore predefinito 0, viene generato un ValueChanged evento. Ecco un frammento di codice XAML:

<Slider ValueChanged="OnSliderValueChanged"
        Maximum="20"
        Minimum="10" />

Quando Minimum è impostato su 10, Value viene impostato anche su 10 e l'evento ValueChanged viene generato. Questo problema può verificarsi prima che il resto della pagina sia stato costruito e il gestore potrebbe tentare di fare riferimento ad altri elementi nella pagina che non sono ancora stati creati. Potrebbe essere necessario aggiungere codice al ValueChanged gestore che verifica la presenza null di valori di altri elementi nella pagina. In alternativa, è possibile impostare il gestore eventi dopo l'inizializzazione ValueChanged dei Slider valori.

Differenze di implementazione della piattaforma

Gli screenshot mostrati in precedenza il valore di Slider con un numero diverso di punti decimali. Questo riguarda il Slider modo in cui viene implementato nelle piattaforme Android e UWP.

Implementazione di Android

L'implementazione android di Slider è basata su Android SeekBar e imposta sempre la Max proprietà su 1000. Ciò significa che in Slider Android sono presenti solo 1.001 valori discreti. Se si imposta l'oggetto Slider su su 0 e su Maximum 5000, come Slider viene modificato, la Value proprietà ha valori pari a Minimum 0, 5, 10, 15 e così via.

Implementazione della piattaforma UWP

L'implementazione UWP di Slider è basata sul controllo UWP Slider . La StepFrequency proprietà della piattaforma UWP Slider è impostata sulla differenza tra le Maximum proprietà e Minimum diviso per 10, ma non maggiore di 1.

Ad esempio, per l'intervallo predefinito da 0 a 1, la StepFrequency proprietà è impostata su 0,1. Slider Poiché viene modificato, la Value proprietà è limitata a 0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9 e 1.0. (Questo è evidente nell'ultima pagina nel Esempio sliderDemos . Quando la differenza tra le Maximum proprietà e Minimum è 10 o superiore, StepFrequency viene impostata su 1 e la Value proprietà ha valori integrali.

Soluzione StepSlider

Il capitolo 27 illustra una maggiore versatilitàStepSlider. Renderer personalizzati del libro Creazione di app per dispositivi mobili con Xamarin.Forms. è StepSlider simile a Slider ma aggiunge una Steps proprietà per specificare il numero di valori tra Minimum e Maximum.

Dispositivi di scorrimento per la selezione dei colori

Le due pagine finali dell'esempio SliderDemos usano entrambe tre Slider istanze per la selezione dei colori. La prima pagina gestisce tutte le interazioni nel file code-behind, mentre la seconda pagina mostra come usare il data binding con viewModel.

Gestione dei dispositivi di scorrimento nel file code-behind

La pagina Dispositivi di scorrimento colori RGB crea un'istanza di per BoxView visualizzare un colore, tre Slider istanze per selezionare i componenti rosso, verde e blu del colore e tre Label elementi per la visualizzazione di tali valori di colore:

<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 oggetto fornisce a tutti e tre Slider gli elementi un intervallo compreso tra 0 e 255. Gli Slider elementi condividono lo stesso ValueChanged gestore, implementato nel file 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);
    }
}

La prima sezione imposta la Text proprietà di una delle Label istanze su una stringa di testo breve che indica il valore dell'oggetto Slider in formato esadecimale. È quindi possibile accedere a tutte e tre Slider le istanze per creare un Color valore dai componenti RGB:

RGB Color Sliders

Associazione del dispositivo di scorrimento a un viewModel

La pagina HSL Color Sliders (Dispositivi di scorrimento colori HSL) mostra come usare un viewModel per eseguire i calcoli usati per creare un Color valore dai valori di tonalità, saturazione e luminosità. Come tutti i ViewModel, la HSLColorViewModel classe implementa l'interfaccia INotifyPropertyChanged e genera un PropertyChanged evento ogni volta che una delle proprietà 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 e l'interfaccia INotifyPropertyChanged sono descritti nell'articolo Data Binding.

Il file HslColorSlidersPage.xaml crea un'istanza di HslColorViewModel e lo imposta sulla proprietà della BindingContext pagina. In questo modo tutti gli elementi del file XAML possono essere associati alle proprietà in 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>

Man mano che gli Slider elementi vengono modificati, gli BoxView elementi e Label vengono aggiornati da ViewModel:

HSL Color Sliders

Il StringFormat componente dell'estensione Binding di markup è impostato per un formato "F2" per visualizzare due posizioni decimali. La formattazione delle stringhe nei data binding è descritta nell'articolo Formattazione di stringhe. Tuttavia, la versione UWP del programma è limitata ai valori 0, 0.1, 0.2, ... 0.9 e 1.0. Si tratta di un risultato diretto dell'implementazione della piattaforma UWP Slider , come descritto in precedenza nella sezione Differenze di implementazione della piattaforma.