Xamarin.Forms Bottone
Il pulsante risponde a un tocco o a un clic che indirizza un'applicazione a eseguire una determinata attività.
Button
è il controllo interattivo più fondamentale in tutti .Xamarin.Forms In Button
genere viene visualizzata una stringa di testo breve che indica un comando, ma può anche visualizzare un'immagine bitmap o una combinazione di testo e un'immagine. L'utente preme Button
con un dito o lo fa clic con un mouse per avviare tale comando.
Gestione dei clic dei pulsanti
Button
definisce un Clicked
evento generato quando l'utente tocca Button
con un dito o un puntatore del mouse. L'evento viene generato quando il dito o il pulsante del mouse viene rilasciato dalla superficie di Button
. La Button
proprietà deve essere IsEnabled
impostata su true
affinché risponda ai tap.
La pagina Basic Button Click nell'esempio illustra come creare un'istanza di in Button
XAML e gestire il relativo Clicked
evento. Il file BasicButtonClickPage.xaml contiene un oggetto StackLayout
con un Label
oggetto e un Button
oggetto :
<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>
Tende Button
a occupare tutto lo spazio per cui è consentito. Ad esempio, se non si imposta la HorizontalOptions
proprietà di Button
su un valore diverso Fill
da , l'oggetto Button
occupa la larghezza intera del relativo elemento padre.
Per impostazione predefinita, è Button
rettangolare, ma è possibile assegnargli angoli arrotondati usando la CornerRadius
proprietà , come descritto di seguito nella sezione Aspetto pulsante.
La proprietà Text
specifica il testo visualizzato nel Button
. L'evento Clicked
è impostato su un gestore eventi denominato OnButtonClicked
. Questo gestore si trova nel file 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);
}
}
Con il tocco su Button
viene eseguito il metodo OnButtonClicked
. L'argomento sender
è l'oggetto Button
responsabile di questo evento. È possibile usarlo per accedere all'oggetto Button
o per distinguere tra più Button
oggetti che condividono lo stesso Clicked
evento.
Questo gestore specifico Clicked
chiama una funzione di animazione che ruota i Label
360 gradi in 1000 millisecondi. Ecco il programma in esecuzione nei dispositivi iOS e Android e come applicazione piattaforma UWP (Universal Windows Platform) (UWP) sul desktop di Windows 10:
Si noti che il OnButtonClicked
metodo include il async
modificatore perché await
viene usato all'interno del gestore eventi. Un Clicked
gestore eventi richiede il async
modificatore solo se il corpo del gestore usa await
.
Ogni piattaforma esegue il rendering in Button
modo specifico. Nella sezione Aspetto pulsante verrà illustrato come impostare i colori e rendere visibile il Button
bordo per un aspetto più personalizzato. Button
implementa l'interfaccia IFontElement
, quindi include FontFamily
le proprietà , FontSize
e FontAttributes
.
Creazione di un pulsante nel codice
È comune creare un'istanza di in Button
XAML, ma è anche possibile creare un Button
oggetto nel codice. Ciò potrebbe risultare utile quando l'applicazione deve creare più pulsanti in base ai dati enumerabili con un foreach
ciclo.
La pagina Clic pulsante codice illustra come creare una pagina equivalente funzionalmente alla pagina Clic pulsante di base, ma interamente in C#:
public class CodeButtonClickPage : ContentPage
{
public CodeButtonClickPage ()
{
Title = "Code Button Click";
Label label = new Label
{
Text = "Click the Button below",
FontSize = Device.GetNamedSize(NamedSize.Large, typeof(Label)),
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center
};
Button button = new Button
{
Text = "Click to Rotate Text!",
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center
};
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);
Content = new StackLayout
{
Children =
{
label,
button
}
};
}
}
Tutto viene eseguito nel costruttore della classe. Poiché il Clicked
gestore è una sola istruzione lunga, può essere collegata all'evento molto semplicemente:
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);
Naturalmente, è anche possibile definire il gestore eventi come metodo separato (proprio come il OnButtonClick
metodo in Clic pulsante di base) e allegare il metodo all'evento:
button.Clicked += OnButtonClicked;
Disabilitazione del pulsante
In alcuni casi un'applicazione si trova in uno stato specifico in cui un particolare Button
clic non è un'operazione valida. In questi casi, l'oggetto Button
deve essere disabilitato impostando la relativa IsEnabled
proprietà su false
. L'esempio classico è un Entry
controllo per un nome file accompagnato da un file aperto Button
: Button
deve essere abilitato solo se un testo è stato digitato in Entry
.
È possibile usare per DataTrigger
questa attività, come illustrato nell'articolo Trigger di dati.
Uso dell'interfaccia del comando
È possibile che un'applicazione risponda ai Button
tap senza gestire l'evento Clicked
. Button
implementa un meccanismo di notifica alternativo denominato comando o interfaccia di comando. Questo è costituito da due proprietà:
Command
di tipoICommand
, un'interfaccia definita nello spazio deiSystem.Windows.Input
nomi .CommandParameter
proprietà di tipoObject
.
Questo approccio è particolarmente adatto in relazione all'associazione dati e in particolare quando si implementa l'architettura MVVM (Model-View-ViewModel). Questi argomenti sono illustrati negli articoli Data Binding, Da data binding a MVVM e MVVM.
In un'applicazione MVVM il modello di visualizzazione definisce le proprietà di tipo ICommand
che vengono quindi connesse agli elementi XAML Button
con data binding. Xamarin.Forms definisce Command
anche le classi e Command<T>
che implementano l'interfaccia ICommand
e supportano il modello di visualizzazione nella definizione delle proprietà di tipo ICommand
.
L'esecuzione di comandi è descritta in modo più dettagliato nell'articolo Interfaccia comando, ma la pagina Comando pulsante di base nell'esempio illustra l'approccio di base.
La CommandDemoViewModel
classe è un modello di visualizzazione molto semplice che definisce una proprietà di tipo double
denominato Number
e due proprietà di tipo ICommand
denominato 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; }
}
Le due ICommand
proprietà vengono inizializzate nel costruttore della classe con due oggetti di tipo Command
. I Command
costruttori includono una piccola funzione (denominata argomento del execute
costruttore) che raddoppia o metà la Number
proprietà.
Il file BasicButtonCommand.xaml imposta il relativo BindingContext
su un'istanza di CommandDemoViewModel
. L'elemento Label
e due Button
elementi contengono associazioni alle tre proprietà in CommandDemoViewModel
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonDemos"
x:Class="ButtonDemos.BasicButtonCommandPage"
Title="Basic Button Command">
<ContentPage.BindingContext>
<local:CommandDemoViewModel />
</ContentPage.BindingContext>
<StackLayout>
<Label Text="{Binding Number, StringFormat='Value is now {0}'}"
FontSize="Large"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center" />
<Button Text="Multiply by 2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Command="{Binding MultiplyBy2Command}" />
<Button Text="Divide by 2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="Center"
Command="{Binding DivideBy2Command}" />
</StackLayout>
</ContentPage>
Man mano che vengono toccati i due Button
elementi, vengono eseguiti i comandi e il valore del numero cambia:
Il vantaggio di questo approccio rispetto Clicked
ai gestori è che tutta la logica che coinvolge la funzionalità di questa pagina si trova nel modello di visualizzazione anziché nel file code-behind, ottenendo una migliore separazione dell'interfaccia utente dalla logica di business.
È anche possibile che gli Command
oggetti controllino l'abilitazione e la disabilitazione degli Button
elementi. Si supponga, ad esempio, di voler limitare l'intervallo di valori numerici compresi tra 210 e 2-10. È possibile aggiungere un'altra funzione al costruttore (denominato canExecute
argomento) che restituisce true
se Button
deve essere abilitato. Ecco la modifica al CommandDemoViewModel
costruttore:
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));
}
···
}
Le chiamate al metodo di Command
sono necessarie in modo che il Command
metodo possa chiamare il canExecute
metodo e determinare se deve Button
essere disabilitato o ChangeCanExecute
meno. Con questa modifica del codice, man mano che il numero raggiunge il limite, l'oggetto Button
è disabilitato:
È possibile associare due o più Button
elementi alla stessa ICommand
proprietà. Gli Button
elementi possono essere distinti usando la CommandParameter
proprietà di Button
. In questo caso, si vuole usare la classe generica Command<T>
. L'oggetto CommandParameter
viene quindi passato come argomento ai execute
metodi e canExecute
. Questa tecnica viene illustrata in dettaglio nella sezione Comandi di base dell'articolo Interfaccia di comando.
L'esempio usa anche questa tecnica nella relativa MainPage
classe. Il file MainPage.xaml contiene una Button
per ogni pagina dell'esempio:
<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>
Ogni proprietà Button
è Command
associata a una proprietà denominata NavigateCommand
e l'oggetto CommandParameter
è impostato su un Type
oggetto corrispondente a una delle classi di pagine nel progetto.
Tale NavigateCommand
proprietà è di tipo ICommand
e viene definita nel file 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; }
}
Il costruttore inizializza la NavigateCommand
proprietà in un Command<Type>
oggetto perché Type
è il tipo dell'oggetto CommandParameter
impostato nel file XAML. Ciò significa che il execute
metodo ha un argomento di tipo Type
che corrisponde a questo CommandParameter
oggetto. La funzione crea un'istanza della pagina e quindi passa a essa.
Si noti che il costruttore termina impostandolo BindingContext
su se stesso. Questa operazione è necessaria per le proprietà nel file XAML da associare alla NavigateCommand
proprietà .
Premendo e rilasciando il pulsante
Oltre all'evento Clicked
, Button
definisce anche gli eventi Pressed
e Released
. L'evento Pressed
si verifica quando un dito preme su un Button
oggetto o quando viene premuto un pulsante del mouse con il puntatore posizionato su Button
. L'evento Released
si verifica quando viene rilasciato il dito o il pulsante del mouse. In genere, viene generato anche un Clicked
evento contemporaneamente all'evento Released
, ma se il puntatore del mouse o il dito si allontana dalla superficie dell'oggetto Button
prima del rilascio, l'evento Clicked
potrebbe non verificarsi.
Gli Pressed
eventi e non vengono spesso usati, ma possono essere usati per scopi speciali, come illustrato nella pagina Press and Release Button .The and Released
Release Button are not used, but they can be used for special purposes, as illustrate nella pagina Press and Release Button . Il file XAML contiene un Label
oggetto e un Button
oggetto con gestori associati per gli Pressed
eventi e 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>
Il file code-behind anima l'oggetto Label
quando si verifica un Pressed
evento, ma sospende la rotazione quando si verifica un Released
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();
}
}
Il risultato è che l'unico Label
ruota mentre un dito è in contatto con , Button
e si interrompe quando il dito viene rilasciato:
Questo tipo di comportamento ha applicazioni per i giochi: un dito tenuto su un Button
oggetto potrebbe far muovere un oggetto sullo schermo in una particolare direzione.
Aspetto pulsante
Eredita Button
o definisce diverse proprietà che ne influiscono sull'aspetto:
TextColor
è il colore delButton
testoBackgroundColor
è il colore dello sfondo del testoBorderColor
è il colore di un'area che circonda ilButton
FontFamily
è la famiglia di caratteri utilizzata per il testoFontSize
è la dimensione del testoFontAttributes
indica se il testo è in corsivo o grassettoBorderWidth
è la larghezza del bordoCornerRadius
è il raggio dell'angolo delButton
CharacterSpacing
è la spaziatura tra i caratteri delButton
testo.TextTransform
determina la combinazione di maiuscole e minuscole delButton
testo.
Nota
La Button
classe dispone Margin
inoltre di proprietà e Padding
che controllano il comportamento del layout dell'oggetto Button
. Per altre informazioni, vedere l'articolo sulle proprietà Margin e Padding.
Gli effetti di sei di queste proprietà (esclusi FontFamily
e FontAttributes
) vengono illustrati nella pagina Aspetto pulsante. Un'altra proprietà, Image
, è descritta nella sezione Uso delle bitmap con il pulsante .
Tutte le visualizzazioni e i data binding nella pagina Aspetto pulsante sono definiti nel file 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>
Nella Button
parte superiore della pagina sono associate tre Color
proprietà agli Picker
elementi nella parte inferiore della pagina. Gli elementi negli Picker
elementi sono colori della NamedColor
classe inclusa nel progetto. Tre Slider
elementi contengono associazioni bidirezionali alle FontSize
proprietà , BorderWidth
e CornerRadius
di Button
.
Questo programma consente di sperimentare combinazioni di tutte queste proprietà:
Per visualizzare il Button
bordo, è necessario impostare un oggetto su un BorderColor
valore diverso da Default
e su BorderWidth
un valore positivo.
In iOS si noterà che le larghezze dei bordi di grandi dimensioni nell'interno dell'oggetto Button
e interferiscono con la visualizzazione del testo. Se si sceglie di usare un bordo con un iOS Button
, è probabile che si voglia iniziare e terminare la proprietà con spazi per conservarne la Text
visibilità.
Nella piattaforma UWP, selezionando un valore CornerRadius
che supera la metà dell'altezza di genera un'eccezione Button
.
Stati di visualizzazione pulsante
Button
dispone di un oggetto Pressed
VisualState
che può essere usato per avviare una modifica visiva a Button
quando viene premuto dall'utente, purché sia abilitato.
L'esempio XAML seguente illustra come definire uno stato di visualizzazione per lo Pressed
stato:
<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>
Specifica Pressed
VisualState
che, quando Button
viene premuto , la relativa Scale
proprietà verrà modificata dal valore predefinito da 1 a 0,8. Normal
VisualState
Specifica che quando l'oggetto Button
è in uno stato normale, la relativa Scale
proprietà verrà impostata su 1. Di conseguenza, l'effetto complessivo è che, quando Button
viene premuto, viene ridimensionato leggermente più piccolo e, quando Button
viene rilasciato, viene ridimensionato in base alle dimensioni predefinite.
Per altre informazioni sugli stati di visualizzazione, vedere Xamarin.Forms Visual State Manager.
Creazione di un interruttore
È possibile sottoclasse Button
in modo che funzioni come un interruttore on-off: tocca il pulsante una volta per attivare o disattivare il pulsante e toccalo di nuovo per disattivarlo.
La classe seguente deriva da Button
e definisce un nuovo evento denominato Toggled
e una proprietà booleana denominata IsToggled
.ToggleButton
Queste sono le stesse due proprietà definite da 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");
}
}
Il ToggleButton
costruttore associa un gestore all'evento Clicked
in modo che possa modificare il valore della IsToggled
proprietà. Il OnIsToggledChanged
metodo genera l'evento Toggled
.
L'ultima riga del OnIsToggledChanged
metodo chiama il metodo statico VisualStateManager.GoToState
con le due stringhe di testo "ToggledOn" e "ToggledOff". È possibile leggere informazioni su questo metodo e su come l'applicazione può rispondere agli stati di visualizzazione nell'articolo Gestione Xamarin.Forms stati di Visual.
Poiché ToggleButton
effettua la chiamata a VisualStateManager.GoToState
, la classe stessa non deve includere alcuna funzionalità aggiuntiva per modificare l'aspetto del pulsante in base al relativo IsToggled
stato. È responsabilità del codice XAML che ospita l'oggetto ToggleButton
.
La pagina Demo pulsante attiva/disattiva contiene due istanze di ToggleButton
, tra cui il markup di Visual State Manager che imposta , Text
BackgroundColor
e TextColor
del pulsante in base allo stato di visualizzazione:
<?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>
I Toggled
gestori eventi si trovano nel file code-behind. Sono responsabili dell'impostazione della FontAttributes
proprietà dell'oggetto Label
in base allo stato dei pulsanti:
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;
}
}
}
Ecco il programma in esecuzione in iOS, Android e la piattaforma UWP:
Uso di bitmap con pulsanti
La Button
classe definisce una ImageSource
proprietà che consente di visualizzare un'immagine bitmap in Button
, da sola o in combinazione con il testo. È anche possibile specificare la disposizione del testo e dell'immagine.
La ImageSource
proprietà è di tipo ImageSource
, il che significa che le bitmap possono essere caricate da un file, una risorsa incorporata, un URI o un flusso.
Nota
Mentre un Button
oggetto può caricare una GIF animata, visualizzerà solo il primo fotogramma della GIF.
Ogni piattaforma supportata da Xamarin.Forms consente di archiviare le immagini in più dimensioni per risoluzioni in pixel diverse dei vari dispositivi su cui l'applicazione potrebbe essere eseguita. Queste bitmap multiple sono denominate o archiviate in modo che il sistema operativo possa scegliere la corrispondenza migliore per la risoluzione di visualizzazione video del dispositivo.
Per una bitmap in un Button
oggetto , le dimensioni migliori sono in genere comprese tra 32 e 64 unità indipendenti dal dispositivo, a seconda della dimensione desiderata. Le immagini usate in questo esempio si basano su una dimensione di 48 unità indipendenti dal dispositivo.
Nel progetto iOS la cartella Resources contiene tre dimensioni di questa immagine:
- Bitmap quadrata a 48 pixel archiviata come /Resources/MonkeyFace.png
- Bitmap quadrata a 96 pixel archiviata come /Resource/MonkeyFace@2x.png
- Bitmap quadrata a 144 pixel archiviata come /Resource/MonkeyFace@3x.png
A tutte e tre le bitmap è stata assegnata un'azione di compilazione bundleResource.
Per il progetto Android, le bitmap hanno lo stesso nome, ma vengono archiviate in sottocartelle diverse della cartella Resources :
- Bitmap quadrata a 72 pixel archiviata come /Resources/drawable-hdpi/MonkeyFace.png
- Bitmap quadrata a 96 pixel archiviata come /Resources/drawable-xhdpi/MonkeyFace.png
- Bitmap quadrata a 144 pixel archiviata come /Resources/drawable-xxhdpi/MonkeyFace.png
- Bitmap quadrata a 192 pixel archiviata come /Resources/drawable-xxxhdpi/MonkeyFace.png
A questi dati è stata assegnata un'azione di compilazione di AndroidResource.
Nel progetto UWP le bitmap possono essere archiviate in qualsiasi punto del progetto, ma in genere vengono archiviate in una cartella personalizzata o nella cartella Assets esistente. Il progetto UWP contiene queste bitmap:
- Bitmap quadrata a 48 pixel archiviata come /Assets/MonkeyFace.scale-100.png
- Bitmap quadrata a 96 pixel archiviata come /Assets/MonkeyFace.scale-200.png
- Bitmap quadrata a 192 pixel archiviata come /Assets/MonkeyFace.scale-400.png
Tutti hanno ricevuto un'azione di compilazione del contenuto.
È possibile specificare la modalità di disposizione delle proprietà e ImageSource
nell'oggetto Button
utilizzando la ContentLayout
proprietà di Button
.Text
Questa proprietà è di tipo ButtonContentLayout
, che è una classe incorporata in Button
. Il costruttore ha due argomenti:
- Membro dell'enumerazione
ImagePosition
:Left
,Top
,Right
oBottom
che indica la modalità di visualizzazione della bitmap rispetto al testo. - Valore
double
per la spaziatura tra la bitmap e il testo.
Le impostazioni predefinite sono Left
e 10 unità. Due proprietà di sola lettura di ButtonContentLayout
denominate Position
e Spacing
forniscono i valori di tali proprietà.
Nel codice è possibile creare e Button
impostare la ContentLayout
proprietà come segue:
Button button = new Button
{
Text = "button text",
ImageSource = new FileImageSource
{
File = "image filename"
},
ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};
In XAML è necessario specificare solo il membro di enumerazione o la spaziatura o entrambi in qualsiasi ordine separato da virgole:
<Button Text="button text"
ImageSource="image filename"
ContentLayout="Right, 20" />
La pagina Demo pulsante immagine usa OnPlatform
per specificare nomi di file diversi per i file bitmap iOS, Android e UWP. Se vuoi usare lo stesso nome file per ogni piattaforma ed evitare l'uso di OnPlatform
, dovrai archiviare le bitmap UWP nella directory radice del progetto.
La prima Button
nella pagina Demo pulsante immagine imposta la Image
proprietà ma non la Text
proprietà :
<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 le bitmap UWP vengono archiviate nella directory radice del progetto, questo markup può essere notevolmente semplificato:
<Button ImageSource="MonkeyFace.png" />
Per evitare un sacco di markup ripetitivo nel file ImageButtonDemo.xaml , viene definito anche un implicito Style
per impostare la ImageSource
proprietà. Questa operazione Style
viene applicata automaticamente a cinque altri Button
elementi. Ecco il file 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>
I quattro Button
elementi finali usano la ContentLayout
proprietà per specificare una posizione e una spaziatura del testo e della bitmap:
Sono stati ora illustrati i vari modi in cui è possibile gestire Button
gli eventi e modificare l'aspetto Button
.