iOS Designer でのカスタム コントロールの使用

警告

iOS Designer は、Visual Studio 2019 バージョン 16.8 および Visual Studio 2019 for Mac バージョン 8.8 で非推奨とされ、Visual Studio 2019 バージョン 16.9 および Visual Studio for Mac バージョン 8.9 から削除されています。 iOS ユーザー インターフェイスを構築する推奨される方法は、Xcode を実行している Mac 上で直接行う方法です。 詳細については、「Xcode を使用したユーザーインターフェイスの設計」を参照してください。

必要条件

iOS 用 Xamarin Designerは、Windows 上の Visual Studio for Mac および Visual Studio 2017 以降で使用できます。

このガイドでは、はじめに ガイドで説明されている内容を理解していることを前提としています。

チュートリアル

重要

Xamarin.Studio 5.5 以降では、カスタム コントロールを作成する方法は、以前のバージョンとは若干異なります。 カスタム コントロールを作成するには、 IComponent インターフェイスが必要か (関連する実装メソッドを使用)、または クラスに で注釈を付 [DesignTimeVisible(true)]けることができます。 後者のメソッドは、次のチュートリアルの例で使用されています。

  1. iOS > App > Single View Application > C# テンプレートから新しいソリューションを作成し、名前を付けてScratchTicket、新しいプロジェクト ウィザードを続行します。

    新しいソリューションの作成

  2. という名前 ScratchTicketViewの新しい空のクラス ファイルを作成します。

    新しい ScratchTicketView クラスを作成する

  3. クラスに次のコードを ScratchTicketView 追加します。

    using System;
    using System.ComponentModel;
    using CoreGraphics;
    using Foundation;
    using UIKit;
    
    namespace ScratchTicket
    {
        [Register("ScratchTicketView"), DesignTimeVisible(true)]
        public class ScratchTicketView : UIView
        {
            CGPath path;
            CGPoint initialPoint;
            CGPoint latestPoint;
            bool startNewPath = false;
            UIImage image;
    
            [Export("Image"), Browsable(true)]
            public UIImage Image
            {
                get { return image; }
                set
                {
                    image = value;
                    SetNeedsDisplay();
                }
            }
    
            public ScratchTicketView(IntPtr p)
                : base(p)
            {
                Initialize();
            }
    
            public ScratchTicketView()
            {
                Initialize();
            }
    
            void Initialize()
            {
                initialPoint = CGPoint.Empty;
                latestPoint = CGPoint.Empty;
                BackgroundColor = UIColor.Clear;
                Opaque = false;
                path = new CGPath();
                SetNeedsDisplay();
            }
    
            public override void TouchesBegan(NSSet touches, UIEvent evt)
            {
                base.TouchesBegan(touches, evt);
    
                var touch = touches.AnyObject as UITouch;
    
                if (touch != null)
                {
                    initialPoint = touch.LocationInView(this);
                }
            }
    
            public override void TouchesMoved(NSSet touches, UIEvent evt)
            {
                base.TouchesMoved(touches, evt);
    
                var touch = touches.AnyObject as UITouch;
    
                if (touch != null)
                {
                    latestPoint = touch.LocationInView(this);
                    SetNeedsDisplay();
                }
            }
    
            public override void TouchesEnded(NSSet touches, UIEvent evt)
            {
                base.TouchesEnded(touches, evt);
                startNewPath = true;
            }
    
            public override void Draw(CGRect rect)
            {
                base.Draw(rect);
    
                using (var g = UIGraphics.GetCurrentContext())
                {
                    if (image != null)
                        g.SetFillColor((UIColor.FromPatternImage(image).CGColor));
                    else
                        g.SetFillColor(UIColor.LightGray.CGColor);
                    g.FillRect(rect);
    
                    if (!initialPoint.IsEmpty)
                    {
                        g.SetLineWidth(20);
                        g.SetBlendMode(CGBlendMode.Clear);
                        UIColor.Clear.SetColor();
    
                        if (path.IsEmpty || startNewPath)
                        {
                            path.AddLines(new CGPoint[] { initialPoint, latestPoint });
                            startNewPath = false;
                        }
                        else
                        {
                            path.AddLineToPoint(latestPoint);
                        }
    
                        g.SetLineCap(CGLineCap.Round);
                        g.AddPath(path);
                        g.DrawPath(CGPathDrawingMode.Stroke);
                    }
                }
            }
        }
    }
    
  4. 、、および Monkey.png ファイル (GitHub から利用可能) を Resources フォルダーに追加します。FillTexture.pngFillTexture2.png

  5. ファイルを Main.storyboard ダブルクリックしてデザイナーで開きます。

    iOS Designer

  6. イメージ ビューツールボックスからストーリーボードのビューにドラッグ アンド ドロップします。

    レイアウトに追加されたイメージ ビュー

  7. [イメージ ビュー] を選択し、その Image プロパティを にMonkey.png変更します。

    Image View Image プロパティを Monkey.pngに設定する

  8. サイズ クラスを使用している場合は、このイメージ ビューを制限する必要があります。 イメージを 2 回クリックして制約モードにします。 中央固定ハンドルをクリックして中央に制限し、垂直方向と水平方向の両方に揃えます。

    画像の中央揃え

  9. 高さと幅を制限するには、サイズ固定ハンドル ("ボーン" の形をしたハンドル) をクリックし、それぞれ幅と高さを選択します。

    制約の追加

  10. ツールバーの [更新] ボタンをクリックして、制約に基づいてフレームを更新します。

    [制約] ツール バー

  11. 次に、ツールボックスの [カスタム コンポーネント] の下にスクラッチ チケット ビューが表示されるようにプロジェクトをビルドします。

    [カスタム コンポーネント] ツールボックス

  12. スクラッチ チケット ビューをドラッグ アンド ドロップして、サルの画像の上に表示されるようにします。 次に示すように、スクラッチ チケット ビューがサルを完全にカバーするようにドラッグ ハンドルを調整します。

    イメージ ビューのスクラッチ チケット ビュー

  13. 外接する四角形を描画して両方のビューを選択して、スクラッチ チケット ビューをイメージ ビューに制限します。 次に示すように、幅、高さ、中央、中央に制限し、制約に基づいてフレームを更新するオプションを選択します。

    制約の中央揃えと追加

  14. アプリケーションを実行し、画像を "スクラッチオフ" してサルを明らかにします。

    サンプル アプリの実行

Design-Timeプロパティの追加

デザイナーには、プロパティ型の数値、列挙、文字列、bool、CGSize、UIColor、UIImage のカスタム コントロールに対するデザイン時のサポートも含まれています。 デモを行うために、 に プロパティを追加して ScratchTicketView 、"スクラッチオフ" されたイメージを設定してみましょう。

プロパティの クラスに次の ScratchTicketView コードを追加します。

[Export("Image"), Browsable(true)]
public UIImage Image
{
    get { return image; }
    set {
            image = value;
              SetNeedsDisplay ();
        }
}

次のように、 メソッドに null チェックをDraw追加することもできます。

public override void Draw(CGRect rect)
{
    base.Draw(rect);

    using (var g = UIGraphics.GetCurrentContext())
    {
        if (image != null)
            g.SetFillColor ((UIColor.FromPatternImage (image).CGColor));
        else
            g.SetFillColor (UIColor.LightGray.CGColor);

        g.FillRect(rect);

        if (!initialPoint.IsEmpty)
        {
             g.SetLineWidth(20);
             g.SetBlendMode(CGBlendMode.Clear);
             UIColor.Clear.SetColor();

             if (path.IsEmpty || startNewPath)
             {
                 path.AddLines(new CGPoint[] { initialPoint, latestPoint });
                 startNewPath = false;
             }
             else
             {
                 path.AddLineToPoint(latestPoint);
             }

             g.SetLineCap(CGLineCap.Round);
             g.AddPath(path);
             g.DrawPath(CGPathDrawingMode.Stroke);
        }
    }
}

引数が にtrue設定された と を含めると、デザイナーの [プロパティ] パネルに プロパティが表示されます。ExportAttributeBrowsableAttribute プロパティを プロジェクトに含まれる別のイメージ (など FillTexture2.png) に変更すると、次に示すように、コントロールはデザイン時に更新されます。

デザイン時プロパティの編集

まとめ

この記事では、カスタム コントロールを作成し、iOS デザイナーを使用して iOS アプリケーションで使用する方法について説明しました。 デザイナーの ツールボックスでアプリケーションで使用できるように、コントロールを作成してビルドする方法について説明しました。 さらに、デザイン時と実行時の両方で適切にレンダリングされるようにコントロールを実装する方法と、デザイナーでカスタム コントロール プロパティを公開する方法についても説明しました。