Création d’interfaces utilisateur iOS dans le code dans Xamarin.iOS
L’interface utilisateur d’une application iOS est semblable à une vitrine : l’application obtient généralement une fenêtre, mais elle peut remplir la fenêtre avec autant d’objets que nécessaire, et les objets et les dispositions peuvent être modifiés en fonction de ce que l’application souhaite afficher. Les objets dans ce scénario, les éléments que l’utilisateur voit, sont appelés des affichages. Pour générer un seul écran dans une application, les affichages sont empilés les uns sur les autres dans une hiérarchie d’affichage de contenu. Cette hiérarchie est gérée par un contrôleur d’affichage unique. Les applications à plusieurs écrans ont plusieurs hiérarchies d’affichage de contenu, chacune avec son propre contrôleur d’affichage. L’application place les affichages dans la fenêtre pour créer une hiérarchie d’affichage de contenu différente selon l’écran sur lequel se trouve l’utilisateur.
Le diagramme ci-dessous illustre les relations entre la fenêtre, les affichages, les sous-affichages et le contrôleur d’affichage qui font apparaître l’interface utilisateur dans l’écran de l’appareil :
Ces hiérarchies d’affichage peuvent être construites à l’aide du Générateur d’interface de Xcode, mais il est judicieux d’avoir une compréhension fondamentale de la façon de fonctionner entièrement dans le code. Cet article décrit quelques points de base pour vous familiariser avec le développement d’interface utilisateur en code uniquement.
Création d’un projet code uniquement
Modèle de projet vide iOS
Tout d’abord, créez un projet iOS dans Visual Studio à l’aide du > projet Nouveau projet > Visual C# > i Téléphone &iPad > iOS App (Xamarin), illustré ci-dessous :
Sélectionnez ensuite le modèle de projet Application vide :
Le modèle Projet vide ajoute 4 fichiers au projet :
- AppDelegate.cs - Contient une
UIApplicationDelegate
sous-classe,AppDelegate
qui est utilisée pour gérer les événements d’application à partir d’iOS. La fenêtre d’application est créée dans la méthode de l’applicationAppDelegate
FinishedLaunching
. - Main.cs : contient le point d’entrée de l’application, qui spécifie la classe pour le
AppDelegate
. - Info.plist : fichier de liste de propriétés qui contient des informations de configuration d’application.
- Entitlements.plist : fichier de liste de propriétés qui contient des informations sur les fonctionnalités et les autorisations de l’application.
Les applications iOS sont créées à l’aide du modèle MVC. Le premier écran affiché par une application est créé à partir du contrôleur d’affichage racine de la fenêtre. Consultez le guide Hello, iOS Multiscreen pour plus d’informations sur le modèle MVC lui-même.
L’implémentation de l’ajout AppDelegate
par le modèle crée la fenêtre d’application, dont il n’existe qu’une seule pour chaque application iOS et la rend visible avec le code suivant :
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;
}
}
Si vous deviez exécuter cette application maintenant, vous obtiendriez probablement une exception levée indiquant que Application windows are expected to have a root view controller at the end of application launch
. Nous allons ajouter un contrôleur et le rendre le contrôleur de vue racine de l’application.
Ajout d’un contrôleur
Votre application peut contenir de nombreux contrôleurs de vue, mais elle doit avoir un contrôleur de vue racine pour contrôler tous les contrôleurs de vue. Ajoutez un contrôleur à la fenêtre en créant une UIViewController
instance et en la définissant sur la Window.RootViewController
propriété :
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;
}
}
Chaque contrôleur a une vue associée, accessible à partir de la View
propriété. Le code ci-dessus modifie la propriété UIColor.LightGray
de la BackgroundColor
vue pour qu’elle soit visible, comme indiqué ci-dessous :
Nous pourrions également définir n’importe quelle UIViewController
sous-classe de RootViewController
cette façon, y compris les contrôleurs de UIKit ainsi que ceux que nous écrivons nous-mêmes. Par exemple, le code suivant ajoute un UINavigationController
élément comme suit 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;
}
}
Cela produit le contrôleur imbriqué dans le contrôleur de navigation, comme indiqué ci-dessous :
Création d’un contrôleur de vue
Maintenant que nous avons vu comment ajouter un contrôleur en tant que RootViewController
fenêtre, voyons comment créer un contrôleur de vue personnalisé dans le code.
Ajoutez une nouvelle classe nommée CustomViewController
comme indiqué ci-dessous :
La classe doit hériter de UIViewController
, qui se trouve dans l’espace UIKit
de noms, comme indiqué :
using System;
using UIKit;
namespace CodeOnlyDemo
{
class CustomViewController : UIViewController
{
}
}
Initialisation de la vue
UIViewController
contient une méthode appelée qui est appelée ViewDidLoad
lorsque le contrôleur d’affichage est chargé en mémoire pour la première fois. Il s’agit d’un emplacement approprié pour effectuer l’initialisation de la vue, par exemple la définition de ses propriétés.
Par exemple, le code suivant ajoute un bouton et un gestionnaire d’événements pour pousser un nouveau contrôleur d’affichage sur la pile de navigation lorsque le bouton est enfoncé :
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);
}
}
}
Pour charger ce contrôleur dans votre application et illustrer la navigation simple, créez une instance de CustomViewController
. Créez un contrôleur de navigation, transmettez votre instance de contrôleur de vue et définissez le nouveau contrôleur de RootViewController
navigation sur celui de la AppDelegate
fenêtre comme précédemment :
var cvc = new CustomViewController ();
var navController = new UINavigationController (cvc);
Window.RootViewController = navController;
Maintenant, lorsque l’application se charge, celle-ci CustomViewController
est chargée à l’intérieur d’un contrôleur de navigation :
Cliquez sur le bouton pour pousser un nouveau contrôleur d’affichage sur la pile de navigation :
Génération de la hiérarchie d’affichage
Dans l’exemple ci-dessus, nous avons commencé à créer une interface utilisateur dans le code en ajoutant un bouton au contrôleur de vue.
Les interfaces utilisateur iOS sont composées d’une hiérarchie d’affichage. Des vues supplémentaires, telles que des étiquettes, des boutons, des curseurs, etc. sont ajoutées en tant que sous-vues d’une vue parente.
Par exemple, nous allons modifier l’écran CustomViewController
pour créer un écran de connexion où l’utilisateur peut entrer un nom d’utilisateur et un mot de passe. L’écran se compose de deux champs de texte et d’un bouton.
Ajout des champs de texte
Tout d’abord, supprimez le bouton et le gestionnaire d’événements ajoutés dans la section Initialisation de la vue.
Ajoutez un contrôle pour le nom d’utilisateur en créant et initialisant un UITextField
, puis en l’ajoutant à la hiérarchie d’affichage, comme indiqué ci-dessous :
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);
}
}
Lorsque nous créons le UITextField
, nous définissons la Frame
propriété pour définir son emplacement et sa taille. Dans iOS, la coordonnée 0,0 se trouve dans le coin supérieur gauche avec +x à droite et +y vers le bas. Après avoir défini les Frame
deux autres propriétés, nous appelons View.AddSubview
à ajouter la UITextField
hiérarchie d’affichage. Cela rend la usernameField
sous-vue de l’instance UIView
référencée par la View
propriété. Une sous-vue est ajoutée avec un ordre z supérieur à son affichage parent. Il apparaît donc devant l’affichage parent sur l’écran.
L’application avec l’élément UITextField
inclus est illustrée ci-dessous :
Nous pouvons ajouter un UITextField
mot de passe de la même manière, cette fois seulement nous définissons la SecureTextEntry
propriété sur true, comme indiqué ci-dessous :
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);
}
}
Le paramètre SecureTextEntry = true
masque le texte entré dans l’utilisateur UITextField
, comme indiqué ci-dessous :
Ajout du bouton
Ensuite, nous allons ajouter un bouton afin que l’utilisateur puisse envoyer le nom d’utilisateur et le mot de passe. Le bouton est ajouté à la hiérarchie d’affichage comme n’importe quel autre contrôle, en le transmettant à nouveau en tant qu’argument à la méthode de AddSubview
la vue parente.
Le code suivant ajoute le bouton et inscrit un gestionnaire d’événements pour l’événement 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);
Avec cela en place, l’écran de connexion s’affiche maintenant comme indiqué ci-dessous :
Contrairement aux versions précédentes d’iOS, l’arrière-plan du bouton par défaut est transparent. La modification de la propriété du BackgroundColor
bouton change ceci :
submitButton.BackgroundColor = UIColor.White;
Cela entraîne un bouton carré plutôt que le bouton arrondi typique. Pour obtenir le bord arrondi, utilisez l’extrait de code suivant :
submitButton.Layer.CornerRadius = 5f;
Avec ces modifications, la vue se présente comme suit :
Ajout de plusieurs vues à la hiérarchie d’affichage
iOS fournit une fonctionnalité permettant d’ajouter plusieurs vues à la hiérarchie de vues à l’aide AddSubviews
de .
View.AddSubviews(new UIView[] { usernameField, passwordField, submitButton });
Ajout de fonctionnalités de bouton
Lorsqu’un bouton est cliqué, vos utilisateurs s’attendent à ce qu’un événement se produise. Par exemple, une alerte s’affiche ou la navigation est effectuée sur un autre écran.
Ajoutons du code pour envoyer (push) un deuxième contrôleur d’affichage sur la pile de navigation.
Tout d’abord, créez le deuxième contrôleur d’affichage :
var loginVC = new UIViewController () { Title = "Login Success!"};
loginVC.View.BackgroundColor = UIColor.Purple;
Ensuite, ajoutez la fonctionnalité à l’événement TouchUpInside
:
submitButton.TouchUpInside += (sender, e) => {
this.NavigationController.PushViewController (loginVC, true);
};
La navigation est illustrée ci-dessous :
Notez que, par défaut, lorsque vous utilisez un contrôleur de navigation, iOS donne à l’application une barre de navigation et un bouton Précédent pour vous permettre de revenir dans la pile.
Itération dans la hiérarchie d’affichage
Il est possible d’effectuer une itération dans la hiérarchie de sous-vues et de sélectionner une vue particulière. Par exemple, pour rechercher chacun UIButton
et donner à ce bouton un autre BackgroundColor
, l’extrait de code suivant peut être utilisé
foreach(var subview in View.Subviews)
{
if (subview is UIButton)
{
var btn = subview as UIButton;
btn.BackgroundColor = UIColor.Green;
}
}
Toutefois, cela ne fonctionnera pas si la vue en cours d’itération est une UIView
car toutes les vues reviennent en tant UIView
qu’objets ajoutés à la vue parente eux-mêmes héritent UIView
.
Gestion de la rotation
Si l’utilisateur fait pivoter l’appareil en paysage, les contrôles ne sont pas redimensionnés correctement, comme l’illustre la capture d’écran suivante :
Une façon de résoudre ce problème consiste à définir la AutoresizingMask
propriété sur chaque vue. Dans ce cas, nous voulons que les contrôles s’étirent horizontalement, de sorte que nous définissions chaque AutoresizingMask
. L’exemple suivant concerne usernameField
, mais la même chose doit être appliquée à chaque gadget de la hiérarchie d’affichage.
usernameField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
Maintenant, lorsque nous pivotons l’appareil ou le simulateur, tout s’étend pour remplir l’espace supplémentaire, comme indiqué ci-dessous :
Création de vues personnalisées
Outre l’utilisation de contrôles qui font partie d’UIKit, les vues personnalisées peuvent également être utilisées. Une vue personnalisée peut être créée en hériter et en UIView
substituant Draw
. Nous allons créer une vue personnalisée et l’ajouter à la hiérarchie d’affichage pour illustrer.
Héritage de UIView
La première chose à faire est de créer une classe pour l’affichage personnalisé. Nous allons le faire à l’aide du modèle De classe dans Visual Studio pour ajouter une classe vide nommée CircleView
. La classe de base doit être définie UIView
sur , que nous rappelons se trouve dans l’espace UIKit
de noms. Nous aurons également besoin de l’espace System.Drawing
de noms. Les autres System.*
espaces de noms ne seront pas utilisés dans cet exemple. N’hésitez donc pas à les supprimer.
La classe doit ressembler à cela :
using System;
namespace CodeOnlyDemo
{
class CircleView : UIView
{
}
}
Dessin dans un UIView
Chaque UIView
méthode est Draw
appelée par le système lorsqu’elle doit être dessinée. Draw
ne devrait jamais être appelé directement. Il est appelé par le système pendant le traitement de la boucle d’exécution. La première fois par le biais de la boucle d’exécution après l’ajout d’une vue à la hiérarchie d’affichage, sa Draw
méthode est appelée. Les appels suivants se Draw
produisent lorsque l’affichage est marqué comme nécessitant d’être dessiné en appelant ou SetNeedsDisplay
SetNeedsDisplayInRect
sur l’affichage.
Nous pouvons ajouter du code de dessin à notre vue en ajoutant ce code à l’intérieur de la méthode substituée Draw
, comme indiqué ci-dessous :
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);
}
}
Étant CircleView
donné qu’il s’agit d’un UIView
, nous pouvons également définir UIView
des propriétés. Par exemple, nous pouvons définir le BackgroundColor
constructeur :
public CircleView()
{
BackgroundColor = UIColor.White;
}
Pour utiliser le CircleView
code que nous venons de créer, nous pouvons l’ajouter en tant que sous-affichage à la hiérarchie d’affichage dans un contrôleur existant, comme nous l’avons fait avec le et UIButton
les UILabels
versions antérieures, ou nous pouvons le charger en tant qu’affichage d’un nouveau contrôleur. Nous allons faire ce dernier.
Chargement d’une vue
UIViewController
a une méthode nommée LoadView
appelée par le contrôleur pour créer sa vue. Il s’agit d’un emplacement approprié pour créer une vue et l’affecter à la propriété du View
contrôleur.
Tout d’abord, nous avons besoin d’un contrôleur, donc créez une classe vide nommée CircleController
.
Ajoutez CircleController
le code suivant pour définir la View
valeur a CircleView
(vous ne devez pas appeler l’implémentation base
dans votre remplacement) :
using UIKit;
namespace CodeOnlyDemo
{
class CircleController : UIViewController
{
CircleView view;
public override void LoadView()
{
view = new CircleView();
View = view;
}
}
}
Enfin, nous devons présenter le contrôleur au moment de l’exécution. Procédons ainsi en ajoutant un gestionnaire d’événements sur le bouton Envoyer que nous avons ajouté précédemment, comme suit :
submitButton.TouchUpInside += delegate
{
Console.WriteLine("Submit button clicked");
//circleController is declared as class variable
circleController = new CircleController();
PresentViewController(circleController, true, null);
};
Maintenant, lorsque nous exécutons l’application et appuyez sur le bouton Envoyer, la nouvelle vue avec un cercle s’affiche :
Création d’un écran de lancement
Un écran de lancement s’affiche lorsque votre application démarre comme un moyen d’afficher à vos utilisateurs qu’elle est réactive. Étant donné qu’un écran de lancement s’affiche lorsque votre application est chargée, elle ne peut pas être créée dans le code, car l’application est toujours chargée en mémoire.
Lorsque vous créez un projet iOS dans Visual Studio, un écran de lancement est fourni pour vous sous la forme d’un fichier .xib, qui se trouve dans le dossier Ressources à l’intérieur de votre projet.
Cela peut être modifié en double-cliquant dessus et en l’ouvrant dans le Générateur d’interface Xcode.
Apple recommande qu’un fichier .xib ou Storyboard soit utilisé pour les applications ciblant iOS 8 ou une version ultérieure, lorsque vous lancez un fichier dans le Générateur d’interface Xcode, vous pouvez utiliser les classes de taille et la disposition automatique pour adapter votre disposition afin qu’elle semble correcte, et s’affiche correctement, pour toutes les tailles d’appareil. Une image de lancement statique peut être utilisée en plus d’un .xib ou storyboard pour permettre la prise en charge des applications ciblant des versions antérieures.
Pour plus d’informations sur la création d’un écran de lancement, reportez-vous aux documents ci-dessous :
- Création d’un écran de lancement à l’aide d’un .xib
- Gestion des écrans de lancement avec des storyboards
Important
À partir d’iOS 9, Apple recommande que les storyboards doivent être utilisés comme méthode principale de création d’un écran de lancement.
Création d’une image de lancement pour les applications pré-iOS 8
Une image statique peut être utilisée en plus d’un écran de lancement .xib ou Storyboard si vous ciblez des versions antérieures à iOS 8.
Cette image statique peut être définie dans le fichier Info.plist ou en tant que catalogue de ressources (pour iOS 7) dans votre application. Vous devez fournir des images distinctes pour chaque taille d’appareil (320x480, 640x960, 640x1136) sur lesquelles votre application peut s’exécuter. Pour plus d’informations sur les tailles de l’écran de lancement, consultez le guide Des images de l’écran de lancement.
Important
Si votre application n’a pas d’écran de lancement, vous remarquerez peut-être qu’elle ne correspond pas entièrement à l’écran. Si c’est le cas, vous devez vous assurer d’inclure, au moins, une image 640x1136 nommée Default-568@2x.png
à votre info.plist.
Résumé
Cet article a décrit comment développer des applications iOS par programmation dans Visual Studio. Nous avons examiné comment créer un projet à partir d’un modèle de projet vide, en expliquant comment créer et ajouter un contrôleur de vue racine à la fenêtre. Nous avons ensuite montré comment utiliser des contrôles de UIKit pour créer une hiérarchie d’affichage au sein d’un contrôleur pour développer un écran d’application. Ensuite, nous avons examiné comment mettre les vues de manière appropriée dans différentes orientations et nous avons vu comment créer une vue personnalisée en sous-classe UIView
, ainsi que comment charger la vue au sein d’un contrôleur. Enfin, nous avons exploré comment ajouter un écran de lancement à une application.