Xamarin.Forms スライダー

サンプルのダウンロードサンプルのダウンロード

連続する値の範囲から選択する場合は、スライダーを使用します。

Xamarin.FormsSliderは、ユーザーが連続範囲から値を選択doubleするために操作できる水平バーです。

では Slider 、 型の 3 つのプロパティが定義されます double

  • Minimum は範囲の最小値で、既定値は 0 です。
  • Maximum は範囲の最大値で、既定値は 1 です。
  • Valueはスライダーの値です。この値は と Maximum の間Minimumで指定でき、既定値は 0 です。

3 つのプロパティはすべて オブジェクトによって BindableProperty サポートされます。 プロパティの Value 既定の BindingMode.TwoWayバインド モードは です。これは、 Model-View-ViewModel (MVVM) アーキテクチャを使用するアプリケーションのバインディング ソースとして適していることを意味します。

警告

内部的には、 Slider が よりMaximum小さいことがMinimum保証されます。 または Maximum が 以下MaximumになるようにMinimum設定されている場合Minimumは、例外が発生します。 プロパティと Maximum プロパティの設定の詳細については、以下の「注意事項」セクションをMinimum参照してください。

Slider 、 と の ValueMinimum になるように プロパティを Maximum強制します。 プロパティが Minimum プロパティより Value 大きい値に設定されている場合、 プロパティは SliderValueMinimum設定されます。 同様に、 が よりValue小さい値に設定されている場合Maximumは、 プロパティを ValueMaximum設定しますSlider

Sliderは、 ValueChanged のユーザー操作Sliderによって、またはプログラムが プロパティをValue直接設定したときに変更されたときに発生するイベントをValue定義します。 前の ValueChanged 段落で説明したように プロパティが Value 強制されると、イベントも発生します。

ValueChangedEventArgsイベントに付随ValueChangedする オブジェクトには、 型doubleと 型の両方の 2 つのプロパティがあります OldValueNewValue。 イベントが発生した時点では、 の NewValue 値は オブジェクトの ValueSlider プロパティと同じです。

Slider また、ドラッグ アクションの DragStarted 先頭と DragCompleted 末尾で発生する イベントと イベントも定義します。 ValueChangedイベントとは異なり、 DragStarted イベントと DragCompleted イベントは、 のユーザー操作によってのみ発生しますSlider。 イベントが DragStarted 発生すると、 DragStartedCommandICommandの が実行されます。 同様に、イベントが DragCompleted 発生すると、 DragCompletedCommandICommandの が実行されます。

警告

、、または End の制約のない水平レイアウト オプションCenterStartは、 と共にSlider使用しないでください。 Android と UWP の両方で、 Slider は長さが 0 のバーに折りたたまれます。iOS では、バーは非常に短くなります。 の既定HorizontalOptionsFill設定をそのまま使用します。レイアウトに配置する場合は、 のAuto幅はSliderGrid使用しないでください。

には Slider 、その外観に影響を与えるいくつかのプロパティも定義されています。

注意

ThumbColorプロパティと ThumbImageSource プロパティは相互に排他的です。 両方のプロパティが設定されている場合、 ThumbImageSource プロパティが優先されます。

基本的なスライダー のコードとマークアップ

SliderDemos サンプルは、機能的には同じ 3 つのページで始まりますが、さまざまな方法で実装されています。 最初のページでは C# コードのみを使用し、2 番目のページではコード内のイベント ハンドラーで XAML を使用し、3 番目のページでは XAML ファイルのデータ バインディングを使用してイベント ハンドラーを回避できます。

コードでのスライダーの作成

SliderDemos サンプルの [基本的なスライダー コード] ページには、コード内に と の 2 つのLabelオブジェクトをSlider作成する方法が示されています。

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は 360 のプロパティをMaximum持つよう初期化されます。 のハンドラーはValueChanged、 オブジェクトの プロパティをsliderValue使用して最初Labelの の プロパティをRotation設定し、 メソッドとNewValueイベント引数の プロパティを使用String.Formatして 2 番目Labelの の プロパティをText設定Sliderします。 の現在の値 Slider を取得するこれら 2 つの方法は交換可能です。

iOS および Android デバイスで実行されているプログラムを次に示します。

基本的なスライダー コード

2 つ目 Label は、 が操作されるまで Slider "(初期化されていない)" というテキストを表示します。これにより、最初 ValueChanged のイベントが発生します。 表示される小数点以下の桁数がプラットフォームごとに異なっていることを確認してください。 これらの違いは、 のプラットフォーム実装 Slider に関連しており、この記事の「 プラットフォーム実装の違い」セクションで後述します。

XAML でのスライダーの作成

基本的なスライダー XAML ページは、基本的なスライダー コードと機能的には同じですが、主に 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>

分離コード ファイルには、 イベントのハンドラーが 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);
    }
}

イベント ハンドラーは、 引数を介してsenderイベントを発生させる をSlider取得することもできます。 プロパティには Value 、現在の値が含まれています。

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

Slider属性 ("slider" など) を持つ x:Name XAML ファイルにオブジェクトの名前が指定されている場合、イベント ハンドラーはそのオブジェクトを直接参照できます。

double value = slider.Value;

スライダーのデータ バインディング

[基本的なスライダー バインド] ページには、データ バインディングを使用してイベント ハンドラーを排除する、ほぼ同等のプログラムをValue記述する方法が示されています。

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

Rotation 1 つ目Labelの の プロパティは、 の SliderプロパティにValueバインドされます。2 番目Labelの プロパティは Text 仕様でStringFormatバインドされます。 [ 基本的なスライダー バインド] ページの機能は、前の 2 つのページとは少し異なります。ページが最初に表示されると、2 番目 Label のページに値を含むテキスト文字列が表示されます。 これは、データ バインディングを使用する利点です。 データ バインディングなしでテキストを表示するには、 の プロパティLabelを明示的に初期化Textするか、クラス コンストラクターからイベント ハンドラーを呼び出してイベントのValueChanged発生をシミュレートする必要があります。

注意事項

プロパティの Minimum 値は、常に プロパティの値より小さくする Maximum 必要があります。 次のコード スニペットを使用すると、 によって Slider 例外が発生します。

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

C# コンパイラは、これら 2 つのプロパティを順番に設定するコードを Minimum 生成します。プロパティが 10 に設定されると、既定値 Maximum の 1 より大きくなります。 この場合は、 プロパティを最初に設定することで、例外を Maximum 回避できます。

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

既定値の 0 より大きいため、20 にMinimum設定Maximumしても問題ありません。 が設定されている場合 Minimum 、値は 20 の Maximum 値より小さくなります。

XAML には同じ問題があります。 が常に を超MinimumえるMaximum順序でプロパティを設定します。

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

Maximum の値は負のMinimum数に設定できますが、 が常に よりMaximum小さい順序Minimumでのみ設定できます。

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

プロパティはValue常に 値以上でMaximumMinimum 以下です。 がその範囲外の値に設定されている場合 Value 、値は範囲内に収まるように強制されますが、例外は発生しません。 たとえば、次のコードでは例外は発生 しません

Slider slider = new Slider
{
    Value = 10
};

代わりに、 プロパティの Value 値は 1 に Maximum 強制されます。

上記のコード スニペットを次に示します。

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

が 10 に設定されている場合MinimumValueは、 も 10 に設定されます。

プロパティが ValueChanged 既定値の 0 以外のものに強制された時点 Value でイベント ハンドラーがアタッチされている場合は、 ValueChanged イベントが発生します。 XAML のスニペットを次に示します。

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

が 10 に設定されている場合 Minimum は、 Value も 10 に設定され、イベントが ValueChanged 発生します。 これは、ページの残りの部分が構築される前に発生する可能性があり、ハンドラーは、まだ作成されていないページ上の他の要素を参照しようとする可能性があります。 ページ上の他の要素の値を ValueChanged チェック null するコードをハンドラーに追加することもできます。 または、値の初期化後に ValueChanged イベント ハンドラーを Slider 設定することもできます。

プラットフォームの実装の違い

前に示したスクリーンショットでは、 の Slider 値が異なる小数点数で表示されます。 これは、 Slider が Android および UWP プラットフォームでどのように実装されるかに関連しています。

Android の実装

の Android 実装 Slider は Android SeekBar に基づいており、常に プロパティを Max 1000 に設定します。 これは、Android 上の には Slider 1,001 個の不連続値しかないことを意味します。 を SliderMinimum 0 に設定し Maximum 、 を 5000 に設定した Slider 場合、 が操作されると、 Value プロパティの値は 0、5、10、15 などになります。

UWP の実装

Slider UWP 実装は、UWP Slider コントロールに基づいています。 UWP Slider の プロパティはStepFrequency、 プロパティと Minimum プロパティのMaximum差を 10 で割った値に設定されますが、1 より大きくはありません。

たとえば、既定の範囲の 0 から 1 の場合、 StepFrequency プロパティは 0.1 に設定されます。 Sliderが操作されると、Valueプロパティは 0、0.1、0.2、0.3、0.4、0.5、0.6、0.7、0.8、0.9、1.0 に制限されます。 (これは SliderDemos サンプルの最後のページで明らかです)。プロパティと Minimum プロパティの差Maximumが 10 以上の場合、 StepFrequency は 1 に設定されValue、プロパティには整数値が設定されます。

StepSlider ソリューション

より汎用性の高いStepSlider方法については、第 27 章で説明します。を使用したモバイル アプリXamarin.Formsの作成に関する書籍のカスタム レンダラー。 StepSliderは にSlider似ていますが、 Steps と の間Minimumの値の数を指定する プロパティを追加しますMaximum

色を選択するためのスライダー

SliderDemos サンプルの最後の 2 ページでは、どちらも 3 つのSliderインスタンスを使用して色を選択します。 最初のページは分離コード ファイル内のすべての操作を処理し、2 番目のページでは ViewModel でデータ バインディングを使用する方法を示します。

分離コード ファイルでのスライダーの処理

[RGB カラー スライダー] ページでは、 をインスタンス化して色を表示し、色の赤、緑、青のコンポーネントを選択する 3 つのSliderインスタンス、およびこれらの色値を表示するための 3 つのLabel要素をインスタンス化BoxViewします。

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

Style 、3 つの Slider 要素すべてに 0 から 255 の範囲を与えます。 要素は Slider 、分離コード ファイルに実装されている同じ ValueChanged ハンドラーを共有します。

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

最初のセクションでは、 Text インスタンスの 1 つの プロパティに Label 、 の値を 16 進数で示す短いテキスト文字列を Slider 設定します。 次に、3 つの Slider インスタンスすべてにアクセスして、RGB コンポーネントから値を作成 Color します。

RGB カラー スライダー

スライダーを ViewModel にバインドする

[HSL カラー スライダー] ページでは、ViewModel を使用して、色相、彩度、明度の値から値をColor作成するために使用される計算を実行する方法を示します。 すべての ViewModel と同様に、 クラスは HSLColorViewModel インターフェイスを INotifyPropertyChanged 実装し、いずれかのプロパティが PropertyChanged 変更されるたびにイベントを発生させます。

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 と INotifyPropertyChanged インターフェイスについては、 データ バインディングに関する記事で説明します。

HslColorSlidersPage.xaml ファイルは をHslColorViewModelインスタンス化し、ページの BindingContext プロパティに設定します。 これにより、XAML ファイル内のすべての要素を 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 操作されると、 BoxView 要素と Label 要素は ViewModel から更新されます。

HSL カラー スライダー

マークアップ拡張のBindingコンポーネントはStringFormat、小数点以下 2 桁を表示する "F2" の形式に設定されます。 (データ バインディングでの文字列の書式設定については、「 文字列の書式設定」の記事で説明します)。ただし、プログラムの UWP バージョンは、0、0.1、0.2、..の値に制限されています。0.9、1.0。 これは、「プラットフォームの実装の違い」セクションで説明したように、UWP Slider の実装の直接的な結果です。