はじめに
こんにちは、@hiro128_777です。
前回は、UIViewのLayerの差し替えについてご説明しました。
今回のお話はUIについてです。Xamarin.iOS では、UIについては storyboard をそのまま利用できます。ですが、実際にアプリを開発すると、storyboard だけで完結するのはなかなか難しく、どうしてもコードで UI を記述する場面が出てきてしまいます。
ところが、Xamarin.iOS で UI をコードで作成する方法の情報は非常に少ないです。そこで、今回は、storyboard の C# コードへの移植方法についてご説明します。
今回も Apple 公式の写真撮影のサンプルアプリを題材にします。
以下よりサンプルコードをダウンロードして下さい。
developer.apple.com
その中の、Main.storyboard
ファイルのコードを見てみましょう。
では早速移植していきましょう。
なお、Xamarin.IOS のコードによる iOS ユーザーインターフェイスの作成については、以下の公式ドキュメントも非常に参考になります。
docs.microsoft.com
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 = true
、userInteractionEnabled="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>
の部分は、InsertSegment
メソッドが準備されているので、それを使うと以下のようになります。
C#
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エレメントの移植が完了しました。
今回はここまでです。
次回はこちらからどうぞ!
hiro128.hatenablog.jp