Bagikan melalui


Xamarin.Forms Kancing

Tombol merespons ketukan atau klik yang mengarahkan aplikasi untuk melakukan tugas tertentu.

Button adalah kontrol interaktif paling mendasar di semua Xamarin.Forms. Button biasanya menampilkan string teks pendek yang menunjukkan perintah, tetapi juga dapat menampilkan gambar bitmap, atau kombinasi teks dan gambar. Pengguna menekan Button dengan jari atau mengkliknya dengan mouse untuk memulai perintah tersebut.

Menangani klik tombol

ButtonClicked menentukan peristiwa yang diaktifkan saat pengguna mengetuk Button dengan jari atau penunjuk mouse. Peristiwa dipicu ketika jari atau tombol mouse dilepaskan dari permukaan Button. Button properti harus IsEnabled diatur ke true agar properti merespons ketukan.

Halaman Klik Tombol Dasar dalam sampel menunjukkan cara membuat instans Button di XAML dan menangani peristiwanya Clicked . File BasicButtonClickPage.xaml berisi StackLayout dengan dan 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>

Cenderung Button menempati semua ruang yang diizinkan untuk itu. Misalnya, jika Anda tidak mengatur HorizontalOptions properti ke Button sesuatu selain Fill, Button akan menempati lebar penuh induknya.

Secara default, Button persegi panjang, tetapi Anda dapat memberikan sudut bulat dengan menggunakan CornerRadius properti , seperti yang dijelaskan di bawah ini di bagian Tampilan tombol.

Properti Text menentukan teks yang muncul di Button. Kejadian Clicked diatur ke penanganan aktivitas bernama OnButtonClicked. Handler ini terletak di 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);
    }
}

Ketika diketuk Button , metode akan OnButtonClicked dijalankan. Argumen sender adalah objek yang Button bertanggung jawab atas peristiwa ini. Anda dapat menggunakan ini untuk mengakses Button objek, atau untuk membedakan antara beberapa Button objek yang berbagi peristiwa yang sama Clicked .

Handler khusus Clicked ini memanggil fungsi animasi yang memutar Label 360 derajat dalam 1000 milidetik. Berikut adalah program yang berjalan di perangkat iOS dan Android, dan sebagai aplikasi Platform Windows Universal (UWP) di desktop Windows 10:

Klik Tombol Dasar

Perhatikan bahwa OnButtonClicked metode menyertakan pengubah async karena await digunakan dalam penanganan aktivitas. Penanganan Clicked aktivitas memerlukan pengubah async hanya jika isi handler menggunakan await.

Setiap platform merender dengan Button cara spesifiknya sendiri. Di bagian Tampilan tombol, Anda akan melihat cara mengatur warna dan membuat Button batas terlihat untuk tampilan yang lebih disesuaikan. ButtonIFontElement mengimplementasikan antarmuka, sehingga mencakup FontFamilyproperti , FontSize, dan FontAttributes .

Membuat tombol dalam kode

Adalah umum untuk membuat instans Button di XAML, tetapi Anda juga dapat membuat Button dalam kode. Ini mungkin nyaman ketika aplikasi Anda perlu membuat beberapa tombol berdasarkan data yang dapat dihitung dengan perulangan foreach .

Halaman Klik Tombol Kode menunjukkan cara membuat halaman yang secara fungsional setara dengan halaman Klik Tombol Dasar tetapi sepenuhnya di 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
            }
        };
    }
}

Semuanya dilakukan di konstruktor kelas. Karena handler Clicked hanya satu pernyataan panjang, itu dapat dilampirkan ke peristiwa dengan sangat sederhana:

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

Tentu saja, Anda juga dapat menentukan penanganan aktivitas sebagai metode terpisah (sama seperti OnButtonClick metode di Klik Tombol Dasar) dan melampirkan metode tersebut ke peristiwa:

button.Clicked += OnButtonClicked;

Menonaktifkan tombol

Terkadang aplikasi berada dalam status tertentu di mana klik tertentu Button bukan operasi yang valid. Dalam kasus tersebut Button , harus dinonaktifkan dengan mengatur propertinya IsEnabled ke false. Contoh klasik adalah Entry kontrol untuk nama file yang disertai dengan file-open Button: harus Button diaktifkan hanya jika beberapa teks telah diketik ke Entrydalam . Anda bisa menggunakan untuk tugas ini, seperti yang DataTrigger diperlihatkan dalam artikel Pemicu Data.

Menggunakan antarmuka perintah

Dimungkinkan bagi aplikasi untuk menanggapi ketukan Button tanpa menangani Clicked peristiwa. menerapkan Button mekanisme pemberitahuan alternatif yang disebut perintah atau antarmuka perintah . Ini terdiri dari dua properti:

Pendekatan ini sangat cocok sehubungan dengan pengikatan data, dan terutama saat menerapkan arsitektur Model-View-ViewModel (MVVM). Topik-topik ini dibahas dalam artikel Pengikatan Data, Dari Pengikatan Data ke MVVM, dan MVVM.

Dalam aplikasi MVVM, viewmodel menentukan properti jenis ICommand yang kemudian terhubung ke elemen XAML Button dengan pengikatan data. Xamarin.Forms juga mendefinisikan Command kelas dan Command<T> yang mengimplementasikan ICommand antarmuka dan membantu viewmodel dalam menentukan properti jenis ICommand.

Perintah dijelaskan secara lebih rinci dalam artikel Antarmuka Perintah tetapi halaman Perintah Tombol Dasar dalam sampel menunjukkan pendekatan dasar.

Kelas CommandDemoViewModel ini adalah viewmodel yang sangat sederhana yang mendefinisikan properti jenis double bernama Number, dan dua properti jenis ICommand bernama MultiplyBy2Command dan 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; }
}

Dua ICommand properti diinisialisasi dalam konstruktor kelas dengan dua objek jenis Command. Konstruktor Command menyertakan sedikit fungsi (disebut execute argumen konstruktor) yang menggandakan atau memisahkan Number properti.

File BasicButtonCommand.xaml mengaturnya BindingContext ke instans CommandDemoViewModel. Elemen Label dan dua Button elemen berisi pengikatan ke tiga properti di 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>

Saat dua Button elemen diketuk, perintah dijalankan, dan nilai perubahan angka:

Perintah Tombol Dasar

Keuntungan dari pendekatan ini daripada Clicked handler adalah bahwa semua logika yang melibatkan fungsionalitas halaman ini terletak di viewmodel daripada file code-behind, mencapai pemisahan antarmuka pengguna yang lebih baik dari logika bisnis.

Dimungkinkan Command juga bagi objek untuk mengontrol pengaktifan dan penonaktifan Button elemen. Misalnya, Anda ingin membatasi rentang nilai angka antara 210 dan 2–10. Anda dapat menambahkan fungsi lain ke konstruktor (disebut canExecute argumen) yang mengembalikan true jika Button harus diaktifkan. Berikut adalah modifikasi pada CommandDemoViewModel konstruktor:

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

Panggilan ke ChangeCanExecute metode diperlukan sehingga Command metode dapat memanggil canExecute metode dan menentukan apakah Button harus dinonaktifkan Command atau tidak. Dengan perubahan kode ini, karena angka mencapai batas, dinonaktifkan Button :

Perintah Tombol Dasar - Diubah

Dimungkinkan bagi dua elemen atau lebih Button untuk terikat ke properti yang sama ICommand . Elemen Button dapat dibedakan menggunakan CommandParameter properti .Button Dalam hal ini, Anda harus menggunakan kelas generik Command<T> . Objek CommandParameter kemudian diteruskan sebagai argumen ke execute metode dan canExecute . Teknik ini ditampilkan secara rinci di bagian Perintah Dasar dari artikel Antarmuka Perintah.

Sampel juga menggunakan teknik ini di kelasnya MainPage . File MainPage.xaml berisi Button untuk setiap halaman sampel:

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

Masing-masing Button memiliki properti yang Command terikat ke properti bernama NavigateCommand, dan CommandParameter diatur ke objek yang Type sesuai dengan salah satu kelas halaman dalam proyek.

Properti NavigateCommand tersebut berjenis ICommand dan didefinisikan dalam 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; }
}

Konstruktor menginisialisasi NavigateCommand properti ke Command<Type> objek karena Type merupakan jenis objek yang CommandParameter diatur dalam file XAML. Ini berarti bahwa execute metode memiliki argumen jenis Type yang sesuai dengan objek ini CommandParameter . Fungsi membuat instans halaman lalu menavigasi ke halaman tersebut.

Perhatikan bahwa konstruktor menyimpulkan dengan mengaturnya BindingContext ke dirinya sendiri. Ini diperlukan untuk properti dalam file XAML untuk mengikat ke NavigateCommand properti .

Menekan dan melepaskan tombol

Clicked Selain peristiwa, Button juga menentukan Pressed dan Released peristiwa. Peristiwa Pressed terjadi ketika jari menekan pada , atau tombol mouse ditekan Buttondengan penunjuk yang diposisikan di Buttonatas . Peristiwa Released terjadi ketika tombol jari atau mouse dilepaskan. Umumnya, Clicked peristiwa juga diaktifkan pada saat yang sama dengan Released peristiwa, tetapi jika jari atau penunjuk mouse menjauh dari permukaan Button sebelum dilepaskan, Clicked peristiwa mungkin tidak terjadi.

Peristiwa Pressed dan Released tidak sering digunakan, tetapi dapat digunakan untuk tujuan khusus, seperti yang ditunjukkan di halaman Tombol Tekan dan Rilis. File XAML berisi Label dan Button dengan handler yang dilampirkan untuk Pressed peristiwa dan 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>

File code-behind menganimasikan Label kapan peristiwa Pressed terjadi, tetapi menangguhkan rotasi saat peristiwa Released terjadi:

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

Hasilnya adalah bahwa satu-satunya Label berputar saat jari bersentuhan dengan Button, dan berhenti ketika jari dilepaskan:

Tekan dan Lepaskan Tombol

Perilaku semacam ini memiliki aplikasi untuk game: Jari yang Button dipegang mungkin membuat objek di layar bergerak ke arah tertentu.

Tampilan tombol

Mewarisi Button atau mendefinisikan beberapa properti yang memengaruhi penampilannya:

Catatan

Kelas ini Button juga memiliki Margin properti dan Padding yang mengontrol perilaku Buttontata letak . Untuk informasi selengkapnya, lihat Margin dan Padding.

Efek dari enam properti ini (tidak termasuk FontFamily dan FontAttributes) ditunjukkan di halaman Tampilan Tombol. Properti lain, Image, dibahas di bagian Menggunakan bitmap dengan tombol .

Semua tampilan dan pengikatan data di halaman Tampilan Tombol ditentukan dalam 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>

Di Button bagian atas halaman memiliki tiga Color properti yang terikat ke Picker elemen di bagian bawah halaman. Item dalam Picker elemen adalah warna dari kelas yang NamedColor disertakan dalam proyek. Tiga Slider elemen berisi pengikatan dua arah ke FontSizeproperti , BorderWidth, dan CornerRadius dari Button.

Program ini memungkinkan Anda untuk bereksperimen dengan kombinasi semua properti ini:

Tampilan Tombol

Untuk melihat Button batas, Anda harus mengatur BorderColor ke sesuatu selain Default, dan ke BorderWidth nilai positif.

Di iOS, Anda akan melihat bahwa lebar batas besar mengganggu interior Button dan mengganggu tampilan teks. Jika Anda memilih untuk menggunakan batas dengan iOS Button, Anda mungkin ingin memulai dan mengakhiri Text properti dengan spasi untuk mempertahankan visibilitasnya.

Pada UWP, memilih CornerRadius yang melebihi setengah tinggi dari Button menimbulkan pengecualian.

Status visual tombol

Button memiliki Pressed VisualState yang dapat digunakan untuk memulai perubahan visual ke Button saat ditekan oleh pengguna, asalkan diaktifkan.

Contoh XAML berikut menunjukkan cara menentukan status visual untuk Pressed status:

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

Pressed VisualState Menentukan bahwa ketika Button ditekan, propertinya Scale akan diubah dari nilai defaultnya 1 menjadi 0,8. Normal VisualState Menentukan bahwa ketika Button berada dalam keadaan normal, propertinya Scale akan diatur ke 1. Oleh karena itu, efek keseluruhannya adalah ketika Button ditekan, skalanya akan sedikit lebih kecil, dan ketika Button dirilis, skalanya akan diskalakan ulang ke ukuran defaultnya.

Untuk informasi selengkapnya tentang status visual, lihat Xamarin.Forms Visual State Manager.

Membuat tombol alih

Dimungkinkan untuk subkelas Button sehingga berfungsi seperti tombol on-off: Ketuk tombol sekali untuk mengaktifkan tombol dan mengetuknya lagi untuk mematikannya.

Kelas berikut ToggleButton berasal dari Button dan mendefinisikan peristiwa baru bernama Toggled dan properti Boolean bernama IsToggled. Ini adalah dua properti yang sama yang ditentukan oleh 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");
    }
}

ToggleButton Konstruktor melampirkan handler ke Clicked peristiwa sehingga dapat mengubah nilai IsToggled properti. Metode ini OnIsToggledChanged menembakkan Toggled peristiwa.

Baris OnIsToggledChanged terakhir metode memanggil metode statis VisualStateManager.GoToState dengan dua string teks "ToggledOn" dan "ToggledOff". Anda dapat membaca tentang metode ini dan bagaimana aplikasi Anda dapat merespons status visual dalam artikel Manajer Xamarin.Forms Status Visual.

Karena ToggleButton melakukan panggilan ke VisualStateManager.GoToState, kelas itu sendiri tidak perlu menyertakan fasilitas tambahan untuk mengubah tampilan tombol berdasarkan keadaannya IsToggled . Itulah tanggung jawab XAML yang menghosting ToggleButton.

Halaman Demo Tombol Alih berisi dua instans ToggleButton, termasuk markup Visual State Manager yang mengatur Text, BackgroundColor, dan TextColor tombol berdasarkan status 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>

Penanganan Toggled aktivitas berada dalam file code-behind. Mereka bertanggung jawab untuk mengatur FontAttributes properti Label berdasarkan status tombol:

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

Berikut adalah program yang berjalan di iOS, Android, dan UWP:

Tombol Matikan/Matikan Demo

Menggunakan bitmap dengan tombol

Kelas Button menentukan ImageSource properti yang memungkinkan Anda menampilkan gambar bitmap pada Button, baik sendiri atau dalam kombinasi dengan teks. Anda juga dapat menentukan bagaimana teks dan gambar disusun.

Properti ImageSource berjenis ImageSource, yang berarti bahwa bitmap dapat dimuat dari file, sumber daya tersemat, URI, atau aliran.

Catatan

Button Meskipun dapat memuat GIF animasi, itu hanya akan menampilkan bingkai pertama GIF.

Setiap platform yang didukung oleh Xamarin.Forms memungkinkan gambar disimpan dalam beberapa ukuran untuk resolusi piksel yang berbeda dari berbagai perangkat yang mungkin dijalankan aplikasi. Beberapa bitmap ini diberi nama atau disimpan sedih sehingga sistem operasi dapat memilih kecocokan terbaik untuk resolusi tampilan video perangkat.

Untuk bitmap pada Button, ukuran terbaik biasanya antara 32 dan 64 unit independen perangkat, tergantung pada seberapa besar Anda menginginkannya. Gambar yang digunakan dalam contoh ini didasarkan pada ukuran 48 unit independen perangkat.

Dalam proyek iOS, folder Sumber Daya berisi tiga ukuran gambar ini:

  • Bitmap persegi 48 piksel disimpan sebagai /Resources/MonkeyFace.png
  • Bitmap persegi 96 piksel disimpan sebagai /Resource/MonkeyFace@2x.png
  • Bitmap persegi 144 piksel disimpan sebagai /Resource/MonkeyFace@3x.png

Ketiga bitmap diberikan Build Action of BundleResource.

Untuk proyek Android, bitmap semuanya memiliki nama yang sama, tetapi disimpan di subfolder folder Sumber Daya yang berbeda:

  • Bitmap persegi 72 piksel disimpan sebagai /Resources/drawable-hdpi/MonkeyFace.png
  • Bitmap persegi 96 piksel disimpan sebagai /Resources/drawable-xhdpi/MonkeyFace.png
  • Bitmap persegi 144 piksel disimpan sebagai /Resources/drawable-xxhdpi/MonkeyFace.png
  • Bitmap persegi 192 piksel disimpan sebagai /Resources/drawable-xxxhdpi/MonkeyFace.png

Ini diberikan Tindakan Build AndroidResource.

Dalam proyek UWP, bitmap dapat disimpan di mana saja dalam proyek, tetapi umumnya disimpan dalam folder kustom atau folder Aset yang ada. Proyek UWP berisi bitmap ini:

  • Bitmap persegi 48 piksel disimpan sebagai /Aset/MonkeyFace.scale-100.png
  • Bitmap persegi 96 piksel disimpan sebagai /Aset/MonkeyFace.scale-200.png
  • Bitmap persegi 192 piksel disimpan sebagai /Aset/MonkeyFace.scale-400.png

Mereka semua diberi Tindakan Build Konten.

Anda dapat menentukan bagaimana Text properti dan ImageSource diatur pada Button menggunakan ContentLayout properti .Button Properti ini berjenis ButtonContentLayout, yang merupakan kelas tersemat di Button. Konstruktor memiliki dua argumen:

  • Anggota ImagePosition enumerasi: Left, , RightTop, atau Bottom menunjukkan bagaimana bitmap muncul relatif terhadap teks.
  • Nilai double untuk penspasian antara bitmap dan teks.

Defaultnya adalah Left dan 10 unit. Dua properti baca-saja bernama ButtonContentLayout Position dan Spacing menyediakan nilai properti tersebut.

Dalam kode, Anda dapat membuat Button dan mengatur ContentLayout properti seperti ini:

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

Di XAML, Anda hanya perlu menentukan anggota enumerasi, atau penspasian, atau keduanya dalam urutan apa pun yang dipisahkan oleh koma:

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

Halaman Demo Tombol Gambar menggunakan OnPlatform untuk menentukan nama file yang berbeda untuk file bitmap iOS, Android, dan UWP. Jika Anda ingin menggunakan nama file yang sama untuk setiap platform dan menghindari penggunaan OnPlatform, Anda harus menyimpan bitmap UWP di direktori akar proyek.

Yang pertama Button pada halaman Demo Tombol Gambar mengatur Image properti tetapi bukan Text properti :

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

Jika bitmap UWP disimpan di direktori akar proyek, markup ini dapat sangat disederhanakan:

<Button ImageSource="MonkeyFace.png" />

Untuk menghindari banyak markup berulang dalam file ImageButtonDemo.xaml , implisit Style juga didefinisikan untuk mengatur ImageSource properti. Ini Style secara otomatis diterapkan ke lima elemen lainnya Button . Berikut adalah file XAML lengkap:

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

Empat Button elemen terakhir menggunakan ContentLayout properti untuk menentukan posisi dan penspasian teks dan bitmap:

Demo Tombol Gambar

Anda sekarang telah melihat berbagai cara untuk menangani Button peristiwa dan mengubah Button penampilan.