Xamarin.Forms Przycisk
Przycisk odpowiada na naciśnięcie lub kliknięcie, które kieruje aplikację do wykonania określonego zadania.
Jest Button
to najbardziej podstawowa interaktywna kontrolka we wszystkich elementach Xamarin.Forms. Zazwyczaj Button
wyświetla krótki ciąg tekstowy wskazujący polecenie, ale może również wyświetlać obraz mapy bitowej lub kombinację tekstu i obrazu. Użytkownik naciska Button
palcem lub klika go myszą, aby zainicjować to polecenie.
Obsługa kliknięć przycisków
Button
Clicked
Definiuje zdarzenie, które jest wyzwalane, gdy użytkownik naciska Button
palcem lub wskaźnikiem myszy. Zdarzenie jest wyzwalane, gdy palec lub przycisk myszy jest zwalniany z powierzchni Button
. Właściwość musi być IsEnabled
ustawiona Button
na true
, aby odpowiadała na naciśnięcia.
Na stronie Kliknięcie przycisku podstawowego w przykładzie pokazano, jak utworzyć wystąpienie Button
elementu w języku XAML i obsłużyć jego Clicked
zdarzenie. Plik BasicButtonClickPage.xaml zawiera obiekt StackLayout
z elementem i Label
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>
Ma Button
tendencję do zajmowania całej przestrzeni, która jest dla niego dozwolona. Jeśli na przykład nie ustawisz HorizontalOptions
właściwości Button
innej wartości niż Fill
, Button
właściwość będzie zajmować pełną szerokość jej elementu nadrzędnego.
Domyślnie Button
obiekt jest prostokątny, ale można nadać jej zaokrąglone rogi za pomocą CornerRadius
właściwości , jak opisano poniżej w sekcji Wygląd przycisku.
Właściwość Text
określa tekst wyświetlany w obiekcie Button
. Zdarzenie Clicked
jest ustawione na program obsługi zdarzeń o nazwie OnButtonClicked
. Ta procedura obsługi znajduje się w pliku za pomocą kodu, BasicButtonClickPage.xaml.cs:
public partial class BasicButtonClickPage : ContentPage
{
public BasicButtonClickPage ()
{
InitializeComponent ();
}
async void OnButtonClicked(object sender, EventArgs args)
{
await label.RelRotateTo(360, 1000);
}
}
W przypadku naciśnięcia obiektu Button
jest wykonywana metoda OnButtonClicked
. Argument sender
jest obiektem odpowiedzialnym Button
za to zdarzenie. Można go użyć, aby uzyskać dostęp do Button
obiektu lub rozróżnić wiele Button
obiektów współużytkowania tego samego Clicked
zdarzenia.
Ten konkretny Clicked
program obsługi wywołuje funkcję animacji, która obraca Label
360 stopni w 1000 milisekundach. Oto program działający na urządzeniach z systemami iOS i Android oraz jako aplikacja platforma uniwersalna systemu Windows (UWP) na pulpicie systemu Windows 10:
Zwróć uwagę, że OnButtonClicked
metoda zawiera async
modyfikator, ponieważ await
jest używana w programie obsługi zdarzeń. Program Clicked
obsługi zdarzeń wymaga async
modyfikatora tylko wtedy, gdy treść programu obsługi używa elementu await
.
Każda platforma renderuje Button
element w określony sposób. W sekcji Wygląd przycisku zobaczysz, jak ustawić kolory i uwidocznić Button
obramowanie w celu uzyskania bardziej dostosowanych wyglądów. Button
implementuje IFontElement
interfejs, więc zawiera FontFamily
właściwości , FontSize
i FontAttributes
.
Tworzenie przycisku w kodzie
Tworzenie wystąpienia elementu Button
w języku XAML jest powszechne, ale można również utworzyć element Button
w kodzie. Może to być wygodne, gdy aplikacja musi utworzyć wiele przycisków na podstawie danych, które można wyliczać za pomocą foreach
pętli.
Na stronie Kliknięcie przycisku kodu pokazano, jak utworzyć stronę, która jest funkcjonalnie równoważna stronie kliknięcia przycisku podstawowego, ale w całości w języku 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
}
};
}
}
Wszystko jest wykonywane w konstruktorze klasy. Clicked
Ponieważ procedura obsługi jest długa tylko jedną instrukcją, można ją bardzo łatwo dołączyć do zdarzenia:
button.Clicked += async (sender, args) => await label.RelRotateTo(360, 1000);
Oczywiście można również zdefiniować procedurę obsługi zdarzeń jako oddzielną metodę (podobnie jak OnButtonClick
metoda w kliknięciu przycisku podstawowego) i dołączyć tę metodę do zdarzenia:
button.Clicked += OnButtonClicked;
Wyłączanie przycisku
Czasami aplikacja jest w określonym stanie, w którym określone Button
kliknięcie nie jest prawidłową operacją. W takich przypadkach właściwość powinna być wyłączona Button
, ustawiając jej IsEnabled
właściwość na false
. Klasyczny przykład to kontrolka Entry
dla nazwy pliku, której towarzyszy plik otwarty Button
: Button
element powinien być włączony tylko wtedy, gdy w pliku Entry
został wpisany jakiś tekst .
Możesz użyć elementu DataTrigger
dla tego zadania, jak pokazano w artykule Wyzwalacze danych.
Korzystanie z interfejsu poleceń
Aplikacja może reagować na Button
naciśnięcia bez obsługi Clicked
zdarzenia. Funkcja Button
implementuje alternatywny mechanizm powiadamiania nazywany interfejsem polecenia lub polecenia . Składa się z dwóch właściwości:
Command
typuICommand
, interfejs zdefiniowany wSystem.Windows.Input
przestrzeni nazw.CommandParameter
właściwość typuObject
.
Takie podejście jest szczególnie odpowiednie w połączeniu z powiązaniem danych, a szczególnie podczas implementowania architektury Model-View-ViewModel (MVVM). Te tematy zostały omówione w artykułach Powiązanie danych, Od powiązań danych do MVVM i MVVM.
W aplikacji MVVM model widoku definiuje właściwości typu ICommand
, które są następnie połączone z elementami XAML Button
z powiązaniami danych. Xamarin.Forms definiuje Command
również klasy, Command<T>
które implementują ICommand
interfejs i pomagają modelowi widoku w definiowaniu właściwości typu ICommand
.
Polecenie zostało szczegółowo opisane w artykule Interfejs poleceń, ale strona Podstawowe polecenie w przykładzie przedstawia podstawowe podejście.
Klasa CommandDemoViewModel
jest bardzo prostym modelem widoków, który definiuje właściwość typu o nazwie Number
i dwie właściwości typu double
ICommand
o nazwie MultiplyBy2Command
i DivideBy2Command
:
class CommandDemoViewModel : INotifyPropertyChanged
{
double number = 1;
public event PropertyChangedEventHandler PropertyChanged;
public CommandDemoViewModel()
{
MultiplyBy2Command = new Command(() => Number *= 2);
DivideBy2Command = new Command(() => Number /= 2);
}
public double Number
{
set
{
if (number != value)
{
number = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Number"));
}
}
get
{
return number;
}
}
public ICommand MultiplyBy2Command { private set; get; }
public ICommand DivideBy2Command { private set; get; }
}
ICommand
Dwie właściwości są inicjowane w konstruktorze klasy z dwoma obiektami typu Command
. Konstruktory Command
zawierają niewielką funkcję (nazywaną argumentem konstruktora execute
), która podwaja lub połówkę Number
właściwości.
Plik BasicButtonCommand.xaml ustawia go BindingContext
na wystąpienie klasy CommandDemoViewModel
. Element Label
i dwa Button
elementy zawierają powiązania z trzema właściwościami w pliku 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>
Gdy dwa Button
elementy są mapowane, polecenia są wykonywane, a liczba zmienia wartość:
Zaletą tej metody Clicked
obsługi jest to, że cała logika obejmująca funkcje tej strony znajduje się w modelu widoków, a nie w pliku z kodem, co zapewnia lepszą separację interfejsu użytkownika z logiki biznesowej.
Istnieje również możliwość Command
kontrolowania i wyłączania Button
elementów przez obiekty. Załóżmy na przykład, że chcesz ograniczyć zakres wartości liczbowych z zakresu od 210 do 2–10. Do konstruktora (nazywanego argumentem canExecute
) można dodać inną funkcję, która zwraca true
wartość , jeśli Button
ma zostać włączona. Oto modyfikacja konstruktora CommandDemoViewModel
:
class CommandDemoViewModel : INotifyPropertyChanged
{
···
public CommandDemoViewModel()
{
MultiplyBy2Command = new Command(
execute: () =>
{
Number *= 2;
((Command)MultiplyBy2Command).ChangeCanExecute();
((Command)DivideBy2Command).ChangeCanExecute();
},
canExecute: () => Number < Math.Pow(2, 10));
DivideBy2Command = new Command(
execute: () =>
{
Number /= 2;
((Command)MultiplyBy2Command).ChangeCanExecute();
((Command)DivideBy2Command).ChangeCanExecute();
},
canExecute: () => Number > Math.Pow(2, -10));
}
···
}
Wywołania ChangeCanExecute
metody Command
są niezbędne, Command
aby metoda mogła wywołać metodę canExecute
i określić, czy powinna być wyłączona Button
, czy nie. Po zmianie tego kodu w miarę osiągnięcia limitu liczba jest wyłączona Button
:
Istnieje możliwość, że co najmniej dwa Button
elementy mają być powiązane z tą samą ICommand
właściwością. Button
Elementy można odróżnić za pomocą CommandParameter
właściwości Button
. W takim przypadku należy użyć klasy ogólnej Command<T>
. Obiekt CommandParameter
jest następnie przekazywany jako argument do execute
metod i canExecute
. Ta technika jest szczegółowo pokazana w sekcji Podstawowe polecenia w artykule Interfejs wiersza polecenia.
W przykładzie użyto również tej techniki w swojej MainPage
klasie. Plik MainPage.xaml zawiera Button
element dla każdej strony przykładu:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:ButtonDemos"
x:Class="ButtonDemos.MainPage"
Title="Button Demos">
<ScrollView>
<FlexLayout Direction="Column"
JustifyContent="SpaceEvenly"
AlignItems="Center">
<Button Text="Basic Button Click"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:BasicButtonClickPage}" />
<Button Text="Code Button Click"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:CodeButtonClickPage}" />
<Button Text="Basic Button Command"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:BasicButtonCommandPage}" />
<Button Text="Press and Release Button"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:PressAndReleaseButtonPage}" />
<Button Text="Button Appearance"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:ButtonAppearancePage}" />
<Button Text="Toggle Button Demo"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:ToggleButtonDemoPage}" />
<Button Text="Image Button Demo"
Command="{Binding NavigateCommand}"
CommandParameter="{x:Type local:ImageButtonDemoPage}" />
</FlexLayout>
</ScrollView>
</ContentPage>
Każda Button
właściwość jest Command
powiązana z właściwością o nazwie NavigateCommand
, a CommandParameter
właściwość jest ustawiona na Type
obiekt odpowiadający jednej z klas stron w projekcie.
Ta NavigateCommand
właściwość jest typu ICommand
i jest zdefiniowana w pliku za kodem:
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
NavigateCommand = new Command<Type>(async (Type pageType) =>
{
Page page = (Page)Activator.CreateInstance(pageType);
await Navigation.PushAsync(page);
});
BindingContext = this;
}
public ICommand NavigateCommand { private set; get; }
}
Konstruktor inicjuje NavigateCommand
właściwość do obiektu, ponieważ Type
jest typem Command<Type>
CommandParameter
obiektu ustawionego w pliku XAML. Oznacza to, że execute
metoda ma argument typu Type
, który odpowiada temu CommandParameter
obiektowi. Funkcja tworzy wystąpienie strony, a następnie przechodzi do niej.
Zwróć uwagę, że konstruktor kończy się ustawieniem samego siebie BindingContext
. Jest to konieczne, aby właściwości w pliku XAML wiązały się z właściwością NavigateCommand
.
Naciśnięcie i zwolnienie przycisku
Oprócz zdarzenia Clicked
obiekt Button
definiuje zdarzenia Pressed
i Released
. Zdarzenie Pressed
występuje, gdy naciśnięcie palca na Button
obiekcie lub naciśnięcie przycisku myszy jest naciśnięty z wskaźnikiem umieszczonym Button
nad . Zdarzenie Released
występuje po zwolnieniu palca lub przycisku myszy. Ogólnie rzecz biorąc, Clicked
zdarzenie jest również wyzwalane w tym samym czasie co Released
zdarzenie, ale jeśli palec lub wskaźnik myszy przesuwa się z dala od powierzchni Button
przed zwolnieniem, Clicked
zdarzenie może nie wystąpić.
Zdarzenia Pressed
i Released
nie są często używane, ale mogą być używane do celów specjalnych, jak pokazano na stronie Przycisk prasy i wydania. Plik XAML zawiera element Label
i Button
z procedurami obsługi dołączonymi do zdarzeń Pressed
i 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>
Plik związany z kodem animuje Label
Pressed
czas wystąpienia zdarzenia, ale zawiesza rotację w przypadku Released
wystąpienia zdarzenia:
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();
}
}
Rezultatem jest to, że Label
tylko obraca się, gdy palec jest w kontakcie z Button
, i zatrzymuje się po zwolnieniu palca:
Takie zachowanie ma zastosowania do gier: palec trzymany na ekranie Button
może sprawić, że obiekt na ekranie porusza się w określonym kierunku.
Wygląd przycisku
Dziedziczy Button
lub definiuje kilka właściwości, które wpływają na jej wygląd:
TextColor
jest koloremButton
tekstuBackgroundColor
jest kolorem tła do tego tekstuBorderColor
jest kolorem obszaru otaczającegoButton
FontFamily
jest rodziną czcionek używaną dla tekstuFontSize
jest rozmiarem tekstuFontAttributes
wskazuje, czy tekst jest kursywą, czy pogrubionyBorderWidth
to szerokość obramowaniaCornerRadius
to promień narożnikaButton
CharacterSpacing
jest odstępem między znakamiButton
tekstu.TextTransform
określa wielkość literButton
tekstu.
Uwaga
Klasa Button
ma Margin
również właściwości i Padding
kontrolujące zachowanie układu obiektu Button
. Aby uzyskać więcej informacji, zobacz Margines i wypełnienie.
Efekty sześciu z tych właściwości (z wyłączeniem FontFamily
i FontAttributes
) są pokazane na stronie Wygląd przycisku. W sekcji Używanie map bitowych z przyciskiem omówiono inną właściwość . Image
Wszystkie widoki i powiązania danych na stronie Wygląd przycisku są zdefiniowane w pliku 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>
W Button
górnej części strony znajdują się jej trzy Color
właściwości powiązane z Picker
elementami w dolnej części strony. Elementy w elementach Picker
są kolorami z klasy uwzględnionej NamedColor
w projekcie. Trzy Slider
elementy zawierają powiązania dwukierunkowe z właściwościami FontSize
, BorderWidth
i CornerRadius
.Button
Ten program umożliwia eksperymentowanie z kombinacjami wszystkich tych właściwości:
Aby wyświetlić obramowanie Button
, musisz ustawić wartość na inną BorderColor
niż Default
, i BorderWidth
na wartość dodatnią.
W systemie iOS zauważysz, że duże szerokości obramowania wtargną do wnętrza Button
obiektu i zakłócają wyświetlanie tekstu. Jeśli zdecydujesz się używać obramowania z systemem iOS Button
, prawdopodobnie chcesz rozpocząć i zakończyć Text
właściwość spacjami, aby zachować jej widoczność.
W przypadku platformy UWP wybranie elementu CornerRadius
, które przekracza połowę wysokości wyjątku Button
.
Stany wizualizacji przycisku
Button
Pressed
VisualState
element ma wartość , która może służyć do inicjowania zmiany wizualizacji Button
po naciśnięciu przez użytkownika, pod warunkiem, że jest włączona.
W poniższym przykładzie XAML pokazano, jak zdefiniować stan wizualizacji Pressed
dla stanu:
<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>
Określa Pressed
VisualState
, że po naciśnięciu Button
klawisza właściwość Scale
zostanie zmieniona z domyślnej wartości 1 na 0,8. Określa Normal
VisualState
, że gdy Button
właściwość jest w stanie normalnym, jej Scale
właściwość zostanie ustawiona na 1. W związku z tym ogólny efekt polega na tym, że po naciśnięciu Button
klawisza jest ona nieco mniejsza, a po jej wydaniu Button
zostanie ponownie przeskalowana do rozmiaru domyślnego.
Aby uzyskać więcej informacji na temat stanów wizualizacji, zobacz Xamarin.Forms Visual State Manager.
Tworzenie przycisku przełącznika
Istnieje możliwość podklasy Button
tak, aby działała jak przełącznik włączony: naciśnij przycisk raz, aby przełączyć przycisk i nacisnąć go ponownie, aby wyłączyć go.
Następująca ToggleButton
klasa pochodzi z Button
klasy i definiuje nowe zdarzenie o nazwie i właściwość logiczną o nazwie Toggled
IsToggled
. Są to te same dwie właściwości zdefiniowane przez element Xamarin.FormsSwitch
:
class ToggleButton : Button
{
public event EventHandler<ToggledEventArgs> Toggled;
public static BindableProperty IsToggledProperty =
BindableProperty.Create("IsToggled", typeof(bool), typeof(ToggleButton), false,
propertyChanged: OnIsToggledChanged);
public ToggleButton()
{
Clicked += (sender, args) => IsToggled ^= true;
}
public bool IsToggled
{
set { SetValue(IsToggledProperty, value); }
get { return (bool)GetValue(IsToggledProperty); }
}
protected override void OnParentSet()
{
base.OnParentSet();
VisualStateManager.GoToState(this, "ToggledOff");
}
static void OnIsToggledChanged(BindableObject bindable, object oldValue, object newValue)
{
ToggleButton toggleButton = (ToggleButton)bindable;
bool isToggled = (bool)newValue;
// Fire event
toggleButton.Toggled?.Invoke(toggleButton, new ToggledEventArgs(isToggled));
// Set the visual state
VisualStateManager.GoToState(toggleButton, isToggled ? "ToggledOn" : "ToggledOff");
}
}
Konstruktor ToggleButton
dołącza program obsługi do Clicked
zdarzenia, aby mógł zmienić wartość IsToggled
właściwości. Metoda OnIsToggledChanged
uruchamia Toggled
zdarzenie.
Ostatni wiersz OnIsToggledChanged
metody wywołuje metodę statyczną VisualStateManager.GoToState
z dwoma ciągami tekstowymi "ToggledOn" i "ToggledOff". Możesz przeczytać o tej metodzie i sposobie reagowania aplikacji na stany wizualizacji w artykule Visual State Manager.Xamarin.Forms
Ponieważ ToggleButton
wywołuje metodę VisualStateManager.GoToState
, sama klasa nie musi zawierać żadnych dodatkowych obiektów, aby zmienić wygląd przycisku na podstawie jego IsToggled
stanu. Jest to odpowiedzialność za kod XAML hostujący element ToggleButton
.
Strona pokazu przycisku przełączania zawiera dwa wystąpienia ToggleButton
elementu , w tym znaczniki Visual State Manager, które ustawiają Text
element , BackgroundColor
i TextColor
przycisku na podstawie stanu wizualizacji:
<?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>
Programy Toggled
obsługi zdarzeń znajdują się w pliku za pomocą kodu. Są one odpowiedzialne za ustawienie FontAttributes
właściwości Label
na podstawie stanu przycisków:
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;
}
}
}
Oto program uruchomiony w systemach iOS, Android i UWP:
Używanie map bitowych z przyciskami
Klasa Button
definiuje ImageSource
właściwość, która umożliwia wyświetlanie obrazu mapy bitowej na obiekcie , samodzielnie lub w połączeniu Button
z tekstem. Można również określić sposób rozmieszczania tekstu i obrazu.
Właściwość ImageSource
ma typ ImageSource
, co oznacza, że mapy bitowe mogą być ładowane z pliku, zasobu osadzonego, identyfikatora URI lub strumienia.
Uwaga
Button
Chociaż obiekt może załadować animowany plik GIF, będzie wyświetlać tylko pierwszą ramkę gif.
Każda platforma obsługiwana przez Xamarin.Forms program umożliwia przechowywanie obrazów w wielu rozmiarach dla różnych rozdzielczości pikseli różnych urządzeń, na których może działać aplikacja. Te wiele map bitowych jest nazwanych lub przechowywanych w taki sposób, że system operacyjny może wybrać najlepsze dopasowanie do rozdzielczości ekranu wideo urządzenia.
W przypadku mapy bitowej na obiekcie najlepszym rozmiarem Button
jest zwykle od 32 do 64 jednostek niezależnych od urządzenia, w zależności od tego, jak duży ma być. Obrazy używane w tym przykładzie są oparte na rozmiarze 48 jednostek niezależnych od urządzenia.
W projekcie systemu iOS folder Resources zawiera trzy rozmiary tego obrazu:
- Mapa bitowa o powierzchni 48 pikseli przechowywana jako /Resources/MonkeyFace.png
- Mapa bitowa o powierzchni 96 pikseli przechowywana jako /Resource/MonkeyFace@2x.png
- Mapa bitowa o powierzchni 144 pikseli przechowywana jako /Resource/MonkeyFace@3x.png
Wszystkie trzy mapy bitowe otrzymały akcję kompilacji BundleResource.
W przypadku projektu systemu Android wszystkie mapy bitowe mają taką samą nazwę, ale są przechowywane w różnych podfolderach folderu Resources :
- Mapa bitowa o powierzchni 72 pikseli przechowywana jako /Resources/drawable-hdpi/MonkeyFace.png
- Mapa bitowa o powierzchni 96 pikseli przechowywana jako /Resources/drawable-xhdpi/MonkeyFace.png
- Mapa bitowa kwadratowa o powierzchni 144 pikseli przechowywana jako /Resources/drawable-xxhdpi/MonkeyFace.png
- Mapa bitowa kwadratowa z 192 pikselami przechowywana jako /Resources/drawable-xxxhdpi/MonkeyFace.png
Otrzymały one akcję kompilacji androidResource.
W projekcie platformy UWP mapy bitowe mogą być przechowywane w dowolnym miejscu w projekcie, ale są one zwykle przechowywane w folderze niestandardowym lub w istniejącym folderze Assets . Projekt platformy UWP zawiera następujące mapy bitowe:
- Mapa bitowa o powierzchni 48 pikseli przechowywana jako /Assets/MonkeyFace.scale-100.png
- Mapa bitowa o powierzchni 96 pikseli przechowywana jako /Assets/MonkeyFace.scale-200.png
- Mapa bitowa kwadratowa z 192 pikselami przechowywana jako /Assets/MonkeyFace.scale-400.png
Wszystkie one otrzymały akcję kompilacji zawartości.
Możesz określić sposób Text
rozmieszczania Button
właściwości i ImageSource
przy użyciu ContentLayout
właściwości Button
. Ta właściwość jest typu ButtonContentLayout
, który jest klasą osadzoną w obiekcie Button
. Konstruktor ma dwa argumenty:
- Element członkowski
ImagePosition
wyliczenia:Left
, ,Top
Right
lubBottom
wskazujący sposób wyświetlania mapy bitowej względem tekstu. double
Wartość odstępu między mapą bitową a tekstem.
Wartości domyślne to Left
i 10 jednostek. Dwie właściwości tylko do odczytu nazwane ButtonContentLayout
Position
i Spacing
podają wartości tych właściwości.
W kodzie możesz utworzyć Button
właściwość i ustawić następującą ContentLayout
właściwość:
Button button = new Button
{
Text = "button text",
ImageSource = new FileImageSource
{
File = "image filename"
},
ContentLayout = new Button.ButtonContentLayout(Button.ButtonContentLayout.ImagePosition.Right, 20)
};
W języku XAML należy określić tylko składowy wyliczenia lub odstępy albo obie w dowolnej kolejności rozdzielone przecinkami:
<Button Text="button text"
ImageSource="image filename"
ContentLayout="Right, 20" />
Strona pokazowa przycisku obrazu służy OnPlatform
do określania różnych nazw plików map bitowych systemów iOS, Android i UWP. Jeśli chcesz użyć tej samej nazwy pliku dla każdej platformy i uniknąć użycia OnPlatform
programu , musisz przechowywać mapy bitowe platformy UWP w katalogu głównym projektu.
Pierwszy Button
na stronie Pokaz przycisku obrazu ustawia Image
właściwość, ale nie Text
właściwość:
<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>
Jeśli mapy bitowe platformy uwP są przechowywane w katalogu głównym projektu, ten znacznik można znacznie uprościć:
<Button ImageSource="MonkeyFace.png" />
Aby uniknąć wielu powtórzonych znaczników w pliku ImageButtonDemo.xaml , niejawny kod jest Style
również definiowany w celu ustawienia ImageSource
właściwości. Jest to Style
automatycznie stosowane do pięciu innych Button
elementów. Oto kompletny plik XAML:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ButtonDemos.ImageButtonDemoPage">
<FlexLayout Direction="Column"
JustifyContent="SpaceEvenly"
AlignItems="Center">
<FlexLayout.Resources>
<Style TargetType="Button">
<Setter Property="ImageSource">
<OnPlatform x:TypeArguments="ImageSource">
<On Platform="iOS, Android" Value="MonkeyFace.png" />
<On Platform="UWP" Value="Assets/MonkeyFace.png" />
</OnPlatform>
</Setter>
</Style>
</FlexLayout.Resources>
<Button>
<Button.ImageSource>
<OnPlatform x:TypeArguments="ImageSource">
<On Platform="iOS, Android" Value="MonkeyFace.png" />
<On Platform="UWP" Value="Assets/MonkeyFace.png" />
</OnPlatform>
</Button.ImageSource>
</Button>
<Button Text="Default" />
<Button Text="Left - 10"
ContentLayout="Left, 10" />
<Button Text="Top - 10"
ContentLayout="Top, 10" />
<Button Text="Right - 20"
ContentLayout="Right, 20" />
<Button Text="Bottom - 20"
ContentLayout="Bottom, 20" />
</FlexLayout>
</ContentPage>
Ostatnie cztery Button
elementy korzystają z ContentLayout
właściwości w celu określenia położenia i odstępów między tekstem a mapą bitową:
Znasz już różne sposoby obsługi Button
zdarzeń i zmieniania wyglądu Button
.