Anmerkung
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen, dich anzumelden oder die Verzeichnisse zu wechseln.
Der Zugriff auf diese Seite erfordert eine Genehmigung. Du kannst versuchen , die Verzeichnisse zu wechseln.
In diesem Artikel werden mehrere Tipps, Features und Techniken behandelt, die ein Entwickler zum Erstellen einer modernen macOS-App in Xamarin.Mac verwenden kann.
Erstellen moderner Designs mit modernen Ansichten
Ein modernes Aussehen enthält eine moderne Fenster- und Symbolleistendarstellung, z. B. die unten gezeigte Beispiel-App:
Aktivieren von Inhaltsansichten in voller Größe
Um dies in einer Xamarin.Mac-App zu erreichen, möchte der Entwickler eine Inhaltsansicht mit voller Größe verwenden, was bedeutet, dass sich der Inhalt unter den Bereichen Tool und Titelleiste erweitert und von macOS automatisch verschwommen wird.
Um dieses Feature im Code zu aktivieren, erstellen Sie eine benutzerdefinierte Klasse für die NSWindowController und lassen sie wie folgt aussehen:
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
}
}
Dieses Feature kann auch im Benutzeroberflächen-Generator von Xcode aktiviert werden, indem sie das Fenster auswählen und die Inhaltsansicht in voller Größe überprüfen:
Wenn Sie eine Inhaltsansicht mit voller Größe verwenden, muss der Entwickler den Inhalt möglicherweise unter den Titel- und Symbolleistenbereichen versatzen, sodass bestimmte Inhalte (z. B. Bezeichnungen) nicht darunter geschoben werden.
Um dieses Problem zu erschweren, können die Bereiche "Titel" und "Toolleiste" eine dynamische Höhe basierend auf der Aktion aufweisen, die der Benutzer gerade ausführt, die Version von macOS, die der Benutzer installiert hat, und/oder die Mac-Hardware, auf der die App ausgeführt wird.
Daher funktioniert das Einfache hartcodieren des Offsets beim Gestalten der Benutzeroberfläche nicht. Der Entwickler muss einen dynamischen Ansatz verfolgen.
Apple enthält die Key-Value Observable-Eigenschaft ContentLayoutRect der NSWindow Klasse, um den aktuellen Inhaltsbereich im Code abzurufen. Der Entwickler kann diesen Wert verwenden, um die erforderlichen Elemente manuell zu positionieren, wenn sich der Inhaltsbereich ändert.
Die bessere Lösung ist die Verwendung von AutoLayout- und Größenklassen, um die UI-Elemente entweder im Code oder im Schnittstellen-Generator zu positionieren.
Code wie das folgende Beispiel kann verwendet werden, um UI-Elemente mithilfe von AutoLayout- und Größenklassen im Ansichtscontroller der App zu positionieren:
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
}
}
Dieser Code erstellt Speicher für eine obere Einschränkung, die auf eine Bezeichnung (ItemTitle) angewendet wird, um sicherzustellen, dass sie nicht unter den Bereich "Titel" und "Symbolleiste" fällt:
public NSLayoutConstraint topConstraint { get; set; }
Durch Überschreiben der Methode des Ansichtscontrollers UpdateViewConstraints kann der Entwickler testen, ob die erforderliche Einschränkung bereits erstellt und bei Bedarf erstellt wurde.
Wenn eine neue Einschränkung erstellt werden muss, wird auf die ContentLayoutGuide Eigenschaft des Window-Steuerelements zugegriffen, auf das eingeschränkt werden muss, und in eine NSLayoutGuide:
var contentLayoutGuide = ItemTitle.Window?.ContentLayoutGuide as NSLayoutGuide;
Auf die TopAnchor-Eigenschaft der Datei NSLayoutGuide wird zugegriffen, und wenn sie verfügbar ist, wird sie verwendet, um eine neue Einschränkung mit dem gewünschten Offsetbetrag zu erstellen, und die neue Einschränkung wird aktiviert, um sie anzuwenden:
// Assemble constraint and activate it
topConstraint = topAnchor.ConstraintEqualToAnchor (topAnchor, 20);
topConstraint.Active = true;
Aktivieren optimierter Symbolleisten
Ein normales macOS-Fenster enthält eine standardmäßige Titelleiste, die am oberen Rand des Fensters ausgeführt wird. Wenn das Fenster auch eine Symbolleiste enthält, wird es unter diesem Titelleistenbereich angezeigt:
Wenn Sie eine optimierte Symbolleiste verwenden, verschwindet der Titelbereich, und die Symbolleiste wird in der Position der Titelleiste in Übereinstimmung mit den Schaltflächen "Fenster schließen", "Minimieren" und "Maximieren" nach oben verschoben:
Die optimierte Symbolleiste wird durch Überschreiben der ViewWillAppear Methode der NSViewController optimierten Symbolleiste aktiviert und sieht wie folgt aus:
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
// Enable streamlined Toolbars
View.Window.TitleVisibility = NSWindowTitleVisibility.Hidden;
}
Dieser Effekt wird in der Regel für Shoebox-Anwendungen (ein Fenster-Apps) wie Karten, Kalender, Notizen und Systemeinstellungen verwendet.
Verwenden von Zubehöransichtscontrollern
Je nach Design der App möchte der Entwickler möglicherweise auch den Titelleistenbereich durch einen Zubehör-Ansichtscontroller ergänzen, der direkt unterhalb des Bereichs "Titel-/Toolleiste" angezeigt wird, um kontextabhängige Steuerelemente für den Benutzer basierend auf der aktivität bereitzustellen, an der sie derzeit beteiligt sind:
Der Zubehöransichtscontroller wird automatisch verschwommen und die Größe des Systems ohne Eingreifen des Entwicklers geändert.
Gehen Sie wie folgt vor, um einen Zubehör-Ansichtscontroller hinzuzufügen:
Doppelklicken Sie im Projektmappen-Explorer auf die Datei
Main.storyboard, um sie zur Bearbeitung zu öffnen.Ziehen Sie einen benutzerdefinierten Ansichtscontroller in die Hierarchie des Fensters:
Layout der Ui der Zubehöransicht:
Machen Sie die Zubehöransicht als Steckdose und alle anderen Aktionen oder Outlets für die Benutzeroberfläche verfügbar:
Speichern Sie die Änderungen.
Kehren Sie zu Visual Studio für Mac zurück, um die Änderungen zu synchronisieren.
Bearbeiten Sie das NSWindowController Und machen Sie es wie folgt aussehen:
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
}
}
Die wichtigsten Punkte dieses Codes sind der Ort, an dem die Ansicht auf die benutzerdefinierte Ansicht festgelegt ist, die im Schnittstellen-Generator definiert und als Steckdose verfügbar gemacht wurde:
accessoryView.View = AccessoryViewGoBar;
Und das LayoutAttribute definiert , wo das Zubehör angezeigt wird:
accessoryView.LayoutAttribute = NSLayoutAttribute.Bottom;
Da macOS jetzt vollständig lokalisiert ist, sind die Left Eigenschaften Right NSLayoutAttribute veraltet und sollten durch Leading und Trailingersetzt werden.
Verwenden von Windows-Registerkarten
Darüber hinaus kann das macOS-System Zubehör-Ansichtscontroller zum Fenster der App hinzufügen. Um beispielsweise Tabbed Windows zu erstellen, in dem mehrere der Windows-Apps in einem virtuellen Fenster zusammengeführt werden:
In der Regel muss der Entwickler in seinen Xamarin.Mac-Apps tabbed Windows verwenden, das System behandelt sie automatisch wie folgt:
- Windows wird beim Aufrufen der
OrderFrontMethode automatisch Tabstopps angezeigt. - Windows wird beim Aufrufen der
OrderOutMethode automatisch untabbediert. - Im Code werden alle Tabbed-Fenster weiterhin als "sichtbar" betrachtet, jedoch werden alle Nicht-Front-Tabs vom System mit CoreGraphics ausgeblendet.
- Verwenden Sie die
TabbingIdentifierEigenschaft,NSWindowum Windows in Registerkarten zu gruppieren. - Wenn es sich um eine
NSDocumentbasierte App handelt, werden mehrere dieser Features automatisch aktiviert (z. B. die Plusschaltfläche, die der Registerkartenleiste hinzugefügt wird) ohne Entwickleraktion. NSDocumentNicht basierende Apps können die Schaltfläche "Plus" in der Registerkartengruppe aktivieren, um ein neues Dokument hinzuzufügen, indem dieGetNewWindowForTabMethode derNSWindowsController.
Wenn Sie alle Teile zusammenführen, könnte die AppDelegate App, die systembasierte Windows-Registerkarten verwenden wollte, wie folgt aussehen:
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
}
}
Wo die NewDocumentNumber Eigenschaft die Anzahl der neuen Dokumente nachverfolgt, die erstellt wurden, und die NewDocument Methode erstellt ein neues Dokument und zeigt es an.
Die NSWindowController könnte dann wie folgt aussehen:
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
}
}
Wo die statische App Eigenschaft eine Verknüpfung zum Aufrufen der AppDelegate. Die SetDefaultDocumentTitle Methode legt basierend auf der Anzahl der erstellten neuen Dokumente einen neuen Dokumenttitel fest.
Der folgende Code teilt macOS mit, dass die App Registerkarten bevorzugt, und stellt eine Zeichenfolge bereit, mit der die Windows-App in Registerkarten gruppiert werden kann:
// Prefer Tabbed Windows
Window.TabbingMode = NSWindowTabbingMode.Preferred;
Window.TabbingIdentifier = "Main";
Die folgende Überschreibungsmethode fügt der Registerkartenleiste eine Plusschaltfläche hinzu, die ein neues Dokument erstellt, wenn der Benutzer darauf klickt:
public override void GetNewWindowForTab (NSObject sender)
{
// Ask app to open a new document window
App.NewDocument (this);
}
Verwenden der Kernanimation
Kernanimation ist ein leistungsstarkes Grafikrenderingmodul, das in macOS integriert ist. Die Kernanimation wurde optimiert, um die GPU (Graphics Processing Unit) zu nutzen, die in moderner macOS-Hardware verfügbar ist, anstatt die Grafikvorgänge auf der CPU auszuführen, was den Computer verlangsamen kann.
Die CALayervon der Kernanimation bereitgestellte Animation kann für Aufgaben wie schnelles und flüssiges Scrollen und Animationen verwendet werden. Die Benutzeroberfläche einer App sollte aus mehreren Unteransichten und Ebenen bestehen, um die Hauptanimation vollständig nutzen zu können.
Ein CALayer Objekt bietet mehrere Eigenschaften, mit denen der Entwickler steuern kann, was dem Benutzer auf dem Bildschirm angezeigt wird, z. B.:
Content- Dies kann einNSImageoderCGImageder den Inhalt der Ebene bereitstellt.BackgroundColor- Legt die Hintergrundfarbe der Ebene als eineCGColorBorderWidth- Legt die Rahmenbreite fest.BorderColor- Legt die Rahmenfarbe fest.
Um Kerngrafiken in der Benutzeroberfläche der App zu verwenden, muss sie Layer Backed Views verwenden, was Apple vorschlägt, dass der Entwickler immer in der Inhaltsansicht des Fensters aktivieren sollte. Auf diese Weise erben alle untergeordneten Ansichten automatisch auch layer backing.
Darüber hinaus schlägt Apple vor, layer backed Views zu verwenden, anstatt eine neue CALayer als Unterlayer hinzuzufügen, da das System automatisch mehrere der erforderlichen Einstellungen verarbeitet (z. B. diejenigen, die von einem Retina Display benötigt werden).
Die Layersicherung kann aktiviert werden, indem sie den WantsLayer Schnittstellen-Generator von NSView true Xcode im Ansichtseffekt-Inspektor festlegen, indem Sie die Kernanimationsschicht überprüfen:
Neuauszeichnen von Ansichten mit Ebenen
Ein weiterer wichtiger Schritt bei der Verwendung von Layer Backed Views in einer Xamarin.Mac-App ist das LayerContentsRedrawPolicy Festlegen des Werts NSView OnSetNeedsDisplay in der NSViewController Zum Beispiel:
public override void ViewWillAppear ()
{
base.ViewWillAppear ();
// Set the content redraw policy
View.LayerContentsRedrawPolicy = NSViewLayerContentsRedrawPolicy.OnSetNeedsDisplay;
}
Wenn der Entwickler diese Eigenschaft nicht festlegt, wird die Ansicht immer neu gezeichnet, wenn sich der Frameursprung ändert, was aus Leistungsgründen nicht gewünscht wird. Wenn diese Eigenschaft auf OnSetNeedsDisplay den Entwickler festgelegt ist, muss dies manuell festgelegt werden NeedsDisplay , damit true der Inhalt jedoch neu gezeichnet wird.
Wenn eine Ansicht als geändert markiert ist, überprüft das System die WantsUpdateLayer Eigenschaft der Ansicht. Wenn die Methode zurückgegeben true wird, wird die UpdateLayer Methode aufgerufen, andernfalls wird die DrawRect Methode der Ansicht aufgerufen, um den Inhalt der Ansicht zu aktualisieren.
Apple hat bei Bedarf die folgenden Vorschläge zum Aktualisieren eines Views-Inhalts:
- Apple bevorzugt die Verwendung
UpdateLaternach Möglichkeit,DrawRectda es eine erhebliche Leistungssteigerung bietet. - Verwenden Sie dasselbe
layer.Contentsfür UI-Elemente, die ähnlich aussehen. - Apple bevorzugt auch den Entwickler, seine Benutzeroberfläche mithilfe von Standardansichten zu verfassen, z
NSTextField. B. immer wieder.
Erstellen Sie zum Verwenden UpdateLayereine benutzerdefinierte Klasse für den NSView Code, und gestalten Sie den Code wie folgt:
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
}
}
Verwenden des modernen Ziehens und Ablegens
Um dem Benutzer eine moderne Drag- und Drop-Oberfläche zu bieten, sollte der Entwickler Drag Flocking in den Drag and Drop-Vorgängen ihrer App übernehmen. Drag Flocking ist der Ort, an dem jede einzelne Datei oder jedes Element, das gezogen wird, anfangs als einzelnes Element angezeigt wird, das sich zusammen unter dem Cursor mit einer Anzahl der Elemente gruppieren kann, während der Benutzer den Ziehvorgang fortsetzt.
Wenn der Benutzer den Drag-Vorgang beendet, werden die einzelnen Elemente entflockt und zu ihren ursprünglichen Positionen zurückkehren.
Im folgenden Beispielcode wird Drag Flocking in einer benutzerdefinierten Ansicht aktiviert:
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
}
}
Der Herdeeffekt wurde erreicht, indem jedes Element an die BeginDraggingSession Methode des NSView als separates Element in einem Array gezogen wird.
Verwenden Sie beim Arbeiten mit einer oder oder NSTableView NSOutlineViewder Klasse die PastboardWriterForRow Methode, NSTableViewDataSource um den Dragging-Vorgang zu starten:
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
}
}
Dadurch kann der Entwickler eine Einzelperson NSDraggingItem für jedes Element in der Tabelle bereitstellen, das gezogen wird, im Gegensatz zu der älteren Methode WriteRowsWith , die alle Zeilen als einzelne Gruppe in das Einfügebrett schreibt.
Verwenden Sie beim Arbeiten mit NSCollectionViewsder Methode erneut die PasteboardWriterForItemAt Methode im Gegensatz zu der WriteItemsAt Methode, wenn das Ziehen beginnt.
Der Entwickler sollte immer vermeiden, große Dateien auf dem Einfügebrett zu platzieren. New to macOS Sierra, File Promises allow the developer to place references to given files on the pasteboard that will later be erfüllt when the user finishes the Drop operation using the new NSFilePromiseProvider and NSFilePromiseReceiver classes.
Verwenden der modernen Ereignisverfolgung
Bei einem Benutzeroberflächenelement (z. B. a NSButton), das einem Titel- oder Toolleistenbereich hinzugefügt wurde, sollte der Benutzer auf das Element klicken und ein Ereignis als normal auslösen lassen (z. B. anzeigen eines Popupfensters). Da sich das Element jedoch auch im Bereich "Titel" oder "Symbolleiste" befindet, sollte der Benutzer auch auf das Element klicken und ziehen können, um das Fenster zu verschieben.
Erstellen Sie dazu im Code eine benutzerdefinierte Klasse für das Element (z NSButton. B. ) und überschreiben Sie das MouseDown Ereignis wie folgt:
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);
}
}
Dieser Code verwendet die TrackEventsMatching Methode, mit der NSWindow das UI-Element verknüpft ist, um die LeftMouseUp Ereignisse abzufangen LeftMouseDragged . Bei einem LeftMouseUp Ereignis antwortet das UI-Element normal. Für das LeftMouseDragged Ereignis wird das Ereignis an die NSWindow's PerformWindowDrag Methode übergeben, um das Fenster auf dem Bildschirm zu verschieben.
Das Aufrufen der PerformWindowDrag Methode der NSWindow Klasse bietet die folgenden Vorteile:
- Das Fenster kann verschoben werden, auch wenn die App nicht mehr reagiert (z. B. beim Verarbeiten einer Deep-Schleife).
- Der Leerraumwechsel funktioniert wie erwartet.
- Die Leerzeichenleiste wird normal angezeigt.
- Das Ausrichten und Ausrichten von Fenstern funktionieren normal.
Verwenden moderner Containeransichtssteuerelemente
macOS Sierra bietet viele moderne Verbesserungen an den vorhandenen Containeransichtssteuerelementen, die in früheren Versionen des Betriebssystems verfügbar sind.
Verbesserungen der Tabellenansicht
Der Entwickler sollte immer die neue NSView basierte Version von Containeransichtssteuerelementen verwenden, z NSTableView. B. . Zum Beispiel:
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
}
}
Dadurch können benutzerdefinierte Tabellenzeilenaktionen an bestimmte Zeilen in der Tabelle angefügt werden (z. B. Wischen nach rechts zum Löschen der Zeile). Um dieses Verhalten zu aktivieren, überschreiben Sie die RowActions Methode der 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
}
}
Die statische Wird verwendet, um eine neue Tabellenzeilenaktion NSTableViewRowAction.FromStyle der folgenden Formatvorlagen zu erstellen:
Regular– Führt eine standardmäßige, nicht destruktive Aktion aus, z. B. das Bearbeiten des Zeileninhalts.Destructive– Führt eine destruktive Aktion aus, z. B. das Löschen der Zeile aus der Tabelle. Diese Aktionen werden mit einem roten Hintergrund gerendert.
Verbesserungen der Bildlaufansicht
Wenn Sie eine Bildlaufansicht (NSScrollView) direkt oder als Teil eines anderen Steuerelements (z NSTableView. B. ) verwenden, kann der Inhalt der Bildlaufansicht unter den Bereichen Titel und Symbolleiste in einer Xamarin.Mac-App mit einem modernen Aussehen und Ansichten schieben.
Daher kann das erste Element im Inhaltsbereich der Bildlaufansicht teilweise vom Bereich "Titel" und "Symbolleiste" verdeckt werden.
Um dieses Problem zu beheben, hat Apple der NSScrollView Klasse zwei neue Eigenschaften hinzugefügt:
ContentInsets– Ermöglicht es dem Entwickler, einNSEdgeInsetsObjekt bereitzustellen, das den Offset definiert, der oben in der Bildlaufansicht angewendet wird.AutomaticallyAdjustsContentInsets– Wenntruedie Bildlaufansicht denContentInsetsEntwickler automatisch behandelt.
Mithilfe des ContentInsets Entwicklers kann der Start der Bildlaufansicht angepasst werden, um die Aufnahme von Zubehör wie:
- Eine Sortieranzeige wie die in der Mail-App angezeigte.
- Ein Suchfeld.
- Eine Schaltfläche "Aktualisieren" oder "Aktualisieren".
Automatisches Layout und Lokalisierung in modernen Apps
Apple enthält mehrere Technologien in Xcode, mit denen der Entwickler problemlos eine internationalisierte macOS-App erstellen kann. Xcode ermöglicht es dem Entwickler jetzt, benutzergerichteten Text aus dem Benutzeroberflächendesign der App in den Storyboarddateien zu trennen und Tools zur Aufrechterhaltung dieser Trennung zu bieten, wenn sich die Benutzeroberfläche ändert.
Weitere Informationen finden Sie im Internationalisierungs- und Lokalisierungshandbuch von Apple.
Implementieren der Basis-Internationalisierung
Durch die Implementierung der Base Internationalization kann der Entwickler eine einzelne Storyboarddatei bereitstellen, um die Benutzeroberfläche der App darzustellen und alle benutzerorientierten Zeichenfolgen zu trennen.
Wenn der Entwickler die anfängliche Storyboarddatei (oder Dateien) erstellt, die die Benutzeroberfläche der App definieren, werden sie in der Base Internationalization (die Sprache, die der Entwickler spricht) erstellt.
Als Nächstes kann der Entwickler Lokalisierungen und die Base Internationalization-Zeichenfolgen (im Storyboard-UI-Design) exportieren, die in mehrere Sprachen übersetzt werden können.
Später können diese Lokalisierungen importiert werden, und Xcode generiert die sprachspezifischen Zeichenfolgendateien für das Storyboard.
Implementieren des automatischen Layouts zur Unterstützung der Lokalisierung
Da lokalisierte Versionen von Zeichenfolgenwerten sehr große Größen und/oder Leserichtung aufweisen können, sollte der Entwickler das automatische Layout verwenden, um die Benutzeroberfläche der App in einer Storyboarddatei zu positionieren und zu vergrößern.
Apple schlägt Folgendes vor:
- Einschränkungen für feste Breite entfernen – Alle textbasierten Ansichten sollten die Größe basierend auf ihrem Inhalt ändern dürfen. Die Ansicht mit fester Breite kann ihre Inhalte in bestimmten Sprachen zuschneiden.
- Verwenden Sie systeminterne Inhaltsgrößen : Standardmäßig werden textbasierte Ansichten automatisch so angepasst, dass sie ihren Inhalt anpassen. Wählen Sie für textbasierte Ansicht, die nicht ordnungsgemäß angepasst wird, diese im Schnittstellen-Generator von Xcode aus, und wählen Sie dann "Größe an Inhalt anpassen">aus.
- Anwenden von vorangestellten und nachgestellten Attributen – Da sich die Richtung des Texts basierend auf der Sprache des Benutzers ändern kann, verwenden Sie die neuen
Leadingund Einschränkungsattribute im Gegensatz zu den vorhandenenRightundTrailingLeftAttributen.LeadingundTrailingwird basierend auf der Sprachenrichtung automatisch angepasst. - An angrenzende Ansichten anheften – Dies ermöglicht es den Ansichten, die Position zu ändern und ihre Größe zu ändern, wenn sich die Ansichten um sie herum ändern, als Reaktion auf die ausgewählte Sprache.
- Legen Sie keine Windows-Mindest- und/oder Maximalgrößen fest: Windows kann die Größe ändern, wenn die ausgewählte Sprache die Größe ihrer Inhaltsbereiche ändert.
- Ständiges Testen des Layouts – Während der Entwicklung bei der App sollte ständig in verschiedenen Sprachen getestet werden. Weitere Details finden Sie in der Dokumentation zu Apple Testing Your Internationalized App .
- Mit NSStackViews können Sie Ansichten zusammen -
NSStackViewsanheften, sodass ihre Inhalte auf vorhersehbare Weise verschoben und vergrößert werden können und die Größe der Inhalte basierend auf der ausgewählten Sprache geändert wird.
Lokalisieren im Schnittstellen-Generator von Xcode
Apple hat mehrere Features im Benutzeroberflächen-Generator von Xcode bereitgestellt, die der Entwickler beim Entwerfen oder Bearbeiten der Benutzeroberfläche einer App verwenden kann, um die Lokalisierung zu unterstützen. Der Abschnitt "Textrichtung " des Attributinspektors ermöglicht es dem Entwickler, Hinweise zur Verwendung und Aktualisierung der Richtung in einer ausgewählten textbasierten Ansicht (z NSTextField. B. ):
Es gibt drei mögliche Werte für die Textrichtung:
- Natürlich – Das Layout basiert auf der Zeichenfolge, die dem Steuerelement zugewiesen ist.
- Von links nach rechts – Das Layout wird immer nach links nach rechts gezwungen.
- Von rechts nach links – Das Layout wird immer nach rechts nach links gezwungen.
Für das Layout gibt es zwei mögliche Werte:
- Von links nach rechts - Das Layout ist immer von links nach rechts.
- Von rechts nach links - Das Layout ist immer von rechts nach links.
Diese sollten in der Regel nur geändert werden, wenn eine bestimmte Ausrichtung erforderlich ist.
Die Mirror-Eigenschaft weist das System an, bestimmte Steuerelementeigenschaften (z. B. die Zellenbildposition) zu kippen. Es gibt drei mögliche Werte:
- Automatisch – Die Position ändert sich automatisch basierend auf der richtung der ausgewählten Sprache.
- In der Schnittstelle von rechts nach links – Die Position wird nur in Rechts-nach-links-basierten Sprachen geändert.
- Nie - Die Position wird sich nie ändern.
Wenn der Entwickler die Ausrichtung "Center", "Blocksatz" oder "Vollständig" für den Inhalt einer textbasierten Ansicht angegeben hat, werden diese basierend auf der ausgewählten Sprache niemals gekippt.
Vor macOS Sierra wurden steuerelemente, die im Code erstellt wurden, nicht automatisch gespiegelt. Der Entwickler musste Code wie die folgende verwenden, um die Spiegelung zu behandeln:
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;
}
}
Gibt an, wo das Alignment Steuerelement ImagePosition basierend auf UserInterfaceLayoutDirection dem Steuerelement festgelegt wird.
macOS Sierra fügt mehrere neue Komfortkonstruktoren (über die statische CreateButton Methode) hinzu, die mehrere Parameter (z. B. Title, Image und Action) verwenden und automatisch gespiegelt werden. Zum Beispiel:
var button2 = NSButton.CreateButton (myTitle, myImage, () => {
// Take action when the button is pressed
...
});
Verwenden von Systemdarstellungen
Moderne macOS-Apps können ein neues Dunkles Interface-Aussehen übernehmen, das gut für Die Bilderstellung, -bearbeitung oder -präsentations-Apps geeignet ist:
Dazu können Sie eine Codezeile hinzufügen, bevor das Fenster angezeigt wird. Zum Beispiel:
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
}
}
Die statische GetAppearance Methode der NSAppearance Klasse wird verwendet, um eine benannte Darstellung aus dem System zu erhalten (in diesem Fall NSAppearance.NameVibrantDark).
Apple hat die folgenden Vorschläge für die Verwendung von Systemdarstellungen:
- Bevorzugen Sie benannte Farben gegenüber hartcodierten Werten (z
LabelColor. B. undSelectedControlColor). - Verwenden Sie nach Möglichkeit das Systemstandard-Steuerelementformat.
Eine macOS-App, die die Systemdarstellungen verwendet, funktioniert automatisch ordnungsgemäß für Benutzer, die Barrierefreiheitsfeatures über die Systemeinstellungen-App aktiviert haben. Daher schlägt Apple vor, dass der Entwickler immer Systemdarstellungen in ihren macOS-Apps verwenden sollte.
Entwerfen von UIs mit Storyboards
Storyboards ermöglichen es entwicklern, nicht nur die einzelnen Elemente zu entwerfen, aus denen die Benutzeroberfläche einer App besteht, sondern den UI-Fluss und die Hierarchie der angegebenen Elemente visualisieren und entwerfen.
Controller ermöglichen es dem Entwickler, Elemente in einer Einheit von Komposition und Segues abstrakt zu sammeln und den typischen "Klebecode" zu entfernen, der zum Verschieben in der Ansichtshierarchie erforderlich ist:
Weitere Informationen finden Sie in unserer Dokumentation zur Einführung in Storyboards .
Es gibt viele Instanzen, in denen eine bestimmte Szene, die in einem Storyboard definiert ist, Daten aus einer vorherigen Szene in der Ansichtshierarchie erfordert. Apple hat die folgenden Vorschläge zum Übergeben von Informationen zwischen Szenen:
- Die Abhängigkeiten von Daten sollten immer nach unten durch die Hierarchie überlappen.
- Vermeiden Sie strukturelle Abhängigkeiten der Benutzeroberfläche, da dies die Flexibilität der Benutzeroberfläche begrenzt.
- Verwenden Sie C#-Schnittstellen, um generische Datenabhängige bereitzustellen.
Der Ansichtscontroller, der als Quelle der Segue fungiert, kann die Methode überschreiben und alle PrepareForSegue erforderlichen Initialisierungen (z. B. Das Übergeben von Daten) ausführen, bevor der Segue ausgeführt wird, um den Zielansichtscontroller anzuzeigen. Zum Beispiel:
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;
}
}
Weitere Informationen finden Sie in unserer Segues-Dokumentation .
Verteilen von Aktionen
Basierend auf dem Design der macOS-App kann es vorkommen, dass sich der beste Handler für eine Aktion für ein UI-Steuerelement an einer anderen Stelle in der UI-Hierarchie befindet. Dies gilt in der Regel für Menüs und Menüelemente, die sich in ihrer eigenen Szene befinden, getrennt von der restlichen Benutzeroberfläche der App.
Um diese Situation zu behandeln, kann der Entwickler eine benutzerdefinierte Aktion erstellen und die Aktion an die Antwortkette übergeben. Weitere Informationen finden Sie in der Dokumentation "Arbeiten mit benutzerdefinierten Fensteraktionen ".
Moderne Mac-Features
Apple hat mehrere benutzerorientierte Features in macOS Sierra enthalten, die es dem Entwickler ermöglichen, die Mac-Plattform optimal zu nutzen, z. B.:
- NSUserActivity – Auf diese Weise kann die App die Aktivität beschreiben, an der der Benutzer derzeit beteiligt ist.
NSUserActivitywurde ursprünglich erstellt, um HandOff zu unterstützen, wo eine Aktivität auf einem der Geräte des Benutzers aufgenommen und auf einem anderen Gerät fortgesetzt werden konnte.NSUserActivityfunktioniert in macOS genauso wie in iOS. Weitere Details finden Sie in unserer Dokumentation zur Handoff iOS. - Siri auf dem Mac – Siri verwendet die aktuelle Aktivität (
NSUserActivity), um Kontext zu den Befehlen bereitzustellen, die ein Benutzer ausgeben kann. - Zustandswiederherstellung – Wenn der Benutzer eine App unter macOS beendet und später neu gestartet wird, wird die App automatisch in den vorherigen Zustand zurückgegeben. Der Entwickler kann die Zustandswiederherstellungs-API verwenden, um vorübergehende UI-Zustände zu codieren und wiederherzustellen, bevor die Benutzeroberfläche dem Benutzer angezeigt wird. Wenn die App
NSDocumentbasiert, wird die Zustandswiederherstellung automatisch behandelt. Um die Zustandswiederherstellung für nichtNSDocumentbasierte Apps zu aktivieren, legen Sie dieRestorableNSWindowKlasse auftrue. - Dokumente in der Cloud – Vor macOS Sierra musste sich eine App explizit für die Arbeit mit Dokumenten im iCloud-Laufwerk des Benutzers anmelden. In macOS Sierra werden die Ordner "Desktop" und "Dokumente" des Benutzers möglicherweise automatisch mit ihrem iCloud-Laufwerk vom System synchronisiert. Daher können lokale Kopien von Dokumenten gelöscht werden, um Speicherplatz auf dem Computer des Benutzers freizugeben.
NSDocumentBasierende Apps behandeln diese Änderung automatisch. Alle anderen App-Typen müssen zumNSFileCoordinatorSynchronisieren von Lese- und Schreibvorgängen von Dokumenten verwendet werden.
Zusammenfassung
Dieser Artikel enthält mehrere Tipps, Features und Techniken, die ein Entwickler zum Erstellen einer modernen macOS-App in Xamarin.Mac verwenden kann.











