Tworzenie interfejsów użytkownika systemu iOS w kodzie na platformie Xamarin.iOS
Interfejs użytkownika aplikacji dla systemu iOS jest jak witryna sklepu — aplikacja zazwyczaj pobiera jedno okno, ale może wypełnić okno tak wieloma obiektami, jak to wymaga, a obiekty i ustalenia można zmienić w zależności od tego, co aplikacja chce wyświetlić. Obiekty w tym scenariuszu — elementy widoczne przez użytkownika — są nazywane widokami. Aby utworzyć pojedynczy ekran w aplikacji, widoki są ułożone na siebie nawzajem w hierarchii widoków zawartości, a hierarchia jest zarządzana przez pojedynczy kontroler widoku. Aplikacje z wieloma ekranami mają wiele hierarchii widoków zawartości, z których każdy ma własny kontroler widoków, a aplikacja umieszcza widoki w oknie, aby utworzyć inną hierarchię widoku zawartości na podstawie ekranu, na podstawie którego znajduje się użytkownik.
Na poniższym diagramie przedstawiono relacje między oknami, widokami, widokami podrzędnymi i kontrolerem widoku, które łączą interfejs użytkownika z ekranem urządzenia:
Te hierarchie widoków można konstruować przy użyciu konstruktora interfejsu Xcode, jednak dobrze jest mieć podstawową wiedzę na temat sposobu pracy w całości w kodzie. W tym artykule przedstawiono niektóre podstawowe kwestie, które umożliwiają rozpoczęcie pracy przy użyciu interfejsu użytkownika tylko do kodu.
Tworzenie projektu tylko do kodu
Pusty szablon projektu dla systemu iOS
Najpierw utwórz projekt systemu iOS w programie Visual Studio przy użyciu projektu File > New Project > Visual C# > i Telefon & iPad iOS > App (Xamarin), jak pokazano poniżej:
Następnie wybierz szablon projektu Pusta aplikacja :
Szablon Empty Project (Pusty projekt) dodaje do projektu 4 pliki:
- AppDelegate.cs — zawiera podklasę
UIApplicationDelegate
,AppDelegate
która służy do obsługi zdarzeń aplikacji z systemu iOS. Okno aplikacji jest tworzone w metodzieAppDelegate
FinishedLaunching
. - Main.cs — zawiera punkt wejścia dla aplikacji, który określa klasę dla klasy
AppDelegate
. - Info.plist — plik listy właściwości zawierający informacje o konfiguracji aplikacji.
- Entitlements.plist — plik listy właściwości zawierający informacje o możliwościach i uprawnieniach aplikacji.
Aplikacje systemu iOS są tworzone przy użyciu wzorca MVC. Pierwszy ekran wyświetlany przez aplikację jest tworzony na podstawie głównego kontrolera widoku okna. Aby uzyskać więcej informacji na temat samego wzorca MVC, zobacz przewodnik Hello, iOS Multiscreen.
Implementacja dodawana AppDelegate
przez szablon tworzy okno aplikacji, z którego jest dostępna tylko jedna dla każdej aplikacji systemu iOS i powoduje, że jest ona widoczna za pomocą następującego kodu:
public class AppDelegate : UIApplicationDelegate
{
public override UIWindow Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
// create a new window instance based on the screen size
Window = new UIWindow(UIScreen.MainScreen.Bounds);
// make the window visible
Window.MakeKeyAndVisible();
return true;
}
}
Jeśli chcesz teraz uruchomić tę aplikację, prawdopodobnie zostanie zgłoszony wyjątek z informacją o tym, że Application windows are expected to have a root view controller at the end of application launch
. Dodajmy kontroler i ustawmy go jako kontroler widoku głównego aplikacji.
Dodawanie kontrolera
Aplikacja może zawierać wiele kontrolerów widoku, ale musi mieć jeden kontroler widoku głównego, aby kontrolować wszystkie kontrolery widoku. Dodaj kontroler do okna, tworząc UIViewController
wystąpienie i ustawiając je na Window.RootViewController
właściwość :
public class AppDelegate : UIApplicationDelegate
{
// class-level declarations
public override UIWindow Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// create a new window instance based on the screen size
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var controller = new UIViewController();
controller.View.BackgroundColor = UIColor.LightGray;
Window.RootViewController = controller;
// make the window visible
Window.MakeKeyAndVisible();
return true;
}
}
Każdy kontroler ma skojarzony widok, który jest dostępny z właściwości.View
Powyższy kod zmienia właściwość widoku BackgroundColor
na UIColor.LightGray
tak, aby była widoczna, jak pokazano poniżej:
Możemy również ustawić dowolną UIViewController
podklasę RootViewController
w ten sposób, w tym kontrolery z zestawu UIKit, a także te, które piszemy. Na przykład następujący kod dodaje element UINavigationController
jako :RootViewController
public class AppDelegate : UIApplicationDelegate
{
// class-level declarations
public override UIWindow Window
{
get;
set;
}
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
// create a new window instance based on the screen size
Window = new UIWindow(UIScreen.MainScreen.Bounds);
var controller = new UIViewController();
controller.View.BackgroundColor = UIColor.LightGray;
controller.Title = "My Controller";
var navController = new UINavigationController(controller);
Window.RootViewController = navController;
// make the window visible
Window.MakeKeyAndVisible();
return true;
}
}
Spowoduje to utworzenie kontrolera zagnieżdżonego w kontrolerze nawigacji, jak pokazano poniżej:
Tworzenie kontrolera widoku
Teraz, gdy zobaczyliśmy, jak dodać kontroler jako RootViewController
okno, zobaczmy, jak utworzyć niestandardowy kontroler widoku w kodzie.
Dodaj nową klasę o nazwie, CustomViewController
jak pokazano poniżej:
Klasa powinna dziedziczyć z UIViewController
klasy , która znajduje się w UIKit
przestrzeni nazw, jak pokazano poniżej:
using System;
using UIKit;
namespace CodeOnlyDemo
{
class CustomViewController : UIViewController
{
}
}
Inicjowanie widoku
UIViewController
zawiera metodę o nazwie , która jest wywoływana ViewDidLoad
, gdy kontroler widoku jest po raz pierwszy załadowany do pamięci. Jest to odpowiednie miejsce do inicjowania widoku, takiego jak ustawienie jego właściwości.
Na przykład poniższy kod dodaje przycisk i procedurę obsługi zdarzeń, aby wypchnąć nowy kontroler widoku do stosu nawigacji po naciśnięciu przycisku:
using System;
using CoreGraphics;
using UIKit;
namespace CodyOnlyDemo
{
public class CustomViewController : UIViewController
{
public CustomViewController ()
{
}
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
View.BackgroundColor = UIColor.White;
Title = "My Custom View Controller";
var btn = UIButton.FromType (UIButtonType.System);
btn.Frame = new CGRect (20, 200, 280, 44);
btn.SetTitle ("Click Me", UIControlState.Normal);
var user = new UIViewController ();
user.View.BackgroundColor = UIColor.Magenta;
btn.TouchUpInside += (sender, e) => {
this.NavigationController.PushViewController (user, true);
};
View.AddSubview (btn);
}
}
}
Aby załadować ten kontroler w aplikacji i zademonstrować prostą nawigację, utwórz nowe wystąpienie klasy CustomViewController
. Utwórz nowy kontroler nawigacji, przekaż wystąpienie kontrolera widoku i ustaw nowy kontroler nawigacji na okno RootViewController
w AppDelegate
następujący sposób:
var cvc = new CustomViewController ();
var navController = new UINavigationController (cvc);
Window.RootViewController = navController;
Teraz, gdy aplikacja zostanie załadowana, CustomViewController
element zostanie załadowany wewnątrz kontrolera nawigacji:
Kliknięcie przycisku spowoduje wypchnięcie nowego kontrolera widoku do stosu nawigacji:
Kompilowanie hierarchii widoków
W powyższym przykładzie zaczęliśmy tworzyć interfejs użytkownika w kodzie, dodając przycisk do kontrolera widoku.
Interfejsy użytkownika systemu iOS składają się z hierarchii widoków. Dodatkowe widoki, takie jak etykiety, przyciski, suwaki itp., są dodawane jako widoki podrzędne niektórych widoków nadrzędnych.
Na przykład zmodyfikujmy CustomViewController
element , aby utworzyć ekran logowania, na którym użytkownik może wprowadzić nazwę użytkownika i hasło. Ekran będzie składać się z dwóch pól tekstowych i przycisku.
Dodawanie pól tekstowych
Najpierw usuń przycisk i procedurę obsługi zdarzeń, która została dodana w sekcji Inicjowanie widoku .
Dodaj kontrolkę dla nazwy użytkownika, tworząc i inicjując element UITextField
, a następnie dodając ją do hierarchii widoków, jak pokazano poniżej:
class CustomViewController : UIViewController
{
UITextField usernameField;
public override void ViewDidLoad()
{
base.ViewDidLoad();
View.BackgroundColor = UIColor.Gray;
nfloat h = 31.0f;
nfloat w = View.Bounds.Width;
usernameField = new UITextField
{
Placeholder = "Enter your username",
BorderStyle = UITextBorderStyle.RoundedRect,
Frame = new CGRect(10, 82, w - 20, h)
};
View.AddSubview(usernameField);
}
}
Podczas tworzenia UITextField
obiektu ustawiamy Frame
właściwość , aby zdefiniować jej lokalizację i rozmiar. W systemie iOS współrzędna 0,0 znajduje się w lewym górnym rogu z +x w prawo i +y w dół. Po ustawieniu parametru Frame
wraz z kilkoma innymi właściwościami wywołujemy metodę View.AddSubview
, aby dodać UITextField
element do hierarchii widoków. Dzięki usernameField
temu widok podrzędny UIView
wystąpienia, do którego View
odwołuje się właściwość. Widok podrzędny jest dodawany z kolejnością z większą niż jej widok nadrzędny, więc pojawia się przed widokiem nadrzędnym na ekranie.
Aplikacja z dołączonym elementem UITextField
jest pokazana poniżej:
Możemy dodać UITextField
element dla hasła w podobny sposób, tym razem ustawimy SecureTextEntry
właściwość na true, jak pokazano poniżej:
public class CustomViewController : UIViewController
{
UITextField usernameField, passwordField;
public override void ViewDidLoad()
{
// keep the code the username UITextField
passwordField = new UITextField
{
Placeholder = "Enter your password",
BorderStyle = UITextBorderStyle.RoundedRect,
Frame = new CGRect(10, 114, w - 20, h),
SecureTextEntry = true
};
View.AddSubview(usernameField);
View.AddSubview(passwordField);
}
}
Ustawienie SecureTextEntry = true
ukrywa tekst wprowadzony przez UITextField
użytkownika, jak pokazano poniżej:
Dodawanie przycisku
Następnie dodamy przycisk, aby użytkownik mógł przesłać nazwę użytkownika i hasło. Przycisk jest dodawany do hierarchii widoków, podobnie jak każda inna kontrolka, przekazując go jako argument do metody widoku nadrzędnego AddSubview
.
Poniższy kod dodaje przycisk i rejestruje procedurę obsługi zdarzeń dla TouchUpInside
zdarzenia:
var submitButton = UIButton.FromType (UIButtonType.RoundedRect);
submitButton.Frame = new CGRect (10, 170, w - 20, 44);
submitButton.SetTitle ("Submit", UIControlState.Normal);
submitButton.TouchUpInside += (sender, e) => {
Console.WriteLine ("Submit button pressed");
};
View.AddSubview(submitButton);
W tym miejscu zostanie wyświetlony ekran logowania, jak pokazano poniżej:
W przeciwieństwie do poprzednich wersji systemu iOS domyślne tło przycisku jest przezroczyste. Zmiana właściwości przycisku BackgroundColor
powoduje zmianę następujących zmian:
submitButton.BackgroundColor = UIColor.White;
Spowoduje to naciśnięcie przycisku kwadratowego, a nie typowego zaokrąglonego przycisku krawędzi. Aby uzyskać zaokrąglone krawędzie, użyj następującego fragmentu kodu:
submitButton.Layer.CornerRadius = 5f;
Po wprowadzeniu tych zmian widok będzie wyglądać następująco:
Dodawanie wielu widoków do hierarchii widoków
System iOS udostępnia funkcję dodawania wielu widoków do hierarchii widoków przy użyciu polecenia AddSubviews
.
View.AddSubviews(new UIView[] { usernameField, passwordField, submitButton });
Dodawanie funkcji przycisku
Po kliknięciu przycisku użytkownicy będą oczekiwać, że coś się stanie. Na przykład wyświetlany jest alert lub nawigacja jest wykonywana na innym ekranie.
Dodajmy kod, aby wypchnąć drugi kontroler widoku do stosu nawigacji.
Najpierw utwórz drugi kontroler widoku:
var loginVC = new UIViewController () { Title = "Login Success!"};
loginVC.View.BackgroundColor = UIColor.Purple;
Następnie dodaj funkcję do TouchUpInside
zdarzenia:
submitButton.TouchUpInside += (sender, e) => {
this.NavigationController.PushViewController (loginVC, true);
};
Nawigacja jest pokazana poniżej:
Zauważ, że domyślnie w przypadku korzystania z kontrolera nawigacji system iOS udostępnia aplikacji pasek nawigacyjny i przycisk wstecz, aby umożliwić powrót przez stos.
Iterowanie za pośrednictwem hierarchii widoków
Istnieje możliwość iterowania przez hierarchię widoku podrzędnego i wybranie dowolnego określonego widoku. Aby na przykład znaleźć każdy UIButton
z nich i nadać mu inny BackgroundColor
przycisk, można użyć następującego fragmentu kodu
foreach(var subview in View.Subviews)
{
if (subview is UIButton)
{
var btn = subview as UIButton;
btn.BackgroundColor = UIColor.Green;
}
}
Nie będzie to jednak działać, jeśli widok jest iterated dla elementu , UIView
ponieważ wszystkie widoki zostaną przywrócone jako UIView
obiekty dodane do widoku nadrzędnego dziedziczą UIView
wartość .
Obsługa rotacji
Jeśli użytkownik obraca urządzenie w poziomie, kontrolki nie zmieniają odpowiedniego rozmiaru, jak pokazano na poniższym zrzucie ekranu:
Jednym ze sposobów rozwiązania tego problemu AutoresizingMask
jest ustawienie właściwości w każdym widoku. W tym przypadku chcemy, aby kontrolki rozciągały się w poziomie, więc ustawilibyśmy każdy AutoresizingMask
element . Poniższy przykład dotyczy usernameField
elementu , ale ten sam element należy zastosować do każdego gadżetu w hierarchii widoków.
usernameField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
Teraz, gdy obracamy urządzenie lub symulator, wszystko rozciąga się, aby wypełnić dodatkowe miejsce, jak pokazano poniżej:
Tworzenie widoków niestandardowych
Oprócz używania kontrolek będących częścią zestawu UIKit można również używać widoków niestandardowych. Widok niestandardowy można utworzyć, dziedzicząc z UIView
i przesłaniając Draw
element . Utwórzmy widok niestandardowy i dodajmy go do hierarchii widoków w celu zademonstrowania.
Dziedziczenie z widoku interfejsu użytkownika
Pierwszą rzeczą, którą musimy zrobić, jest utworzenie klasy dla widoku niestandardowego. Zrobimy to przy użyciu szablonu Klasa w programie Visual Studio, aby dodać pustą klasę o nazwie CircleView
. Klasa bazowa powinna być ustawiona na UIView
, którą przypominamy w UIKit
przestrzeni nazw. Będziemy również potrzebować System.Drawing
przestrzeni nazw. Inne różne System.*
przestrzenie nazw nie będą używane w tym przykładzie, więc możesz je usunąć.
Klasa powinna wyglądać następująco:
using System;
namespace CodeOnlyDemo
{
class CircleView : UIView
{
}
}
Rysowanie w widoku interfejsu użytkownika
Każda UIView
z nich ma metodę wywoływaną Draw
przez system, gdy musi zostać narysowana. Draw
nigdy nie należy wywoływać bezpośrednio. Jest on wywoływany przez system podczas przetwarzania pętli przebiegu. Po pierwszym przejściu przez pętlę uruchamiania po dodaniu widoku do hierarchii widoków wywoływana jest jej Draw
metoda. Kolejne wywołania są Draw
wykonywane, gdy widok jest oznaczony jako wymagający rysowania przez wywołanie SetNeedsDisplay
elementu lub SetNeedsDisplayInRect
w widoku.
Możemy dodać kod rysunku do naszego widoku, dodając taki kod wewnątrz metody przesłoniętej Draw
, jak pokazano poniżej:
public override void Draw(CGRect rect)
{
base.Draw(rect);
//get graphics context
using (var g = UIGraphics.GetCurrentContext())
{
// set up drawing attributes
g.SetLineWidth(10.0f);
UIColor.Green.SetFill();
UIColor.Blue.SetStroke();
// create geometry
var path = new CGPath();
path.AddArc(Bounds.GetMidX(), Bounds.GetMidY(), 50f, 0, 2.0f * (float)Math.PI, true);
// add geometry to graphics context and draw
g.AddPath(path);
g.DrawPath(CGPathDrawingMode.FillStroke);
}
}
Ponieważ CircleView
element to UIView
, możemy również ustawić UIView
właściwości. Na przykład możemy ustawić BackgroundColor
element w konstruktorze:
public CircleView()
{
BackgroundColor = UIColor.White;
}
Aby użyć właśnie utworzonego CircleView
obiektu, możemy dodać go jako widok podrzędny do hierarchii widoków w istniejącym kontrolerze, tak jak w przypadku elementów UILabels
i UIButton
wcześniejszych, lub załadować go jako widok nowego kontrolera. Zróbmy to drugie.
Ładowanie widoku
UIViewController
ma metodę o nazwie LoadView
, która jest wywoływana przez kontroler w celu utworzenia widoku. Jest to odpowiednie miejsce do utworzenia widoku i przypisania go do właściwości kontrolera View
.
Najpierw potrzebujemy kontrolera, więc utwórz nową pustą klasę o nazwie CircleController
.
W CircleController
pliku dodaj następujący kod, aby ustawić View
element na wartość ( CircleView
implementacja base
nie powinna być wywoływana w zastąpieniu):
using UIKit;
namespace CodeOnlyDemo
{
class CircleController : UIViewController
{
CircleView view;
public override void LoadView()
{
view = new CircleView();
View = view;
}
}
}
Na koniec musimy przedstawić kontroler w czasie wykonywania. Zróbmy to, dodając procedurę obsługi zdarzeń na dodanym wcześniej przycisku przesyłania w następujący sposób:
submitButton.TouchUpInside += delegate
{
Console.WriteLine("Submit button clicked");
//circleController is declared as class variable
circleController = new CircleController();
PresentViewController(circleController, true, null);
};
Teraz po uruchomieniu aplikacji i naciśnięciu przycisku przesyłania zostanie wyświetlony nowy widok z okręgiem:
Tworzenie ekranu uruchamiania
Ekran uruchamiania jest wyświetlany, gdy aplikacja zostanie uruchomiona jako sposób wyświetlania użytkownikom, że odpowiada. Ponieważ podczas ładowania aplikacji jest wyświetlany ekran uruchamiania, nie można go utworzyć w kodzie, ponieważ aplikacja jest nadal ładowana do pamięci.
Podczas tworzenia projektu systemu iOS w programie Visual Studio zostanie udostępniony ekran uruchamiania w postaci pliku .xib, który można znaleźć w folderze Resources w projekcie.
Można to edytować, klikając go dwukrotnie i otwierając go w narzędziu Xcode Interface Builder.
Firma Apple zaleca, aby plik .xib lub Storyboard był używany w aplikacjach przeznaczonych dla systemu iOS 8 lub nowszego. Po uruchomieniu pliku w narzędziu Xcode Interface Builder można użyć klas rozmiarów i automatycznego układu, aby dostosować układ tak, aby wyglądał dobrze i wyświetlał poprawnie dla wszystkich rozmiarów urządzeń. Statyczny obraz uruchamiania może być używany oprócz pliku .xib lub Storyboard, aby umożliwić obsługę aplikacji przeznaczonych dla wcześniejszych wersji.
Aby uzyskać więcej informacji na temat tworzenia ekranu uruchamiania, zapoznaj się z poniższymi dokumentami:
- Tworzenie ekranu uruchamiania przy użyciu pliku .xib
- Zarządzanie ekranami uruchamiania za pomocą scenorysów
Ważne
Od systemu iOS 9 firma Apple zaleca, aby scenorysy były używane jako podstawowa metoda tworzenia ekranu uruchamiania.
Tworzenie obrazu uruchamiania dla aplikacji w wersji wstępnej dla systemu iOS 8
Obraz statyczny może być używany oprócz ekranu uruchamiania platformy .xib lub Storyboard, jeśli aplikacja jest przeznaczona dla wersji starszych niż iOS 8.
Ten statyczny obraz można ustawić w pliku Info.plist lub jako wykaz zasobów (dla systemu iOS 7) w aplikacji. Musisz podać oddzielne obrazy dla każdego rozmiaru urządzenia (320x480, 640x960, 640x1136), na których aplikacja może działać. Aby uzyskać więcej informacji na temat rozmiarów ekranu uruchamiania, zobacz przewodnik Launch Screen Images (Uruchamianie obrazów ekranu).
Ważne
Jeśli aplikacja nie ma ekranu uruchamiania, możesz zauważyć, że nie mieści się on w pełni na ekranie. Jeśli tak jest, pamiętaj o dołączeniu co najmniej obrazu 640x1136 o nazwie Default-568@2x.png
do pliku Info.plist.
Podsumowanie
W tym artykule omówiono sposób programowego tworzenia aplikacji dla systemu iOS w programie Visual Studio. Przyjrzeliśmy się, jak utworzyć projekt z pustego szablonu projektu, omawiając sposób tworzenia i dodawania kontrolera widoku głównego do okna. Następnie pokazaliśmy, jak za pomocą kontrolek z zestawu UIKit utworzyć hierarchię widoków w kontrolerze w celu utworzenia ekranu aplikacji. Następnie sprawdziliśmy, jak ustawić widoki odpowiednio w różnych orientacjach i zobaczyliśmy, jak utworzyć widok niestandardowy przez podklasę UIView
, a także jak załadować widok w obrębie kontrolera. Na koniec dowiesz się, jak dodać ekran uruchamiania do aplikacji.