Botão
A UI do aplicativo multiplataforma .NET (.NET MAUI) Button exibe texto e responde a um toque ou clique que direciona o aplicativo para realizar uma tarefa. Um Button geralmente exibe uma pequena sequência de texto indicando um comando, mas também pode exibir uma imagem bitmap ou uma combinação de texto e uma imagem. Quando o Button é pressionado com o dedo ou clicado com o mouse, ele inicia esse comando.
Button define as propriedades a seguir:
BorderColor
, do tipo Color, descreve a cor da borda do botão.BorderWidth
, do tipodouble
, define a largura da borda do botão.CharacterSpacing
, do tipodouble
, define o espaçamento entre os caracteres do texto do botão.Command
, do tipo ICommand, define o comando que é executado quando o botão é tocado.CommandParameter
, do tipoobject
, é o parâmetro passado paraCommand
.ContentLayout
, do tipoButtonContentLayout
, define o objeto que controla a posição da imagem do botão e o espaçamento entre a imagem e o texto do botão.CornerRadius
, do tipoint
, descreve o raio do canto da borda do botão.FontAttributes
, do tipoFontAttributes
, determina o estilo de texto.FontAutoScalingEnabled
, do tipobool
, define se o texto do botão refletirá as preferências de escala definidas no sistema operacional. O valor padrão dessa propriedade étrue
.FontFamily
, do tipostring
, define a família da fonte.FontSize
, do tipodouble
, define o tamanho da fonte.- ImageSource, do tipo ImageSource, especifica uma imagem bitmap a ser exibida como o conteúdo do botão.
LineBreakMode
, do tipoLineBreakMode
, determina como o texto deve ser tratado quando não pode caber em uma linha.Padding
, do tipoThickness
, determina o preenchimento do botão.Text
, do tipostring
, define o texto exibido como o conteúdo do botão.TextColor
, do tipo Color, descreve a cor do texto do botão.TextTransform
, do tipoTextTransform
, define a caixa do texto do botão.
Essas propriedades são apoiadas por objetos BindableProperty, o que significa que podem ser alvos de associações de dados e ser estilizada.
Observação
Embora Button defina uma propriedade ImageSource, que permite exibir uma imagem no Button, esta propriedade deve ser usada ao exibir um pequeno ícone próximo ao texto Button.
Além disso, Button define eventos Clicked
, Pressed
e Released
. O evento Clicked
é gerado quando um toque Button com o dedo ou o ponteiro do mouse é liberado da superfície do botão. O evento Pressed
é gerado quando um dedo pressiona um Button ou um botão do mouse é pressionado com o ponteiro posicionado sobre Button. O evento Released
é gerado quando o dedo ou o botão do mouse é liberado. Geralmente, um evento Clicked
também é acionado ao mesmo tempo que o evento Released
, mas se o dedo ou o ponteiro do mouse deslizar para fora da superfície do Button antes de ser liberado, o evento Clicked
poderá não ocorrer.
Importante
Um Button deve ter sua propriedade IsEnabled
definida como true
para responder aos toques.
Crie um botão
Para criar um botão, crie um objeto Button e manipule seu evento Clicked
.
O exemplo XAML a seguir mostra como criar um Button:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.BasicButtonClickPage"
Title="Basic Button Click">
<StackLayout>
<Button Text="Click to Rotate Text!"
VerticalOptions="Center"
HorizontalOptions="Center"
Clicked="OnButtonClicked" />
<Label x:Name="label"
Text="Click the Button above"
FontSize="18"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
A propriedade Text
especifica o texto exibido no Button. O evento Clicked
está definido para um manipulador de eventos chamado OnButtonClicked
. Esse manipulador está localizado no arquivo code-behind:
public partial class BasicButtonClickPage : ContentPage
{
public BasicButtonClickPage ()
{
InitializeComponent ();
}
async void OnButtonClicked(object sender, EventArgs args)
{
await label.RelRotateTo(360, 1000);
}
}
Nesse exemplo, quando Button é tocado, o método OnButtonClicked
é executado. O argumento sender
é o Button objeto responsável por esse evento. Você pode usar isso para acessar o objeto Button ou para distinguir entre vários objetos Button que compartilham o mesmo evento Clicked
. O manipulador Clicked
chama uma função de animação que gira Label 360 graus em 1000 milissegundos:
O código C# equivalente para criar um Button é:
Button button = new Button
{
Text = "Click to Rotate Text!",
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Center
};
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);
Use a interface de comando
Um aplicativo pode responder a toques Button sem manipular o evento Clicked
. O Button implementa um mecanismo de notificação alternativo chamado interface de comando ou comandos. Isso consiste em duas propriedades:
Command
do tipo ICommand, uma interface definida no namespaceSystem.Windows.Input
.CommandParameter
propriedade do tipoObject
.
Essa abordagem é particularmente adequada em conexão com ligação de dados e, particularmente, ao implementar o padrão Model-View-ViewModel (MVVM). Em uma aplicação MVVM, o viewmodel define propriedades do tipo ICommand que são então conectadas a Button objetos com ligações de dados. O .NET MAUI também define as classes Command
e Command<T>
que implementam a interface ICommand e auxiliam o viewmodel na definição de propriedades do tipo ICommand. Para obter mais informações sobre os comandos, consulte Comando.
O exemplo a seguir mostra uma classe viewmodel muito simples que define uma propriedade do tipo double
nomeado Number
e duas propriedades do tipo ICommand nomeado MultiplyBy2Command
e DivideBy2Command
:
public class CommandDemoViewModel : INotifyPropertyChanged
{
double number = 1;
public event PropertyChangedEventHandler PropertyChanged;
public ICommand MultiplyBy2Command { get; private set; }
public ICommand DivideBy2Command { get; private set; }
public CommandDemoViewModel()
{
MultiplyBy2Command = new Command(() => Number *= 2);
DivideBy2Command = new Command(() => Number /= 2);
}
public double Number
{
get
{
return number;
}
set
{
if (number != value)
{
number = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Number"));
}
}
}
}
Nesse exemplo, as duas propriedades ICommand são inicializadas no construtor da classe com dois objetos do tipo Command
. Os construtores Command
incluem uma pequena função (chamada de argumento do construtor execute
) que dobra ou reduz pela metade o valor da propriedade Number
.
O exemplo XAML a seguir consome a classe CommandDemoViewModel
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
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="18"
VerticalOptions="Center"
HorizontalOptions="Center" />
<Button Text="Multiply by 2"
VerticalOptions="Center"
HorizontalOptions="Center"
Command="{Binding MultiplyBy2Command}" />
<Button Text="Divide by 2"
VerticalOptions="Center"
HorizontalOptions="Center"
Command="{Binding DivideBy2Command}" />
</StackLayout>
</ContentPage>
Nesse exemplo, o elemento Label e dois objetos Button contêm ligações às três propriedades na classe CommandDemoViewModel
. À medida que os dois objetos Button são tocados, os comandos são executados e o número muda de valor. A vantagem dessa abordagem sobre os manipuladores Clicked
é que toda a lógica que envolve a funcionalidade dessa página está localizada no viewmodel e não no arquivo code-behind, conseguindo uma melhor separação entre a interface do usuário e a lógica de negócios.
Também é possível que os objetos Command
controlem a habilitação e desabilitação dos objetos Button. Por exemplo, suponha que você queira limitar o intervalo de valores numéricos entre 2 10 e 2–10. Você pode adicionar outra função ao construtor (chamada canExecute
argumento) que retorna true
se o Button deve ser habilitado:
public 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));
}
···
}
Nesse exemplo, as chamadas para o método ChangeCanExecute
de Command
são necessárias para que o método Command
possa chamar o método canExecute
e determinar se Button deve ser desabilitado ou não. Com essa mudança de código, conforme o número atinge o limite, o Button fica desabilitado.
Também é possível que dois ou mais elementos Button sejam vinculados à mesma propriedade ICommand. Os elementos Button podem ser distinguidos usando a propriedade CommandParameter
de Button. Nesse caso, você desejará usar a classe Command<T>
genérica. O objeto CommandParameter
é então passado como argumento para os métodos execute
e canExecute
. Para obter mais informações, veja Comandandos.
Pressione e solte o botão
O evento Pressed
é gerado quando um dedo pressiona um Button ou um botão do mouse é pressionado com o ponteiro posicionado sobre Button. O evento Released
é gerado quando o dedo ou o botão do mouse é liberado. Geralmente, um evento Clicked
também é acionado ao mesmo tempo que o evento Released
, mas se o dedo ou o ponteiro do mouse deslizar para fora da superfície do Button antes de ser liberado, o evento Clicked
poderá não ocorrer.
O exemplo XAML a seguir mostra um Label e um Button com manipuladores anexados para os eventos Pressed
e Released
:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.PressAndReleaseButtonPage"
Title="Press and Release Button">
<StackLayout>
<Button Text="Press to Rotate Text!"
VerticalOptions="Center"
HorizontalOptions="Center"
Pressed="OnButtonPressed"
Released="OnButtonReleased" />
<Label x:Name="label"
Text="Press and hold the Button above"
FontSize="18"
VerticalOptions="Center"
HorizontalOptions="Center" />
</StackLayout>
</ContentPage>
O arquivo code-behind anima o Label quando ocorre um evento Pressed
, mas suspende a rotação quando ocorre um evento Released
:
public partial class PressAndReleaseButtonPage : ContentPage
{
IDispatcherTimer timer;
Stopwatch stopwatch = new Stopwatch();
public PressAndReleaseButtonPage()
{
InitializeComponent();
timer = Dispatcher.CreateTimer();
timer.Interval = TimeSpan.FromMilliseconds(16);
timer.Tick += (s, e) =>
{
label.Rotation = 360 * (stopwatch.Elapsed.TotalSeconds % 1);
};
}
void OnButtonPressed(object sender, EventArgs args)
{
stopwatch.Start();
timer.Start();
}
void OnButtonReleased(object sender, EventArgs args)
{
stopwatch.Stop();
timer.Stop();
}
}
O resultado é que o Label só gira enquanto um dedo está em contato com o Button e para quando o dedo é liberado.
Estados visuais Button
Button possui um Pressed
VisualState que pode ser usado para iniciar uma mudança visual no Button quando pressionado, desde que esteja habilitado.
O exemplo XAML a seguir mostra como definir um estado visual para o estado Pressed
:
<Button Text="Click me!"
...>
<VisualStateManager.VisualStateGroups>
<VisualStateGroupList>
<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>
<VisualState x:Name="PointerOver" />
</VisualStateGroup>
</VisualStateGroupList>
</VisualStateManager.VisualStateGroups>
</Button>
Nesse exemplo, Pressed
VisualState especifica que quando Button for pressionado, sua propriedade Scale
será alterada de seu valor padrão de 1 para 0,8. O Normal
VisualState especifica que quando o Button estiver em estado normal, sua propriedade Scale
será definida como 1. Portanto, o efeito geral é que quando o Button é pressionado, ele é redimensionado para ser um pouco menor, e quando o Button é liberado, ele é redimensionado para seu tamanho padrão.
Importante
Para que um Button retorne ao seu estado Normal
, o VisualStateGroup
também deve definir um estado PointerOver
. Se usar os estilos ResourceDictionary
criados pelo modelo de projeto de aplicativo .NET MAUI, você já terá um estilo implícito Button
que define o estado PointerOver
.
Para obter mais informações sobre estados visuais, consulte Estados visuais.
Use bitmaps com botões
A classe Button define uma propriedade ImageSource que permite exibir uma pequena imagem bitmap no Button, sozinha ou em combinação com texto. Você também pode especificar como o texto e a imagem serão organizados. A propriedade ImageSource é do tipo ImageSource, o que significa que os bitmaps podem ser carregados de um arquivo, recurso integrado, URI ou fluxo.
Os bitmaps não são dimensionados para caber em um Button. O melhor tamanho geralmente é entre 32 e 64 unidades independentes de dispositivo, dependendo do tamanho desejado para o bitmap.
Você pode especificar como as propriedades Text
e ImageSource são organizadas no Button usando a propriedade ContentLayout
de Button. Essa propriedade é do tipo ButtonContentLayout
e seu construtor possui dois argumentos:
- Um membro da enumeração
ImagePosition
:Left
,Top
,Right
ouBottom
indicando como o bitmap aparece em relação ao texto. - Um valor
double
para o espaçamento entre o bitmap e o texto.
No XAML, você pode criar um Button e definir a propriedade ContentLayout
especificando apenas o membro de enumeração, ou o espaçamento, ou ambos, em qualquer ordem separada por vírgulas:
<Button Text="Button text"
ImageSource="button.png"
ContentLayout="Right, 20" />
Este é o código C# equivalente:
Button button = new Button
{
Text = "Button text",
ImageSource = new FileImageSource
{
File = "button.png"
},
ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};
Observação
Se a Button contiver texto e uma imagem, pode não ser possível encaixar todo o conteúdo dentro do botão e, portanto, você deve dimensionar sua imagem manualmente para obter o layout desejado.
Desabilitar um botão
Às vezes, um aplicativo entra em um estado em que um clique Button não é uma operação válida. Nesses casos, o Button pode ser desabilitado definindo a propriedade IsEnabled
dele como false
.