Xamarin.Forms Botão
O Button responde a um toque ou clique que direciona um aplicativo para realizar uma tarefa específica.
O Button
é o controle interativo mais fundamental em todos os Xamarin.Forms. O Button
geralmente exibe uma cadeia de caracteres de texto curta indicando um comando, mas também pode exibir uma imagem de bitmap ou uma combinação de texto e uma imagem. O usuário pressiona o Button
com um dedo ou clica com o mouse para iniciar esse comando.
Manipulando cliques de botão
Button
Define um Clicked
evento que é acionado quando o usuário toca no com um dedo ou ponteiro do Button
mouse. O evento é acionado quando o dedo ou o botão do mouse é liberado da superfície do Button
. O Button
deve ter sua IsEnabled
propriedade definida como true
para responder a toques.
A página Clique no Botão Básico no exemplo demonstra como instanciar um Button
em XAML e manipular seu Clicked
evento. O arquivo BasicButtonClickPage.xaml contém um StackLayout
com a Label
e um 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>
Eles Button
tendem a ocupar todo o espaço que é permitido para isso. Por exemplo, se você não definir a HorizontalOptions
propriedade de para algo diferente Fill
de Button
, o Button
ocupará toda a largura de seu pai.
Por padrão, o Button
é retangular, mas você pode dar a ele cantos arredondados usando a propriedade, conforme descrito abaixo na seção Aparência do CornerRadius
botão.
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, BasicButtonClickPage.xaml.cs:
public partial class BasicButtonClickPage : ContentPage
{
public BasicButtonClickPage ()
{
InitializeComponent ();
}
async void OnButtonClicked(object sender, EventArgs args)
{
await label.RelRotateTo(360, 1000);
}
}
Quando o 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
.
Esse manipulador específico Clicked
chama uma função de animação que gira os Label
360 graus em 1000 milissegundos. Aqui está o programa em execução em dispositivos iOS e Android e como um aplicativo UWP (Plataforma Universal do Windows) na área de trabalho do Windows 10:
Observe que o OnButtonClicked
método inclui o async
modificador porque await
é usado no manipulador de eventos. Um Clicked
manipulador de eventos requer o async
modificador somente se o corpo do manipulador usar await
.
Cada plataforma renderiza o Button
de sua própria maneira específica. Na seção Aparência do botão, você verá como definir cores e tornar a Button
borda visível para aparências mais personalizadas. Button
implementa a IFontElement
interface, portanto, inclui FontFamily
, FontSize
, e propriedades FontAttributes
.
Criando um botão no código
É comum instanciar um Button
em XAML, mas você também pode criar um Button
no código. Isso pode ser conveniente quando seu aplicativo precisa criar vários botões com base em dados enumeráveis com um foreach
loop.
A página Clique no Botão de Código demonstra como criar uma página que seja funcionalmente equivalente à página Clique no Botão Básico, mas inteiramente em 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
}
};
}
}
Tudo é feito no construtor da classe. Como o Clicked
manipulador tem apenas uma instrução, ele pode ser anexado ao evento de forma muito simples:
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);
Claro, você também pode definir o manipulador de eventos como um método separado (assim como o OnButtonClick
método em Basic Button Click) e anexar esse método ao evento:
button.Clicked += OnButtonClicked;
Desativando o botão
Às vezes, um aplicativo está em um estado específico em que um clique específico Button
não é uma operação válida. Nesses casos, o Button
deve ser desabilitado, definindo sua propriedade IsEnabled
como false
. O exemplo clássico é um Entry
controle para um nome de arquivo acompanhado por um arquivo aberto Button
: O Button
deve ser habilitado somente se algum texto tiver sido digitado Entry
no .
Você pode usar a DataTrigger
para essa tarefa, conforme mostrado no artigo Gatilhos de Dados.
Usando a interface de comando
É possível que um aplicativo responda a Button
toques sem manipular o Clicked
evento. O Button
implementa um mecanismo de notificação alternativo chamado interface de comando ou comandos. Isso consiste em duas propriedades:
Command
do tipoICommand
, uma interface definida no namespaceSystem.Windows.Input
.CommandParameter
propriedade do tipoObject
.
Essa abordagem é particularmente adequada em conexão com a associação de dados e, particularmente, ao implementar a arquitetura MVVM (Model-View-ViewModel). Esses tópicos são discutidos nos artigos Associação de dados, De associações de dados ao MVVM e MVVM.
Em um aplicativo MVVM, o viewmodel define propriedades do tipo ICommand
que são conectadas aos elementos XAML Button
com associações de dados. Xamarin.Forms também define Command
e Command<T>
classes que implementam a ICommand
interface e auxiliam o viewmodel na definição de propriedades do tipo ICommand
.
O comando é descrito com mais detalhes no artigo A interface de comando, mas a página Comando de botão básico no exemplo mostra a abordagem básica.
A CommandDemoViewModel
classe é um viewmodel muito simples que define uma propriedade do tipo double
chamado Number
, e duas propriedades do tipo ICommand
chamado MultiplyBy2Command
e 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; }
}
As duas ICommand
propriedades são inicializadas no construtor da classe com dois objetos do tipo Command
. Os Command
construtores incluem uma pequena função (chamada de argumento do execute
construtor) que dobra ou reduz a Number
propriedade pela metade.
O arquivo BasicButtonCommand.xaml define sua BindingContext
instância como CommandDemoViewModel
. O Label
elemento e dois Button
elementos contêm ligações para as três propriedades em 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>
À medida que os dois Button
elementos 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 Command
objetos controlem a ativação e desativação dos Button
elementos. 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 de canExecute
argumento) que retorna true
se o Button
deve ser habilitado. Aqui está a modificação no CommandDemoViewModel
construtor:
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));
}
···
}
As chamadas para o ChangeCanExecute
método de são necessárias para que o Command
método possa chamar o canExecute
método e determinar se o deve ser desabilitado Command
Button
ou não. Com essa alteração de código, à medida que o número atinge o limite, o Button
é desabilitado:
É possível que dois ou mais Button
elementos sejam vinculados à mesma ICommand
propriedade. 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
. Essa técnica é mostrada em detalhes na seção Comandos básicos do artigo Interface de comando.
A amostra também usa essa técnica em sua MainPage
classe. O arquivo MainPage.xaml contém um Button
para cada página do exemplo:
<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 Button
um tem sua Command
propriedade vinculada a uma propriedade chamada NavigateCommand
, e o CommandParameter
é definido como um Type
objeto correspondente a uma das classes de página no projeto.
Essa NavigateCommand
propriedade é do tipo ICommand
e é definida no arquivo code-behind:
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; }
}
O construtor inicializa a NavigateCommand
propriedade para um Command<Type>
objeto porque Type
é o tipo do CommandParameter
objeto definido no arquivo XAML. Isso significa que o execute
método tem um argumento do tipo Type
que corresponde a esse CommandParameter
objeto. A função instancia a página e, em seguida, navega até ela.
Observe que o construtor conclui definindo-o BindingContext
como si mesmo. Isso é necessário para que as propriedades no arquivo XAML sejam associadas à NavigateCommand
propriedade.
Pressionando e soltando o botão
Além de evento Clicked
, Button
também define eventos Pressed
e Released
. O Pressed
evento ocorre quando um dedo pressiona um Button
, ou um botão do mouse é pressionado com o ponteiro posicionado sobre o Button
. O Released
evento ocorre quando o dedo ou o botão do mouse é liberado. Geralmente, um Clicked
evento também é disparado ao mesmo tempo que o Released
evento, mas se o ponteiro do dedo ou do mouse deslizar para longe da superfície do Button
antes de ser liberado, o Clicked
evento pode não ocorrer.
Os Pressed
eventos and Released
não são usados com frequência, mas podem ser usados para fins especiais, conforme demonstrado na página Botão Pressionar e Soltar. O arquivo XAML contém a Label
e a Button
com manipuladores anexados para os Pressed
eventos and Released
:
<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>
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
{
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();
}
}
O resultado é que o only gira Label
enquanto um dedo está em contato com o Button
, e para quando o dedo é liberado:
Esse tipo de comportamento tem aplicações para jogos: um dedo pressionado em um Button
pode fazer um objeto na tela se mover em uma direção específica.
Aparência do botão
O Button
herda ou define várias propriedades que afetam sua aparência:
TextColor
é a cor doButton
textoBackgroundColor
é a cor do plano de fundo desse textoBorderColor
é a cor de uma área ao redor doButton
FontFamily
é a família de fontes usada para o textoFontSize
é o tamanho do textoFontAttributes
indica se o texto está em itálico ou negritoBorderWidth
é a largura da bordaCornerRadius
é o raio do canto doButton
CharacterSpacing
é o espaçamento entre os caracteres doButton
texto.TextTransform
determina o uso de maiúsculas e minúsculas doButton
texto.
Observação
A Button
classe também tem Margin
propriedades e Padding
que controlam o comportamento do layout do Button
. Para saber mais, confira Margens e preenchimento.
Os efeitos de seis dessas propriedades (excluindo FontFamily
e FontAttributes
) são demonstrados na página Aparência do botão . Outra propriedade, Image
, é discutida na seção Usando bitmaps com botão.
Todas as exibições e associações de dados na página Aparência do Botão são definidas no arquivo 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>
O Button
na parte superior da página tem suas três Color
propriedades vinculadas a Picker
elementos na parte inferior da página. Os itens nos Picker
elementos são cores da NamedColor
classe incluída no projeto. Três Slider
elementos contêm ligações bidirecionais para as FontSize
propriedades , BorderWidth
e CornerRadius
do Button
.
Este programa permite que você experimente combinações de todas essas propriedades:
Para ver a Button
borda, você precisará definir a BorderColor
para algo diferente de Default
, e o BorderWidth
para um valor positivo.
No iOS, você notará que grandes larguras de borda se intrometem no interior do Button
e interferem na exibição do texto. Se você optar por usar uma borda com um iOS Button
, provavelmente desejará começar e terminar a Text
propriedade com espaços para manter sua visibilidade.
Na UWP, selecionar um CornerRadius
que exceda a metade da altura do Button
gera uma exceção.
Estados visuais Button
Button
tem um Pressed
VisualState
que pode ser usado para iniciar uma alteração visual no Button
quando pressionado pelo usuário, 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>
<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>
O Pressed
VisualState
especifica que, quando o Button
for pressionado, sua Scale
propriedade 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.
Para obter mais informações sobre estados visuais, consulte O Xamarin.Forms Gerenciador de Estado Visual.
Criando um botão de alternância
É possível criar uma subclasse Button
para que funcione como um botão liga-desliga: Toque no botão uma vez para ativar o botão e toque novamente para desativá-lo.
A classe a seguir ToggleButton
deriva Button
e define um novo evento chamado Toggled
e uma propriedade booleana chamada IsToggled
. Estas são as mesmas duas propriedades definidas pelo 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");
}
}
O ToggleButton
construtor anexa um manipulador ao Clicked
evento para que ele possa alterar o valor da IsToggled
propriedade. O OnIsToggledChanged
método aciona o Toggled
evento.
A última linha do método chama o método estático VisualStateManager.GoToState
com as duas cadeias de OnIsToggledChanged
caracteres de texto "ToggledOn" e "ToggledOff". Você pode ler sobre esse método e como seu aplicativo pode responder a estados visuais no artigo O Xamarin.Forms Gerenciador de Estado Visual.
Como ToggleButton
faz a chamada para VisualStateManager.GoToState
, a classe em si não precisa incluir nenhum recurso adicional para alterar a aparência do botão com base em seu IsToggled
estado. Essa é a responsabilidade do XAML que hospeda o ToggleButton
.
A página Demonstração do botão de alternância contém duas instâncias de ToggleButton
, incluindo a marcação do Visual State Manager que define o Text
, BackgroundColor
e TextColor
do botão com base no estado 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>
Os Toggled
manipuladores de eventos estão no arquivo code-behind. Eles são responsáveis por definir a FontAttributes
Label
propriedade do com base no estado dos botões:
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;
}
}
}
Aqui está o programa em execução no iOS, Android e UWP:
Usando bitmaps com botões
A Button
classe define uma ImageSource
propriedade que permite exibir uma imagem de bitmap no , sozinho ou em combinação com texto Button
. 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.
Observação
Embora um Button
possa carregar um GIF animado, ele exibirá apenas o primeiro quadro do GIF.
Cada plataforma suportada permite Xamarin.Forms que as imagens sejam armazenadas em vários tamanhos para diferentes resoluções de pixel dos vários dispositivos em que o aplicativo pode ser executado. Esses vários bitmaps são nomeados ou armazenados de forma que o sistema operacional possa escolher a melhor correspondência para a resolução de exibição de vídeo do dispositivo.
Para um bitmap em um Button
, o melhor tamanho geralmente é entre 32 e 64 unidades independentes de dispositivo, dependendo do tamanho desejado. As imagens usadas neste exemplo são baseadas em um tamanho de 48 unidades independentes de dispositivo.
No projeto iOS, a pasta Resources contém três tamanhos desta imagem:
- Um bitmap quadrado de 48 pixels armazenado como /Resources/MonkeyFace.png
- Um bitmap quadrado de 96 pixels armazenado como /Resource/MonkeyFace@2x.png
- Um bitmap quadrado de 144 pixels armazenado como /Resource/MonkeyFace@3x.png
Todos os três bitmaps receberam uma ação de build de BundleResource.
Para o projeto Android, todos os bitmaps têm o mesmo nome, mas são armazenados em subpastas diferentes da pasta Resources :
- Um bitmap quadrado de 72 pixels armazenado como /Resources/drawable-hdpi/MonkeyFace.png
- Um bitmap quadrado de 96 pixels armazenado como /Resources/drawable-xhdpi/MonkeyFace.png
- Um bitmap quadrado de 144 pixels armazenado como /Resources/drawable-xxhdpi/MonkeyFace.png
- Um bitmap quadrado de 192 pixels armazenado como /Resources/drawable-xxxhdpi/MonkeyFace.png
Eles receberam uma ação de build de AndroidResource.
No projeto UWP, os bitmaps podem ser armazenados em qualquer lugar do projeto, mas geralmente são armazenados em uma pasta personalizada ou na pasta existente do Assets . O projeto UWP contém estes bitmaps:
- Um bitmap quadrado de 48 pixels armazenado como /Assets/MonkeyFace.scale-100.png
- Um bitmap quadrado de 96 pixels armazenado como /Assets/MonkeyFace.scale-200.png
- Um bitmap quadrado de 192 pixels armazenado como /Assets/MonkeyFace.scale-400.png
Todos eles receberam uma Ação de Construção de Conteúdo.
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
, que é uma classe incorporada em Button
. O construtor tem 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.
Os padrões são Left
e 10 unidades. Duas propriedades somente leitura de ButtonContentLayout
named Position
e Spacing
fornecem os valores dessas propriedades.
No código, você pode criar um Button
e definir a ContentLayout
propriedade assim:
Button button = new Button
{
Text = "button text",
ImageSource = new FileImageSource
{
File = "image filename"
},
ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};
Em XAML, você precisa especificar apenas o membro de enumeração, ou o espaçamento, ou ambos em qualquer ordem separada por vírgulas:
<Button Text="button text"
ImageSource="image filename"
ContentLayout="Right, 20" />
A página Demonstração do Botão de Imagem é usada OnPlatform
para especificar nomes de arquivo diferentes para os arquivos de bitmap iOS, Android e UWP. Se você quiser usar o mesmo nome de arquivo para cada plataforma e evitar o uso de OnPlatform
, precisará armazenar os bitmaps UWP no diretório raiz do projeto.
O primeiro Button
na página Demonstração do botão Imagem define a propriedade, Image
mas não a Text
propriedade:
<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>
Se os bitmaps UWP forem armazenados no diretório raiz do projeto, essa marcação poderá ser consideravelmente simplificada:
<Button ImageSource="MonkeyFace.png" />
Para evitar muitas marcações repetitivas no arquivo ImageButtonDemo.xaml , um implícito Style
também é definido para definir a ImageSource
propriedade. Isso Style
é aplicado automaticamente a cinco outros Button
elementos. Aqui está o arquivo 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>
Os quatro Button
elementos finais usam a ContentLayout
propriedade para especificar uma posição e espaçamento do texto e do bitmap:
Agora você viu as várias maneiras de lidar com Button
eventos e alterar a Button
aparência.