Partager via


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 :

Ce diagramme illustre les relations entre la fenêtre, les vues, les sous-vues et le contrôleur de vue

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 :

Boîte de dialogue Nouveau projet

Sélectionnez ensuite le modèle de projet Application vide :

Boîte de dialogue Sélectionner un modèle

Le modèle Projet vide ajoute 4 fichiers au projet :

Fichiers projet

  1. 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’applicationAppDelegateFinishedLaunching.
  2. Main.cs : contient le point d’entrée de l’application, qui spécifie la classe pour le AppDelegate .
  3. Info.plist : fichier de liste de propriétés qui contient des informations de configuration d’application.
  4. 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 :

L’arrière-plan de l’affichage est un gris clair visible

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 :

Contrôleur imbriqué dans le contrôleur de navigation

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 :

CustomViewController est chargé à 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 :

Un nouveau contrôleur d’affichage envoyé 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 :

L’application avec UITextField inclus

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 :

La définition de la valeur SecureTextEntry true masque le texte entré par l’utilisateur

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 :

Écran de connexion

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 :

Exemple d’exécution de la vue

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 AddSubviewsde .

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 :

La navigation est illustrée dans ce graphique

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 :

Si l’utilisateur fait pivoter l’appareil en paysage, les contrôles ne sont pas redimensionnés de manière appropriée

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 :

Tous les contrôles s’étendent pour remplir l’espace supplémentaire

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 UIViewsur , 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 SetNeedsDisplaySetNeedsDisplayInRect 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 :

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 :

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.