Xamarin.iOS でのコードでの iOS ユーザー インターフェイスの作成

iOS アプリのユーザー インターフェイスはネットショップのようなものです。通常、アプリケーションは 1 つのウィンドウを取得しますが、必要な数のオブジェクトでウィンドウをいっぱいにすることができ、アプリが表示する内容に応じてオブジェクトと配置を変更できます。 このシナリオのオブジェクト (ユーザーに表示される物事) はビューと呼ばれます。 アプリケーションで 1 つの画面をビルドするには、コンテンツ ビュー階層にビューが相互に積み重ねられ、階層が単一のビュー コントローラーによって管理されます。 複数の画面を持つアプリケーションには、複数のコンテンツ ビュー階層、それぞれに独自のビュー コントローラー、およびウィンドウ内のアプリケーションの場所のビューがあり、ユーザーに表示される画面に基づいて異なるコンテンツ ビュー階層を作成します。

次の図は、デバイスの画面にユーザー インターフェイスを表示するウィンドウ、ビュー、サブビュー、およびビュー コントローラー間の関係を示しています。

This diagram illustrates the relationships between the Window, Views, Subviews, and View Controller

これらのビュー階層は Xcode のインターフェイス ビルダーを使用して構築できますが、コード内で完全に動作する方法を基本的に理解することをお勧めします。 この記事では、コードのみのユーザー インターフェイス開発を開始して実行するための基本的なポイントについて説明します。

コードのみのプロジェクトの作成

iOS の空のプロジェクト テンプレート

まず、次に示すように、File New Project > Visual C# > i電話 & iPad > iOS App (Xamarin) プロジェクトを使用して>、Visual Studio で iOS プロジェクトを作成します。

New Project Dialog

次に、空のアプリ プロジェクト テンプレートを選択します。

Select a Template Dialog

空のプロジェクト テンプレートは、プロジェクトに 4 つのファイルを追加します。

Project Files

  1. AppDelegate.cs - サブクラスが含まれています UIApplicationDelegate 。サブクラスは、 AppDelegate iOS からのアプリケーション イベントを処理するために使用されます。 アプリケーション ウィンドウは's FinishedLaunching メソッドでAppDelegate作成されます。
  2. Main.cs - アプリケーションのエントリ ポイントを格納します。この AppDelegate エントリ ポイントは、.
  3. Info.plist - アプリケーション構成情報を含むプロパティ リスト ファイル。
  4. Entitlements.plist – アプリケーションの機能とアクセス許可に関する情報を含むプロパティ リスト ファイル。

iOS アプリケーションは MVC パターン使用して構築されます。 アプリケーションが表示する最初の画面は、ウィンドウのルート ビュー コントローラーから作成されます。 MVC パターン自体の 詳細については、Hello, iOS マルチスクリーン ガイドを参照してください。

テンプレートによって追加された実装 AppDelegate では、アプリケーション ウィンドウが作成されます。このウィンドウは、すべての iOS アプリケーションに対して 1 つだけであり、次のコードで表示されます。

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;
    }
}

このアプリケーションを今すぐ実行すると、そのことを示す例外がスローされる可能性があります Application windows are expected to have a root view controller at the end of application launch。 コントローラーを追加し、アプリのルート ビュー コントローラーにしましょう。

コントローラーを追加する

アプリには多数のビュー コントローラーを含めることができますが、すべてのビュー コントローラーを制御するには、1 つのルート ビュー コントローラーが必要です。 インスタンスを作成してプロパティに設定して、コントローラーを UIViewController ウィンドウに Window.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;

        Window.RootViewController = controller;

        // make the window visible
        Window.MakeKeyAndVisible();

        return true;
    }
}

すべてのコントローラーには、プロパティからアクセスできるビューが View 関連付けられています。 上記のコードでは、ビューの BackgroundColor プロパティが UIColor.LightGray 次のように表示されるように変更されます。

The View's background is a visible light gray

UIKit のコントローラーや自分で記述したコントローラーを含め、この方法でサブクラスRootViewControllerを設定UIViewControllerすることもできます。 たとえば、次のコードは次のように a を UINavigationController 追加します 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;
    }
}

これにより、次に示すように、ナビゲーション コントローラー内に入れ子になったコントローラーが生成されます。

The controller nested within the navigation controller

ビュー コントローラーの作成

ウィンドウとして RootViewController コントローラーを追加する方法を見てきたので、コードでカスタム ビュー コントローラーを作成する方法を見てみましょう。

次のような名前 CustomViewController の新しいクラスを追加します。

次に示すように、クラスは名前空間内にあるUIKit継承元である必要がありますUIViewController

using System;
using UIKit;

namespace CodeOnlyDemo
{
    class CustomViewController : UIViewController
    {
    }
}

ビューの初期化

UIViewController には、View コントローラーが最初にメモリに読み込まれるときに呼び出されるメソッド ViewDidLoad が含まれています。 これは、ビューのプロパティの設定など、ビューの初期化を行うのに適した場所です。

たとえば、次のコードは、ボタンが押されたときにナビゲーション スタックに新しいビュー コントローラーをプッシュするボタンとイベント ハンドラーを追加します。

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);

        }
    }
}

このコントローラーをアプリケーションに読み込み、簡単なナビゲーションを示すには、次の CustomViewController新しいインスタンスを作成します。 新しいナビゲーション コントローラーを作成し、ビュー コントローラー インスタンスを渡し、前と同様に新しいナビゲーション コントローラーをウィンドウ RootViewControllerAppDelegate 設定します。

var cvc = new CustomViewController ();

var navController = new UINavigationController (cvc);

Window.RootViewController = navController;

アプリケーションが読み込まれると、 CustomViewController ナビゲーション コントローラー内に読み込まれます。

The CustomViewController is loaded inside a navigation controller

ボタンをクリックすると、新しいビュー コントローラーがナビゲーション スタックにプッシュされます

A new View Controller pushed onto the navigation stack

ビュー階層の構築

上記の例では、ビュー コントローラーにボタンを追加して、コード内にユーザー インターフェイスを作成し始めました。

iOS ユーザー インターフェイスは、ビュー階層で構成されます。 ラベル、ボタン、スライダーなどの追加のビューは、親ビューのサブビューとして追加されます。

たとえば、ユーザーがユーザー名とパスワードを CustomViewController 入力できるログイン画面を作成するために編集しましょう。 画面は、2 つのテキスト フィールドとボタンで構成されます。

テキスト フィールドの追加

最初に、[ビューの初期化] セクションに追加されたボタンとイベント ハンドラーを削除します。

次に示すように、ユーザー名のコントロールを作成して初期化 UITextField し、ビュー階層に追加することで、ユーザー名のコントロールを追加します。

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);
    }
}

を作成 UITextFieldするときに、プロパティを Frame 設定して、その場所とサイズを定義します。 iOS では、0,0 座標は左上にあり、+x は右に、+y は下にあります。 他のいくつかのプロパティと共にFrame設定した後、ビュー階層に追加UITextFieldするために呼び出View.AddSubviewします。 これにより、プロパティが usernameField 参照するインスタンスの UIView サブビューが View 作成されます。 サブビューは、親ビューより高い z オーダーで追加されるため、画面上の親ビューの前に表示されます。

含まれているアプリケーションを UITextField 次に示します。

The application with the UITextField included

次に示すように、同様の方法で for パスワードを追加 UITextField できます。今回は、プロパティを SecureTextEntry true に設定します。

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);
   }
}

次に示すように、ユーザーが入力したUITextFieldテキストを非表示SecureTextEntry = trueにします。

Setting SecureTextEntry true hides the text entered by the user

ボタンの追加

次に、ユーザーがユーザー名とパスワードを送信できるようにボタンを追加します。 ボタンは、他のコントロールと同様に、親ビューの AddSubview メソッドに引数として渡すことによって、ビュー階層に追加されます。

次のコードは、ボタンを追加し、イベントのイベント ハンドラーを 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);

これで、ログイン画面が次のように表示されます。

The login screen

以前のバージョンの iOS とは異なり、既定のボタンの背景は透明です。 ボタンのプロパティを変更すると、次の BackgroundColor 変更が行われます。

submitButton.BackgroundColor = UIColor.White;

これにより、一般的な丸い端付きボタンではなく、正方形のボタンが生成されます。 丸められたエッジを取得するには、次のスニペットを使用します。

submitButton.Layer.CornerRadius = 5f;

これらの変更により、ビューは次のようになります。

An example run of the view

ビュー階層への複数のビューの追加

iOS には、複数のビューを使用 AddSubviewsしてビュー階層に追加する機能が用意されています。

View.AddSubviews(new UIView[] { usernameField, passwordField, submitButton });

ボタン機能の追加

ボタンがクリックされると、ユーザーは何かが起こることを期待します。 たとえば、アラートが表示されたり、別の画面にナビゲーションが実行されたりします。

ナビゲーション スタックに 2 つ目のビュー コントローラーをプッシュするコードを追加してみましょう。

最初に、2 つ目のビュー コントローラーを作成します。

var loginVC = new UIViewController () { Title = "Login Success!"};
loginVC.View.BackgroundColor = UIColor.Purple;

次に、イベントに機能を TouchUpInside 追加します。

submitButton.TouchUpInside += (sender, e) => {
                this.NavigationController.PushViewController (loginVC, true);
            };

ナビゲーションを次に示します。

The navigation is illustrated in this chart

既定では、ナビゲーション コントローラーを使用すると、iOS によってアプリケーションにナビゲーション バーと戻るボタンが表示され、スタック内を戻ることができます。

ビュー階層の反復処理

サブビュー階層を反復処理し、特定のビューを選択することができます。 たとえば、それぞれ UIButton を検索し、そのボタンに別 BackgroundColorのボタンを付けるために、次のスニペットを使用できます。

foreach(var subview in View.Subviews)
{
    if (subview is UIButton)
    {
         var btn = subview as UIButton;
         btn.BackgroundColor = UIColor.Green;
    }
}

ただし、これは、すべてのビューが親ビューに追加されたオブジェクト自体がUIView継承UIViewするように戻ってくるのUIViewで、反復処理対象のビューがaである場合は機能しません。

回転の処理

次のスクリーンショットに示すように、ユーザーがデバイスを横向きに回転させる場合、コントロールのサイズは適切に変更されません。

If the user rotates the device to landscape, the controls do not resize appropriately

これを修正する 1 つの方法は、各ビューでプロパティを AutoresizingMask 設定する方法です。 この場合、コントロールを水平方向に拡大し、それぞれ AutoresizingMaskを設定します。 次の例は for usernameFieldですが、ビュー階層内の各ガジェットにも同じ値を適用する必要があります。

usernameField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;

次に示すように、デバイスまたはシミュレーターを回転させると、すべてが拡張され、追加の領域が埋まるようにします。

All the controls stretch to fill the additional space

カスタム ビューの作成

UIKit の一部であるコントロールを使用するだけでなく、カスタム ビューを使用することもできます。 カスタム ビューは、継承 UIView とオーバーライド Drawによって作成できます。 カスタム ビューを作成し、それをビュー階層に追加してデモを行いましょう。

UIView からの継承

最初に行う必要があるのは、カスタム ビューのクラスを作成することです。 これを行うには、Visual Studio のクラス テンプレートを使用して、という名前CircleViewの空のクラスを追加します。 基底クラスを設定する UIView必要があります。これは、名前空間内に存在することを思い出します UIKit 。 名前空間も必要 System.Drawing になります。 この例では他 System.* のさまざまな名前空間は使用されないため、自由に削除してください。

クラスは次のようになります。

using System;

namespace CodeOnlyDemo
{
    class CircleView : UIView
    {
    }
}

UIView での描画

すべての UIView メソッドには、 Draw 描画する必要があるときにシステムによって呼び出されるメソッドがあります。 Draw を直接呼び出すべきではありません。 これは、実行ループ処理中にシステムによって呼び出されます。 ビューがビュー階層に追加された後、実行ループを初めて実行すると、その Draw メソッドが呼び出されます。 後続のDraw呼び出しは、ビューを呼び出すかビューで描画SetNeedsDisplaySetNeedsDisplayInRectする必要があるとしてマークされている場合に発生します。

次に示すように、オーバーライドされた Draw メソッド内にこのようなコードを追加することで、ビューに描画コードを追加できます。

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);
    }
}

そのためCircleViewUIView、プロパティも設定UIViewできます。 たとえば、コンストラクターで次の値を BackgroundColor 設定できます。

public CircleView()
{
    BackgroundColor = UIColor.White;
}

先ほど作成したビューをCircleView使用するには、以前と同様UILabelsUIButtonに、既存のコントローラーのビュー階層にサブビューとして追加するか、新しいコントローラーのビューとして読み込むことができます。 後者を実行してみましょう。

ビューの読み込み

UIViewController には、ビューを作成するためにコントローラーによって呼び出される名前の LoadView メソッドがあります。 これは、ビューを作成してコントローラーの View プロパティに割り当てるのに適した場所です。

まず、コントローラーが必要なので、という名前 CircleControllerの新しい空のクラスを作成します。

CircleControllerのコードを追加してaにCircleView設定Viewします(オーバーライドで実装をbase呼び出すべきではありません)。

using UIKit;

namespace CodeOnlyDemo
{
    class CircleController : UIViewController
    {
        CircleView view;

        public override void LoadView()
        {
            view = new CircleView();
            View = view;
        }
    }
}

最後に、実行時にコントローラーを提示する必要があります。 これを行うには、前に追加した送信ボタンに次のようにイベント ハンドラーを追加します。

submitButton.TouchUpInside += delegate
{
    Console.WriteLine("Submit button clicked");

    //circleController is declared as class variable
    circleController = new CircleController();
    PresentViewController(circleController, true, null);
};

アプリケーションを実行して送信ボタンをタップすると、新しいビューに円が表示されます。

The new view with a circle is displayed

起動画面の作成

アプリの起動時に起動画面が表示され、応答していることをユーザーに表示できます。 起動画面はアプリの読み込み時に表示されるため、アプリケーションがまだメモリに読み込まれているため、コード内に作成することはできません。

Visual Studio で iOS プロジェクトを作成すると、プロジェクト内の Resources フォルダーにある .xib ファイルの形式で起動画面が表示されます。

これを編集するには、ダブルクリックして Xcode インターフェイス ビルダーで開きます。

iOS 8 以降をターゲットとするアプリケーションには .xib またはストーリーボード ファイルを使用することをお勧めします。Xcode インターフェイス ビルダーでいずれかのファイルを起動すると、サイズ クラスと自動レイアウトを使用して、すべてのデバイス サイズに対して適切に表示されるようにレイアウトを調整できます。 静的起動イメージは、.xib または Storyboard に加えて使用して、以前のバージョンを対象とするアプリケーションのサポートを可能にすることができます。

起動画面の作成の詳細については、以下のドキュメントを参照してください。

重要

iOS 9 の時点で、Apple では、起動画面を作成する主な方法としてストーリーボードを使用することをお勧めします。

iOS 8 より前のアプリケーションの起動イメージの作成

アプリケーションが iOS 8 より前のバージョンを対象とする場合は、.xib またはストーリーボードの起動画面に加えて静的イメージを使用できます。

この静的イメージは、Info.plist ファイルで設定することも、アプリケーションのアセット カタログ (iOS 7 の場合) として設定することもできます。 アプリケーションを実行できるデバイス サイズ (320 x 480、640x960、640x1136) ごとに個別のイメージを指定する必要があります。 起動画面のサイズの詳細については、「画面イメージの起動」ガイドを参照してください。

重要

アプリに起動画面がない場合は、画面に完全に収まらないことがあります。 この場合は、少なくとも Info.plist に名前が付けられた Default-568@2x.png 640 x 1136 イメージを含めるようにしてください。

まとめ

この記事では、Visual Studio で iOS アプリケーションをプログラムで開発する方法について説明しました。 空のプロジェクト テンプレートからプロジェクトをビルドする方法について説明し、ルート ビュー コントローラーを作成してウィンドウに追加する方法について説明しました。 次に、UIKit のコントロールを使用して、コントローラー内にビュー階層を作成し、アプリケーション画面を開発する方法について説明しました。 次に、ビューをさまざまな向きで適切にレイアウトする方法と、サブクラス化 UIViewしてカスタム ビューを作成する方法、およびコントローラー内でビューを読み込む方法を確認しました。 最後に、アプリケーションに起動画面を追加する方法について説明しました。