Creazione di interfacce utente iOS nel codice in Xamarin.iOS
L'interfaccia utente di un'app iOS è simile a una vetrina: l'applicazione in genere ottiene una finestra, ma può riempire la finestra con il numero di oggetti necessari e gli oggetti e le disposizioni possono essere modificati a seconda di ciò che l'app vuole visualizzare. Gli oggetti di questo scenario, ovvero gli elementi visibili per l'utente, sono chiamati visualizzazioni. In un'applicazione con un'unica finestra, le visualizzazioni vengono disposte una sopra l'altra in una gerarchia di visualizzazione del contenuto gestita da un unico controller di visualizzazione. Le applicazioni con più schermate hanno più gerarchie di visualizzazione del contenuto, ognuna con un proprio controller di visualizzazione, e l'applicazione inserisce visualizzazioni nella finestra per creare gerarchie di visualizzazione del contenuto diverse in base alla schermata visualizzata dall'utente.
Il diagramma seguente illustra le relazioni tra la finestra, le visualizzazioni, le visualizzazioni secondarie e il controller di visualizzazione che visualizzano l'interfaccia utente sullo schermo del dispositivo:
Queste gerarchie di visualizzazione possono essere costruite usando Interface Builder di Xcode, ma è bene avere una conoscenza fondamentale del funzionamento del tutto nel codice. Questo articolo illustra alcuni punti di base per iniziare a funzionare con lo sviluppo dell'interfaccia utente di sola codice.
Creazione di un progetto solo codice
Modello di progetto iOS vuoto
Prima di tutto, creare un progetto iOS in Visual Studio usando il progetto File > Nuovo progetto > Visual C# > i Telefono & iPad > iOS App (Xamarin), illustrato di seguito:
Selezionare quindi il modello di progetto App vuota:
Il modello Progetto vuoto aggiunge 4 file al progetto:
- AppDelegate.cs: contiene una
UIApplicationDelegate
sottoclasse,AppDelegate
, che viene usata per gestire gli eventi dell'applicazione da iOS. La finestra dell'applicazione viene creata nelAppDelegate
metodo delFinishedLaunching
. - Main.cs : contiene il punto di ingresso per l'applicazione, che specifica la classe per .
AppDelegate
- Info.plist - File di elenco delle proprietà che contiene le informazioni di configurazione dell'applicazione.
- Entitlements.plist : file di elenco delle proprietà che contiene informazioni sulle funzionalità e sulle autorizzazioni dell'applicazione.
Le applicazioni iOS vengono compilate usando il modello MVC. La prima schermata visualizzata da un'applicazione viene creata dal controller di visualizzazione radice della finestra. Per altri dettagli sul modello MVC stesso, vedere la guida a più schermi Hello, iOS.
L'implementazione per l'aggiunta AppDelegate
dal modello crea la finestra dell'applicazione, di cui è presente una sola per ogni applicazione iOS e la rende visibile con il codice seguente:
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;
}
}
Se si eseguisse ora questa applicazione, è probabile che venga generata un'eccezione che indica che Application windows are expected to have a root view controller at the end of application launch
. Aggiungere un controller e impostarlo come controller di visualizzazione radice dell'app.
Aggiunta di un controller
L'app può contenere molti controller di visualizzazione, ma deve avere un controller di visualizzazione radice per controllare tutti i controller di visualizzazione. Aggiungere un controller alla finestra creando un'istanza UIViewController
e impostandola sulla Window.RootViewController
proprietà :
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;
}
}
Ogni controller ha una visualizzazione associata, accessibile dalla View
proprietà . Il codice precedente modifica la proprietà della BackgroundColor
visualizzazione in UIColor.LightGray
in modo che sia visibile, come illustrato di seguito:
Potremmo impostare qualsiasi UIViewController
sottoclasse come RootViewController
in questo modo, inclusi i controller di UIKit e quelli che scriviamo noi stessi. Ad esempio, il codice seguente aggiunge un oggetto UINavigationController
come 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;
}
}
Questo produce il controller annidato all'interno del controller di spostamento, come illustrato di seguito:
Creazione di un controller di visualizzazione
Ora che è stato illustrato come aggiungere un controller come finestra RootViewController
, verrà illustrato come creare un controller di visualizzazione personalizzato nel codice.
Aggiungere una nuova classe denominata CustomViewController
come illustrato di seguito:
La classe deve ereditare da UIViewController
, che si trova nello spazio dei UIKit
nomi , come illustrato di seguito:
using System;
using UIKit;
namespace CodeOnlyDemo
{
class CustomViewController : UIViewController
{
}
}
Inizializzazione della visualizzazione
UIViewController
contiene un metodo chiamato che viene chiamato ViewDidLoad
quando il controller View viene caricato per la prima volta in memoria. Si tratta di una posizione appropriata per l'inizializzazione della visualizzazione, ad esempio l'impostazione delle proprietà.
Ad esempio, il codice seguente aggiunge un pulsante e un gestore eventi per eseguire il push di un nuovo controller di visualizzazione nello stack di navigazione quando viene premuto il pulsante:
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);
}
}
}
Per caricare questo controller nell'applicazione e illustrare la navigazione semplice, creare una nuova istanza di CustomViewController
. Creare un nuovo controller di spostamento, passare l'istanza del controller di visualizzazione e impostare il nuovo controller di RootViewController
spostamento sulla finestra come AppDelegate
prima:
var cvc = new CustomViewController ();
var navController = new UINavigationController (cvc);
Window.RootViewController = navController;
A questo punto, CustomViewController
quando l'applicazione viene caricata all'interno di un controller di spostamento:
Facendo clic sul pulsante, si eseguirà il push di un nuovo controller di visualizzazione nello stack di spostamento:
Compilazione della gerarchia di viste
Nell'esempio precedente è stata avviata la creazione di un'interfaccia utente nel codice aggiungendo un pulsante al controller di visualizzazione.
Le interfacce utente iOS sono costituite da una gerarchia di visualizzazioni. Le visualizzazioni aggiuntive, ad esempio etichette, pulsanti, dispositivi di scorrimento e così via, vengono aggiunte come visualizzazioni secondarie di alcune visualizzazioni padre.
Ad esempio, modificare per CustomViewController
creare una schermata di accesso in cui l'utente può immettere un nome utente e una password. La schermata sarà costituita da due campi di testo e un pulsante.
Aggiunta dei campi di testo
Rimuovere prima di tutto il pulsante e il gestore eventi aggiunti nella sezione Inizializzazione della vista .
Aggiungere un controllo per il nome utente creando e inizializzando e UITextField
quindi aggiungendolo alla gerarchia di visualizzazione, come illustrato di seguito:
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);
}
}
Quando si crea UITextField
, si imposta la proprietà per definirne la Frame
posizione e le dimensioni. In iOS la coordinata 0,0 si trova in alto a sinistra con +x a destra e +y verso il basso. Dopo aver impostato insieme Frame
un paio di altre proprietà, viene chiamato View.AddSubview
per aggiungere l'oggetto UITextField
alla gerarchia di visualizzazione. In questo modo viene usernameField
creata una visualizzazione secondaria dell'istanza UIView
a cui fa riferimento la View
proprietà. Viene aggiunta una visualizzazione secondaria con un ordine z superiore a quello padre, quindi viene visualizzato davanti alla visualizzazione padre sullo schermo.
L'applicazione con l'oggetto UITextField
incluso è illustrata di seguito:
È possibile aggiungere un UITextField
oggetto per la password in modo simile, solo questa volta la proprietà viene impostata SecureTextEntry
su true, come illustrato di seguito:
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);
}
}
L'impostazione SecureTextEntry = true
nasconde il testo immesso nell'oggetto UITextField
dall'utente, come illustrato di seguito:
Aggiunta del pulsante
Verrà quindi aggiunto un pulsante in modo che l'utente possa inviare il nome utente e la password. Il pulsante viene aggiunto alla gerarchia di visualizzazione come qualsiasi altro controllo, passandolo di nuovo come argomento al metodo della AddSubview
visualizzazione padre.
Il codice seguente aggiunge il pulsante e registra un gestore eventi per l'evento TouchUpInside
:
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);
Con questo aspetto, la schermata di accesso viene ora visualizzata come illustrato di seguito:
A differenza delle versioni precedenti di iOS, lo sfondo del pulsante predefinito è trasparente. La modifica della proprietà del BackgroundColor
pulsante cambia:
submitButton.BackgroundColor = UIColor.White;
In questo modo verrà generato un pulsante quadrato anziché il tipico pulsante arrotondato. Per ottenere il bordo arrotondato, usare il frammento di codice seguente:
submitButton.Layer.CornerRadius = 5f;
Con queste modifiche, la visualizzazione sarà simile alla seguente:
Aggiunta di più visualizzazioni alla gerarchia di visualizzazione
iOS offre una funzionalità per aggiungere più visualizzazioni alla gerarchia di visualizzazione usando AddSubviews
.
View.AddSubviews(new UIView[] { usernameField, passwordField, submitButton });
Aggiunta della funzionalità del pulsante
Quando si fa clic su un pulsante, gli utenti si aspettano che si verifichi un evento. Ad esempio, viene visualizzato un avviso o lo spostamento viene eseguito su un'altra schermata.
Aggiungere un codice per eseguire il push di un secondo controller di visualizzazione nello stack di navigazione.
Creare prima di tutto il secondo controller di visualizzazione:
var loginVC = new UIViewController () { Title = "Login Success!"};
loginVC.View.BackgroundColor = UIColor.Purple;
Aggiungere quindi la funzionalità all'evento TouchUpInside
:
submitButton.TouchUpInside += (sender, e) => {
this.NavigationController.PushViewController (loginVC, true);
};
La navigazione è illustrata di seguito:
Si noti che per impostazione predefinita, quando si usa un controller di spostamento, iOS fornisce all'applicazione una barra di spostamento e un pulsante Indietro per consentire di tornare indietro nello stack.
Iterazione nella gerarchia di visualizzazione
È possibile scorrere la gerarchia della visualizzazione secondaria e selezionare qualsiasi visualizzazione specifica. Ad esempio, per trovare ogni UIButton
elemento e assegnare un pulsante diverso BackgroundColor
, è possibile usare il frammento di codice seguente
foreach(var subview in View.Subviews)
{
if (subview is UIButton)
{
var btn = subview as UIButton;
btn.BackgroundColor = UIColor.Green;
}
}
Ciò, tuttavia, non funzionerà se la visualizzazione per cui viene eseguita l'iterazione è perché UIView
tutte le visualizzazioni verranno restituite come oggetti UIView
aggiunti alla visualizzazione padre stessi ereditano UIView
.
Gestione della rotazione
Se l'utente ruota il dispositivo in orizzontale, i controlli non vengono ridimensionati in modo appropriato, come illustrato nello screenshot seguente:
Un modo per risolvere questo problema consiste nell'impostare la AutoresizingMask
proprietà in ogni visualizzazione. In questo caso si vuole che i controlli si allungino orizzontalmente, quindi si impostano ogni AutoresizingMask
oggetto . L'esempio seguente è per usernameField
, ma lo stesso deve essere applicato a ogni gadget nella gerarchia di visualizzazione.
usernameField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
Ora, quando si ruota il dispositivo o il simulatore, tutto si estende per riempire lo spazio aggiuntivo, come illustrato di seguito:
Creazione di visualizzazioni personalizzate
Oltre a usare controlli che fanno parte di UIKit, è anche possibile usare visualizzazioni personalizzate. È possibile creare una vista personalizzata ereditando da UIView
ed eseguendo l'override di Draw
. Creare una vista personalizzata e aggiungerla alla gerarchia di visualizzazione da illustrare.
Ereditarietà da UIView
La prima cosa da fare è creare una classe per la visualizzazione personalizzata. A questo scopo si userà il modello classe in Visual Studio per aggiungere una classe vuota denominata CircleView
. La classe base deve essere impostata su UIView
, che viene richiamata nello spazio dei UIKit
nomi . Sarà necessario anche lo System.Drawing
spazio dei nomi. Gli altri System.*
spazi dei nomi non verranno usati in questo esempio, quindi è possibile rimuoverli.
La classe dovrebbe risultare simile alla seguente:
using System;
namespace CodeOnlyDemo
{
class CircleView : UIView
{
}
}
Disegno in un oggetto UIView
Ogni UIView
oggetto ha un Draw
metodo chiamato dal sistema quando deve essere disegnato. Draw
non deve mai essere chiamato direttamente. Viene chiamato dal sistema durante l'elaborazione del ciclo di esecuzione. La prima volta che si esegue il ciclo di esecuzione dopo l'aggiunta di una vista alla gerarchia di visualizzazione, viene chiamato il relativo Draw
metodo. Le chiamate successive da Draw
eseguire quando la vista è contrassegnata come necessario per essere disegnata chiamando SetNeedsDisplay
o SetNeedsDisplayInRect
nella vista.
È possibile aggiungere codice di disegno alla vista aggiungendo tale codice all'interno del metodo sottoposto Draw
a override, come illustrato di seguito:
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);
}
}
Poiché CircleView
è , UIView
è anche possibile impostare UIView
le proprietà. Ad esempio, è possibile impostare nel BackgroundColor
costruttore:
public CircleView()
{
BackgroundColor = UIColor.White;
}
Per usare l'oggetto CircleView
appena creato, è possibile aggiungerlo come visualizzazione secondaria alla gerarchia di visualizzazione in un controller esistente, come è stato fatto con UILabels
e UIButton
in precedenza, oppure caricarlo come visualizzazione di un nuovo controller. Facciamo quest'ultima.
Caricamento di una visualizzazione
UIViewController
dispone di un metodo denominato LoadView
chiamato dal controller per crearne la visualizzazione. Si tratta di una posizione appropriata per creare una vista e assegnarla alla proprietà del View
controller.
Prima di tutto, è necessario un controller, quindi creare una nuova classe vuota denominata CircleController
.
Aggiungere CircleController
il codice seguente per impostare su View
( CircleView
non è consigliabile chiamare l'implementazione nell'override base
):
using UIKit;
namespace CodeOnlyDemo
{
class CircleController : UIViewController
{
CircleView view;
public override void LoadView()
{
view = new CircleView();
View = view;
}
}
}
Infine, è necessario presentare il controller in fase di esecuzione. A questo scopo, aggiungere un gestore eventi sul pulsante di invio aggiunto in precedenza, come indicato di seguito:
submitButton.TouchUpInside += delegate
{
Console.WriteLine("Submit button clicked");
//circleController is declared as class variable
circleController = new CircleController();
PresentViewController(circleController, true, null);
};
A questo punto, quando si esegue l'applicazione e si tocca il pulsante di invio, viene visualizzata la nuova visualizzazione con un cerchio:
Creazione di una schermata di avvio
Una schermata di avvio viene visualizzata all'avvio dell'app come modo per visualizzare agli utenti che è reattiva. Poiché una schermata di avvio viene visualizzata quando l'app viene caricata, non può essere creata nel codice perché l'applicazione viene ancora caricata in memoria.
Quando si crea un progetto iOS in Visual Studio, viene fornita una schermata di avvio sotto forma di file xib, disponibile nella cartella Risorse all'interno del progetto.
Questa operazione può essere modificata facendo doppio clic su di essa e aprendola in Xcode Interface Builder.
Apple consiglia di usare un file con estensione xib o Storyboard per le applicazioni destinate a iOS 8 o versioni successive, quando si avvia uno dei file in Xcode Interface Builder, è possibile usare classi di dimensioni e layout automatico per adattare il layout in modo che risulti corretto e visualizzato correttamente per tutte le dimensioni del dispositivo. Un'immagine di avvio statica può essere usata oltre a un file con estensione xib o Storyboard per consentire il supporto per le applicazioni destinate alle versioni precedenti.
Per altre informazioni sulla creazione di una schermata di avvio, vedere i documenti seguenti:
- Creazione di una schermata di avvio tramite un file con estensione xib
- Gestione delle schermate di avvio con storyboard
Importante
A partire da iOS 9, Apple consiglia di usare storyboard come metodo principale per la creazione di una schermata di avvio.
Creazione di un'immagine di avvio per le applicazioni pre-iOS 8
Un'immagine statica può essere usata oltre a una schermata di avvio con estensione xib o Storyboard se l'applicazione è destinata alle versioni precedenti a iOS 8.
Questa immagine statica può essere impostata nel file Info.plist o come catalogo asset (per iOS 7) nell'applicazione. Sarà necessario fornire immagini separate per ogni dimensione del dispositivo (320x480, 640x960, 640x1136) su cui l'applicazione può essere eseguita. Per altre informazioni sulle dimensioni della schermata di avvio, vedere la guida Launch Screen Images (Immagini dello schermo di avvio).
Importante
Se la tua app non ha schermata di avvio, potresti notare che non rientra completamente nello schermo. In questo caso, è necessario assicurarsi di includere, almeno, un'immagine 640x1136 denominata Default-568@2x.png
nel file Info.plist.
Riepilogo
Questo articolo ha illustrato come sviluppare applicazioni iOS a livello di codice in Visual Studio. È stato illustrato come compilare un progetto da un modello di progetto vuoto, illustrando come creare e aggiungere un controller di visualizzazione radice alla finestra. È stato quindi illustrato come usare i controlli di UIKit per creare una gerarchia di visualizzazione all'interno di un controller per sviluppare una schermata dell'applicazione. Successivamente è stato esaminato come impostare il layout delle visualizzazioni in modo appropriato in diversi orientamenti ed è stato illustrato come creare una visualizzazione personalizzata sottoclassando UIView
, nonché come caricare la vista all'interno di un controller. Infine è stato illustrato come aggiungere una schermata di avvio a un'applicazione.