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

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

Swift, Objective-C を Xamarin.iOS に移植する際のポイント(4) 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


前回は、storyboard のUIエレメントの C#コードへの移植方についてご説明しました。

hiro128.hatenablog.jp

そこで、今回は、UIエレメントよりもさらに情報の少ない storyboard の制約のC#コードへの移植方法についてご説明します。

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

以下よりサンプルコードをダウンロードして下さい。
developer.apple.com

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

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

制約の移植

個別のUIエレメント内で完結する制約はUIエレメントを生成する箇所に記載していますので、ここでは、複数のUIエレメントの関係性の制約を移植します。

複数のUIエレメントの関係性の制約はMain.storyboardの161行目~188行目に記述されています。

1つ目の制約を見てみましょう。

<constraint firstItem="3eR-Rn-XpZ" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="125-kC-WZF"/>

firstItem, secondItemにそれぞれ文字列が入っていますが、これはそれぞれ特定のUIエレメントを指し示しています。

firstItem3eR-Rn-XpZを検索すると、20行目に、id="3eR-Rn-XpZ"とあります。

<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="3eR-Rn-XpZ" userLabel="Preview" customClass="PreviewView" customModule="AVCam" customModuleProvider="target">

よって3eR-Rn-XpZPreviewViewを指し示しています。

同様にsecondItemnyU-fN-aJhを検索すると、189行目に、id="nyU-fN-aJh"とあります。

<viewLayoutGuide key="safeArea" id="nyU-fN-aJh"/>

safeAreaとはiPhone Xを考慮した上下左右のマージンを取った領域です。今回はiOS10対応の移植なので、centerXつまり、左右の中心点を考える上では、Viewと同じ領域と考えて差し支えありません。

よってidをUIエレメントに置き換えて記述すると、以下のようになります。

C#

View.AddConstraint(NSLayoutConstraint.Create(PreviewView, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0));



同様にその他の制約を移植すると以下のようになります。
※一部制約変更しています。



元のstoryboardの制約

<constraint firstItem="eI6-gV-W7d" firstAttribute="top" secondItem="9i1-NX-Qxg" secondAttribute="bottom" constant="8" id="6iA-0j-auu"/> /* iOS10対応のため変更あり */
<constraint firstItem="eI6-gV-W7d" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="ACB-oH-2jU"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="height" secondItem="eRT-dK-6dM" secondAttribute="height" id="AEV-ew-H4g"/>
<constraint firstItem="Pii-2r-R2l" firstAttribute="top" secondItem="eI6-gV-W7d" secondAttribute="bottom" constant="8" id="B43-ME-uK5"/>
<constraint firstItem="3eR-Rn-XpZ" firstAttribute="height" secondItem="8bC-Xf-vdC" secondAttribute="height" id="Ice-47-M9N"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="top" secondItem="rUJ-G6-RPv" secondAttribute="top" id="NFm-e8-abT"/>
<constraint firstItem="FZr-Ip-7WL" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="OaZ-uO-vXY"/>
<constraint firstItem="FAC-co-10c" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="Oow-A6-mDp"/>
<constraint firstItem="9i1-NX-Qxg" firstAttribute="top" secondItem="8bC-Xf-vdC" secondAttribute="top" constant="8" id="PNv-qh-VmU"/> /* 削除 */
<constraint firstItem="zf0-db-esM" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="Ris-mI-8lA"/>
<constraint firstItem="Pii-2r-R2l" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="SXi-MU-H9D"/>
<constraint firstItem="zf0-db-esM" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="W6q-xJ-jfF"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="height" secondItem="rUJ-G6-RPv" secondAttribute="height" id="aQi-F7-E2b"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="top" secondItem="FAC-co-10c" secondAttribute="bottom" constant="20" id="aSR-Je-0lW"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="top" secondItem="eRT-dK-6dM" secondAttribute="top" id="bQd-ro-0Hw"/>
<constraint firstItem="nyU-fN-aJh" firstAttribute="bottom" secondItem="uCj-6P-mHF" secondAttribute="bottom" constant="20" id="eWs-co-Aaz"/>
<constraint firstItem="3eR-Rn-XpZ" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="igk-MQ-CGt"/>
<constraint firstItem="rUJ-G6-RPv" firstAttribute="leading" secondItem="uCj-6P-mHF" secondAttribute="trailing" constant="20" id="lsk-Hm-rTd"/>
<constraint firstItem="nyU-fN-aJh" firstAttribute="centerX" secondItem="uCj-6P-mHF" secondAttribute="centerX" id="m8a-cF-Rf0"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="width" secondItem="rUJ-G6-RPv" secondAttribute="width" id="o8j-gw-35B"/>
<constraint firstItem="3eR-Rn-XpZ" firstAttribute="width" secondItem="8bC-Xf-vdC" secondAttribute="width" id="pSC-xP-dl0"/>
<constraint firstItem="uCj-6P-mHF" firstAttribute="width" secondItem="eRT-dK-6dM" secondAttribute="width" id="s8u-Y8-n27"/>
<constraint firstItem="FZr-Ip-7WL" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="sTY-i6-czN"/>
<constraint firstItem="9i1-NX-Qxg" firstAttribute="centerX" secondItem="nyU-fN-aJh" secondAttribute="centerX" id="wWj-VD-34F"/> /* 削除 */
<constraint firstItem="uCj-6P-mHF" firstAttribute="leading" secondItem="eRT-dK-6dM" secondAttribute="trailing" constant="20" id="zwj-TX-t6O"/>


移植後のC#の制約

View.AddConstraint(NSLayoutConstraint.Create(LivePhotoModeButton, NSLayoutAttribute.Top, NSLayoutRelation.Equal, View, NSLayoutAttribute.Top, 1.0f, 80f));// iOS10対応のため変更あり
View.AddConstraint(NSLayoutConstraint.Create(LivePhotoModeButton, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, RecordButton, NSLayoutAttribute.Height, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(CapturingLivePhotoLabel, NSLayoutAttribute.Top, NSLayoutRelation.Equal, LivePhotoModeButton, NSLayoutAttribute.Bottom, 1.0f, 8.0f));
View.AddConstraint(NSLayoutConstraint.Create(PreviewView, NSLayoutAttribute.Height, NSLayoutRelation.Equal, View, NSLayoutAttribute.Height, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Top, NSLayoutRelation.Equal, CameraButton, NSLayoutAttribute.Top, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(ResumeButton, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(CaptureModeControl, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(CameraUnavailableLabel, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterY, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(CapturingLivePhotoLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0));
View.AddConstraint(NSLayoutConstraint.Create(CameraUnavailableLabel, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterX, 1.0f, 0));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Height, NSLayoutRelation.Equal, CameraButton, NSLayoutAttribute.Height, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Top, NSLayoutRelation.Equal, CaptureModeControl, NSLayoutAttribute.Bottom, 1.0f, 20f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Top, NSLayoutRelation.Equal, RecordButton, NSLayoutAttribute.Top, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(View, NSLayoutAttribute.Bottom, NSLayoutRelation.Equal, PhotoButton, NSLayoutAttribute.Bottom, 1.0f, 20f));
View.AddConstraint(NSLayoutConstraint.Create(PreviewView, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterY, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(CameraButton, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, PhotoButton, NSLayoutAttribute.Trailing, 1.0f, 20f));
View.AddConstraint(NSLayoutConstraint.Create(View, NSLayoutAttribute.CenterX, NSLayoutRelation.Equal, PhotoButton, NSLayoutAttribute.CenterX, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Width, NSLayoutRelation.Equal, RecordButton, NSLayoutAttribute.Width, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PreviewView, NSLayoutAttribute.Width, NSLayoutRelation.Equal, View, NSLayoutAttribute.Width, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Width, NSLayoutRelation.Equal, RecordButton, NSLayoutAttribute.Width, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(ResumeButton, NSLayoutAttribute.CenterY, NSLayoutRelation.Equal, View, NSLayoutAttribute.CenterY, 1.0f, 0f));
View.AddConstraint(NSLayoutConstraint.Create(PhotoButton, NSLayoutAttribute.Leading, NSLayoutRelation.Equal, RecordButton, NSLayoutAttribute.Trailing, 1.0f, 20f));

これで制約の移植が完了しました。

今回はここまでです。