Projekt interfejsu użytkownika .storyboard/.xib-less w środowisku Xamarin.Mac
W tym artykule opisano tworzenie interfejsu użytkownika aplikacji platformy Xamarin.Mac bezpośrednio z poziomu kodu języka C#, bez plików scenorysu, plików xib lub narzędzia Interface Builder.
Omówienie
Podczas pracy z językami C# i .NET w aplikacji platformy Xamarin.Mac masz dostęp do tych samych elementów interfejsu użytkownika i narzędzi, które wykonuje deweloper pracujący w Objective-C środowisku I Xcode . Zazwyczaj podczas tworzenia aplikacji platformy Xamarin.Mac użyjesz narzędzia Interface Builder środowiska Xcode z plikami .storyboard lub .xib, aby utworzyć i obsługiwać interfejs użytkownika aplikacji.
Istnieje również możliwość utworzenia interfejsu użytkownika aplikacji Xamarin.Mac bezpośrednio w kodzie języka C#. W tym artykule omówimy podstawy tworzenia interfejsów użytkownika i elementów interfejsu użytkownika w kodzie języka C#.
Przełączanie okna w celu używania kodu
Podczas tworzenia nowej aplikacji platformy Xamarin.Mac Cocoa domyślnie zostanie wyświetlone standardowe puste okno. Te okna są definiowane w pliku Main.storyboard (lub tradycyjnie MainWindow.xib) automatycznie dołączonym do projektu. Obejmuje to również plik ViewController.cs , który zarządza głównym widokiem aplikacji (lub ponownie tradycyjnie MainWindow.cs i plikiem MainWindowController.cs ).
Aby przełączyć się do okna Xibless dla aplikacji, wykonaj następujące czynności:
Otwórz aplikację, której chcesz przestać używać
.storyboard
plików lub xib, aby zdefiniować interfejs użytkownika w Visual Studio dla komputerów Mac.W okienku rozwiązania kliknij prawym przyciskiem myszy plik Main.storyboard lub MainWindow.xib i wybierz polecenie Usuń:
W oknie dialogowym Usuń kliknij przycisk Usuń, aby całkowicie usunąć scenorys lub .xib z projektu:
Teraz musimy zmodyfikować plik MainWindow.cs , aby zdefiniować układ okna i zmodyfikować plik ViewController.cs lub MainWindowController.cs , aby utworzyć wystąpienie klasy MainWindow
, ponieważ nie używamy już pliku .storyboard lub xib.
Nowoczesne aplikacje platformy Xamarin.Mac korzystające z scenorysów dla interfejsu użytkownika mogą nie zawierać automatycznie plików MainWindow.cs, ViewController.cs ani MainWindowController.cs . W razie potrzeby wystarczy dodać nową pustą klasę języka C# do projektu (Dodaj>nowy plik...>Ogólna>pusta klasa) i nadaj jej nazwę tak samo jak brakujący plik.
Definiowanie okna w kodzie
Następnie zmodyfikuj plik MainWindow.cs i utwórz go w następujący sposób:
using System;
using Foundation;
using AppKit;
using CoreGraphics;
namespace MacXibless
{
public partial class MainWindow : NSWindow
{
#region Private Variables
private int NumberOfTimesClicked = 0;
#endregion
#region Computed Properties
public NSButton ClickMeButton { get; set;}
public NSTextField ClickMeLabel { get ; set;}
#endregion
#region Constructors
public MainWindow (IntPtr handle) : base (handle)
{
}
[Export ("initWithCoder:")]
public MainWindow (NSCoder coder) : base (coder)
{
}
public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
// Define the user interface of the window here
Title = "Window From Code";
// Create the content view for the window and make it fill the window
ContentView = new NSView (Frame);
// Add UI elements to window
ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
ContentView.AddSubview (ClickMeButton);
ClickMeLabel = new NSTextField (new CGRect (120, Frame.Height - 65, Frame.Width - 130, 20)) {
BackgroundColor = NSColor.Clear,
TextColor = NSColor.Black,
Editable = false,
Bezeled = false,
AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin,
StringValue = "Button has not been clicked yet."
};
ContentView.AddSubview (ClickMeLabel);
}
#endregion
#region Override Methods
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Wireup events
ClickMeButton.Activated += (sender, e) => {
// Update count
ClickMeLabel.StringValue = (++NumberOfTimesClicked == 1) ? "Button clicked one time." : string.Format("Button clicked {0} times.",NumberOfTimesClicked);
};
}
#endregion
}
}
Omówimy kilka kluczowych elementów.
Najpierw dodaliśmy kilka obliczonych właściwości , które będą działać podobnie do gniazd (tak jak w przypadku utworzenia okna w pliku .storyboard lub xib):
public NSButton ClickMeButton { get; set;}
public NSTextField ClickMeLabel { get ; set;}
Zapewni to dostęp do elementów interfejsu użytkownika, które będą wyświetlane w oknie. Ponieważ okno nie jest zawyżone z pliku .storyboard lub .xib, musimy utworzyć wystąpienie tego okna (jak zobaczymy później w MainWindowController
klasie). To właśnie robi ta nowa metoda konstruktora:
public MainWindow(CGRect contentRect, NSWindowStyle aStyle, NSBackingStore bufferingType, bool deferCreation): base (contentRect, aStyle,bufferingType,deferCreation) {
...
}
W tym miejscu zaprojektujemy układ okna i umieścimy wszystkie elementy interfejsu użytkownika potrzebne do utworzenia wymaganego interfejsu użytkownika. Aby można było dodać do okna dowolne elementy interfejsu użytkownika, musi on zawierać elementy w widoku zawartości:
ContentView = new NSView (Frame);
Spowoduje to utworzenie widoku zawartości, który wypełni okno. Teraz do okna dodamy nasz pierwszy element interfejsu użytkownika , , NSButton
:
ClickMeButton = new NSButton (new CGRect (10, Frame.Height-70, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
ContentView.AddSubview (ClickMeButton);
Pierwszą rzeczą, którą należy zauważyć, jest to, że w przeciwieństwie do systemu iOS system macOS używa notacji matematycznej do definiowania układu współrzędnych okna. Dlatego punkt początkowy znajduje się w lewym dolnym rogu okna, z wartościami rosnącymi w prawo i w prawym górnym rogu okna. Podczas tworzenia nowego NSButton
elementu bierzemy to pod uwagę podczas definiowania jego położenia i rozmiaru na ekranie.
Właściwość AutoresizingMask = NSViewResizingMask.MinYMargin
informuje przycisk, że chcemy pozostać w tej samej lokalizacji w górnej części okna, gdy rozmiar okna zostanie zmieniony w pionie. Ponownie jest to wymagane, ponieważ (0,0) znajduje się w lewym dolnym rogu okna.
Na koniec metoda dodaje element NSButton
do widoku zawartości, ContentView.AddSubview (ClickMeButton)
aby był wyświetlany na ekranie po uruchomieniu aplikacji i wyświetlonym oknie.
Następnie do okna zostanie dodana etykieta, która będzie wyświetlać liczbę NSButton
kliknięć:
ClickMeLabel = new NSTextField (new CGRect (120, Frame.Height - 65, Frame.Width - 130, 20)) {
BackgroundColor = NSColor.Clear,
TextColor = NSColor.Black,
Editable = false,
Bezeled = false,
AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin,
StringValue = "Button has not been clicked yet."
};
ContentView.AddSubview (ClickMeLabel);
Ponieważ system macOS nie ma określonego elementu interfejsu użytkownika etykiety , dodaliśmy specjalnie stylizowany, nieedytowalny NSTextField
element do działania jako etykieta. Podobnie jak poprzednio, rozmiar i lokalizacja uwzględniają, że (0,0) znajduje się w lewym dolnym rogu okna. Właściwość AutoresizingMask = NSViewResizingMask.WidthSizable | NSViewResizingMask.MinYMargin
używa operatora or do łączenia dwóch NSViewResizingMask
funkcji. Spowoduje to, że etykieta pozostanie w tej samej lokalizacji w górnej części okna, gdy rozmiar okna zostanie zmieniony w pionie i zmniejsza się i zwiększa szerokość, ponieważ rozmiar okna jest zmieniany w poziomie.
Ponownie metoda dodaje element NSTextField
do widoku zawartości, ContentView.AddSubview (ClickMeLabel)
aby był wyświetlany na ekranie po uruchomieniu aplikacji i otwarciu okna.
Dostosowywanie kontrolera okna
Ponieważ projekt elementu MainWindow
nie jest już ładowany z pliku .storyboard lub .xib, musimy wprowadzić pewne zmiany w kontrolerze okien. Zmodyfikuj plik MainWindowController.cs i utwórz go w następujący sposób:
using System;
using Foundation;
using AppKit;
using CoreGraphics;
namespace MacXibless
{
public partial class MainWindowController : NSWindowController
{
public MainWindowController (IntPtr handle) : base (handle)
{
}
[Export ("initWithCoder:")]
public MainWindowController (NSCoder coder) : base (coder)
{
}
public MainWindowController () : base ("MainWindow")
{
// Construct the window from code here
CGRect contentRect = new CGRect (0, 0, 1000, 500);
base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);
// Simulate Awaking from Nib
Window.AwakeFromNib ();
}
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
}
public new MainWindow Window {
get { return (MainWindow)base.Window; }
}
}
}
Omówimy kluczowe elementy tej modyfikacji.
Najpierw zdefiniujemy nowe wystąpienie MainWindow
klasy i przypiszemy je do właściwości podstawowego kontrolera Window
okna:
CGRect contentRect = new CGRect (0, 0, 1000, 500);
base.Window = new MainWindow(contentRect, (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable), NSBackingStore.Buffered, false);
Definiujemy lokalizację okna ekranu z elementem CGRect
. Podobnie jak układ współrzędnych okna, ekran definiuje (0,0) jako dolny lewy róg. Następnie zdefiniujemy styl okna przy użyciu operatora Or , aby połączyć co najmniej NSWindowStyle
dwie funkcje:
... (NSWindowStyle.Titled | NSWindowStyle.Closable | NSWindowStyle.Miniaturizable | NSWindowStyle.Resizable) ...
Dostępne są następujące NSWindowStyle
funkcje:
- Obramowanie — okno nie będzie miało obramowania.
- Tytuł — okno będzie mieć pasek tytułu.
- Closable — okno ma przycisk Zamknij i można je zamknąć.
- Miniaturyzacja — okno ma miniaturyzowany przycisk i można je zminimalizować.
- Możliwość zmiany rozmiaru — okno będzie miało przycisk zmiany rozmiaru i można go zmienić.
- Narzędzie — okno jest oknem stylu narzędzia (panel).
- DocModal — jeśli okno jest panelem, będzie to modalne zamiast systemowe.
- NonactivatingPanel — jeśli okno jest panelem, nie zostanie wykonane główne okno.
- TexturedBackground — okno będzie miało teksturowane tło.
- Nieskalowane — okno nie zostanie skalowane.
- UnifiedTitleAndToolbar — obszary tytułu i paska narzędzi okna zostaną dołączone.
- Hud — okno będzie wyświetlane jako panel ekranu z głową.
- FullScreenWindow — okno może wprowadzać tryb pełnoekranowy.
- FullSizeContentView — widok zawartości okna znajduje się za tytułem i obszarem paska narzędzi.
Dwie ostatnie właściwości definiują typ buforowania dla okna i jeśli rysunek okna zostanie odroczony. Aby uzyskać więcej informacji na NSWindows
temat programu , zobacz dokumentację dotyczącą wprowadzenia firmy Apple do systemu Windows .
Na koniec, ponieważ okno nie jest zawyżone z pliku .storyboard lub xib, musimy zasymulować go w naszym MainWindowController.cs przez wywołanie metody windows AwakeFromNib
:
Window.AwakeFromNib ();
Umożliwi to kod w oknie tak samo jak standardowe okno załadowane z pliku .storyboard lub .xib.
Wyświetlanie okna
Po usunięciu pliku .storyboard lub .xib oraz MainWindow.cs i MainWindowController.cs zmodyfikowanych plików będziesz używać okna tak samo jak w przypadku dowolnego normalnego okna utworzonego w narzędziu Xcode Interface Builder z plikiem xib.
Poniższe polecenie utworzy nowe wystąpienie okna i jego kontrolera i wyświetli okno na ekranie:
private MainWindowController mainWindowController;
...
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
Na tym etapie, jeśli aplikacja zostanie uruchomiona, a przycisk kliknął kilka razy, zostaną wyświetlone następujące elementy:
Dodawanie okna tylko kodu
Jeśli chcemy dodać tylko kod, okno xibless do istniejącej aplikacji Xamarin.Mac kliknij prawym przyciskiem myszy projekt w okienku rozwiązania i wybierz polecenie Dodaj>nowy plik... W oknie dialogowym Nowy plik wybierz okno Xamarin.Mac>Cocoa z kontrolerem, jak pokazano poniżej:
Podobnie jak wcześniej usuniemy domyślny plik storyboard lub xib z projektu (w tym przypadku SecondWindow.xib) i wykonaj kroki opisane w sekcji Przełączanie okna do użycia kodu powyżej, aby zastosować definicję okna do kodu.
Dodawanie elementu interfejsu użytkownika do okna w kodzie
Niezależnie od tego, czy okno zostało utworzone w kodzie, czy załadowane z pliku .storyboard lub xib, czasami chcemy dodać element interfejsu użytkownika do okna z kodu. Na przykład:
var ClickMeButton = new NSButton (new CGRect (10, 10, 100, 30)){
AutoresizingMask = NSViewResizingMask.MinYMargin
};
MyWindow.ContentView.AddSubview (ClickMeButton);
Powyższy kod tworzy nowy NSButton
i dodaje go do wystąpienia okna na potrzeby wyświetlania MyWindow
. Zasadniczo każdy element interfejsu użytkownika, który można zdefiniować w narzędziu Interface Builder programu Xcode w pliku .storyboard lub xib, można utworzyć w kodzie i wyświetlić w oknie.
Definiowanie paska menu w kodzie
Z powodu bieżących ograniczeń na platformie Xamarin.Mac nie zaleca się tworzenia paska menu aplikacji Xamarin.Mac—NSMenuBar
w kodzie, ale nadal używasz pliku Main.storyboard lub MainMenu.xib , aby go zdefiniować. Oznacza to, że można dodawać i usuwać menu i elementy menu w kodzie języka C#.
Na przykład zmodyfikuj plik AppDelegate.cs i utwórz metodę DidFinishLaunching
podobną do następującej:
public override void DidFinishLaunching (NSNotification notification)
{
mainWindowController = new MainWindowController ();
mainWindowController.Window.MakeKeyAndOrderFront (this);
// Create a Status Bar Menu
NSStatusBar statusBar = NSStatusBar.SystemStatusBar;
var item = statusBar.CreateStatusItem (NSStatusItemLength.Variable);
item.Title = "Phrases";
item.HighlightMode = true;
item.Menu = new NSMenu ("Phrases");
var address = new NSMenuItem ("Address");
address.Activated += (sender, e) => {
Console.WriteLine("Address Selected");
};
item.Menu.AddItem (address);
var date = new NSMenuItem ("Date");
date.Activated += (sender, e) => {
Console.WriteLine("Date Selected");
};
item.Menu.AddItem (date);
var greeting = new NSMenuItem ("Greeting");
greeting.Activated += (sender, e) => {
Console.WriteLine("Greetings Selected");
};
item.Menu.AddItem (greeting);
var signature = new NSMenuItem ("Signature");
signature.Activated += (sender, e) => {
Console.WriteLine("Signature Selected");
};
item.Menu.AddItem (signature);
}
Powyższe polecenie tworzy menu Pasek stanu na podstawie kodu i wyświetla je po uruchomieniu aplikacji. Aby uzyskać więcej informacji na temat pracy z menu, zobacz dokumentację menu .
Podsumowanie
W tym artykule szczegółowo opatrzono tworzenie interfejsu użytkownika aplikacji Xamarin.Mac w kodzie języka C#, a nie przy użyciu narzędzia Interface Builder środowiska Xcode z plikami .storyboard lub .xib.