Upload
naver-d2
View
1.870
Download
2
Embed Size (px)
Citation preview
가로세로 어느 방향도 자유롭게유연성있는 아이폰 앱 레이아웃 구현
유연한 레이아웃?
우리가 만든 앱은..?
무엇이 문제일까
첫번째,
320
320 = 아이폰 화면너비
세로
CGRectMake(320 - 27 - 6, y, 27, 28);
480
480320 |
if (UIInterfaceOrientationIsPortrait(orientation)) {
width = 320;
} else if (UIInterfaceOrientationIsLandscape(orientation)) {
width = 480;
}
1024768
320 480 768 1024
if (iPhone) {
if (UIInterfaceOrientationIsPortrait(orientation)) {
width = 320;
} else if (UIInterfaceOrientationIsLandscape(orientation)) {
width = 480;
}
} else if (iPad) {
if (UIInterfaceOrientationIsPortrait(orientation)) {
width = 768;
} else if (UIInterfaceOrientationIsLandscape(orientation)) {
width = 1024;
}
}
과연 이것으로 끝?
두번째,
절대 좌표
세로 화면
photo.frame = CGRectMake(0, 0, 77, 77);
name.frame = CGRectMake(77 + 10, 10, 320 - 77 - 10 - 50, 15);
status.frame = CGRectMake(77 + 10, 28, 320 - 77 - 10 - 50, 15);
가로 화면 - 기대
가로 화면 - 실제
그럼 이제 어떻게..?
문제점1) 고정된 화면 너비 값 필요2) 절대좌표 사용
해결방법1) 고정된 화면 너비 값 제거2) 절대좌표 제거
해결방법1) 고정된 화면 너비 값 제거2) 절대좌표 제거
상태 바
[[UIApplication sharedApplication] statusBarFrame];
if (iPhone) {
if (UIInterfaceOrientationIsPortrait(orientation)) {
width = 320;
} else if (UIInterfaceOrientationIsLandscape(orientation)) {
width = 480;
}
} else if (iPad) {
if (UIInterfaceOrientationIsPortrait(orientation)) {
width = 768;
} else if (UIInterfaceOrientationIsLandscape(orientation)) {
width = 1024;
}
}
width = [[UIApplication sharedApplication] statusBarFrame].size.width;
해결방법1) 고정된 화면 너비 값 제거2) 절대좌표 제거
아직 끝난게 아니다?
화면 너비 ≠ 뷰의 너비
뷰의 너비
뷰의 너비는 변할 수 있다
뷰의 크기는 변할 수 있다
문제점1) 고정된 화면 너비 값 필요2) 절대좌표 사용
해결방법1) 고정된 화면 너비 값 제거2) 절대좌표 제거
해결방법1) 화면 크기에 대한 가정을 제거2) 절대좌표 제거
뷰의 크기는 언제라도 변할 수 있다고 가정할 것. 반드시. 꼭!
어떻게 하면 정확한 뷰의 너비를 얻을 수 있는가
어떻게 하면 임의의 뷰의 너비로 배치할 수 있는가
어떻게 하면 뷰의 크기가 변해도 잘 배치되는가
오토리사이징Autoresizing
UIView@property (nonatomic) UIViewAutoresizing autoresizingMask
상위뷰의 크기가 변할때하위뷰는 그에 맞춰어떻게 변할 것인가
오토리사이징 마스크 - 네비게이션 바
bar.autoresizingMask =
UIViewAutoresizingFlexibleWidth |
UIViewAutoresizingFlexibleBottomMargin;
오토리사이징 마스크 - 탭 바
오토리사이징 마스크 - 뷰 중앙정렬
view.autoresizingMask =
UIViewAutoresizingFlexibleTopMargin |
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleLeftMargin |
UIViewAutoresizingFlexibleRightMargin;
오토리사이징 마스크 - 백그라운드 뷰
프로필 이미지
오토리사이징 마스크 - 프로필 이미지
profile.autoresizingMask =
UIViewAutoresizingFlexibleBottomMargin |
UIViewAutoresizingFlexibleRightMargin;
프로필 이미지
대화명
메시지
시간
상위 뷰의
영향만 받는 요소
다른 요소들의
영향을 받는 요소
오토리사이징 만으로는
모든 것을 해결할 수 없다
뷰 레이아웃 코딩
뷰 프레임 코딩
뷰 코딩
노가다
커스텀 뷰
커스텀 뷰 클래스vs
뷰 컨트롤러
기준
- 임의 크기의 뷰 생성 UIViewController
- 해당 뷰 안에 하위 뷰 배치 UIView
화면 회전↓
뷰 컨트롤러↓
뷰↓
서브 뷰 레이아웃
shouldAutorotateToInterfaceOrientation:
layoutSubviews
self.view
UIView- initWithFrame:
- layoutSubviews
기준
- 임의 크기의 뷰 생성 initWithFrame:
- 해당 뷰 안에 하위 뷰 배치 layoutSubviews
핵심 포인트
1) 화면 너비가 아닌 현재 뷰의 너비를 기준
2) 각 요소의 절대 위치가 아닌 요소간 간격
을 고려
프레임frame
제대로 알고 사용하자
UIView.frame 상위 뷰 상에 자신이 위치한 영역
.bounds 자신의 영역
바운드
{0, 0, 150, 150}
100
100
150
150
프레임
{100, 100, 150, 150}
69
69
212
212
바운드
{0, 0, 150, 150}
프레임
{69, 69, 212, 212}
window
application frame
status bar
{0, 20, 320, 460}
- (void)loadView { [super loadView]; self.view.backgroundColor = [UIColor redColor]; CGRect f = [[UIScreen mainScreen] applicationFrame]; UIView *bg = [[UIView alloc] initWithFrame:f]; bg.backgroundColor = [UIColor grayColor]; [self.view addSubview:bg]; [bg release];}
결과는..
왜?
application frame
status bar
{0, 20, 320, 460}
application frame
status bar
{0, 20, 320, 460}
센터center
CGRect f = CGRectMake(50, 100, 150, 150);UIView *view = [[UIView alloc] initWithFrame:f];[self.view addSubview:view];
f = CGRectMake(0, 0, 80, 80);UIView *subview = [[UIView alloc] initWithFrame:f];subview.center = view.center;[view addSubview:subview];
CGRect f = CGRectMake(50, 100, 150, 150);UIView *view = [[UIView alloc] initWithFrame:f];[self.view addSubview:view];
f = CGRectMake(0, 0, 80, 80);UIView *subview = [[UIView alloc] initWithFrame:f];subview.center = view.center;[view addSubview:subview];
CGRect f = CGRectMake(50, 100, 150, 150);UIView *view = [[UIView alloc] initWithFrame:f];[self.view addSubview:view];
f = CGRectMake(0, 0, 80, 80);UIView *subview = [[UIView alloc] initWithFrame:f];subview.center = view.center;[self.view addSubview:subview];
기준이 되는 좌표계가
어디인가에 따라
결과가 달라진다
기준이 되는 좌표계가
동일하다면
결과는 같아진다
상위 뷰가
동일하다면
결과는 같아진다
“뷰 계층구조를
적절하게 구성하라”
CGRect 시리즈
CGRectGetMinXCGRectGetMidXCGRectGetMaxX
CGRectGetMaxYframe.origin.y + frame.size.height
메시지
메시지 Y = 대화명 최대 Y + 간격
메시지 Y = 대화명 최대 Y + 간격메시지 Y = 대화명 최대 Y + 간격
메시지 Y = 대화명 Y + 대화명 H + 간격msgFrame.origin.y = nameFrame.origin.y + nameFrame.size.height + 5;
msgFrame.origin.y = CGRectGetMaxY(nameFrame) + 5;
그러나..
텍스트 길이는
변한다.
텍스트 라벨의 크기는
변한다.
텍스트 라벨의 크기는
변해야 한다.
텍스트 라벨의 크기를
구해야 한다.
NSString- sizeWithFont:
- sizeWithFont:constrainedToSize:
NSString- sizeWithFont:
- sizeWithFont:constrainedToSize:
CGFloat maxWidth = 150.0f;
CGSize maxSize = CGSizeMake(maxWidth, CGFLOAT_MAX);CGSize size = [msg.text sizeWithFont:msg.font constrainedToSize:maxSize];
CGRect f = msg.frame;f.size.height = size.height;msg.frame = f;
CGFloat maxWidth = CGRectGetWidth(self.bounds) - (CGRectGetWidth(photo.bounds) + CGRectGetWidth(time.bounds) + offset1 + offset2 + offset3 + offset4); CGSize maxSize = CGSizeMake(maxWidth, CGFLOAT_MAX);CGSize size = [msg.text sizeWithFont:msg.font constrainedToSize:maxSize];
CGRect f = msg.frame;f.size.width = size.width;f.size.height = size.height;msg.frame = f;
시간
CGRect f = time.frame;f.origin.x = CGRectGetMaxX(msg.frame) + 5;f.origin.y = CGRectGetMaxY(msg.frame) - CGRectGetHeight(f);time.frame = f;
해결방법1) 화면 크기에 대한 가정을 제거2) 절대좌표 제거
해결방법1) 화면 크기에 대한 가정을 제거2) 절대좌표 제거
Mission Complete
배치 순서는
화면 좌표계 방향과
동일하다
배치 순서는
좌에서 우로
위에서 아래로
지금까지..
뷰의 너비는
항상 변한다고 가정하라
1
화면 너비 보다는
현재 뷰의 너비를 기준으로
2
각 요소들의 절대 위치보다
요소들간의 상대적 위치를 고려
3
다른 요소의 영향을 받지 않는 요소는
오토리사이징 마스크를 적용
4
프레임은 상위 뷰 좌표계 기준이고
바운드는 자신의 좌표계 기준이다
5
뷰 계층구조를 잘 구성하고
다른 요소의 프레임을 최대한 활용
6
레이아웃 순서는
좌에서 우로, 위에서 아래로
7
?
Q & A
트위터 redleafgogo
미투데이 redleafgogo
감사합니다