iOS: iPhone 프로그램에 커스텀 UI 컨트롤 개발하기 Part 1

이 글은 Stanford 대학에서 제공한 "Developing Apps for iOS" 강의 내용을 참고하여 작성한 것임을 밝힌다. (제 5강, 6강의 내용 중 웃는 얼굴을 그리는 커스텀 컨트롤 데모 부분을 참고하였다.)

iPhone 프로그램의 View를 작성 시 이미 SDK에서 제공되는 표준 View 외에 개발자가 원하는 커스텀 View를 직접 작성할 수 있다. 이 글에서는 커스텀 뷰를 이용하여 화면에 웃는 얼굴을 그리는 코드를 작성하면서 아래와 같은 지식을 습득하도록 한다.
  • 커스텀 View를 만드는 방법
  • UISlider 컨트롤 사용법
  • Protocol과 delegate을 활용하는 방법
  • property를 사용하여 IBOutlet으로 관리하는 컨트롤들의 메모리 관리 방법

이 데모 코드는 아래와 같은 MVC 구조를 가진다.
  • Model: int happiness
  • View: UISlider, FaceView 커스텀 뷰
  • Controller: HappinessViewController

우선, 웃는 얼굴을 화면에 보여주는 커스텀 뷰를 구현해보자.

1. Xcode에서 새로운 프로젝트 생성
View-based Application으로 생성. 프로젝트 이름은 Happiness로 한다.

2. FaceView class를 추가 (커스텀 뷰를 구현하기 위한 class)
Classes의 context menu에서 Add / New File ... 을 선택한 후 Objective-C class를 UIView subclass로 생성한다. 파일 명은 FaceView로 한다. Classes에 FaceView.m과 FaceView.h가 생성된다.

3. FaceView.m 파일의 drawRect 코드 구현 
커스텀 뷰 화면에 웃는 얼굴을 그리기 위하여 drawRect 메소드를 구현한다. 구현 코드는 아래와 같다.

- (void)drawCircleAtPoint:(CGPoint)p withRadius:(CGFloat)radius 
                          inContext:(CGContextRef)context 
{
 UIGraphicsPushContext(context);
 CGContextBeginPath(context);
 CGContextAddArc(context, p.x, p.y, radius, 0, 2 * M_PI, YES);
 CGContextStrokePath(context);
 UIGraphicsPopContext();
}

- (void)drawRect:(CGRect)rect {
    CGPoint midPoint;
 midPoint.x = self.bounds.origin.x + self.bounds.size.width / 2;
 midPoint.y = self.bounds.origin.y + self.bounds.size.height / 2;
 
 CGFloat size = self.bounds.size.width / 2;
 if (self.bounds.size.height > self.bounds.size.width) 
  size = self.bounds.size.height / 2;
 size *= 0.9;
 
 CGContextRef context = UIGraphicsGetCurrentContext();
 [self drawCircleAtPoint:midPoint withRadius:size inContext:context];
 
#define EYE_H 0.35
#define EYE_V 0.35
#define EYE_RADIUS 0.1
 
 CGPoint eyePoint;
 eyePoint.x = midPoint.x - size * EYE_H;
 eyePoint.y = midPoint.y - size * EYE_V;
 [self drawCircleAtPoint:eyePoint withRadius:size * EYE_RADIUS inContext:context];
 eyePoint.x += size * EYE_H * 2;
 [self drawCircleAtPoint:eyePoint withRadius:size * EYE_RADIUS inContext:context];
 
#define MOUTH_H 0.45
#define MOUTH_V 0.4
#define MOUTH_SMILE 0.25
 
 CGPoint mouthStart;
 mouthStart.x = midPoint.x - MOUTH_H * size;
 mouthStart.y = midPoint.y + MOUTH_V * size;
 CGPoint mouthEnd = mouthStart;
 mouthEnd.x += MOUTH_H * size * 2;
 CGPoint mouthCP1 = mouthStart;
 mouthCP1.x += MOUTH_H * size * 2/3;
 CGPoint mouthCP2 = mouthEnd;
 mouthCP2.x -= MOUTH_H * size * 2/3;
 
 CGFloat smileOffset = MOUTH_SMILE * size;
 mouthCP1.y += smileOffset;
 mouthCP2.y += smileOffset;
 
 CGContextBeginPath(context);
 CGContextMoveToPoint(context, mouthStart.x, mouthStart.y);
 CGContextAddCurveToPoint(context, mouthCP1.x, mouthCP1.y, mouthCP2.x, mouthCP2.y, mouthEnd.x, mouthEnd.y);
 CGContextStrokePath(context);
}

4. Interface Builder에서 FaceView 커스텀 뷰를 추가
Resources의 HappinessViewController.xib을 선택하여 Interface Builder를 실행한다. Interface Builder이 라이브러리에서 View를 선택하여 프로그램 화면에 추가하고 이 View의 Inspector의 Identity 항목에서 Class를 FaceView로 선택한다. 작업이 완료된 아래 화면을 참고하기 바란다.


5. 저장하고 실행하면 아래와 같은 화면이 나타난다. 현재까지 진행한 결과를 정리해보면 
  • Custom View의 화면을 그리기 위해서는 UIView에서 sub class한 클래스에서 drawRect 메소드를 구현해준다.
  • Interface Builder에서 custom view를 화면에 추가하기 위해서는 View를 추가한 후 inspector에서 이 view의 클래스를 윈하는 custom view 클래스로 지정해준다.


Part 2에서는 delegate를 이용하여 FaceView의 웃는 얼굴 모습을 외부 컨트롤에 의해 변경할 수 있도록 한다.

댓글

이 블로그의 인기 게시물

Wireless: HotSpot 2.0 이란?

Apple M1 Mac Mini에서 이더리움 (Ethereum) 채굴하기

Java: Java for Game? Java가 Game 개발에 어울릴까?