Xamarin.Forms Tlačítko

Download Sample Stažení ukázky

Tlačítko odpoví klepnutím nebo kliknutím, které aplikaci přesměruje, aby provedla konkrétní úlohu.

Je Button to nejzákladnější interaktivní ovládací prvek ve všech .Xamarin.Forms Obvykle Button se zobrazí krátký textový řetězec označující příkaz, ale může také zobrazit rastrový obrázek nebo kombinaci textu a obrázku. Uživatel stiskne Button prstem nebo na něj klikne myší a zahájí tento příkaz.

Většina témat probíraných níže odpovídá stránkám v ukázce ButtonDemos .

Zpracování kliknutí na tlačítko

ButtonClicked definuje událost, která se aktivuje, když uživatel klepne Button prstem nebo ukazatelem myši. Událost se aktivuje, když je tlačítko prstu nebo myši uvolněno z povrchu Button. Vlastnost Button musí mít IsEnabled nastavenou tak true , aby odpovídala na klepnutí.

Stránka Kliknutí na základní tlačítko v ukázce ButtonDemos ukazuje, jak vytvořit instanci Button v XAML a zpracovat její Clicked událost. Soubor BasicButtonClickPage.xaml obsahuje jak StackLayout s, LabelButtontak i :

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

Obvykle Button zabírají veškerý prostor, který je pro něj povolený. Pokud například nenastavíte HorizontalOptions vlastnost na jinou hodnotuButton, FillButton bude zabírat plnou šířku nadřazeného objektu.

Ve výchozím nastavení je obdélníkový Button , ale můžete jej zaokrouhlit rohy pomocí CornerRadius vlastnosti, jak je popsáno níže v části Vzhled tlačítka.

Vlastnost Text určuje text, který se zobrazí v objektu Button. Událost Clicked je nastavena na obslužnou rutinu události s názvem OnButtonClicked. Tato obslužná rutina se nachází v souboru kódu BasicButtonClickPage.xaml.cs:

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

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

Při klepnutí na objekt Button se spustí metoda OnButtonClicked. Argument sender je Button objekt zodpovědný za tuto událost. Můžete ho použít pro přístup k objektu Button nebo k rozlišení mezi více Button objekty, které sdílejí stejnou Clicked událost.

Tato konkrétní Clicked obslužná rutina volá animační funkci, která otočí Label 360 stupňů v milisekundách o 1000 milisekund. Tady je program spuštěný na zařízeních s iOSem a Androidem a jako Univerzální platforma Windows (UPW) na stolním počítači s Windows 10:

Basic Button Click

Všimněte si, že OnButtonClicked metoda obsahuje async modifikátor, protože await se používá v obslužné rutině události. Obslužná Clicked rutina události vyžaduje async modifikátor pouze v případě, že tělo obslužné rutiny používá await.

Každá platforma vykreslí Button svůj vlastní konkrétní způsob. V části Vzhled tlačítka se dozvíte, jak nastavit barvy a nastavit, aby ohraničení bylo Button viditelné pro více přizpůsobené vzhledy. Button implementuje IFontElement rozhraní, takže zahrnuje FontFamily, FontSizea FontAttributes vlastnosti.

Vytvoření tlačítka v kódu

Vytvoření instance Button v jazyce XAML je běžné, ale můžete také vytvořit Button v kódu. To může být vhodné, když vaše aplikace potřebuje vytvořit více tlačítek na základě dat, která jsou vyčíslitelná smyčkou foreach .

Stránka Kliknutí na tlačítko kódu ukazuje, jak vytvořit stránku, která je funkčně ekvivalentní stránce Základní kliknutí na tlačítko, ale zcela v jazyce 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
            }
        };
    }
}

Všechno se provádí v konstruktoru třídy. Protože obslužná rutina Clicked je jen jeden příkaz dlouhý, může být připojena k události velmi jednoduše:

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

Samozřejmě můžete také definovat obslužnou rutinu události jako samostatnou metodu (stejně jako OnButtonClick metoda v základním kliknutí na tlačítko) a připojit tuto metodu k události:

button.Clicked += OnButtonClicked;

Zakázání tlačítka

Někdy je aplikace v určitém stavu, kdy konkrétní Button kliknutí není platná operace. V těchto případech Button by měla být zakázána nastavením jeho IsEnabled vlastnosti na falsehodnotu . Klasický příklad je ovládací prvek Entry pro název souboru doprovázený soubor-open Button: Mělo Button by být povoleno pouze v případě, že byl do souboru Entryzadán nějaký text . Pro tuto úlohu můžete použít funkci DataTrigger , jak je znázorněno v článku Triggery dat.

Použití příkazového rozhraní

Aplikace může reagovat na Button klepnutí bez zpracování Clicked události. Implementuje Button alternativní mechanismus oznámení, který se nazývá příkaz nebo příkazové rozhraní. Skládá se ze dvou vlastností:

Tento přístup je vhodný zejména v souvislosti s datovou vazbou a zejména při implementaci architektury MVVM (Model-View-ViewModel). Tato témata jsou popsána v článcích Datové vazby, From Data Bindings to MVVM a MVVM.

V aplikaci MVVM model viewmodel definuje vlastnosti typu ICommand , které jsou pak připojeny k elementům XAML Button s datovými vazbami. Xamarin.Forms také definuje Command a Command<T> třídy, které implementují ICommand rozhraní a pomáhají modelu viewmodel při definování vlastností typu ICommand.

Příkazování je podrobněji popsáno v článku Rozhraní příkazů, ale základní tlačítko příkazové stránky v buttonDemos ukázka ukazuje základní přístup.

Třída CommandDemoViewModel je velmi jednoduchý viewmodel, který definuje vlastnost typu double s názvem Number, a dvě vlastnosti typu ICommand pojmenované MultiplyBy2Command a DivideBy2Command:

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

ICommand Dvě vlastnosti jsou inicializovány v konstruktoru třídy se dvěma objekty typu Command. Konstruktory Command obsahují malou funkci (označovanou jako argument konstruktoru execute ), která buď zdvojnásobí nebo polovinu Number vlastnosti.

Soubor BasicButtonCommand.xaml nastaví jeho BindingContext instanci CommandDemoViewModel. Element Label a dva Button prvky obsahují vazby na tři vlastnosti v 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>

Po klepnutí na tyto dva Button prvky se spustí příkazy a hodnota změny čísla:

Basic Button Command

Výhodou tohoto přístupu oproti Clicked obslužným rutinám je, že veškerá logika zahrnující funkce této stránky se nachází v modelu zobrazení, nikoli v souboru kódu, a dosahuje lepšího oddělení uživatelského rozhraní od obchodní logiky.

Objekty mohou také Command řídit povolení a zakázání Button prvků. Předpokládejme například, že chcete omezit rozsah číselných hodnot mezi 210 a 2–10. Do konstruktoru (označovaného jako canExecute argument) můžete přidat další funkci, která se vrátí true , pokud by měla být povolena Button . Tady je úprava konstruktoru CommandDemoViewModel :

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

Volání ChangeCanExecute metody Command jsou nezbytná, aby Command metoda mohl volat metodu canExecute a určit, zda by měla být zakázána Button , nebo ne. Když se tento kód změní, jakmile číslo dosáhne limitu Button , je zakázáno:

Basic Button Command - Modified

Je možné, aby dva nebo více Button prvků byly vázány na stejnou ICommand vlastnost. Prvky Button lze rozlišit pomocí CommandParameter vlastnosti Button. V tomto případě budete chtít použít obecnou Command<T> třídu. Objekt CommandParameter se pak předá jako argument execute a canExecute metody. Tato technika je podrobně zobrazena v části Základní příkazování článku rozhraní příkazového rozhraní.

Ukázka ButtonDemos také používá tuto techniku ve své MainPage třídě. Soubor MainPage.xaml obsahuje Button pro každou stránku ukázky:

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

Každá Button má svou Command vlastnost vazbu na vlastnost s názvem NavigateCommanda CommandParameter je nastavena na Type objekt odpovídající jedné ze tříd stránky v projektu.

Tato NavigateCommand vlastnost je typu ICommand a je definována v souboru kódu za kódem:

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

Konstruktor inicializuje NavigateCommand vlastnost na objekt, Command<Type> protože Type je typ objektu CommandParameter nastaven v souboru XAML. To znamená, že execute metoda má argument typu Type , který odpovídá tomuto CommandParameter objektu. Funkce vytvoří instanci stránky a pak na ni přejde.

Všimněte si, že konstruktor končí tím, že se nastaví BindingContext na sebe. To je nezbytné pro vlastnosti v souboru XAML vytvořit vazbu k NavigateCommand vlastnosti.

Stisknutí a uvolnění tlačítka

Kromě události Clicked objekt Button definuje také události Pressed a Released. K Pressed události dochází, když prst stiskne na Buttonnebo tlačítko myši je stisknuto ukazatelem nad Button. K Released události dochází při uvolnění prstu nebo tlačítka myši. Obecně platí, že Clicked událost se aktivuje současně s Released událostí, ale pokud se prst nebo ukazatel myši posune mimo povrch Button před uvolněním, Clicked událost nemusí nastat.

Události Pressed se často nepoužívají, ale lze je použít pro speciální účely, jak je znázorněno na stránce Tlačítka pro tisk a uvolnění.Released Soubor XAML obsahuje Label a Button s obslužnými rutinami připojenými k událostem Pressed a Released událostem:

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

Soubor kódu za kódem animuje Label , kdy Pressed dojde k události, ale pozastaví otočení, když Released dojde k události:

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

Výsledkem je, že Label se pouze otočí, když je prst v kontaktu s prstem Buttona zastaví se při uvolnění prstu:

Press and Release Button

Tento druh chování má aplikace pro hry: Prst pochytávaný na Button objektu na obrazovce se může pohybovat v určitém směru.

Vzhled tlačítka

Dědí Button nebo definuje několik vlastností, které ovlivňují jeho vzhled:

Poznámka:

Třída ButtonMargin také a Padding vlastnosti, které řídí chování Buttonrozložení . Další informace najdete v článku o okrajích a odsazeních.

Účinky šesti těchto vlastností (s výjimkou FontFamily a FontAttributes) jsou znázorněny na stránce Vzhled tlačítka. Další vlastnost, Image, je popsána v části Použití rastrových obrázků s tlačítkem.

Všechna zobrazení a datové vazby na stránce Vzhled tlačítka jsou definovány v souboru XAML:

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

V Button horní části stránky jsou tři Color vlastnosti svázané s Picker prvky v dolní části stránky. Položky v elementech Picker jsou barvy z NamedColor třídy zahrnuté v projektu. Tři Slider prvky obsahují obousměrné vazby na FontSize, BorderWidtha CornerRadius vlastnosti Button.

Tento program umožňuje experimentovat s kombinacemi všech těchto vlastností:

Button Appearance

Pokud chcete zobrazit ohraničení Button , musíte nastavit jinou BorderColor hodnotu než Defaulta na kladnou BorderWidth hodnotu.

V iOSu si všimnete, že velké šířky ohraničení vniknou do interiéru Button textu a kolidují s zobrazením textu. Pokud se rozhodnete použít ohraničení s iOSem Button, budete pravděpodobně chtít začít a ukončit Text vlastnost mezerami, aby se zachovala jeho viditelnost.

V UPW vyberte CornerRadius hodnotu, která překračuje polovinu výšky Button zvýšení výjimky.

Stavy vizuálů tlačítek

ButtonPressedVisualState má možnost, která se dá použít k zahájení vizuální změny Button při stisknutí uživatele za předpokladu, že je povolená.

Následující příklad XAML ukazuje, jak definovat stav vizuálu Pressed pro stav:

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

Určuje PressedVisualState , že když je Button stisknuto, jeho Scale vlastnost bude změněna z výchozí hodnoty 1 na 0,8. Určuje NormalVisualState , že pokud je v Button normálním stavu, jeho Scale vlastnost bude nastavena na 1. Celkovým účinkem je proto, že při Button stisknutí se zvětší, aby byl o něco menší a při Button uvolnění se znovu škáluje na výchozí velikost.

Další informace o stavech vizuálů naleznete v tématu Správce stavu vizuáluXamarin.Forms.

Vytvoření přepínacího tlačítka

Podtřídu je možné podtřídu Button , aby fungovala jako přepínač zapnuto: Jedním klepnutím na tlačítko tlačítko zapněte a dalším klepnutím ho vypněte.

Následující ToggleButton třída odvozuje a Button definuje novou událost pojmenovanou Toggled a logickou vlastnost s názvem IsToggled. Jedná se o stejné dvě vlastnosti definované pomocí Xamarin.FormsSwitch:

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

Konstruktor ToggleButton připojí obslužnou rutinu Clicked k události, aby mohl změnit hodnotu IsToggled vlastnosti. Metoda OnIsToggledChanged aktivuje Toggled událost.

Poslední řádek OnIsToggledChanged metody volá statickou VisualStateManager.GoToState metodu se dvěma textovými řetězci "ToggledOn" a "ToggledOff". O této metodě a o tom, jak vaše aplikace může reagovat na vizuální stavy, si můžete přečíst v článku Správce stavu vizuáluXamarin.Forms.

Vzhledem k tomu ToggleButton , že je volání VisualStateManager.GoToState, třída sama nemusí obsahovat žádné další zařízení ke změně vzhledu tlačítka na základě jeho IsToggled stavu. To je odpovědnost XAML, která je hostitelem ToggleButton.

Stránka Přepnout tlačítko Demo obsahuje dvě instance ToggleButton, včetně kódu Visual State Manager, který nastaví Text, BackgroundColora TextColor tlačítka na základě vizuálního stavu:

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

Obslužné Toggled rutiny událostí jsou v souboru kódu. Zodpovídají za nastavení FontAttributes vlastnosti Label na základě stavu tlačítek:

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

Tady je program, který běží na iOSu, Androidu a UPW:

Toggle Button Demo

Použití rastrových obrázků s tlačítky

Třída Button definuje ImageSource vlastnost, která umožňuje zobrazit rastrový obrázek na Button, buď samostatně, nebo v kombinaci s textem. Můžete také určit způsob uspořádání textu a obrázku.

Vlastnost ImageSource je typu ImageSource, což znamená, že rastrové obrázky lze načíst ze souboru, vloženého prostředku, identifikátoru URI nebo datového proudu.

Poznámka:

Button I když může načíst animovaný obrázek GIF, zobrazí se pouze první snímek gifu.

Každá platforma podporovaná Xamarin.Forms umožňuje ukládání obrázků ve více velikostech pro různá rozlišení pixelů různých zařízení, na kterých může aplikace běžet. Tyto více rastrových obrázků jsou pojmenovány nebo uloženy tak, aby operační systém mohl vybrat nejlepší shodu pro rozlišení videa zařízení.

U rastrového obrázku na obrázku Buttonje nejlepší velikost obvykle mezi 32 a 64 jednotkami nezávislými na zařízení v závislosti na tom, jak velký chcete, aby byl. Obrázky použité v tomto příkladu jsou založené na velikosti 48 jednotek nezávislých na zařízeních.

V projektu iOS obsahuje složka Resources tři velikosti tohoto obrázku:

  • Čtvercový rastrový obrázek o rozměrech 48 pixelů uložený jako /Resources/MonkeyFace.png
  • Čtvercový rastrový obrázek o rozměrech 96 pixelů uložený jako /Zdroj/MonkeyFace@2x.png
  • Čtvercový rastrový obrázek o rozměrech 144 pixelů uložený jako /Zdroj/MonkeyFace@3x.png

Všechny tři rastrové obrázky dostaly akcisestavení BundleResource.

U projektu Android mají rastrové obrázky stejný název, ale jsou uložené v různých podsložkách složky Resources :

  • Čtvercový rastrový obrázek o rozměrech 72 pixelů uložený jako /Resources/drawable-hdpi/MonkeyFace.png
  • Čtvercový rastr o velikosti 96 pixelů uložený jako /Resources/drawable-xhdpi/MonkeyFace.png
  • Čtvercový rastrový obrázek o velikosti 144 pixelů uložený jako /Resources/drawable-xxhdpi/MonkeyFace.png
  • Čtvercový rastrový obrázek o velikosti 192 pixelů uložený jako /Resources/drawable-xxxhdpi/MonkeyFace.png

Dostali jsme akcisestavení AndroidResource.

V projektu UPW lze rastrové obrázky ukládat kdekoli v projektu, ale obvykle jsou uložené ve vlastní složce nebo ve stávající složce Assets . Projekt UPW obsahuje tyto rastrové obrázky:

  • Čtvercový rastrový obrázek o rozměrech 48 pixelů uložený jako /Assets/MonkeyFace.scale-100.png
  • Čtvercový rastrový obrázek o rozměrech 96 pixelů uložený jako /Assets/MonkeyFace.scale-200.png
  • Čtvercový rastrový obrázek o rozměrech 192 pixelů uložený jako /Assets/MonkeyFace.scale-400.png

Všichni dostali akcisestavení obsahu.

Můžete určit, jak Text jsou vlastnosti uspořádány podle ButtonContentLayout vlastnosti Button.ImageSource Tato vlastnost je typu ButtonContentLayout, což je vložená třída v Button. Konstruktor má dva argumenty:

  • Člen výčtu ImagePosition : Left, Top, , Rightnebo Bottom indikující, jak se rastrový obrázek zobrazuje vzhledem k textu.
  • double Hodnota pro mezery mezi rastrovým obrázkem a textem.

Výchozí hodnoty jsou Left a 10 jednotek. Dvě vlastnosti jen pro čtení s ButtonContentLayout názvem Position a Spacing poskytují hodnoty těchto vlastností.

V kódu můžete vytvořit Button a nastavit ContentLayout vlastnost takto:

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

V jazyce XAML potřebujete zadat pouze člen výčtu, mezery nebo obojí v libovolném pořadí odděleném čárkami:

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

Stránka Ukázka tlačítka obrázku slouží OnPlatform k určení různých názvů souborů rastrových obrázků pro iOS, Android a UPW. Pokud chcete použít stejný název souboru pro každou platformu a vyhnout se použití OnPlatform, budete muset uložit rastrové obrázky UPW v kořenovém adresáři projektu.

První Button na stránce Ukázka tlačítka obrázku nastaví Image vlastnost, ale ne Text vlastnost:

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

Pokud jsou rastrové obrázky UPW uložené v kořenovém adresáři projektu, může být tento kód značně zjednodušený:

<Button ImageSource="MonkeyFace.png" />

Chcete-li zabránit mnoho opakování repetitious revize v ImageButtonDemo.xaml souboru, implicitní Style je také definována pro nastavení ImageSource vlastnosti. To Style se automaticky použije na pět dalších Button prvků. Tady je úplný soubor XAML:

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

Poslední čtyři Button prvky používají ContentLayout vlastnost k určení pozice a mezer textu a rastrového obrázku:

Image Button Demo

Seznámili jste se s různými způsoby, jak můžete zpracovávat Button události a měnit Button vzhled.