個人的なメモ 〜Cocos Sharp 情報を中心に‥

Tomohiro Suzuki @hiro128_777 のブログです。Cocos Sharp の事を中心に書いています。 Microsoft MVP for Visual Studio and Development Technologies 2017- 本ブログと所属組織の公式見解は関係ございません。

Swift, Objective-C を Xamarin.iOS に移植する際のポイント(3) storyboard の Xamarin.iOS C#コードへの移植方法

はじめに

こんにちは、@hiro128_777です。

12月9日(土)に、大阪でXamarin.iOS のハンズオンを開催いたします!

Xcode での開発経験がない方が、iOS の開発を Xamarin で始めてWebで情報を集めると、 Swift や Objective-C の情報はたくさん見つかりますが、Xamarin の情報は案外少ないことに気づきます。
そして、Swift や Objective-C のサンプルコードを見て、Xamarin に移植する必要が出てきますが、これは Xcode での開発経験がないと結構骨が折れる作業です。
そこで今回、Swift, Objective-C のコードを Xamarin.iOS に移植する際のポイントについてハンズオンを行うことにいたしましたので、ご興味がある方はぜひご参加下さい!

jxug.connpass.com


前回は、UIViewのLayerの差し替えについてご説明しました。

hiro128.hatenablog.jp

今回のお話はUIについてです。Xamarin.iOS では、UIについては storyboard をそのまま利用できます。ですが、実際にアプリを開発すると、storyboard だけで完結するのはなかなか難しく、どうしてもコードでUIを記述する場面が出てきてしまいます。

ところが、Xamarin.iOSでUIをコードで作成する方法の情報は非常に少ないです。そこで、今回は、storyboard の C#コードへの移植方法についてご説明します。

今回もApple公式の写真撮影のサンプルアプリを題材にします。

以下よりサンプルコードをダウンロードして下さい。
https://developer.apple.com/library/content/samplecode/AVCam/Introduction/Intro.htmldeveloper.apple.com

その中の、Main.storyboardファイルのコードを見てみましょう。

では早速移植していきましょう。

UIエレメントを割り当てるフィールドを追加

CameraViewController.csを作成し、UIエレメントを割り当てるフィールドを追加します。

C#

public class CameraViewController : UIViewController, IAVCaptureFileOutputRecordingDelegate
{
	PreviewView PreviewView { get; set; }
	UILabel CameraUnavailableLabel { get; set; }
	UIButton ResumeButton { get; set; }
	UIButton RecordButton { get; set; }
	UIButton CameraButton { get; set; }
	UIButton PhotoButton { get; set; }
	UIButton LivePhotoModeButton { get; set; }
	UISegmentedControl CaptureModeControl { get; set; }
	UILabel CapturingLivePhotoLabel { get; set; }
}

UIエレメントを構築するメソッドを追加

UIを構築するメソッドを作成します。

C#

private void InitUI()
{
}
View

Main.storyboard 15行目~18行目のViewに関する設定を移植します。

storyboard

<viewController id="BYZ-38-t0r" customClass="CameraViewController" customModule="AVCam" customModuleProvider="target" sceneMemberID="viewController">
    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>

C#

private void InitUI()
{
	View.ContentMode = UIViewContentMode.ScaleToFill;
	View.Frame = new CGRect(0, 0, 375, 667);
	View.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
}
CameraUnavailableLabel

Main.storyboard 28行目~34行目のCameraUnavailableLabelに関する設定を移植します。

storyboard

<label hidden="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Camera Unavailable" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="zf0-db-esM" userLabel="Camera Unavailable">
    <rect key="frame" x="83.5" y="319" width="208" height="29"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="24"/>
    <color key="textColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    <nil key="highlightedColor"/>
</label>

xmlの各attributeに対応したプロパティを見つけ出し、設定していきます。IntelliSenseをうまく使えば簡単に見つけることができます。

例えばhidden="YES"なら、Hidden = trueuserInteractionEnabled="NO"ならUserInteractionEnabled = falseといった要領です。

わかりにくいプロパティはcolor関係とfontですが、それぞれ、colorはpublic static UIColor FromRGBA(nfloat red, nfloat green, nfloat blue, nfloat alpha);、fontはpublic static UIFont SystemFontOfSize(nfloat size);となります。

全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

CameraUnavailableLabel = new UILabel
{
	Frame = new CGRect(83.5, 319, 208, 29),
	Hidden = true,
	UserInteractionEnabled = false,
	ContentMode = UIViewContentMode.Left,
	Text = "Camera Unavailable",
	TextAlignment = UITextAlignment.Center,
	LineBreakMode = UILineBreakMode.TailTruncation,
	Lines = 0,
	BaselineAdjustment = UIBaselineAdjustment.AlignBaselines,
	AdjustsFontSizeToFitWidth = false,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 1.0f),
	Font = UIFont.SystemFontOfSize(24f),
	TextColor = UIColor.FromRGBA(1.0f, 1.0f, 0.0f, 1.0f),
};
View.AddSubview(CameraUnavailableLabel);

では、同じ要領で他のUIエレメントも追加していきましょう。

PreviewView

Main.storyboard 20行目~27行目のPreviewViewに関する設定を移植します。

storyboard

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3eR-Rn-XpZ" userLabel="Preview" customClass="PreviewView" customModule="AVCam" customModuleProvider="target">
    <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    <gestureRecognizers/>
    <connections>
        <outletCollection property="gestureRecognizers" destination="fY6-qX-ntV" appends="YES" id="G6D-dx-xU8"/>
    </connections>
</view>

InitUI()の先ほど追加したコードの下に以下を追加します。

C#

PreviewView = new PreviewView
{
	Frame = new CGRect(0, 0, 375, 667),
	ContentMode = UIViewContentMode.ScaleToFill,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 1f),
};
View.AddSubview(PreviewView);
PhotoButton

Main.storyboard 68行目~87行目のPhotoButtonに関する設定を移植します。

storyboard

<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="uCj-6P-mHF" userLabel="Photo">
    <rect key="frame" x="147.5" y="617" width="80" height="30"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <constraints>
        <constraint firstAttribute="height" constant="30" id="NtC-UN-gTs"/>
        <constraint firstAttribute="width" constant="80" id="dxU-UP-4Ae"/>
    </constraints>
    <fontDescription key="fontDescription" type="system" pointSize="20"/>
    <state key="normal" title="Photo">
        <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    </state>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
    <connections>
        <action selector="capturePhoto:" destination="BYZ-38-t0r" eventType="touchUpInside" id="o5K-SC-fYn"/>
    </connections>
</button>

わかりにくい箇所をご説明しますと、
buttonType="roundedRect"はXamarin.iOSではコンストラクタでの設定となり、PhotoButton = new UIButton(UIButtonType.RoundedRect)となります。
Viewに設定した仮想解像度、幅:375, 高さ:667に対し、PhotoButtonの高さを30に設定しなさいという制約です。
これは、Xamarin.iOSではNSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1.0f, 30)となります。
widthも同じ要領で設定できます。

storyboard

<action selector="capturePhoto:" destination="BYZ-38-t0r" eventType="touchUpInside" id="o5K-SC-fYn"/>

はイベントハンドラの設定です。

CameraViewController.swiftの521行目を確認すると

Swift

@IBAction private func capturePhoto(_ photoButton: UIButton) {

とありますので、これがイベントハンドラです。Xamarin.iOSではイベントが準備されていますので、C#側のハンドラメソッドをCapturePhoto()のように作成し、設定すれば大丈夫です。

全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

PhotoButton = new UIButton(UIButtonType.RoundedRect)
{
	Frame = new CGRect(147.5, 617, 80, 30),
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
	VerticalAlignment = UIControlContentVerticalAlignment.Center,
	LineBreakMode = UILineBreakMode.MiddleTruncation,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(20f),
};

PhotoButton.SetTitle("Photo", UIControlState.Normal);
PhotoButton.SetTitleShadowColor(UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 1.0f), UIControlState.Normal);
PhotoButton.Layer.CornerRadius = 4f;
PhotoButton.TouchUpInside += (s, e) => CapturePhoto();
PhotoButton.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1.0f, 30));
PhotoButton.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1.0f, 80));
View.AddSubview(PhotoButton);
CameraButton

Main.storyboard 88行目~103行目のCameraButtonに関する設定を移植します。

storyboard

<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="rUJ-G6-RPv" userLabel="Camera">
    <rect key="frame" x="247.5" y="617" width="80" height="30"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="20"/>
    <state key="normal" title="Camera">
        <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    </state>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
    <connections>
        <action selector="changeCamera:" destination="BYZ-38-t0r" eventType="touchUpInside" id="3W0-h3-6fc"/>
    </connections>
</button>


全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

CameraButton = new UIButton(UIButtonType.RoundedRect)
{
	Frame = new CGRect(147.5, 617, 80, 30),
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
	VerticalAlignment = UIControlContentVerticalAlignment.Center,
	LineBreakMode = UILineBreakMode.MiddleTruncation,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(20f),
};

CameraButton.SetTitle("Camera", UIControlState.Normal);
CameraButton.SetTitleShadowColor(UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 1.0f), UIControlState.Normal);
CameraButton.Layer.CornerRadius = 4f;
CameraButton.TouchUpInside += (s, e) => ChangeCamera();
View.AddSubview(CameraButton);
RecordButton

Main.storyboard 52行目~67行目のRecordButtonに関する設定を移植します。

storyboard

<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eRT-dK-6dM" userLabel="Record">
    <rect key="frame" x="47.5" y="617" width="80" height="30"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="20"/>
    <state key="normal" title="Record">
        <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    </state>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
    <connections>
        <action selector="toggleMovieRecording:" destination="BYZ-38-t0r" eventType="touchUpInside" id="9R7-Ok-FpB"/>
    </connections>
</button>


全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

RecordButton = new UIButton(UIButtonType.RoundedRect)
{
	Frame = new CGRect(47.5, 617, 80, 30),
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
	VerticalAlignment = UIControlContentVerticalAlignment.Center,
	LineBreakMode = UILineBreakMode.MiddleTruncation,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(20f),
};

RecordButton.SetTitle("Record", UIControlState.Normal);
RecordButton.SetTitleShadowColor(UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 1f), UIControlState.Normal);
RecordButton.Layer.CornerRadius = 4f;
RecordButton.TouchUpInside += (s, e) => ToggleMovieRecording();
View.AddSubview(RecordButton);
ResumeButton

Main.storyboard 35行目~51行目のResumeButtonに関する設定を移植します。

storyboard

<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="FZr-Ip-7WL" userLabel="Resume">
    <rect key="frame" x="105" y="314" width="165" height="39"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="24"/>
    <inset key="contentEdgeInsets" minX="10" minY="5" maxX="10" maxY="5"/>
    <state key="normal" title="Tap to resume">
        <color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    </state>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
    <connections>
        <action selector="resumeInterruptedSession:" destination="BYZ-38-t0r" eventType="touchUpInside" id="42K-1B-qJd"/>
    </connections>
</button>


全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

ResumeButton = new UIButton(UIButtonType.RoundedRect)
{
	Frame = new CGRect(105, 314, 165, 39),
	Hidden = true,
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
	VerticalAlignment = UIControlContentVerticalAlignment.Center,
	LineBreakMode = UILineBreakMode.MiddleTruncation,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(24f),
};
ResumeButton.SetTitle("Tap to resume", UIControlState.Normal);
ResumeButton.SetTitleShadowColor(UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 1f), UIControlState.Normal);
ResumeButton.Layer.CornerRadius = 4f;
ResumeButton.TouchUpInside += (s, e) => ResumeInterruptedSession();
View.AddSubview(ResumeButton);
CaptureModeControl

Main.storyboard 104行目~113行目のCaptureModeControlに関する設定を移植します。

今度はSegmentedControlですが、要領は同じです。

storyboard

<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" translatesAutoresizingMaskIntoConstraints="NO" id="FAC-co-10c" userLabel="Capture Mode">
    <rect key="frame" x="136" y="569" width="103" height="29"/>
    <segments>
        <segment title="Photo"/>
        <segment title="Movie"/>
    </segments>
    <connections>
        <action selector="toggleCaptureMode:" destination="BYZ-38-t0r" eventType="valueChanged" id="SKd-67-ZHh"/>
    </connections>
</segmentedControl>


ちょっとわかりにくい箇所としては、

<segments>
    <segment title="Photo"/>
    <segment title="Movie"/>
</segments>
```

の部分は、<code>InsertSegment</code>メソッドが準備されているので、それを使うと以下のようになります。

C#
>|cs|
CaptureModeControl.InsertSegment("Photo", 0, true);
CaptureModeControl.InsertSegment("Movie", 1, true);

このあたりのコンストラクタ引数なのか、プロパティなのか、メソッドなのかというさじ加減も慣れると迷わなくなります。

全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。

C#

CaptureModeControl = new UISegmentedControl
{
	Frame = new CGRect(136, 569, 103, 29),
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Left,
	ControlStyle = UISegmentedControlStyle.Plain,
	VerticalAlignment = UIControlContentVerticalAlignment.Top,
	TranslatesAutoresizingMaskIntoConstraints = false,
};
CaptureModeControl.InsertSegment("Photo", 0, true);
CaptureModeControl.InsertSegment("Movie", 1, true);
CaptureModeControl.SelectedSegment = 0;
CaptureModeControl.ValueChanged += (s, e) => ToggleCaptureMode();
View.AddSubview(CaptureModeControl);
LivePhotoModeButton

Main.storyboard 130行目~146行目のLivePhotoModeButtonに関する設定を移植します。

storyboard

<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eI6-gV-W7d" userLabel="Live Photo Mode">
    <rect key="frame" x="96.5" y="41" width="182" height="25"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <constraints>
        <constraint firstAttribute="height" constant="25" id="om7-Gh-HVl"/>
    </constraints>
    <fontDescription key="fontDescription" type="system" pointSize="20"/>
    <state key="normal" title="Live Photo Mode: On"/>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
    <connections>
        <action selector="toggleLivePhotoMode:" destination="BYZ-38-t0r" eventType="touchUpInside" id="JqX-wJ-Xf1"/>
    </connections>
</button>


全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。


C#

LivePhotoModeButton = new UIButton(UIButtonType.RoundedRect)
{
	Frame = new CGRect(96.5, 41, 182, 25),
	Opaque = false,
	ContentMode = UIViewContentMode.ScaleToFill,
	HorizontalAlignment = UIControlContentHorizontalAlignment.Center,
	VerticalAlignment = UIControlContentVerticalAlignment.Center,
	LineBreakMode = UILineBreakMode.MiddleTruncation,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(20f),
};

LivePhotoModeButton.SetTitle("Live Photo Mode: On", UIControlState.Normal);
LivePhotoModeButton.SetTitleShadowColor(UIColor.FromRGBA(0.5f, 0.5f, 0.5f, 1f), UIControlState.Normal);
LivePhotoModeButton.Layer.CornerRadius = 4f;
LivePhotoModeButton.TouchUpInside += (s, e) => ToggleLivePhotoMode();

LivePhotoModeButton.AddConstraint(NSLayoutConstraint.Create(LivePhotoModeButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1.0f, 25));

View.AddSubview(LivePhotoModeButton);
CapturingLivePhotoLabel

Main.storyboard 147行目~158行目のLivePhotoModeButtonに関する設定を移植します。

storyboard

<label hidden="YES" opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Live" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Pii-2r-R2l" userLabel="Capturing Live Photo">
    <rect key="frame" x="172" y="74" width="31" height="20.5"/>
    <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.29999999999999999" colorSpace="custom" customColorSpace="sRGB"/>
    <fontDescription key="fontDescription" type="system" pointSize="17"/>
    <color key="textColor" red="1" green="1" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
    <nil key="highlightedColor"/>
    <userDefinedRuntimeAttributes>
        <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
            <integer key="value" value="4"/>
        </userDefinedRuntimeAttribute>
    </userDefinedRuntimeAttributes>
</label>


全部移植すると以下のようになりますので、InitUI()の先ほど追加したコードの下に以下を追加します。


C#

CapturingLivePhotoLabel = new UILabel
{
	Frame = new CGRect(172, 74, 31, 20.5),
	Hidden = true,
	Opaque = false,
	UserInteractionEnabled = false,
	ContentMode = UIViewContentMode.Left,
	Text = "Live",
	TextAlignment = UITextAlignment.Center,
	LineBreakMode = UILineBreakMode.TailTruncation,
	Lines = 0,
	BaselineAdjustment = UIBaselineAdjustment.AlignBaselines,
	AdjustsFontSizeToFitWidth = false,
	TranslatesAutoresizingMaskIntoConstraints = false,
	BackgroundColor = UIColor.FromRGBA(0.0f, 0.0f, 0.0f, 0.3f),
	Font = UIFont.SystemFontOfSize(17f),
	TextColor = UIColor.FromRGBA(1.0f, 1.0f, 0.0f, 1.0f),
};

CapturingLivePhotoLabel.Layer.CornerRadius = 4f;

CapturingLivePhotoLabel.AddConstraint(NSLayoutConstraint.Create(CapturingLivePhotoLabel, NSLayoutAttribute.Height, NSLayoutRelation.Equal, 1.0f, 25));
CapturingLivePhotoLabel.AddConstraint(NSLayoutConstraint.Create(CapturingLivePhotoLabel, NSLayoutAttribute.Width, NSLayoutRelation.Equal, 1.0f, 40));

View.AddSubview(CapturingLivePhotoLabel);

これでUIエレメントの移植が完了しました。

今回はここまでです。