Xamarin.Forms Botón

Ejemplo de descarga Descarga del ejemplo

El botón responde a una pulsación o un clic que dirige a una aplicación para llevar a cabo una tarea determinada.

es Button el control interactivo más fundamental en todo Xamarin.Forms . normalmente muestra una cadena de texto corta que indica un comando, pero también puede mostrar una imagen de mapa de bits o una combinación Button de texto y una imagen. El usuario presiona con un dedo o hace clic en él Button con un mouse para iniciar ese comando.

La mayoría de los temas que se tratan a continuación corresponden a las páginas del ejemplo ButtonDemos.

Control de clics de botón

Button define un Clicked evento que se desencadena cuando el usuario pulsa con un Button dedo o un puntero del mouse. El evento se desencadena cuando se libera el dedo o el botón del mouse desde la superficie de Button . debe Button tener su propiedad Xamarin_Forms Button _VisualElement_IsEnabled" data-linktype="absolute-path">establecida en para que responda a las IsEnabledtrue pulsaciones.

La página Clic de botón básico del ejemplo ButtonDemos muestra cómo crear una instancia de en XAML y controlar su evento. El archivo BasicButtonClickPage.xaml contiene un objeto con y LabelButton :

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

tiende Button a ocupar todo el espacio que se le permite. Por ejemplo, si no establece la propiedad de en algo distinto de , ocupará el HorizontalOptions ancho completo de su elemento ButtonFillButton primario.

De forma predeterminada, es rectangular, pero puede darle esquinas redondeadas mediante la propiedad ButtonButton data-linktype="absolute-path">de Xamarin_Forms CornerRadius _Button_CornerRadius", como se describe a continuación en la sección Apariencia del botón .

La Xamarin_Forms _Button_Text" data-linktype="absolute-path">especifica Text el texto que aparece en Button . El Clicked evento se establece en un controlador de eventos denominado OnButtonClicked . Este controlador se encuentra en el archivo de código subyacente, BasicButtonClickPage.xaml.cs:

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

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

Cuando se pulsa Button, se ejecuta el método OnButtonClicked. El sender argumento es el objeto responsable de este Button evento. Puede usarlo para acceder al objeto o para distinguir Button entre varios objetos que Button comparten el mismo Clicked evento.

Este controlador concreto llama a una función de animación que gira ClickedLabel los 360 grados en 1000 milisegundos. Este es el programa que se ejecuta en dispositivos iOS y Android, y como una aplicación de Plataforma universal de Windows (UWP) en el escritorio Windows 10 escritorio:

botón Básico Hagaclicen el

Observe que el OnButtonClicked método incluye el modificador porque se usa dentro del controlador de asyncawait eventos. Un Clicked controlador de eventos solo requiere el modificador si el cuerpo del controlador usa asyncawait .

Cada plataforma representa el Button objeto de su propia manera específica. En la sección Aspecto del botón, verá cómo establecer colores y hacer que el borde sea visible para apariencias más personalizadas. Buttonimplementa la interfaz , por lo que incluye IFontElement Xamarin_Forms Button _Button_FontFamily" data-linktype="absolute-path">FontFamily , Xamarin_Forms IFontElement _Button_FontSize" data-linktype="absolute-path">FontSize y Xamarin_Forms _Button_FontAttributes" data-linktype="absolute-path">FontAttributes properties.

Creación de un botón en el código

Es habitual crear instancias de un en Button XAML, pero también puedes crear un elemento Button en el código. Esto puede ser conveniente cuando la aplicación necesita crear varios botones basados en datos que se pueden enumerar con un foreach bucle.

La página Clic en el botón de código muestra cómo crear una página que sea funcionalmente equivalente a la página Clic de botón básico, pero completamente en 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
            }
        };
    }
}

Todo se realiza en el constructor de la clase. Dado que Clicked el controlador es solo una instrucción de larga duración, se puede adjuntar al evento de forma muy sencilla:

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

Por supuesto, también puede definir el controlador de eventos como un método independiente (al igual que el método en Basic Button Click ) y adjuntar ese método OnButtonClick al evento : OnButtonClick

button.Clicked += OnButtonClicked;

Deshabilitar el botón

A veces, una aplicación está en un estado determinado en el que un clic determinado Button no es una operación válida. En esos casos, Button debe deshabilitarse estableciendo su IsEnabled propiedad en false . El ejemplo clásico es un control para un nombre de archivo acompañado de un archivo abierto: solo debe habilitarse si se ha escrito algún texto EntryButton en ButtonEntry . Puede usar para DataTrigger esta tarea, como se muestra en el artículo DataTrigger datos.

Uso de la interfaz de comandos

Es posible que una aplicación responda a las Button pulsaciones sin controlar el Clicked evento. implementa Button un mecanismo de notificación alternativo denominado comando Buttoninterfaz de comandos. Consta de dos propiedades:

Este enfoque es especialmente adecuado en relación con el enlace de datos y, especialmente, al implementar la arquitectura Model-View-ViewModel (MVVM). Estos temas se tratan en los artículos Enlace dedatos , De enlaces de datos a MVVMy MVVM.

En una aplicación MVVM, el modelo de vista define propiedades de tipo que luego se conectan a ICommand los elementos XAML con enlaces de Button datos. Xamarin.Forms también define las Command clases y que implementan la interfaz y ayudan al modelo de vista a definir propiedades de tipo Command<T>ICommandICommand .

Los comandos se describen con más detalle en el artículo La interfaz de comandos, pero la página Comando de botón básico del ejemplo ButtonDemos muestra el enfoque básico.

La clase es un modelo de vista muy simple que define una propiedad de tipo denominada y dos CommandDemoViewModeldouble propiedades de tipo NumberICommandMultiplyBy2Command denominadas y 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; }
}

Las dos ICommand propiedades se inicializan en el constructor de la clase con dos objetos de tipo Command . Los Command constructores incluyen una pequeña función (denominada argumento de constructor) que duplica o reduce a execute la mitad la propiedad Number .

El archivo BasicButtonCommand.xaml establece su en una instancia de CommandDemoViewModel . El Label elemento y dos elementos contienen enlaces a las tres propiedades de ButtonCommandDemoViewModel :

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

A medida que se pulsan los dos elementos, se ejecutan los comandos Button y el número cambia de valor:

Comando de botón básico Comandobásico Comando de

La ventaja de este enfoque sobre los controladores es que toda la lógica que implica la funcionalidad de esta página se encuentra en el modelo de vista en lugar del archivo de código subyacente, lo que consigue una mejor separación de la interfaz de usuario de la lógica de Clicked negocios.

También es posible que los Command objetos controle la habilitación y deshabilitación de los Button elementos. Por ejemplo, supongamos que desea limitar el intervalo de valores numéricos entre 210 y 2–10. Puede agregar otra función al constructor (denominado argumento canExecute ) que devuelve si se debe habilitar trueButton . Esta es la modificación del CommandDemoViewModel constructor:

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

Las llamadas al método de son necesarias para que el método pueda llamar al método y determinar si ChangeCanExecute se debe deshabilitar o no CommandCommandcanExecuteButton . Con este cambio de código, a medida que el número alcanza el límite, Button se deshabilita :

Basic Button Command - ModifiedBasic Button Command - Modified (Comando de botón básico

Es posible enlazar dos o más Button elementos a la misma ICommand propiedad. Los elementos se pueden distinguir mediante la propiedad ButtonButton Xamarin_Forms _Button_CommandParameter" data-linktype="absolute-path">CommandParameter propiedad de Button . En este caso, querrá usar la clase Command<T> genérica . A CommandParameter continuación, el objeto se pasa como argumento a los executecanExecute métodos y . Esta técnica se muestra en detalle en la sección Comandos básicos del artículo Interfaz de comandos.

El ejemplo ButtonDemos también usa esta técnica en su clase . El archivo MainPage.xaml contiene un para cada página del ejemplo:

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

Cada tiene su propiedad enlazada a una propiedad denominada y se establece en un objeto correspondiente a una de las clases ButtonCommand de página del NavigateCommandCommandParameterType proyecto.

Esa NavigateCommand propiedad es de tipo y se define en el archivo de código ICommand subyacente:

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

El constructor inicializa la NavigateCommand propiedad en un objeto porque es el tipo del objeto establecido en el archivo Command<Type>TypeCommandParameter XAML. Esto significa que el execute método tiene un argumento de tipo que corresponde a este objeto TypeCommandParameter . La función crea una instancia de la página y, a continuación, navega a ella.

Observe que el constructor concluye estableciendo su BindingContext en sí mismo. Esto es necesario para que las propiedades del archivo XAML se enlacen a la NavigateCommand propiedad .

Presionar y soltar el botón

Además del evento Clicked, Button también define los eventos Pressed y Released. El evento tiene lugar cuando un dedo presiona un control o se presiona un botón del mouse con el PressedButton puntero situado sobre Button . El Released evento tiene lugar cuando se libera el dedo o el botón del mouse. Por lo general, un evento también se desencadena al mismo tiempo que el evento, pero si el dedo o el puntero del mouse se deslizan fuera de la superficie de antes de ser liberado, es posible que el evento no se ClickedReleasedButtonClicked produzca.

Los eventos y no se usan a menudo, pero se pueden usar con fines especiales, como se muestra en la página Botón de PressedReleased presionar Pressed liberar. El archivo XAML contiene un Label elemento y un con controladores Button adjuntos para los eventos y PressedReleased :

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

El archivo de código subyacente anima cuando se produce un evento, pero suspende la rotación Label cuando se produce un PressedReleased evento:

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

El resultado es que el único gira mientras un dedo está en contacto con y se detiene cuando se libera LabelButton el dedo:

Presionar y soltar botón Presioney suelte el

Este tipo de comportamiento tiene aplicaciones para juegos: un dedo sobre un objeto podría hacer que un objeto en pantalla se mueva Button en una dirección determinada.

Apariencia del botón

hereda Button o define varias propiedades que afectan a su apariencia:

Nota:

La clase también tiene Button Xamarin_Forms Button _View_Margin" data-linktype="absolute-path">Margin and Xamarin_Forms _Button_Padding" data-linktype="absolute-path">properties that control Padding the layout behavior of the Button . Para obtener más información, vea Márgenes y relleno.

Los efectos de seis de estas propiedades (excepto FontFamily y ) se muestran en la página Apariencia FontAttributesFontFamily botón. Otra propiedad, Xamarin_Forms _Button_ImageSource" data-linktype="absolute-path">Image , Imagese describe en la sección Uso de mapas de bits con el botón .

Todas las vistas y enlaces de datos de la página Apariencia del botón se definen en el archivo 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>

en Button la parte superior de la página tiene sus tres propiedades enlazadas a elementos en la parte inferior de la ColorPicker página. Los elementos de los Picker elementos son colores de la clase incluida en el NamedColor proyecto. Tres elementos contienen enlaces de dos vías a las propiedades Slider , y de FontSizeBorderWidthCornerRadiusButton .

Este programa permite experimentar con combinaciones de todas estas propiedades:

Apariencia del botón Apariencia

Para ver el borde, deberá establecer un en algo distinto de Button y en un valor BorderColorDefaultBorderWidth positivo.

En iOS, observará que los anchos de borde grandes se intruen en el interior de e interfieren con la Button presentación de texto. Si decide usar un borde con un iOS, probablemente querrá comenzar y finalizar la propiedad con espacios para ButtonText conservar su visibilidad.

En UWP, al seleccionar un CornerRadius que supere la mitad del alto de , Button se produce una excepción.

Estados visuales de botón

Buttontiene un que se puede usar para iniciar un cambio visual en cuando el usuario lo presiona, siempre que PressedVisualStateButton esté habilitado.

En el ejemplo xaml siguiente se muestra cómo definir un estado visual para el Pressed estado :

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

especifica que, cuando se presiona , su propiedad PressedVisualStateButton Xamarin_Forms Pressed _VisualElement_Scale" data-linktype="absolute-path">se cambiará de su valor predeterminado de 1 a Scale 0,8. especifica NormalVisualState que cuando el objeto está en un Button estado normal, su propiedad se Scale establecerá en 1. Por lo tanto, el efecto general es que, cuando se presiona , se vuelve a escalar para que sea ligeramente más pequeño y, cuando se libera, se vuelve a escalar a su ButtonButton tamaño predeterminado.

Para obtener más información sobre los estados visuales, vea The Xamarin.Forms Visual State Manager .

Creación de un botón de alternancia

Es posible crear subclases para que funcione como un conmutador de activación y desactivación: pulse el botón una vez para activarlo y pulse de nuevo para Button desactivarlo.

La clase ToggleButton siguiente se deriva de y define un nuevo evento denominado y una propiedad ButtonToggled booleana denominada IsToggled . Estas son las mismas dos propiedades definidas por 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");
    }
}

El ToggleButton constructor adjunta un controlador al evento para que pueda cambiar el valor de la propiedad ClickedIsToggled . El OnIsToggledChanged método desaprende el Toggled evento.

La última línea del método llama al método estático con las dos cadenas de texto OnIsToggledChangedVisualStateManager.GoToState "ToggledOn" y "ToggledOff". Puede leer sobre este método y cómo la aplicación puede responder a los estados visuales en el artículo The Xamarin.Forms Visual State Manager .

Dado que realiza la llamada a , la propia clase no necesita incluir ninguna función adicional para cambiar la apariencia del botón ToggleButton en función de su VisualStateManager.GoToStateIsToggled estado. Esa es la responsabilidad del XAML que hospeda ToggleButton .

La página Toggle Button Demo (Alternar demostración de botón) contiene dos instancias de , incluido el marcado de Visual State Manager que establece , y del botón en función del estado TextBackgroundColorTextColor visual:

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

Los Toggled controladores de eventos están en el archivo de código subyacente. Son responsables de establecer la FontAttributes propiedad de en función del estado de los Label botones:

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

Este es el programa que se ejecuta en iOS, Android y UWP:

Demostración de botón de alternancia De

Uso de mapas de bits con botones.

La clase define una propiedad Button Xamarin_Forms Button _Button_Image" data-linktype="absolute-path">que permite mostrar una imagen de mapa de bits en ImageSource , ya sea solo o en combinación con Button texto. También puede especificar cómo se organizan el texto y la imagen.

La propiedad es de tipo , lo que significa que los mapas de bits se pueden cargar desde un ImageSourceImageSource archivo, recurso incrustado, URI o secuencia.

Nota:

Aunque un Button puede cargar un GIF animado, solo mostrará el primer fotograma del GIF.

Cada plataforma compatible con permite almacenar imágenes en varios tamaños para diferentes resoluciones de píxeles de los distintos dispositivos en los que Xamarin.Forms se podría ejecutar la aplicación. Estos mapas de bits se denominan o almacenan de forma que el sistema operativo pueda elegir la mejor coincidencia para la resolución de pantalla de vídeo del dispositivo.

Para un mapa de bits en un , el mejor tamaño suele ser entre 32 y 64 unidades independientes del dispositivo, dependiendo del tamaño que Button quiera que sea. Las imágenes usadas en este ejemplo se basan en un tamaño de 48 unidades independientes del dispositivo.

En el proyecto de iOS, la carpeta Recursos contiene tres tamaños de esta imagen:

  • Mapa de bits cuadrado de 48 píxeles almacenado como /Resources/MonkeyFace.png
  • Mapa de bits cuadrado de 96 píxeles almacenado como /Resource/
  • Mapa de bits cuadrado de 144 píxeles almacenado como /Resource/

A los tres mapas de bits se les ha dado una acción de compilaciónde BundleResource.

Para el proyecto de Android, todos los mapas de bits tienen el mismo nombre, pero se almacenan en subcarpetas diferentes de la carpeta Resources:

  • Mapa de bits cuadrado de 72 píxeles almacenado como /Resources/drawable-hdpi/MonkeyFace.png
  • Mapa de bits cuadrado de 96 píxeles almacenado como /Resources/drawable-xhdpi/MonkeyFace.png
  • Mapa de bits cuadrado de 144 píxeles almacenado como /Resources/drawable-xxhdpi/MonkeyFace.png
  • Mapa de bits cuadrado de 192 píxeles almacenado como /Resources/drawable-xxxhdpi/MonkeyFace.png

Se les ha dado una acción de compilación de AndroidResource.

En el proyecto de UWP, los mapas de bits se pueden almacenar en cualquier parte del proyecto, pero normalmente se almacenan en una carpeta personalizada o en la carpeta assets existente. El proyecto de UWP contiene estos mapas de bits:

  • Mapa de bits cuadrado de 48 píxeles almacenado como /Assets/MonkeyFace.scale-100.png
  • Mapa de bits cuadrado de 96 píxeles almacenado como /Assets/MonkeyFace.scale-200.png
  • Mapa de bits cuadrado de 192 píxeles almacenado como /Assets/MonkeyFace.scale-400.png

Se les ha dado una acción de compilación de contenido.

Puede especificar cómo se organizan las propiedades y en mediante la propiedad TextImageSource Xamarin_Forms ButtonText _Button_ContentLayout" data-linktype="absolute-path">ContentLayout de Button . Esta propiedad es de tipo ButtonContentLayout , que es una clase incrustada en Button . El Xamarin_Forms _Button_ButtonContentLayout__ctor_ Xamarin_Forms _Button_ButtonContentLayout_ImagePosition_System_Double_" data-linktype="absolute-path">constructor tiene dos argumentos:

  • Miembro de la enumeración : , , o que indica cómo aparece el ImagePosition mapa de bits con respecto al LeftTopRightBottom texto.
  • Valor double para el espaciado entre el mapa de bits y el texto.

Los valores predeterminados son Left y 10 unidades. Dos propiedades de solo lectura de Xamarin_Forms ButtonContentLayoutButtonContentLayout _Button_ButtonContentLayout_Position" data-linktype="absolute-path">Position y Xamarin_Forms _Button_ButtonContentLayout_Spacing" data-linktype="absolute-path">Spacing proporcionan los valores de esas propiedades.

En el código, puede crear un Button y establecer la propiedad de la siguiente ContentLayout forma:

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

En XAML, solo debe especificar el miembro de enumeración, el espaciado, o ambos en cualquier orden separados por comas:

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

La página Demostración de botón de imagen usa para especificar nombres de archivo diferentes para los archivos de mapa de bits de iOS, Android y UWP. Si quieres usar el mismo nombre de archivo para cada plataforma y evitar el uso de , tendrás que almacenar los mapas de bits de UWP en el directorio OnPlatform raíz del proyecto.

La primera Button de la página Button de imagen establece la propiedad , pero no la propiedad ImageText :

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

Si los mapas de bits de UWP se almacenan en el directorio raíz del proyecto, este marcado se puede simplificar considerablemente:

<Button ImageSource="MonkeyFace.png" />

Para evitar una gran cantidad de marcado repetitivo en el archivo ImageButtonDemo.xaml, también se define un implícito para establecer la propiedad ImageSource . Esto Style se aplica automáticamente a otros cinco Button elementos. Este es el archivo XAML completo:

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

Los cuatro elementos Button finales usan la propiedad para especificar una posición y un espaciado del texto y el mapa de ContentLayout bits:

Demostración del botón De demostración

Ahora ha visto las distintas formas en que puede controlar eventos Button y cambiar la Button apariencia.