Xamarin.Forms Schaltfläche

Beispiel herunterladen Das Beispiel herunterladen

Die Schaltfläche reagiert auf ein Tippen oder Klicken, das eine Anwendung angibt, eine bestimmte Aufgabe auszuführen.

Das Button ist das grundlegendste interaktive Steuerelement in allen von Xamarin.Forms. Zeigt Button normalerweise eine kurze Textzeichenfolge an, die einen Befehl angibt, kann aber auch ein Bitmapbild oder eine Kombination aus Text und Bild anzeigen. Der Benutzer drückt die Button mit einem Finger oder klickt mit der Maus darauf, um diesen Befehl zu initiieren.

Die meisten der unten erläuterten Themen entsprechen Seiten im ButtonDemos-Beispiel .

Behandeln von Schaltflächenklicks

Button definiert ein Clicked Ereignis, das ausgelöst wird, wenn der Benutzer mit einem Button Finger- oder Mauszeiger darauf tippt. Das Ereignis wird ausgelöst, wenn der Finger oder die Maustaste von der Oberfläche des Buttonfreigegeben wird. Die Button -Eigenschaft muss auf true festgelegt seinIsEnabled, damit es auf Tippen reagieren kann.

Auf der Seite "Einfache Schaltflächenklick" im ButtonDemos-Beispiel wird veranschaulicht, wie sie ein Button in XAML instanziieren und dessen Clicked Ereignis behandeln. Die Datei BasicButtonClickPage.xaml enthält ein StackLayout mit einem Label und einem Button:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.BasicButtonClickPage"
             Title="Basic Button Click">
    <StackLayout>

        <Label x:Name="label"
               Text="Click the Button below"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Click to Rotate Text!"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Clicked="OnButtonClicked" />

    </StackLayout>
</ContentPage>

Der Button nimmt in der Regel den gesamten Platz ein, der dafür zulässig ist. Wenn Sie z. B. die HorizontalOptions Eigenschaft von Button nicht auf etwas anderes als Fillfestlegen, nimmt der Button die volle Breite des übergeordneten Elements ein.

Standardmäßig ist das Button rechteckig, aber Sie können ihm mit der CornerRadius -Eigenschaft abgerundete Ecken geben, wie unten im Abschnitt Schaltflächendarstellung beschrieben.

Die Text-Eigenschaft gibt den Text an, der auf dem Button-Element angezeigt wird. Das Clicked Ereignis ist auf einen Ereignishandler mit dem Namen OnButtonClickedfestgelegt. Dieser Handler befindet sich in der CodeBehind-Datei BasicButtonClickPage.xaml.cs:

public partial class BasicButtonClickPage : ContentPage
{
    public BasicButtonClickPage ()
    {
        InitializeComponent ();
    }

    async void OnButtonClicked(object sender, EventArgs args)
    {
        await label.RelRotateTo(360, 1000);
    }
}

Wenn die Button angetippt wird, wird die OnButtonClicked-Methode ausgeführt. Das sender Argument ist das objekt, das Button für dieses Ereignis verantwortlich ist. Sie können dies verwenden, um auf das Button -Objekt zuzugreifen oder zwischen mehreren Button Objekten zu unterscheiden, die dasselbe Clicked Ereignis gemeinsam nutzen.

Dieser spezielle Clicked Handler ruft eine Animationsfunktion auf, die die Label 360 Grad in 1000 Millisekunden rotiert. Hier sehen Sie das Programm, das auf iOS- und Android-Geräten und als Universelle Windows-Plattform-Anwendung (UWP) auf dem Windows 10 Desktop ausgeführt wird:

Die Schaltfläche

Beachten Sie, dass die OnButtonClicked -Methode den async -Modifizierer enthält, da await im Ereignishandler verwendet wird. Ein Clicked Ereignishandler erfordert den async Modifizierer nur, wenn der Textkörper des Handlers verwendet await.

Jede Plattform rendert die Button auf ihre eigene spezifische Weise. Im Abschnitt Schaltflächendarstellung erfahren Sie, wie Sie Farben festlegen und den Button Rahmen für benutzerdefiniertere Darstellungen sichtbar machen. Buttonimplementiert die IFontElement -Schnittstelle, sodass sie eigenschaften, FontSize, und FontAttributes enthältFontFamily.

Erstellen einer Schaltfläche im Code

Es ist üblich, ein Button in XAML zu instanziieren, aber Sie können auch einen Button in Code erstellen. Dies kann praktisch sein, wenn Ihre Anwendung mehrere Schaltflächen basierend auf Daten erstellen muss, die mit einer foreach Schleife aufgezählt werden können.

Auf der Seite Codeschaltflächenklick wird veranschaulicht, wie eine Seite erstellt wird, die funktional der Seite "Schaltflächenklick basic" entspricht, aber vollständig in C#:

public class CodeButtonClickPage : ContentPage
{
    public CodeButtonClickPage ()
    {
        Title = "Code Button Click";

        Label label = new Label
        {
            Text = "Click the Button below",
            FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
            VerticalOptions = LayoutOptions.CenterAndExpand,
            HorizontalOptions = LayoutOptions.Center
        };

        Button button = new Button
        {
            Text = "Click to Rotate Text!",
            VerticalOptions = LayoutOptions.CenterAndExpand,
            HorizontalOptions = LayoutOptions.Center
        };
        button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);

        Content = new StackLayout
        {
            Children =
            {
                label,
                button
            }
        };
    }
}

Alles wird im Konstruktor der Klasse ausgeführt. Da der Clicked Handler nur eine Anweisung lang ist, kann er ganz einfach an das Ereignis angefügt werden:

button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);

Natürlich können Sie den Ereignishandler auch als separate Methode definieren (genau wie die OnButtonClick Methode in Basic Button Click) und diese Methode an das Ereignis anfügen:

button.Clicked += OnButtonClicked;

Deaktivieren der Schaltfläche

Manchmal befindet sich eine Anwendung in einem bestimmten Zustand, in dem ein bestimmter Button Klick kein gültiger Vorgang ist. In diesen Fällen sollte der Button deaktiviert werden, indem die IsEnabled -Eigenschaft auf falsefestgelegt wird. Das klassische Beispiel ist ein Entry Steuerelement für einen Dateinamen, der von einer geöffneten ButtonDatei begleitet wird: Die Button sollte nur aktiviert werden, wenn Text in den Entryeingegeben wurde. Sie können einen DataTrigger für diese Aufgabe verwenden, wie im Artikel Datentrigger gezeigt .

Verwenden der Befehlsschnittstelle

Es ist möglich, dass eine Anwendung auf Button Tippen reagiert, ohne das Clicked Ereignis zu behandeln. Implementiert Button einen alternativen Benachrichtigungsmechanismus, der als Befehl oder Befehlsschnittstelle bezeichnet wird. Dies besteht aus zwei Eigenschaften:

Dieser Ansatz eignet sich besonders im Zusammenhang mit der Datenbindung und insbesondere bei der Implementierung der MVVM-Architektur (Model-View-ViewModel). Diese Themen werden in den Artikeln Datenbindung, Von Datenbindungen zu MVVM und MVVM erläutert.

In einer MVVM-Anwendung definiert das viewmodel Eigenschaften vom Typ ICommand , die dann mit den XAML-Elementen Button mit Datenbindungen verbunden sind. Xamarin.Forms definiert Command außerdem und Command<T> Klassen, die die ICommand Schnittstelle implementieren und das viewmodel beim Definieren von Eigenschaften des Typs ICommandunterstützen.

Die Befehle werden im Artikel Die Befehlsschnittstelle ausführlicher beschrieben, aber die Seite Grundlegende Schaltflächenbefehle im ButtonDemos-Beispiel zeigt den grundlegenden Ansatz.

Die CommandDemoViewModel -Klasse ist ein sehr einfaches Viewmodel, das eine Eigenschaft vom Typ double mit dem Namen Numberund zwei Eigenschaften des Typs ICommand definiert MultiplyBy2CommandDivideBy2Command:

class CommandDemoViewModel : INotifyPropertyChanged
{
    double number = 1;

    public event PropertyChangedEventHandler PropertyChanged;

    public CommandDemoViewModel()
    {
        MultiplyBy2Command = new Command(() => Number *= 2);

        DivideBy2Command = new Command(() => Number /= 2);
    }

    public double Number
    {
        set
        {
            if (number != value)
            {
                number = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Number"));
            }
        }
        get
        {
            return number;
        }
    }

    public ICommand MultiplyBy2Command { private set; get; }

    public ICommand DivideBy2Command { private set; get; }
}

Die beiden ICommand Eigenschaften werden im Konstruktor der Klasse mit zwei Objekten vom Typ Commandinitialisiert. Die Command Konstruktoren enthalten eine kleine Funktion (als execute Konstruktorargument bezeichnet), die die Number Eigenschaft entweder verdoppelt oder halbiert.

Die Datei BasicButtonCommand.xaml legt ihre BindingContext auf eine instance von CommandDemoViewModelfest. Das Label Element und zwei Button Elemente enthalten Bindungen an die drei Eigenschaften in CommandDemoViewModel:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.BasicButtonCommandPage"
             Title="Basic Button Command">

    <ContentPage.BindingContext>
        <local:CommandDemoViewModel />
    </ContentPage.BindingContext>

    <StackLayout>
        <Label Text="{Binding Number, StringFormat='Value is now {0}'}"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Multiply by 2"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Command="{Binding MultiplyBy2Command}" />

        <Button Text="Divide by 2"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Command="{Binding DivideBy2Command}" />
    </StackLayout>
</ContentPage>

Wenn die beiden Button Elemente getippt werden, werden die Befehle ausgeführt, und die Zahl ändert den Wert:

Basic Button Command

Der Vorteil dieses Ansatzes gegenüber Clicked Handlern besteht darin, dass sich die gesamte Logik, die die Funktionalität dieser Seite betrifft, im Viewmodel und nicht in der CodeBehind-Datei befindet, wodurch eine bessere Trennung der Benutzeroberfläche von der Geschäftslogik erreicht wird.

Es ist auch möglich, dass die Command -Objekte das Aktivieren und Deaktivieren der Button Elemente steuern. Angenommen, Sie möchten den Bereich der Zahlenwerte zwischen 210 und 2–10 begrenzen. Sie können dem Konstruktor (als Argument bezeichnet) eine weitere Funktion hinzufügen, die canExecute zurückgibt true , wenn die Button aktiviert werden soll. Dies ist die Änderung am CommandDemoViewModel Konstruktor:

class CommandDemoViewModel : INotifyPropertyChanged
{
    ···
    public CommandDemoViewModel()
    {
        MultiplyBy2Command = new Command(
            execute: () =>
            {
                Number *= 2;
                ((Command)MultiplyBy2Command).ChangeCanExecute();
                ((Command)DivideBy2Command).ChangeCanExecute();
            },
            canExecute: () => Number < Math.Pow(2, 10));

        DivideBy2Command = new Command(
            execute: () =>
            {
                Number /= 2;
                ((Command)MultiplyBy2Command).ChangeCanExecute();
                ((Command)DivideBy2Command).ChangeCanExecute();
            },
            canExecute: () => Number > Math.Pow(2, -10));
    }
    ···
}

Die Aufrufe der ChangeCanExecute -Methode von Command sind erforderlich, damit die Command -Methode die canExecute -Methode aufrufen und bestimmen kann, ob die Button deaktiviert werden soll oder nicht. Mit dieser Codeänderung wird deaktiviert Button , wenn die Zahl das Limit erreicht:

Schaltflächenbefehl

Es ist möglich, dass zwei oder mehr Button Elemente an dieselbe ICommand Eigenschaft gebunden werden. Die Button Elemente können mithilfe der CommandParameter -Eigenschaft von Buttonunterschieden werden. In diesem Fall sollten Sie die generische Command<T> Klasse verwenden. Das CommandParameter -Objekt wird dann als Argument an die execute Methoden und canExecute übergeben. Diese Technik wird im Abschnitt Grundlegende Befehle des Artikels Befehlsschnittstelle ausführlich veranschaulicht.

Das ButtonDemos-Beispiel verwendet diese Technik auch in seiner MainPage Klasse. Die Datei MainPage.xaml enthält eine Button für jede Seite des Beispiels:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.MainPage"
             Title="Button Demos">
    <ScrollView>
        <FlexLayout Direction="Column"
                    JustifyContent="SpaceEvenly"
                    AlignItems="Center">

            <Button Text="Basic Button Click"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:BasicButtonClickPage}" />

            <Button Text="Code Button Click"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:CodeButtonClickPage}" />

            <Button Text="Basic Button Command"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:BasicButtonCommandPage}" />

            <Button Text="Press and Release Button"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:PressAndReleaseButtonPage}" />

            <Button Text="Button Appearance"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ButtonAppearancePage}" />

            <Button Text="Toggle Button Demo"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ToggleButtonDemoPage}" />

            <Button Text="Image Button Demo"
                    Command="{Binding NavigateCommand}"
                    CommandParameter="{x:Type local:ImageButtonDemoPage}" />

        </FlexLayout>
    </ScrollView>
</ContentPage>

Jede Button Eigenschaft ist Command an eine Eigenschaft mit dem Namen NavigateCommandgebunden, und die CommandParameter ist auf ein Type Objekt festgelegt, das einer der Seitenklassen im Projekt entspricht.

Diese NavigateCommand Eigenschaft ist vom Typ ICommand und wird in der CodeBehind-Datei definiert:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();

        NavigateCommand = new Command<Type>(async (Type pageType) =>
        {
            Page page = (Page)Activator.CreateInstance(pageType);
            await Navigation.PushAsync(page);
        });

        BindingContext = this;
    }

    public ICommand NavigateCommand { private set; get; }
}

Der Konstruktor initialisiert die NavigateCommand -Eigenschaft für ein Command<Type> -Objekt, da Type es sich um den Typ des CommandParameter in der XAML-Datei festgelegten Objekts handelt. Dies bedeutet, dass die execute Methode über ein Argument vom Typ Type verfügt, das diesem CommandParameter Objekt entspricht. Die Funktion instanziiert die Seite und navigiert dann zu ihr.

Beachten Sie, dass der Konstruktor abschließt, indem er seinen BindingContext auf sich selbst festlegt. Dies ist erforderlich, damit Eigenschaften in der XAML-Datei an die NavigateCommand -Eigenschaft gebunden werden können.

Drücken und Loslassen der Taste

Neben dem Clicked-Ereignis definiert das Button-Element auch die Ereignisse Pressed und Released. Das Pressed -Ereignis tritt auf, wenn ein Finger auf einen Buttondrückt oder eine Maustaste gedrückt wird, wobei der Zeiger über den Buttonpositioniert wird. Das Released Ereignis tritt auf, wenn der Finger oder die Maustaste losgelassen wird. Im Allgemeinen wird ein Clicked Ereignis auch zur gleichen Zeit wie das Released Ereignis ausgelöst, aber wenn der Finger- oder Mauszeiger von der Oberfläche des Button entfernt wird, bevor er freigegeben wird, tritt das Clicked Ereignis möglicherweise nicht auf.

Die Pressed Ereignisse und Released werden nicht häufig verwendet, können aber für besondere Zwecke verwendet werden, wie auf der Seite Press and Release Button gezeigt. Die XAML-Datei enthält ein Label und ein Button mit Handlern, die für die Pressed Ereignisse und Released angefügt sind:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.PressAndReleaseButtonPage"
             Title="Press and Release Button">
    <StackLayout>

        <Label x:Name="label"
               Text="Press and hold the Button below"
               FontSize="Large"
               VerticalOptions="CenterAndExpand"
               HorizontalOptions="Center" />

        <Button Text="Press to Rotate Text!"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                Pressed="OnButtonPressed"
                Released="OnButtonReleased" />

    </StackLayout>
</ContentPage>

Die CodeBehind-Datei animiert, Label wenn ein Pressed Ereignis auftritt, hält aber die Drehung an, wenn ein Released Ereignis auftritt:

public partial class PressAndReleaseButtonPage : ContentPage
{
    bool animationInProgress = false;
    Stopwatch stopwatch = new Stopwatch();

    public PressAndReleaseButtonPage ()
    {
        InitializeComponent ();
    }

    void OnButtonPressed(object sender, EventArgs args)
    {
        stopwatch.Start();
        animationInProgress = true;

        Device.StartTimer(TimeSpan.FromMilliseconds(16), () =>
        {
            label.Rotation = 360 * (stopwatch.Elapsed.TotalSeconds % 1);

            return animationInProgress;
        });
    }

    void OnButtonReleased(object sender, EventArgs args)
    {
        animationInProgress = false;
        stopwatch.Stop();
    }
}

Das Ergebnis ist, dass sich der Label einzige dreht, während ein Finger mit dem Buttonin Kontakt ist, und stoppt, wenn der Finger losgelassen wird:

Press and Release Button

Diese Art von Verhalten hat Anwendungen für Spiele: Ein Finger, der auf einem Button gehalten wird, kann dazu führen, dass sich ein Bildschirmobjekt in eine bestimmte Richtung bewegt.

Schaltflächendarstellung

Der Button erbt oder definiert mehrere Eigenschaften, die sich auf die Darstellung auswirken:

  • TextColor ist die Farbe des Button Texts
  • BackgroundColor ist die Farbe des Hintergrunds zu diesem Text
  • BorderColor ist die Farbe eines Bereichs, der den Button
  • FontFamily ist die schriftartenfamilie, die für den Text verwendet wird
  • FontSize ist die Größe des Texts.
  • FontAttributes gibt an, ob der Text kursiv oder fett ist
  • BorderWidth ist die Breite des Rahmens
  • CornerRadius ist der Eckradius des Button
  • CharacterSpacing ist der Abstand zwischen den Zeichen des Button Texts.
  • TextTransform bestimmt die Groß- und Kleinschreibung des Button Texts.

Hinweis

Die Button -Klasse verfügt auch über Margin - und Padding -Eigenschaften, die das Layoutverhalten von Buttonsteuern. Weitere Informationen finden Sie unter Ränder und Abstände.

Die Auswirkungen von sechs dieser Eigenschaften (außer FontFamily und FontAttributes) werden auf der Seite Schaltflächendarstellung veranschaulicht. Eine weitere Eigenschaft, Image, wird im Abschnitt Verwenden von Bitmaps mit Schaltfläche erläutert.

Alle Ansichten und Datenbindungen auf der Seite Schaltflächendarstellung sind in der XAML-Datei definiert:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.ButtonAppearancePage"
             Title="Button Appearance">
    <StackLayout>
        <Button x:Name="button"
                Text="Button"
                VerticalOptions="CenterAndExpand"
                HorizontalOptions="Center"
                TextColor="{Binding Source={x:Reference textColorPicker},
                                    Path=SelectedItem.Color}"
                BackgroundColor="{Binding Source={x:Reference backgroundColorPicker},
                                          Path=SelectedItem.Color}"
                BorderColor="{Binding Source={x:Reference borderColorPicker},
                                      Path=SelectedItem.Color}" />

        <StackLayout BindingContext="{x:Reference button}"
                     Padding="10">

            <Slider x:Name="fontSizeSlider"
                    Maximum="48"
                    Minimum="1"
                    Value="{Binding FontSize}" />

            <Label Text="{Binding Source={x:Reference fontSizeSlider},
                                  Path=Value,
                                  StringFormat='FontSize = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Slider x:Name="borderWidthSlider"
                    Minimum="-1"
                    Maximum="12"
                    Value="{Binding BorderWidth}" />

            <Label Text="{Binding Source={x:Reference borderWidthSlider},
                                  Path=Value,
                                  StringFormat='BorderWidth = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Slider x:Name="cornerRadiusSlider"
                    Minimum="-1"
                    Maximum="24"
                    Value="{Binding CornerRadius}" />

            <Label Text="{Binding Source={x:Reference cornerRadiusSlider},
                                  Path=Value,
                                  StringFormat='CornerRadius = {0:F0}'}"
                   HorizontalTextAlignment="Center" />

            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <Grid.Resources>
                    <Style TargetType="Label">
                        <Setter Property="VerticalOptions" Value="Center" />
                    </Style>
                </Grid.Resources>

                <Label Text="Text Color:"
                       Grid.Row="0" Grid.Column="0" />

                <Picker x:Name="textColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="0" Grid.Column="1" />

                <Label Text="Background Color:"
                       Grid.Row="1" Grid.Column="0" />

                <Picker x:Name="backgroundColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="1" Grid.Column="1" />

                <Label Text="Border Color:"
                       Grid.Row="2" Grid.Column="0" />

                <Picker x:Name="borderColorPicker"
                        ItemsSource="{Binding Source={x:Static local:NamedColor.All}}"
                        ItemDisplayBinding="{Binding FriendlyName}"
                        SelectedIndex="0"
                        Grid.Row="2" Grid.Column="1" />
            </Grid>
        </StackLayout>
    </StackLayout>
</ContentPage>

Der Button oben auf der Seite hat seine drei Color Eigenschaften, die am unteren Rand der Seite an Picker Elemente gebunden sind. Die Elemente in den Picker Elementen sind Farben der Klasse, die NamedColor im Projekt enthalten ist. Drei Slider Elemente enthalten bidirektionale Bindungen an die FontSizeEigenschaften , BorderWidthund CornerRadius von Button.

Mit diesem Programm können Sie mit Kombinationen aller folgenden Eigenschaften experimentieren:

Schaltflächendarstellung

Um den Button Rahmen anzuzeigen, müssen Sie einen BorderColor auf etwas anderes als Defaultfestlegen und den BorderWidth auf einen positiven Wert.

Unter iOS werden Sie feststellen, dass große Rahmenbreiten in das Innere des Button eindringen und die Anzeige von Text beeinträchtigen. Wenn Sie sich für die Verwendung eines Rahmens mit einem iOS Buttonentscheiden, sollten Sie die Eigenschaft wahrscheinlich mit Leerzeichen beginnen und beenden, um die Text Sichtbarkeit beizubehalten.

Auf UWP löst die Auswahl eines CornerRadius , das die Hälfte der Höhe überschreitet Button , eine Ausnahme aus.

Visuelle Schaltflächenzustände

Button verfügt über eine PressedVisualState , die verwendet werden kann, um eine visuelle Änderung am zu Button initiieren, wenn vom Benutzer gedrückt wird, vorausgesetzt, es ist aktiviert.

Das folgende XAML-Beispiel zeigt, wie ein visueller Zustand für den Pressed Zustand definiert wird:

<Button Text="Click me!"
        ...>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup x:Name="CommonStates">
            <VisualState x:Name="Normal">
                <VisualState.Setters>
                    <Setter Property="Scale"
                            Value="1" />
                </VisualState.Setters>
            </VisualState>

            <VisualState x:Name="Pressed">
                <VisualState.Setters>
                    <Setter Property="Scale"
                            Value="0.8" />
                </VisualState.Setters>
            </VisualState>

        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
</Button>

Gibt PressedVisualState an, Scale dass die Button -Eigenschaft beim Drücken von vom Standardwert 1 auf 0,8 geändert wird. Gibt NormalVisualState an, dass seine Eigenschaft auf 1 festgelegt wird, Scale wenn sich die Button Eigenschaft in einem normalen Zustand befindet. Daher besteht der Gesamteffekt darin, dass beim Drücken von etwas Button kleiner skaliert wird, und wenn der Button freigegeben wird, es auf seine Standardgröße neu skaliert wird.

Weitere Informationen zu visuellen Zuständen finden Sie unter Visual Xamarin.Forms State Manager.

Erstellen einer Umschaltfläche

Es ist möglich, eine Unterklasse Button so zu gestalten, dass sie wie ein Ein-Aus-Schalter funktioniert: Tippen Sie einmal auf die Schaltfläche, um die Schaltfläche einzuschalten, und tippen Sie erneut darauf, um sie auszuschalten.

Die folgende ToggleButton Klasse leitet sich von ab Button und definiert ein neues Ereignis mit dem Namen Toggled und eine boolesche Eigenschaft mit dem Namen IsToggled. Dies sind die gleichen beiden Eigenschaften, die durch definiert Xamarin.FormsSwitchwerden:

class ToggleButton : Button
{
    public event EventHandler<ToggledEventArgs> Toggled;

    public static BindableProperty IsToggledProperty =
        BindableProperty.Create("IsToggled", typeof(bool), typeof(ToggleButton), false,
                                propertyChanged: OnIsToggledChanged);

    public ToggleButton()
    {
        Clicked += (sender, args) => IsToggled ^= true;
    }

    public bool IsToggled
    {
        set { SetValue(IsToggledProperty, value); }
        get { return (bool)GetValue(IsToggledProperty); }
    }

    protected override void OnParentSet()
    {
        base.OnParentSet();
        VisualStateManager.GoToState(this, "ToggledOff");
    }

    static void OnIsToggledChanged(BindableObject bindable, object oldValue, object newValue)
    {
        ToggleButton toggleButton = (ToggleButton)bindable;
        bool isToggled = (bool)newValue;

        // Fire event
        toggleButton.Toggled?.Invoke(toggleButton, new ToggledEventArgs(isToggled));

        // Set the visual state
        VisualStateManager.GoToState(toggleButton, isToggled ? "ToggledOn" : "ToggledOff");
    }
}

Der ToggleButton Konstruktor fügt dem Clicked Ereignis einen Handler an, damit er den Wert der IsToggled Eigenschaft ändern kann. Die OnIsToggledChanged -Methode löst das Toggled Ereignis aus.

Die letzte Zeile der OnIsToggledChanged Methode ruft die statische VisualStateManager.GoToState Methode mit den beiden Textzeichenfolgen "ToggledOn" und "ToggledOff" auf. Informationen zu dieser Methode und wie Ihre Anwendung auf visuelle Zustände reagieren kann, finden Sie im Artikel Visual Xamarin.Forms State Manager.

Da ToggleButton der Aufruf von VisualStateManager.GoToStateerfolgt, muss die Klasse selbst keine zusätzlichen Funktionen enthalten, um das Erscheinungsbild der Schaltfläche basierend auf ihrem IsToggled Zustand zu ändern. Dafür ist der XAML-Code verantwortlich, der die hostet ToggleButton.

Die Seite Schaltflächen-Demo umschalten enthält zwei Instanzen von ToggleButton, einschließlich Visual State Manager-Markup, das die TextSchaltfläche BackgroundColor, und TextColor basierend auf dem visuellen Zustand festlegt:

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ButtonDemos"
             x:Class="ButtonDemos.ToggleButtonDemoPage"
             Title="Toggle Button Demo">

    <ContentPage.Resources>
        <Style TargetType="local:ToggleButton">
            <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            <Setter Property="HorizontalOptions" Value="Center" />
        </Style>
    </ContentPage.Resources>

    <StackLayout Padding="10, 0">
        <local:ToggleButton Toggled="OnItalicButtonToggled">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="ToggleStates">
                    <VisualState Name="ToggledOff">
                        <VisualState.Setters>
                            <Setter Property="Text" Value="Italic Off" />
                            <Setter Property="BackgroundColor" Value="#C0C0C0" />
                            <Setter Property="TextColor" Value="Black" />
                        </VisualState.Setters>
                    </VisualState>

                    <VisualState Name="ToggledOn">
                        <VisualState.Setters>
                            <Setter Property="Text" Value=" Italic On " />
                            <Setter Property="BackgroundColor" Value="#404040" />
                            <Setter Property="TextColor" Value="White" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </local:ToggleButton>

        <local:ToggleButton Toggled="OnBoldButtonToggled">
            <VisualStateManager.VisualStateGroups>
                <VisualStateGroup Name="ToggleStates">
                    <VisualState Name="ToggledOff">
                        <VisualState.Setters>
                            <Setter Property="Text" Value="Bold Off" />
                            <Setter Property="BackgroundColor" Value="#C0C0C0" />
                            <Setter Property="TextColor" Value="Black" />
                        </VisualState.Setters>
                    </VisualState>

                    <VisualState Name="ToggledOn">
                        <VisualState.Setters>
                            <Setter Property="Text" Value=" Bold On " />
                            <Setter Property="BackgroundColor" Value="#404040" />
                            <Setter Property="TextColor" Value="White" />
                        </VisualState.Setters>
                    </VisualState>
                </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
        </local:ToggleButton>

        <Label x:Name="label"
               Text="Just a little passage of some sample text that can be formatted in italic or boldface by toggling the two buttons."
               FontSize="Large"
               HorizontalTextAlignment="Center"
               VerticalOptions="CenterAndExpand" />

    </StackLayout>
</ContentPage>

Die Toggled Ereignishandler befinden sich in der CodeBehind-Datei. Sie sind dafür verantwortlich, die FontAttributes -Eigenschaft von Label basierend auf dem Status der Schaltflächen festzulegen:

public partial class ToggleButtonDemoPage : ContentPage
{
    public ToggleButtonDemoPage ()
    {
        InitializeComponent ();
    }

    void OnItalicButtonToggled(object sender, ToggledEventArgs args)
    {
        if (args.Value)
        {
            label.FontAttributes |= FontAttributes.Italic;
        }
        else
        {
            label.FontAttributes &= ~FontAttributes.Italic;
        }
    }

    void OnBoldButtonToggled(object sender, ToggledEventArgs args)
    {
        if (args.Value)
        {
            label.FontAttributes |= FontAttributes.Bold;
        }
        else
        {
            label.FontAttributes &= ~FontAttributes.Bold;
        }
    }
}

Hier sehen Sie das Programm, das unter iOS, Android und der UWP ausgeführt wird:

Demo zum Umschalten von Schaltflächen

Verwenden von Bitmaps mit Schaltflächen

Die Button -Klasse definiert eine ImageSource Eigenschaft, mit der Sie ein Bitmapbild auf dem Buttonanzeigen können, entweder allein oder in Kombination mit Text. Sie können auch angeben, wie Text und Bild angeordnet sind.

Die ImageSource Eigenschaft ist vom Typ ImageSource, was bedeutet, dass die Bitmaps aus einer Datei, eingebetteten Ressource, einem URI oder einem Stream geladen werden können.

Hinweis

Ein Button kann zwar ein animiertes GIF laden, zeigt jedoch nur den ersten Frame der GIF an.

Jede von unterstützte Plattform ermöglicht das Speichern von Xamarin.Forms Bildern in mehreren Größen für unterschiedliche Pixelauflösungen der verschiedenen Geräte, auf denen die Anwendung möglicherweise ausgeführt wird. Diese mehrere Bitmaps werden so benannt oder gespeichert, dass das Betriebssystem die beste Übereinstimmung für die Videoanzeigeauflösung des Geräts auswählen kann.

Für eine Bitmap auf einem Buttonbeträgt die beste Größe normalerweise zwischen 32 und 64 geräteunabhängige Einheiten, je nachdem, wie groß sie sein soll. Die in diesem Beispiel verwendeten Bilder basieren auf einer Größe von 48 geräteunabhängigen Einheiten.

Im iOS-Projekt enthält der Ordner Resources drei Größen dieses Bilds:

  • Eine quadratische Bitmap mit 48 Pixeln, die als /Resources/MonkeyFace.png
  • Eine quadratische Bitmap mit 96 Pixeln, die als /Resource/MonkeyFace@2x.png gespeichert ist
  • Eine quadratische Bitmap mit 144 Pixeln, die als /Resource/MonkeyFace@3x.png gespeichert ist

Alle drei Bitmaps erhielten eine Buildaktion von BundleResource.

Für das Android-Projekt haben alle Bitmaps den gleichen Namen, werden aber in verschiedenen Unterordnern des Ordners Resources gespeichert:

  • Eine quadratische Bitmap mit 72 Pixeln, die als /Resources/drawable-hdpi/MonkeyFace.png
  • Eine quadratische Bitmap mit 96 Pixeln, die als /Resources/drawable-xhdpi/MonkeyFace.png
  • Eine quadratische Bitmap mit 144 Pixeln, die als /Resources/drawable-xxhdpi/MonkeyFace.png
  • Eine quadratische Bitmap mit 192 Pixeln, die als /Resources/drawable-xxxhdpi/MonkeyFace.png

Diese erhielten eine Buildaktion von AndroidResource.

Im UWP-Projekt können Bitmaps an einer beliebigen Stelle im Projekt gespeichert werden, sie werden jedoch in der Regel in einem benutzerdefinierten Ordner oder im vorhandenen Ordner Assets gespeichert. Das UWP-Projekt enthält die folgenden Bitmaps:

  • Eine quadratische Bitmap mit 48 Pixeln, die als "/Assets/MonkeyFace.scale-100.png" gespeichert ist
  • Eine quadratische Bitmap mit 96 Pixeln, die als /Assets/MonkeyFace.scale-200.png gespeichert ist
  • Eine quadratische Bitmap mit 192 Pixeln, die als /Assets/MonkeyFace.scale-400.png gespeichert ist

Sie alle erhielten eine Buildaktion von Inhalten.

Sie können angeben, wie die Text Eigenschaften und ImageSource auf dem Button angeordnet werden, indem Sie die ContentLayout -Eigenschaft von Buttonverwenden. Diese Eigenschaft ist vom Typ ButtonContentLayout, was eine eingebettete Klasse in Buttonist. Der Konstruktor weist zwei Argumente auf:

  • Ein Element der ImagePosition Enumeration: Left, Top, Rightoder Bottom , das angibt, wie die Bitmap relativ zum Text angezeigt wird.
  • Ein double Wert für den Abstand zwischen der Bitmap und dem Text.

Die Standardwerte sind Left und 10 Einheiten. Zwei schreibgeschützte Eigenschaften von ButtonContentLayout benannt Position und Spacing stellen die Werte dieser Eigenschaften bereit.

Im Code können Sie eine Button erstellen und die ContentLayout Eigenschaft wie folgt festlegen:

Button button = new Button
{
    Text = "button text",
    ImageSource = new FileImageSource
    {
        File = "image filename"
    },
    ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};

In XAML müssen Sie nur den Enumerationsmember oder den Abstand oder beides in einer durch Kommas getrennten Reihenfolge angeben:

<Button Text="button text"
        ImageSource="image filename"
        ContentLayout="Right, 20" />

Auf der Seite Image Button Demo werden OnPlatform verschiedene Dateinamen für die Bitmapdateien iOS, Android und UWP angegeben. Wenn Sie für jede Plattform denselben Dateinamen verwenden möchten und die Verwendung von OnPlatformvermeiden möchten, müssen Sie die UWP-Bitmaps im Stammverzeichnis des Projekts speichern.

Die erste Button auf der Seite Image Button Demo legt die Image Eigenschaft, aber nicht die Text Eigenschaft fest:

<Button>
    <Button.ImageSource>
        <OnPlatform x:TypeArguments="ImageSource">
            <On Platform="iOS, Android" Value="MonkeyFace.png" />
            <On Platform="UWP" Value="Assets/MonkeyFace.png" />
        </OnPlatform>
    </Button.ImageSource>
</Button>

Wenn die UWP-Bitmaps im Stammverzeichnis des Projekts gespeichert werden, kann dieses Markup erheblich vereinfacht werden:

<Button ImageSource="MonkeyFace.png" />

Um viele wiederholte Markups in der Datei ImageButtonDemo.xaml zu vermeiden, wird auch ein implizites Style definiert, um die ImageSource Eigenschaft festzulegen. Dies Style wird automatisch auf fünf weitere Button Elemente angewendet. Hier ist die vollständige XAML-Datei:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ButtonDemos.ImageButtonDemoPage">

    <FlexLayout Direction="Column"
                JustifyContent="SpaceEvenly"
                AlignItems="Center">

        <FlexLayout.Resources>
            <Style TargetType="Button">
                <Setter Property="ImageSource">
                    <OnPlatform x:TypeArguments="ImageSource">
                        <On Platform="iOS, Android" Value="MonkeyFace.png" />
                        <On Platform="UWP" Value="Assets/MonkeyFace.png" />
                    </OnPlatform>
                </Setter>
            </Style>
        </FlexLayout.Resources>

        <Button>
            <Button.ImageSource>
                <OnPlatform x:TypeArguments="ImageSource">
                    <On Platform="iOS, Android" Value="MonkeyFace.png" />
                    <On Platform="UWP" Value="Assets/MonkeyFace.png" />
                </OnPlatform>
            </Button.ImageSource>
        </Button>

        <Button Text="Default" />

        <Button Text="Left - 10"
                ContentLayout="Left, 10" />

        <Button Text="Top - 10"
                ContentLayout="Top, 10" />

        <Button Text="Right - 20"
                ContentLayout="Right, 20" />

        <Button Text="Bottom - 20"
                ContentLayout="Bottom, 20" />
    </FlexLayout>
</ContentPage>

Die letzten vier Button Elemente verwenden die ContentLayout -Eigenschaft, um eine Position und einen Abstand des Texts und der Bitmap anzugeben:

Demo der Bildschaltfläche

Sie haben nun die verschiedenen Möglichkeiten kennengelernt, wie Sie Ereignisse behandeln Button und die Button Darstellung ändern können.