Bagikan melalui


Membangun Aplikasi macOS Modern

Artikel ini membahas beberapa tips, fitur, dan teknik yang dapat digunakan pengembang untuk membangun aplikasi macOS modern di Xamarin.Mac.

Membangun Tampilan Modern dengan Pemandangan Modern

Tampilan modern akan menyertakan tampilan Jendela dan Toolbar modern seperti contoh aplikasi yang ditunjukkan di bawah ini:

Contoh UI aplikasi Mac modern

Mengaktifkan Tampilan Konten Berukuran Penuh

Untuk mencapai tampilan ini di aplikasi Xamarin.Mac, pengembang akan ingin menggunakan Tampilan Konten Ukuran Penuh, yang berarti konten meluas di bawah area Alat dan Bilah Judul dan akan secara otomatis diburamkan oleh macOS.

Untuk mengaktifkan fitur ini dalam kode, buat kelas kustom untuk NSWindowController dan membuatnya terlihat seperti berikut:

using System;
using Foundation;
using AppKit;

namespace MacModern
{
    public partial class MainWindowController : NSWindowController
    {
        #region Constructor
        public MainWindowController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void WindowDidLoad ()
        {
            base.WindowDidLoad ();

            // Set window to use Full Size Content View
            Window.StyleMask = NSWindowStyle.FullSizeContentView;
        }
        #endregion
    }
}

Fitur ini juga dapat diaktifkan di Penyusun Antarmuka Xcode dengan memilih Jendela dan memeriksa Tampilan Konten Berukuran Penuh:

Mengedit papan cerita utama di Penyusun Antarmuka Xcode

Saat menggunakan Tampilan Konten Ukuran Penuh, pengembang mungkin perlu mengimbangi konten di bawah area judul dan bilah alat sehingga konten tertentu (seperti label) tidak meluncur di bawahnya.

Untuk mempersulit masalah ini, area Judul dan Bilah Alat dapat memiliki tinggi dinamis berdasarkan tindakan yang saat ini dilakukan pengguna, versi macOS yang telah diinstal pengguna dan/atau perangkat keras Mac yang dijalankan aplikasi.

Akibatnya, hanya pengkodean keras offset saat meletakkan Antarmuka Pengguna tidak akan berfungsi. Pengembang harus mengambil pendekatan dinamis.

Apple telah menyertakan properti Key-Value ObservableContentLayoutRect kelas NSWindow untuk mendapatkan Area Konten saat ini dalam kode. Pengembang dapat menggunakan nilai ini untuk memposisikan elemen yang diperlukan secara manual saat Area Konten berubah.

Solusi yang lebih baik adalah menggunakan Tata Letak Otomatis dan Kelas Ukuran untuk memposisikan elemen UI baik dalam kode atau Penyusun Antarmuka.

Kode seperti contoh berikut dapat digunakan untuk memosisikan elemen UI menggunakan AutoLayout dan Kelas Ukuran di Pengontrol Tampilan aplikasi:

using System;
using AppKit;
using Foundation;

namespace MacModern
{
    public partial class ViewController : NSViewController
    {
        #region Computed Properties
        public NSLayoutConstraint topConstraint { get; set; }
        #endregion

        ...

        #region Override Methods
        public override void UpdateViewConstraints ()
        {
            // Has the constraint already been set?
            if (topConstraint == null) {
                // Get the top anchor point
                var contentLayoutGuide = ItemTitle.Window?.ContentLayoutGuide as NSLayoutGuide;
                var topAnchor = contentLayoutGuide.TopAnchor;

                // Found?
                if (topAnchor != null) {
                    // Assemble constraint and activate it
                    topConstraint = topAnchor.ConstraintEqualToAnchor (topAnchor, 20);
                    topConstraint.Active = true;
                }
            }

            base.UpdateViewConstraints ();
        }
        #endregion
    }
}

Kode ini membuat penyimpanan untuk batasan teratas yang akan diterapkan ke Label (ItemTitle) untuk memastikan bahwa kode tersebut tidak tergelincir di bawah area Judul dan Bilah Alat:

public NSLayoutConstraint topConstraint { get; set; }

Dengan mengesampingkan metode View Controller UpdateViewConstraints , pengembang dapat menguji untuk melihat apakah batasan yang diperlukan telah dibuat dan membuatnya jika diperlukan.

Jika batasan baru perlu dibangun, ContentLayoutGuide properti Jendela kontrol yang perlu dibatasi diakses dan ditransmisikan ke dalam NSLayoutGuide:

var contentLayoutGuide = ItemTitle.Window?.ContentLayoutGuide as NSLayoutGuide;

Properti TopAnchor diakses NSLayoutGuide dan jika tersedia, properti ini digunakan untuk membangun batasan baru dengan jumlah offset yang diinginkan dan batasan baru dibuat aktif untuk menerapkannya:

// Assemble constraint and activate it
topConstraint = topAnchor.ConstraintEqualToAnchor (topAnchor, 20);
topConstraint.Active = true;

Mengaktifkan Bilah Alat Yang Disederhanakan

Jendela macOS normal menyertakan Bilah Judul standar saat dijalankan di sepanjang tepi atas Jendela. Jika Jendela juga menyertakan Bilah Alat, Jendela akan ditampilkan di bawah area Bilah Judul ini:

Toolbar Mac standar

Saat menggunakan Toolbar Yang Disederhanakan, Area Judul menghilang dan Bilah Alat berpindah ke atas ke posisi Bilah Judul, sejalan dengan tombol Tutup Jendela, Minimalkan, dan Maksimalkan:

Toolbar Mac yang disederhanakan

Toolbar Yang Disederhanakan diaktifkan dengan menimpa ViewWillAppear metode NSViewController dan membuatnya terlihat seperti berikut:

public override void ViewWillAppear ()
{
    base.ViewWillAppear ();

    // Enable streamlined Toolbars
    View.Window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}

Efek ini biasanya digunakan untuk Aplikasi Shoebox (satu aplikasi jendela) seperti Peta, Kalender, Catatan, dan Preferensi Sistem.

Menggunakan Pengontrol Tampilan Aksesori

Bergantung pada desain aplikasi, pengembang mungkin juga ingin melengkapi area Bilah Judul dengan Pengontrol Tampilan Aksesori yang muncul tepat di bawah area Bilah Judul/Alat untuk memberikan kontrol sensitif konteks kepada pengguna berdasarkan aktivitas yang saat ini mereka libatkan:

Contoh Pengontrol Tampilan Aksesori

Pengontrol Tampilan Aksesori akan secara otomatis dikaburkan dan diubah ukurannya oleh sistem tanpa intervensi pengembang.

Untuk menambahkan Pengontrol Tampilan Aksesori, lakukan hal berikut:

  1. Di Penjelajah Solusi, klik Main.storyboard dua kali file untuk membukanya untuk pengeditan.

  2. Seret Pengontrol Tampilan Kustom ke hierarki Jendela:

    Menambahkan Pengontrol Tampilan Kustom baru

  3. Tata letak UI Tampilan Aksesori:

    Merancang tampilan baru

  4. Mengekspos Tampilan Aksesori sebagai Outlet dan Tindakan atau Outlet lainnya untuk UI-nya:

    Menambahkan OUtlet yang diperlukan

  5. Simpan perubahan.

  6. Kembali ke Visual Studio untuk Mac untuk menyinkronkan perubahan.

NSWindowController Edit dan buat tampilannya seperti berikut ini:

using System;
using Foundation;
using AppKit;

namespace MacModern
{
    public partial class MainWindowController : NSWindowController
    {
        #region Constructor
        public MainWindowController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void WindowDidLoad ()
        {
            base.WindowDidLoad ();

            // Create a title bar accessory view controller and attach
            // the view created in Interface Builder
            var accessoryView = new NSTitlebarAccessoryViewController ();
            accessoryView.View = AccessoryViewGoBar;

            // Set the location and attach the accessory view to the
            // titlebar to be displayed
            accessoryView.LayoutAttribute = NSLayoutAttribute.Bottom;
            Window.AddTitlebarAccessoryViewController (accessoryView);

        }
        #endregion
    }
}

Poin utama kode ini adalah tempat Tampilan diatur ke Tampilan kustom yang didefinisikan dalam Penyusun Antarmuka dan diekspos sebagai Outlet:

accessoryView.View = AccessoryViewGoBar;

LayoutAttribute Dan yang menentukan di mana aksesori akan ditampilkan:

accessoryView.LayoutAttribute = NSLayoutAttribute.Bottom;

Karena macOS sekarang sepenuhnya dilokalkan, Left properti dan RightNSLayoutAttribute telah tidak digunakan lagi dan harus diganti dengan Leading dan Trailing.

Menggunakan Windows Bertab

Selain itu, sistem macOS mungkin menambahkan Pengontrol Tampilan Aksesori ke Jendela aplikasi. Misalnya, untuk membuat Jendela Bertab di mana beberapa Windows Aplikasi digabungkan ke dalam satu Jendela virtual:

Contoh Jendela Mac bertab

Biasanya, pengembang harus mengambil tindakan terbatas menggunakan Tabbed Windows di aplikasi Xamarin.Mac mereka, sistem akan menanganinya secara otomatis sebagai berikut:

  • Windows akan otomatis ditab ketika OrderFront metode dipanggil.
  • Windows akan otomatis tidak ditabb ketika OrderOut metode dipanggil.
  • Dalam kode semua jendela Bertab masih dianggap "terlihat", namun Tab non-paling depan disembunyikan oleh sistem menggunakan CoreGraphics.
  • TabbingIdentifier Gunakan properti untuk NSWindow mengelompokkan Windows bersama-sama ke dalam Tab.
  • Jika ini adalah NSDocument aplikasi berbasis, beberapa fitur ini akan diaktifkan secara otomatis (seperti tombol plus yang ditambahkan ke Bilah Tab) tanpa tindakan pengembang.
  • Aplikasi non-berbasisNSDocument dapat mengaktifkan tombol "plus" di Grup Tab untuk menambahkan dokumen baru dengan menimpa GetNewWindowForTab metode NSWindowsController.

Menyatukan semua bagian, AppDelegate aplikasi yang ingin menggunakan Windows Tab berbasis sistem bisa terlihat seperti berikut:

using AppKit;
using Foundation;

namespace MacModern
{
    [Register ("AppDelegate")]
    public class AppDelegate : NSApplicationDelegate
    {
        #region Computed Properties
        public int NewDocumentNumber { get; set; } = 0;
        #endregion

        #region Constructors
        public AppDelegate ()
        {
        }
        #endregion

        #region Override Methods
        public override void DidFinishLaunching (NSNotification notification)
        {
            // Insert code here to initialize your application
        }

        public override void WillTerminate (NSNotification notification)
        {
            // Insert code here to tear down your application
        }
        #endregion

        #region Custom Actions
        [Export ("newDocument:")]
        public void NewDocument (NSObject sender)
        {
            // Get new window
            var storyboard = NSStoryboard.FromName ("Main", null);
            var controller = storyboard.InstantiateControllerWithIdentifier ("MainWindow") as NSWindowController;

            // Display
            controller.ShowWindow (this);
        }
        #endregion
    }
}

NewDocumentNumber Di mana properti melacak jumlah dokumen baru yang dibuat dan NewDocument metode membuat dokumen baru dan menampilkannya.

Yang NSWindowController kemudian bisa terlihat seperti:

using System;
using Foundation;
using AppKit;

namespace MacModern
{
    public partial class MainWindowController : NSWindowController
    {
        #region Application Access
        /// <summary>
        /// A helper shortcut to the app delegate.
        /// </summary>
        /// <value>The app.</value>
        public static AppDelegate App {
            get { return (AppDelegate)NSApplication.SharedApplication.Delegate; }
        }
        #endregion

        #region Constructor
        public MainWindowController (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Public Methods
        public void SetDefaultDocumentTitle ()
        {
            // Is this the first document?
            if (App.NewDocumentNumber == 0) {
                // Yes, set title and increment
                Window.Title = "Untitled";
                ++App.NewDocumentNumber;
            } else {
                // No, show title and count
                Window.Title = $"Untitled {App.NewDocumentNumber++}";
            }
        }
        #endregion

        #region Override Methods
        public override void WindowDidLoad ()
        {
            base.WindowDidLoad ();

            // Prefer Tabbed Windows
            Window.TabbingMode = NSWindowTabbingMode.Preferred;
            Window.TabbingIdentifier = "Main";

            // Set default window title
            SetDefaultDocumentTitle ();

            // Set window to use Full Size Content View
            // Window.StyleMask = NSWindowStyle.FullSizeContentView;

            // Create a title bar accessory view controller and attach
            // the view created in Interface Builder
            var accessoryView = new NSTitlebarAccessoryViewController ();
            accessoryView.View = AccessoryViewGoBar;

            // Set the location and attach the accessory view to the
            // titlebar to be displayed
            accessoryView.LayoutAttribute = NSLayoutAttribute.Bottom;
            Window.AddTitlebarAccessoryViewController (accessoryView);

        }

        public override void GetNewWindowForTab (NSObject sender)
        {
            // Ask app to open a new document window
            App.NewDocument (this);
        }
        #endregion
    }
}

Di mana properti statis App menyediakan pintasan untuk sampai ke AppDelegate. Metode ini SetDefaultDocumentTitle menetapkan judul dokumen baru berdasarkan jumlah dokumen baru yang dibuat.

Kode berikut, memberi tahu macOS bahwa aplikasi lebih suka menggunakan tab dan menyediakan string yang memungkinkan Windows aplikasi dikelompokkan ke dalam Tab:

// Prefer Tabbed Windows
Window.TabbingMode = NSWindowTabbingMode.Preferred;
Window.TabbingIdentifier = "Main";

Dan metode penimpaan berikut menambahkan tombol plus ke Bilah Tab yang akan membuat dokumen baru saat diklik oleh pengguna:

public override void GetNewWindowForTab (NSObject sender)
{
    // Ask app to open a new document window
    App.NewDocument (this);
}

Menggunakan Animasi Inti

Core Animation adalah mesin penyajian grafis bertenaga tinggi yang dibangun ke dalam macOS. Core Animation telah dioptimalkan untuk memanfaatkan GPU (Graphics Processing Unit) yang tersedia di perangkat keras macOS modern dibandingkan menjalankan operasi grafis pada CPU, yang dapat memperlambat komputer.

CALayer, yang disediakan oleh Core Animation, dapat digunakan untuk tugas-tugas seperti pengguliran dan animasi yang cepat dan cairan. Antarmuka Pengguna aplikasi harus terdiri dari beberapa subview dan lapisan untuk sepenuhnya memanfaatkan Core Animation.

Objek CALayer menyediakan beberapa properti yang memungkinkan pengembang mengontrol apa yang disajikan di layar kepada pengguna seperti:

  • Content - Bisa berupa NSImage atau CGImage yang menyediakan isi lapisan.
  • BackgroundColor - Mengatur warna latar belakang lapisan sebagai CGColor
  • BorderWidth - Mengatur lebar batas.
  • BorderColor - Mengatur warna batas.

Untuk menggunakan Core Graphics di UI aplikasi, itu harus menggunakan Tampilan Yang Didukung Lapisan, yang disarankan Apple bahwa pengembang harus selalu mengaktifkan di Tampilan Konten Jendela. Dengan cara ini, semua tampilan anak akan secara otomatis mewarisi Layer Backing juga.

Selain itu, Apple menyarankan penggunaan Tampilan Yang Didukung Lapisan dibandingkan dengan menambahkan yang baru CALayer sebagai sublayer karena sistem akan secara otomatis menangani beberapa pengaturan yang diperlukan (seperti yang diperlukan oleh Layar Retina).

Layer Backing dapat diaktifkan dengan mengatur WantsLayer dari NSView ke true atau di dalam Penyusun Antarmuka Xcode di bawah Pemeriksa Efek Tampilan dengan memeriksa Lapisan Animasi Inti:

Pemeriksa Efek Tampilan

Tampilan Redrawing dengan Lapisan

Langkah penting lainnya saat menggunakan Tampilan Yang Didukung Lapisan di aplikasi Xamarin.Mac adalah mengatur LayerContentsRedrawPolicy ke NSViewOnSetNeedsDisplay di NSViewController. Contohnya:

public override void ViewWillAppear ()
{
    base.ViewWillAppear ();

    // Set the content redraw policy
    View.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}

Jika pengembang tidak mengatur properti ini, Tampilan akan digambar ulang setiap kali asal bingkainya berubah, yang tidak diinginkan karena alasan performa. Namun, dengan properti ini diatur ke OnSetNeedsDisplay pengembang secara manual harus diatur NeedsDisplay ke true untuk memaksa konten dirawat ulang.

Saat Tampilan ditandai sebagai kotor, sistem memeriksa WantsUpdateLayer properti Tampilan. Jika mengembalikan true maka UpdateLayer metode dipanggil, jika tidak DrawRect , metode Tampilan dipanggil untuk memperbarui konten Tampilan.

Apple memiliki saran berikut untuk memperbarui konten Tampilan saat diperlukan:

  • Apple lebih suka menggunakan UpdateLater lebih dari DrawRect sesekali karena memberikan peningkatan performa yang signifikan.
  • Gunakan hal yang sama layer.Contents untuk elemen UI yang terlihat mirip.
  • Apple juga lebih suka pengembang menyusun UI mereka menggunakan tampilan standar seperti NSTextField, lagi jika memungkinkan.

Untuk menggunakan UpdateLayer, buat kelas kustom untuk NSView dan buat kode terlihat seperti berikut:

using System;
using Foundation;
using AppKit;

namespace MacModern
{
    public partial class MainView : NSView
    {
        #region Computed Properties
        public override bool WantsLayer {
            get { return true; }
        }

        public override bool WantsUpdateLayer {
            get { return true; }
        }
        #endregion

        #region Constructor
        public MainView (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void DrawRect (CoreGraphics.CGRect dirtyRect)
        {
            base.DrawRect (dirtyRect);

        }

        public override void UpdateLayer ()
        {
            base.UpdateLayer ();

            // Draw view
            Layer.BackgroundColor = NSColor.Red.CGColor;
        }
        #endregion
    }
}

Menggunakan Seret dan Letakkan Modern

Untuk menyajikan pengalaman Seret dan Lepas modern bagi pengguna, pengembang harus mengadopsi Drag Flocking dalam operasi Seret dan Lepas aplikasi mereka. Seret Flocking adalah tempat setiap file atau item individual yang diseret awalnya muncul sebagai elemen individual yang muncul (kelompokkan bersama-sama di bawah kursor dengan hitungan jumlah item) saat pengguna melanjutkan operasi seret.

Jika pengguna mengakhiri operasi Seret, elemen individual akan Membuka blokir dan kembali ke lokasi aslinya.

Contoh kode berikut memungkinkan Drag Flocking pada Tampilan kustom:

using System;
using System.Collections.Generic;
using Foundation;
using AppKit;

namespace MacModern
{
    public partial class MainView : NSView, INSDraggingSource, INSDraggingDestination
    {
        #region Constructor
        public MainView (IntPtr handle) : base (handle)
        {
        }
        #endregion

        #region Override Methods
        public override void MouseDragged (NSEvent theEvent)
        {
            // Create group of string to be dragged
            var string1 = new NSDraggingItem ((NSString)"Item 1");
            var string2 = new NSDraggingItem ((NSString)"Item 2");
            var string3 = new NSDraggingItem ((NSString)"Item 3");

            // Drag a cluster of items
            BeginDraggingSession (new [] { string1, string2, string3 }, theEvent, this);
        }
        #endregion
    }
}

Efek flocking dicapai dengan mengirim setiap item yang diseret ke BeginDraggingSession metode NSView sebagai elemen terpisah dalam array.

Saat bekerja dengan NSTableView atau NSOutlineView, gunakan PastboardWriterForRow metode NSTableViewDataSource kelas untuk memulai operasi Seret:

using System;
using System.Collections.Generic;
using Foundation;
using AppKit;

namespace MacModern
{
    public class ContentsTableDataSource: NSTableViewDataSource
    {
        #region Constructors
        public ContentsTableDataSource ()
        {
        }
        #endregion

        #region Override Methods
        public override INSPasteboardWriting GetPasteboardWriterForRow (NSTableView tableView, nint row)
        {
            // Return required pasteboard writer
            ...

            // Pasteboard writer failed
            return null;
        }
        #endregion
    }
}

Ini memungkinkan pengembang untuk menyediakan individu NSDraggingItem untuk setiap item dalam tabel yang sedang diseret dibandingkan dengan metode WriteRowsWith lama yang menulis semua baris sebagai grup tunggal ke papan tempel.

Saat bekerja dengan , gunakan PasteboardWriterForItemAt lagi metode dibandingkan WriteItemsAt dengan NSCollectionViewsmetode saat Menyeret dimulai.

Pengembang harus selalu menghindari menempatkan file besar di papan tempel. Baru menggunakan macOS Sierra, File Promises memungkinkan pengembang untuk menempatkan referensi ke file tertentu di pasteboard yang nantinya akan terpenuhi ketika pengguna menyelesaikan operasi Drop menggunakan kelas dan NSFilePromiseReceiver baruNSFilePromiseProvider.

Menggunakan Pelacakan Peristiwa Modern

Untuk elemen Antarmuka Pengguna (seperti NSButton) yang telah ditambahkan ke area Judul atau Bilah Alat, pengguna harus dapat mengklik elemen dan mengaktifkan peristiwa seperti biasa (seperti menampilkan jendela popup). Namun, karena item juga berada di area Judul atau Bilah Alat, pengguna harus dapat mengklik dan menyeret elemen untuk memindahkan jendela juga.

Untuk mencapainya dalam kode, buat kelas kustom untuk elemen (seperti NSButton) dan ambil alih MouseDown peristiwa sebagai berikut:

public override void MouseDown (NSEvent theEvent)
{
    var shouldCallSuper = false;

    Window.TrackEventsMatching (NSEventMask.LeftMouseUp, 2000, NSRunLoop.NSRunLoopEventTracking, (NSEvent evt, ref bool stop) => {
        // Handle event as normal
        stop = true;
        shouldCallSuper = true;
    });

    Window.TrackEventsMatching(NSEventMask.LeftMouseDragged, 2000, NSRunLoop.NSRunLoopEventTracking, (NSEvent evt, ref bool stop) => {
        // Pass drag event to window
        stop = true;
        Window.PerformWindowDrag (evt);
    });

    // Call super to handle mousedown
    if (shouldCallSuper) {
        base.MouseDown (theEvent);
    }
}

Kode ini menggunakan TrackEventsMatching metode NSWindow yang dilampirkan elemen UI untuk mencegat LeftMouseUp peristiwa dan LeftMouseDragged . Untuk peristiwa LeftMouseUp , elemen UI merespons seperti biasa. LeftMouseDragged Untuk peristiwa, peristiwa diteruskan ke NSWindowmetode 's PerformWindowDrag untuk memindahkan jendela di layar.

Memanggil PerformWindowDrag metode NSWindow kelas memberikan manfaat berikut:

  • Ini memungkinkan Jendela bergerak, bahkan jika aplikasi digantung (seperti saat memproses perulangan mendalam).
  • Pengalihan ruang akan berfungsi seperti yang diharapkan.
  • Bilah Spasi akan ditampilkan seperti biasa.
  • Penempatan jendela dan perataan berfungsi seperti biasa.

Menggunakan Kontrol Tampilan Kontainer Modern

macOS Sierra memberikan banyak peningkatan modern pada Kontrol Tampilan Kontainer yang ada yang tersedia di versi OS sebelumnya.

Penyempurnaan Tampilan Tabel

Pengembang harus selalu menggunakan versi baru NSView Kontrol Tampilan Kontainer seperti NSTableView. Contohnya:

using System;
using System.Collections.Generic;
using Foundation;
using AppKit;

namespace MacModern
{
    public class ContentsTableDelegate : NSTableViewDelegate
    {
        #region Constructors
        public ContentsTableDelegate ()
        {
        }
        #endregion

        #region Override Methods
        public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
        {
            // Build new view
            var view = new NSView ();
            ...

            // Return the view representing the item to display
            return view;
        }
        #endregion
    }
}

Ini memungkinkan Tindakan Baris Tabel kustom dilampirkan ke baris tertentu dalam tabel (seperti menggesek ke kanan untuk menghapus baris). Untuk mengaktifkan perilaku ini, ambil alih RowActions metode NSTableViewDelegate:

using System;
using System.Collections.Generic;
using Foundation;
using AppKit;

namespace MacModern
{
    public class ContentsTableDelegate : NSTableViewDelegate
    {
        #region Constructors
        public ContentsTableDelegate ()
        {
        }
        #endregion

        #region Override Methods
        public override NSView GetViewForItem (NSTableView tableView, NSTableColumn tableColumn, nint row)
        {
            // Build new view
            var view = new NSView ();
            ...

            // Return the view representing the item to display
            return view;
        }

        public override NSTableViewRowAction [] RowActions (NSTableView tableView, nint row, NSTableRowActionEdge edge)
        {
            // Take action based on the edge
            if (edge == NSTableRowActionEdge.Trailing) {
                // Create row actions
                var editAction = NSTableViewRowAction.FromStyle (NSTableViewRowActionStyle.Regular, "Edit", (action, rowNum) => {
                    // Handle row being edited
                    ...
                });

                var deleteAction = NSTableViewRowAction.FromStyle (NSTableViewRowActionStyle.Destructive, "Delete", (action, rowNum) => {
                    // Handle row being deleted
                    ...
                });

                // Return actions
                return new [] { editAction, deleteAction };
            } else {
                // No matching actions
                return null;
            }
        }
        #endregion
    }
}

Statis NSTableViewRowAction.FromStyle digunakan untuk membuat Tindakan Baris Tabel baru dari gaya berikut:

  • Regular - Melakukan tindakan standar yang tidak merusak seperti mengedit konten baris.
  • Destructive - Melakukan tindakan destruktif seperti menghapus baris dari tabel. Tindakan ini akan dirender dengan latar belakang merah.

Penyempurnaan Tampilan Gulir

Saat menggunakan Tampilan Gulir (NSScrollView) secara langsung, atau sebagai bagian dari kontrol lain (seperti NSTableView), konten Tampilan Gulir dapat meluncur di bawah area Judul dan Bilah Alat di aplikasi Xamarin.Mac menggunakan Tampilan dan Tampilan Modern.

Akibatnya, item pertama di area konten Tampilan Gulir dapat dikaburkan sebagian oleh area Judul dan Bilah Alat.

Untuk memperbaiki masalah ini, Apple telah menambahkan dua properti baru ke NSScrollView kelas :

  • ContentInsets - Memungkinkan pengembang untuk memberikan objek yang NSEdgeInsets menentukan offset yang akan diterapkan ke bagian atas Tampilan Gulir.
  • AutomaticallyAdjustsContentInsets - Jika true Tampilan Gulir akan secara otomatis menangani ContentInsets untuk pengembang.

Dengan menggunakan ContentInsets pengembang dapat menyesuaikan awal Tampilan Gulir untuk memungkinkan penyertaan aksesori seperti:

  • Indikator Urutkan seperti yang diperlihatkan di aplikasi Email.
  • Bidang Pencarian.
  • Tombol Refresh atau Perbarui.

Tata Letak dan Pelokalan Otomatis di Aplikasi Modern

Apple telah menyertakan beberapa teknologi dalam Xcode yang memungkinkan pengembang untuk dengan mudah membuat aplikasi macOS internasional. Xcode sekarang memungkinkan pengembang untuk memisahkan teks yang menghadap pengguna dari desain Antarmuka Pengguna aplikasi dalam file Storyboard-nya dan menyediakan alat untuk mempertahankan pemisahan ini jika UI berubah.

Untuk informasi selengkapnya, silakan lihat Panduan Internasionalisasi dan Pelokalan Apple.

Menerapkan Internasionalisasi Dasar

Dengan menerapkan Base Internationalization, pengembang dapat menyediakan satu file Storyboard untuk mewakili UI aplikasi dan memisahkan semua string yang menghadap pengguna.

Ketika pengembang membuat file Storyboard awal (atau file) yang menentukan Antarmuka Pengguna aplikasi, mereka akan dibangun dalam Internasionalisasi Dasar (bahasa yang diucapkan pengembang).

Selanjutnya, pengembang dapat mengekspor pelokalan dan string Internasionalisasi Dasar (dalam desain UI Storyboard) yang dapat diterjemahkan ke dalam beberapa bahasa.

Nantinya, pelokalan ini dapat diimpor dan Xcode akan menghasilkan file string khusus bahasa untuk Storyboard.

Menerapkan Tata Letak Otomatis untuk Mendukung Pelokalan

Karena versi nilai string yang dilokalkan dapat memiliki ukuran dan/atau arah baca yang sangat berbeda, pengembang harus menggunakan Tata Letak Otomatis untuk memposisikan dan mengukur Antarmuka Pengguna aplikasi dalam file Storyboard.

Apple menyarankan untuk melakukan hal berikut:

  • Hapus Batasan Lebar Tetap - Semua Tampilan berbasis teks harus diizinkan untuk mengubah ukuran berdasarkan kontennya. Tampilan lebar tetap dapat memotong kontennya dalam bahasa tertentu.
  • Gunakan Ukuran Konten Intrinsik - Secara default Tampilan berbasis teks akan berukuran otomatis agar sesuai dengan kontennya. Untuk Tampilan berbasis teks yang tidak berukuran dengan benar, pilih di Penyusun Antarmuka Xcode lalu pilih Edit>Ukuran Agar Pas Dengan Konten.
  • Terapkan Atribut Leading dan Trailing - Karena arah teks dapat berubah berdasarkan bahasa pengguna, gunakan atribut baru Leading dan Trailing batasan dibandingkan dengan atribut dan Left yang adaRight. Leading dan Trailing akan secara otomatis menyesuaikan berdasarkan arah bahasa.
  • Sematkan Tampilan ke Tampilan yang Berdekatan - Ini memungkinkan Tampilan untuk memposisikan ulang dan mengubah ukuran saat Tampilan di sekitarnya berubah sebagai respons terhadap bahasa yang dipilih.
  • Jangan Atur Ukuran Minimum dan/atau Maksimum Windows - Izinkan Windows mengubah ukuran saat bahasa yang dipilih mengubah ukuran area kontennya.
  • Uji Perubahan Tata Letak Secara Konstan - Selama pengembangan di aplikasi harus diuji terus-menerus dalam bahasa yang berbeda. Lihat Dokumentasi aplikasi Pengujian Internasional Apple untuk detail selengkapnya.
  • Gunakan NSStackViews untuk Menyematkan Tampilan Bersama - NSStackViews memungkinkan kontennya bergeser dan berkembang dengan cara yang dapat diprediksi dan ukuran perubahan konten berdasarkan bahasa yang dipilih.

Melokalisasi di Penyusun Antarmuka Xcode

Apple telah menyediakan beberapa fitur di Interface Builder Xcode yang dapat digunakan pengembang saat merancang atau mengedit UI aplikasi untuk mendukung pelokalan. Bagian Arah Teks dari Pemeriksa Atribut memungkinkan pengembang untuk memberikan petunjuk tentang bagaimana arah harus digunakan dan diperbarui pada Tampilan Berbasis Teks tertentu (seperti NSTextField ):

Opsi Arah Teks

Ada tiga nilai yang mungkin untuk Arah Teks:

  • Natural - Tata letak didasarkan pada string yang ditetapkan ke kontrol.
  • Kiri ke Kanan - Tata letak selalu dipaksa untuk kiri ke kanan.
  • Kanan ke Kiri - Tata letak selalu dipaksa ke kanan ke kiri.

Ada dua nilai yang mungkin untuk Tata Letak:

  • Kiri ke Kanan - Tata letak selalu kiri ke kanan.
  • Kanan ke Kiri - Tata letak selalu kanan ke kiri.

Biasanya ini tidak boleh diubah kecuali diperlukan penyelarasan tertentu.

Properti Mirror memberi tahu sistem untuk membalik properti kontrol tertentu (seperti Posisi Gambar Sel). Ini memiliki tiga nilai yang mungkin:

  • Otomatis - Posisi akan berubah secara otomatis berdasarkan arah bahasa yang dipilih.
  • Di Antarmuka Kanan ke Kiri - Posisi hanya akan diubah dalam bahasa berbasis kanan ke kiri.
  • Tidak pernah - Posisi tidak akan pernah berubah.

Jika pengembang telah menentukan Center, Justify , atau Full alignment pada konten Tampilan berbasis teks, ini tidak akan pernah dibalik berdasarkan bahasa yang dipilih.

Sebelum macOS Sierra, kontrol yang dibuat dalam kode tidak akan dicerminkan secara otomatis. Pengembang harus menggunakan kode seperti berikut untuk menangani pencerminan:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();

    // Setting a button's mirroring based on the layout direction
    var button = new NSButton ();
    if (button.UserInterfaceLayoutDirection == NSUserInterfaceLayoutDirection.LeftToRight) {
        button.Alignment = NSTextAlignment.Right;
        button.ImagePosition = NSCellImagePosition.ImageLeft;
    } else {
        button.Alignment = NSTextAlignment.Left;
        button.ImagePosition = NSCellImagePosition.ImageRight;
    }
}

Alignment Di mana dan ImagePosition sedang diatur berdasarkan UserInterfaceLayoutDirection kontrol.

macOS Sierra menambahkan beberapa konstruktor kenyamanan baru (melalui metode statis CreateButton ) yang mengambil beberapa parameter (seperti Judul, Gambar dan Tindakan) dan akan secara otomatis mencerminkan dengan benar. Contohnya:

var button2 = NSButton.CreateButton (myTitle, myImage, () => {
    // Take action when the button is pressed
    ...
});

Menggunakan Tampilan Sistem

Aplikasi macOS modern dapat mengadopsi Tampilan Antarmuka Gelap baru yang berfungsi dengan baik untuk pembuatan gambar, pengeditan, atau aplikasi presentasi:

Contoh UI Jendela Mac gelap

Ini dapat dilakukan dengan menambahkan satu baris kode sebelum Jendela disajikan. Contohnya:

using System;
using AppKit;
using Foundation;

namespace MacModern
{
    public partial class ViewController : NSViewController
    {
        ...

        #region Override Methods
        public override void ViewWillAppear ()
        {
            base.ViewWillAppear ();

            // Apply the Dark Interface Appearance
            View.Window.Appearance = NSAppearance.GetAppearance (NSAppearance.NameVibrantDark);

            ...
        }
        #endregion
    }
}

Metode statis GetAppearanceNSAppearance kelas digunakan untuk mendapatkan penampilan bernama dari sistem (dalam hal NSAppearance.NameVibrantDarkini ).

Apple memiliki saran berikut untuk menggunakan Tampilan Sistem:

  • Lebih suka warna bernama daripada nilai yang dikodekan secara permanen (seperti LabelColor dan SelectedControlColor).
  • Gunakan gaya kontrol standar sistem jika memungkinkan.

Aplikasi macOS yang menggunakan Tampilan Sistem akan secara otomatis berfungsi dengan benar untuk pengguna yang telah mengaktifkan fitur Aksesibilitas dari aplikasi Preferensi Sistem. Akibatnya, Apple menyarankan bahwa pengembang harus selalu menggunakan Tampilan Sistem di app macOS mereka.

Merancang UI dengan Papan Cerita

Papan cerita memungkinkan pengembang untuk tidak hanya merancang elemen individual yang membentuk Antarmuka Pengguna aplikasi, tetapi untuk memvisualisasikan dan merancang alur UI dan hierarki elemen yang diberikan.

Pengontrol memungkinkan pengembang untuk mengumpulkan elemen ke dalam unit komposisi dan Segues abstrak dan menghapus "kode lem" khas yang diperlukan untuk bergerak di seluruh Hierarki Tampilan:

Mengedit UI di Penyusun Antarmuka Xcode

Untuk informasi selengkapnya, silakan lihat dokumentasi Pengenalan Storyboards kami.

Ada banyak instans di mana adegan tertentu yang ditentukan dalam papan cerita akan memerlukan data dari adegan sebelumnya dalam Hierarki Tampilan. Apple memiliki saran berikut untuk meneruskan informasi antar adegan:

  • Dependensi data harus selalu bertekanan ke bawah melalui hierarki.
  • Hindari dependansi struktural UI hardcoding, karena ini membatasi fleksibilitas UI.
  • Gunakan Antarmuka C# untuk menyediakan dependensi data generik.

Pengontrol Tampilan yang bertindak sebagai sumber Segue, dapat mengambil alih PrepareForSegue metode dan melakukan inisialisasi apa pun yang diperlukan (seperti meneruskan data) sebelum Segue dijalankan untuk menampilkan Pengontrol Tampilan target. Contohnya:

public override void PrepareForSegue (NSStoryboardSegue segue, NSObject sender)
{
    base.PrepareForSegue (segue, sender);

    // Take action based on Segue ID
    switch (segue.Identifier) {
    case "MyNamedSegue":
        // Prepare for the segue to happen
        ...
        break;
    }
}

Untuk informasi selengkapnya, silakan lihat dokumentasi Segues kami.

Menyebarkan Tindakan

Berdasarkan desain aplikasi macOS, mungkin ada kalanya handler terbaik untuk Tindakan pada kontrol UI mungkin berada di tempat lain dalam Hierarki UI. Ini biasanya berlaku untuk Menu dan Item Menu yang hidup di adegan mereka sendiri, terpisah dari UI aplikasi lainnya.

Untuk menangani situasi ini, pengembang dapat membuat Tindakan Kustom dan meneruskan Tindakan ke rantai responden. Untuk informasi selengkapnya, silakan lihat dokumentasi Bekerja dengan Tindakan Jendela Kustom kami.

Fitur Mac Modern

Apple telah menyertakan beberapa fitur yang menghadap pengguna di macOS Sierra yang memungkinkan pengembang untuk memanfaatkan platform Mac secara maksimal, seperti:

  • NSUserActivity - Ini memungkinkan aplikasi untuk menjelaskan aktivitas tempat pengguna saat ini terlibat. NSUserActivity awalnya dibuat untuk mendukung HandOff, di mana aktivitas yang dimulai pada salah satu perangkat pengguna dapat diambil dan dilanjutkan di perangkat lain. NSUserActivityberfungsi sama di macOS seperti di iOS, jadi silakan lihat dokumentasi Pengenalan Handoff iOS kami untuk detail selengkapnya.
  • Siri di Mac - Siri menggunakan Aktivitas Saat Ini (NSUserActivity) untuk memberikan konteks ke perintah yang dapat dikeluarkan pengguna.
  • Pemulihan Status - Saat pengguna keluar dari aplikasi di macOS dan kemudian merilisnya kembali, aplikasi akan secara otomatis dikembalikan ke status sebelumnya. Pengembang dapat menggunakan API Pemulihan Status untuk mengodekan dan memulihkan status UI sementara sebelum Antarmuka Pengguna ditampilkan kepada pengguna. Jika aplikasi berbasis NSDocument , Pemulihan Status ditangani secara otomatis. Untuk mengaktifkan Pemulihan Status untuk aplikasi non-berbasisNSDocument , atur RestorableNSWindow kelas ke true.
  • Dokumen di Cloud - Sebelum macOS Sierra, aplikasi harus secara eksplisit ikut serta untuk bekerja dengan dokumen di iCloud Drive pengguna. Di macOS Sierra, folder Desktop dan Dokumen pengguna dapat disinkronkan dengan iCloud Drive mereka secara otomatis oleh sistem. Akibatnya, salinan dokumen lokal dapat dihapus untuk mengosongkan ruang pada komputer pengguna. NSDocument aplikasi berbasis akan secara otomatis menangani perubahan ini. Semua jenis aplikasi lainnya harus menggunakan NSFileCoordinator untuk menyinkronkan pembacaan dan penulisan dokumen.

Ringkasan

Artikel ini telah membahas beberapa tips, fitur, dan teknik yang dapat digunakan pengembang untuk membangun aplikasi macOS modern di Xamarin.Mac.