Xamarin.iOS의 코드에서 iOS 사용자 인터페이스 만들기
iOS 앱의 사용자 인터페이스는 상점과 비슷합니다. 애플리케이션은 일반적으로 하나의 창을 가져오지만 필요한 만큼의 개체로 창을 채울 수 있으며 앱이 표시하려는 항목에 따라 개체와 정렬을 변경할 수 있습니다. 사용자에게 표시되는 항목인 이 시나리오의 개체를 뷰라고 합니다. 애플리케이션에서 단일 화면을 빌드하려면 뷰가 콘텐츠 뷰 계층 구조에 쌓이고 계층 구조는 단일 뷰 컨트롤러에서 관리됩니다. 여러 화면이 있는 애플리케이션은 각각 고유한 뷰 컨트롤러가 있는 여러 콘텐츠 뷰 계층 구조가 있으며, 애플리케이션은 사용자가 보는 화면에 따라 다른 콘텐츠 뷰 계층 구조를 만들도록 창에 뷰를 배치합니다.
다음 다이어그램에는 디바이스 화면에 사용자 인터페이스를 가져오는 창, 뷰, 하위 뷰 및 뷰 컨트롤러 간의 관계가 나와 있습니다.
이러한 뷰 계층 구조는 Xcode의 인터페이스 작성기를 사용하여 생성할 수 있지만 코드에서 완전히 작동하는 방법을 기본적으로 이해하는 것이 좋습니다. 이 문서에서는 코드 전용 사용자 인터페이스 개발을 시작하고 실행하기 위한 몇 가지 기본 사항을 안내합니다.
코드 전용 프로젝트 만들기
iOS 빈 프로젝트 템플릿
먼저 아래와 같이 새 프로젝트 > Visual C# > i전화 및 iPad > iOS 앱(Xamarin) 프로젝트를 사용하여 > Visual Studio에서 iOS 프로젝트를 만듭니다.
그런 다음 빈 앱 프로젝트 템플릿을 선택합니다.
빈 프로젝트 템플릿은 프로젝트에 4개 파일을 추가합니다.
- AppDelegate.cs - iOS의
UIApplicationDelegate
애플리케이션 이벤트를 처리하는 데 사용되는 하위 클래스AppDelegate
를 포함합니다. 애플리케이션 창은 'sFinishedLaunching
메서드에AppDelegate
만들어집니다. - Main.cs - 에 대한 클래스
AppDelegate
를 지정하는 애플리케이션의 진입점을 포함합니다. - Info.plist - 애플리케이션 구성 정보를 포함하는 속성 목록 파일입니다.
- Entitlements.plist – 애플리케이션의 기능 및 권한에 대한 정보가 포함된 속성 목록 파일입니다.
iOS 애플리케이션은 MVC 패턴을 사용하여 빌드됩니다. 애플리케이션이 표시하는 첫 번째 화면은 창의 루트 뷰 컨트롤러에서 만들어집니다. MVC 패턴 자체에 대한 자세한 내용은 Hello, iOS 멀티스크린 가이드를 참조하세요.
템플릿에서 AppDelegate
추가된 구현은 모든 iOS 애플리케이션에 대해 하나만 있는 애플리케이션 창을 만들고 다음 코드로 표시합니다.
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;
}
}
이 애플리케이션을 지금 실행하려는 경우 예외가 throw될 수 있습니다 Application windows are expected to have a root view controller at the end of application launch
. 컨트롤러를 추가하고 앱의 루트 뷰 컨트롤러로 만들어 보겠습니다.
컨트롤러 추가
앱에는 많은 뷰 컨트롤러가 포함될 수 있지만 모든 뷰 컨트롤러를 제어하려면 하나의 루트 뷰 컨트롤러가 있어야 합니다. 인스턴스를 만들고 속성으로 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
변경합니다.
UIKit의 컨트롤러뿐만 아니라 직접 작성하는 컨트롤러를 포함하여 모든 UIViewController
서브클래스를 RootViewController
이러한 방식으로 설정할 수 있습니다. 예를 들어 다음 코드는 다음과 같이 추가합니다 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;
}
}
그러면 아래와 같이 탐색 컨트롤러 내에 중첩된 컨트롤러가 생성됩니다.
뷰 컨트롤러 만들기
이제 창으로 RootViewController
컨트롤러를 추가하는 방법을 살펴보았으므로 코드에서 사용자 지정 뷰 컨트롤러를 만드는 방법을 살펴보겠습니다.
아래와 같이 명명된 CustomViewController
새 클래스를 추가합니다.
클래스는 다음과 같이 네임스페이스에 UIKit
있는 상속UIViewController
되어야 합니다.
using System;
using UIKit;
namespace CodeOnlyDemo
{
class CustomViewController : UIViewController
{
}
}
보기 초기화
UIViewController
에는 뷰 컨트롤러가 메모리에 처음 로드될 때 호출되는 메서드 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
를 만듭니다. 새 탐색 컨트롤러를 만들고, 보기 컨트롤러 인스턴스를 전달하고, 새 탐색 컨트롤러를 이전과 같이 창의 RootViewController
창으로 AppDelegate
설정합니다.
var cvc = new CustomViewController ();
var navController = new UINavigationController (cvc);
Window.RootViewController = navController;
이제 애플리케이션이 로드 CustomViewController
되면 탐색 컨트롤러 내부에 로드됩니다.
단추를 클릭하면 새 보기 컨트롤러가 탐색 스택에 푸시됩니다.
뷰 계층 구조 빌드
위의 예제에서는 뷰 컨트롤러에 단추를 추가하여 코드에서 사용자 인터페이스를 만들기 시작했습니다.
iOS 사용자 인터페이스는 뷰 계층 구조로 구성됩니다. 레이블, 단추, 슬라이더 등과 같은 추가 보기는 일부 부모 보기의 하위 보기로 추가됩니다.
예를 들어 사용자가 사용자 이름과 암호를 입력할 수 있는 로그인 화면을 만들도록 편집 CustomViewController
해 보겠습니다. 화면은 두 개의 텍스트 필드와 단추로 구성됩니다.
텍스트 필드 추가
먼저 뷰 초기화 섹션에 추가된 단추 및 이벤트 처리기를 제거합니다.
아래와 같이 사용자 이름을 만들고 초기화 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
은 다음과 같습니다.
다음과 같이 비슷한 방식으로 암호를 추가할 UITextField
수 있습니다. 이번에는 속성을 true로 설정합니다 SecureTextEntry
.
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);
}
}
설정은 SecureTextEntry = true
아래와 같이 사용자가 입력한 UITextField
텍스트를 숨깁니다.
단추 추가
다음으로, 사용자가 사용자 이름과 암호를 제출할 수 있도록 단추를 추가합니다. 단추를 부모 뷰의 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);
이 경우 로그인 화면이 아래와 같이 표시됩니다.
이전 버전의 iOS와 달리 기본 단추 배경은 투명합니다. 단추의 BackgroundColor
속성을 변경하면 다음이 변경됩니다.
submitButton.BackgroundColor = UIColor.White;
이렇게 하면 일반적인 둥근 가장자리 단추가 아닌 정사각형 단추가 생성됩니다. 둥근 가장자리를 가져오려면 다음 코드 조각을 사용합니다.
submitButton.Layer.CornerRadius = 5f;
이러한 변경 내용으로 보기는 다음과 같이 표시됩니다.
뷰 계층 구조에 여러 보기 추가
iOS는 을 사용하여 AddSubviews
뷰 계층 구조에 여러 보기를 추가하는 기능을 제공합니다.
View.AddSubviews(new UIView[] { usernameField, passwordField, submitButton });
단추 기능 추가
단추를 클릭하면 사용자가 어떤 일이 발생할 것으로 예상합니다. 예를 들어 경고가 표시되거나 다른 화면으로 탐색이 수행됩니다.
두 번째 보기 컨트롤러를 탐색 스택에 푸시하는 코드를 추가해 보겠습니다.
먼저 두 번째 뷰 컨트롤러를 만듭니다.
var loginVC = new UIViewController () { Title = "Login Success!"};
loginVC.View.BackgroundColor = UIColor.Purple;
그런 다음, 이벤트에 기능을 추가합니다 TouchUpInside
.
submitButton.TouchUpInside += (sender, e) => {
this.NavigationController.PushViewController (loginVC, true);
};
탐색은 다음과 같습니다.
기본적으로 탐색 컨트롤러를 사용하는 경우 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
다시 돌아올 경우 작동하지 않습니다.
회전 처리
사용자가 디바이스를 가로로 회전하는 경우 다음 스크린샷과 같이 컨트롤의 크기가 적절하게 조정되지 않습니다.
이 문제를 해결하는 한 가지 방법은 각 보기에서 AutoresizingMask
속성을 설정하는 것입니다. 이 경우 컨트롤을 가로로 확장하여 각각 AutoresizingMask
을 설정합니다. 다음 예제는 usernameField
뷰 계층 구조의 각 가젯에 동일하게 적용해야 합니다.
usernameField.AutoresizingMask = UIViewAutoresizing.FlexibleWidth;
이제 디바이스 또는 시뮬레이터를 회전하면 아래와 같이 추가 공간을 채우기 위해 모든 항목이 늘어나게 됩니다.
사용자 지정 보기 만들기
UIKit의 일부인 컨트롤을 사용하는 것 외에도 사용자 지정 보기를 사용할 수 있습니다. 사용자 지정 보기는 상속하고 재정의 UIView
하여 만들 수 있습니다 Draw
. 사용자 지정 보기를 만들고 보여 줄 뷰 계층 구조에 추가해 보겠습니다.
UIView에서 상속
가장 먼저 해야 할 일은 사용자 지정 보기에 대한 클래스를 만드는 것입니다. Visual Studio의 클래스 템플릿을 사용하여 빈 클래스CircleView
를 추가합니다. 기본 클래스를 네임스페이스에 있는 UIKit
것으로 설정UIView
해야 합니다. 네임스페이 System.Drawing
스도 필요합니다. 다른 다양한 System.*
네임스페이스는 이 예제에서 사용되지 않으므로 자유롭게 제거할 수 있습니다.
이 클래스는 다음과 같이 표시되어야 합니다.
using System;
namespace CodeOnlyDemo
{
class CircleView : UIView
{
}
}
UIView에서 그리기
모든 UIView
메서드는 Draw
그려야 할 때 시스템에서 호출하는 메서드를 가지고 있습니다. Draw
는 직접 호출하지 않아야 합니다. 이 호출은 실행 루프 처리 중에 시스템에서 호출됩니다. 뷰가 뷰 계층 구조에 추가된 후 처음으로 실행 루프를 통해 해당 Draw
메서드가 호출됩니다. 뷰를 Draw
호출하거나 SetNeedsDisplayInRect
뷰에서 그려야 하는 것으로 표시될 때 후속 호출 SetNeedsDisplay
이 발생합니다.
아래와 같이 재정의된 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);
}
}
따라서 CircleView
UIView
속성도 설정할 UIView
수 있습니다. 예를 들어 생성자에서 설정할 BackgroundColor
수 있습니다.
public CircleView()
{
BackgroundColor = UIColor.White;
}
방금 만든 항목을 CircleView
사용하려면 이전과 마찬가지로 기존 컨트롤러의 뷰 계층 구조에 하위 보기로 UILabels
UIButton
추가하거나 새 컨트롤러의 보기로 로드할 수 있습니다. 후자를 수행해 보겠습니다.
보기 로드
UIViewController
에는 컨트롤러가 뷰를 만들기 위해 호출하는 메서드가 있습니다 LoadView
. 보기를 만들고 컨트롤러의 속성에 할당할 수 있는 적절한 위치입니다 View
.
먼저 컨트롤러가 필요하므로 이름이 CircleController
비어 있는 새 클래스를 만듭니다.
CircleController
다음 코드를 추가하여 다음 코드를 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);
};
이제 애플리케이션을 실행하고 제출 단추를 탭하면 원이 있는 새 보기가 표시됩니다.
시작 화면 만들기
앱이 시작되면 사용자에게 응답성이 있음을 표시하는 방법으로 시작 화면이 표시됩니다. 앱이 로드될 때 시작 화면이 표시되기 때문에 애플리케이션이 메모리에 로드되고 있으므로 코드에서 만들 수 없습니다.
Visual Studio에서 iOS 프로젝트를 만들면 프로젝트 내의 Resources 폴더에서 찾을 수 있는 .xib 파일 형식으로 시작 화면이 제공됩니다.
이를 두 번 클릭하고 Xcode 인터페이스 작성기에서 열어 편집할 수 있습니다.
Apple에서는 iOS 8 이상을 대상으로 하는 애플리케이션에 .xib 또는 Storyboard 파일을 사용하는 것이 좋습니다. Xcode 인터페이스 작성기에서 두 파일 중 하나를 시작하면 크기 클래스 및 자동 레이아웃을 사용하여 레이아웃을 조정하여 모든 디바이스 크기에 맞게 올바르게 표시할 수 있습니다. .xib 또는 Storyboard 외에도 정적 시작 이미지를 사용하여 이전 버전을 대상으로 하는 애플리케이션을 지원할 수 있습니다.
시작 화면을 만드는 방법에 대한 자세한 내용은 아래 문서를 참조하세요.
Important
iOS 9를 기준으로 Apple은 스토리보드를 시작 화면을 만드는 기본 방법으로 사용할 것을 권장합니다.
iOS 8 이전 애플리케이션에 대한 시작 이미지 만들기
애플리케이션이 iOS 8 이전 버전을 대상으로 하는 경우 .xib 또는 Storyboard 시작 화면 외에 정적 이미지를 사용할 수 있습니다.
이 정적 이미지는 Info.plist 파일 또는 애플리케이션의 자산 카탈로그(iOS 7용)로 설정할 수 있습니다. 애플리케이션이 실행될 수 있는 각 디바이스 크기(320x480, 640x960, 640x1136)에 대해 별도의 이미지를 제공해야 합니다. 시작 화면 크기에 대한 자세한 내용은 시작 화면 이미지 가이드를 참조하세요.
Important
앱에 시작 화면이 없는 경우 화면에 완전히 맞지 않는 것을 알 수 있습니다. 이 경우 Info.plist에 명명된 Default-568@2x.png
640x1136 이미지 이상을 포함해야 합니다.
요약
이 문서에서는 Visual Studio에서 프로그래밍 방식으로 iOS 애플리케이션을 개발하는 방법을 설명했습니다. 빈 프로젝트 템플릿에서 프로젝트를 빌드하는 방법을 살펴보고 창에 루트 뷰 컨트롤러를 만들고 추가하는 방법을 설명했습니다. 그런 다음 UIKit의 컨트롤을 사용하여 컨트롤러 내에서 뷰 계층 구조를 만들어 애플리케이션 화면을 개발하는 방법을 보여 줍니다. 다음으로 보기가 서로 다른 방향으로 적절하게 배치되도록 하는 방법을 알아보고 서브클래싱을 UIView
통해 사용자 지정 보기를 만드는 방법과 컨트롤러 내에서 뷰를 로드하는 방법을 알아보았습니다. 마지막으로 애플리케이션에 시작 화면을 추가하는 방법을 살펴보겠습니다.