UIView 프레임, 경계 및 중심


320

이러한 속성을 올바른 방법으로 사용하는 방법을 알고 싶습니다.

내가 이해하는 것처럼, frame내가 만들고있는보기의 컨테이너에서 사용할 수 있습니다. 컨테이너 뷰를 기준으로 뷰 위치를 설정합니다. 또한 해당 뷰의 크기를 설정합니다.

또한 center내가 만드는거야 뷰의 컨테이너에서 사용할 수 있습니다. 이 속성은 컨테이너를 기준으로 뷰의 위치를 ​​변경합니다.

마지막으로 bounds뷰 자체와 관련이 있습니다. 뷰의 드로어 블 영역을 변경합니다.

frame과 의 관계에 대한 자세한 정보를 제공 할 수 있습니까 bounds? 무엇에 대한 clipsToBoundsmasksToBounds특성?


1
이 토론은 이미 여기서 해결되었습니다. 그래서 pls는 여기를 보거나 여기에 주어진 개발자 문서를 볼 수 있습니다 developer.apple.com/library/ios/#documentation/uikit/reference/… stackoverflow.com/questions/1210047/… slideshare.net/onoaonoa/cs193p-lecture-5 -view-animation
화려한

답변:


577

내가 묻는 질문은 여러 번 보였으므로 자세한 답변을 드리겠습니다. 더 정확한 내용을 추가하려면 자유롭게 수정하십시오.

먼저 질문에 대한 요약 : 프레임, 경계 및 중심과 관계.

프레임 보기 frame( CGRect)는 superview좌표계 에서 사각형의 위치입니다 . 기본적으로 왼쪽 상단에서 시작합니다.

경계 보기 bounds( CGRect)는 자체 좌표계로보기 사각형을 나타냅니다.

중심 A center는 의 좌표계 로 CGPoint표현되며 superview뷰의 정확한 중심점의 위치를 ​​결정합니다.

UIView + 위치 에서 가져온 이들은 이전 속성 간의 관계입니다 (비공식 방정식이므로 코드에서 작동하지 않습니다).

  • frame.origin = center - (bounds.size / 2.0)

  • center = frame.origin + (bounds.size / 2.0)

  • frame.size = bounds.size

참고 : 뷰가 회전 된 경우 이러한 관계가 적용되지 않습니다. 자세한 내용 은 Stanford CS193p 코스를 기반으로 The Kitchen Drawer 에서 가져온 다음 이미지를 살펴보십시오 . 크레딧은 @Rhubarb 로갑니다 .

프레임, 경계 및 중심

를 사용하면의 frame위치에서 뷰의 위치를 ​​조정하거나 크기를 조정할 수 있습니다 superview. 일반적으로 superview예를 들어 특정 하위 뷰를 생성 할 때에서 사용할 수 있습니다. 예를 들면 다음과 같습니다.

// view1 will be positioned at x = 30, y = 20 starting the top left corner of [self view]
// [self view] could be the view managed by a UIViewController
UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

내부에 그리기 위해 좌표가 필요한 경우 view일반적으로을 참조하십시오 bounds. 전형적인 예 view는 서브 뷰 내 에서 첫 번째의 삽입으로 그릴 수 있습니다 . bounds서브 뷰 를 그리려면 슈퍼 뷰 에 대해 알아야합니다 . 예를 들면 다음과 같습니다.

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(50.0f, 50.0f, 400.0f, 400.0f)];    
view1.backgroundColor = [UIColor redColor];

UIView* view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];    
view2.backgroundColor = [UIColor yellowColor];

[view1 addSubview:view2];

bounds뷰 를 변경하면 다른 동작이 발생합니다 . 예를 들어,을 변경하면 변경 사항 bounds sizeframe적용되며 그 반대의 경우도 마찬가지입니다. center뷰 주변에서 변경이 발생 합니다. 아래 코드를 사용하여 어떤 일이 발생하는지 확인하십시오.

NSLog(@"Old Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"Old Center %@", NSStringFromCGPoint(view2.center));    

CGRect frame = view2.bounds;
frame.size.height += 20.0f;
frame.size.width += 20.0f;
view2.bounds = frame;

NSLog(@"New Frame %@", NSStringFromCGRect(view2.frame));
NSLog(@"New Center %@", NSStringFromCGPoint(view2.center));

또한 변경 bounds origin하면 origin내부 좌표계가 변경 됩니다. 기본적으로 origin(0.0, 0.0)(왼쪽 상단)에 있습니다. 변경할 경우 예를 들어, origin에 대한 view1당신이 볼 수에 대한 이제 왼쪽 상단 (당신이 원하는 경우 이전 코드 주석) view2에 닿을 view1하나. 동기는 매우 간단합니다. view1왼쪽 상단이 현재 위치에 (20.0, 20.0)있지만 view2frame origin시작부터 (20.0, 20.0)일치 한다고 말합니다 .

CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame; 

의 내부 위치를 origin나타내지 만 중심 위치를 나타냅니다 .viewsuperviewbounds

마지막으로 bounds하고 origin있는 개념을 관련이 없습니다. 둘 다 frame뷰 를 도출 할 수 있습니다 (이전 방정식 참조).

View1의 사례 연구

다음 스 니펫을 사용하면 어떻게됩니까?

UIView* view1 = [[UIView alloc] initWithFrame:CGRectMake(30.0f, 20.0f, 400.0f, 400.0f)];
view1.backgroundColor = [UIColor redColor];

[[self view] addSubview:view1];

NSLog(@"view1's frame is: %@", NSStringFromCGRect([view1 frame]));
NSLog(@"view1's bounds is: %@", NSStringFromCGRect([view1 bounds]));
NSLog(@"view1's center is: %@", NSStringFromCGPoint([view1 center]));

상대 이미지.

여기에 이미지 설명을 입력하십시오

대신 [self view]다음과 같이 범위를 변경하면 어떻게됩니까 ?

// previous code here...
CGRect rect = [[self view] bounds];
rect.origin.x += 30.0f;
rect.origin.y += 20.0f;
[[self view] setBounds:rect];

상대 이미지.

여기에 이미지 설명을 입력하십시오

여기서 [self view]왼쪽 상단 모서리는 (30.0, 20.0) 위치에 있지만 view1프레임의 원점이 (30.0, 20.0)부터 시작하므로 일치합니다.

추가 참조 (원하는 경우 다른 참조로 업데이트)

clipsToBounds(출처 Apple Doc)에 관하여

이 값을 YES로 설정하면 서브 뷰가 수신자의 경계에 잘립니다. NO로 설정하면 프레임이 수신자의 가시 범위를 넘어 확장되는 서브 뷰는 클리핑되지 않습니다. 기본값은 NO입니다.

즉,보기 frame(0, 0, 100, 100)있고 해당 하위 보기가 인 경우 해당 하위 보기의 (90, 90, 30, 30)일부만 볼 수 있습니다. 후자는 상위 뷰의 범위를 초과하지 않습니다.

masksToBounds와 같습니다 clipsToBounds. 에 대신 UIView이 속성이에 적용됩니다 CALayer. 후드 아래에서을 clipsToBounds호출합니다 masksToBounds. 자세한 내용 은 UIView의 clipsToBounds와 CALayer의 masksToBounds 간의 관계는 무엇입니까?를 참조하십시오. .


@Rhubarb 당신은 완벽하게 맞습니다. 나는 내 대답에서 지적 할 것입니다. 감사.
Lorenzo B

대답을 얻을지 모르겠지만 경계 원점이 변경되면 하위 뷰가 음의 방향으로 이동하는 이유는 무엇입니까? 그 머리 주위에 내 머리를 넣을 수없는 것 같습니다. 감사!!
nimgrg 2016 년

@nimgrg 뷰가 음의 방향으로 움직이는 것 같지만 그렇지 않습니다. 수퍼 뷰의 내부 좌표가 변경되었습니다.
Lorenzo B

수퍼 뷰의 내부 좌표가 원점 (30.0, 20.0)으로 변경되면 점 (0,0)이 파란색 사각형 내부 또는 외부에 놓이는 경우 내 기하 능력을 용서하십시오. 변경 사항을 추적하고 이해하려고합니다. 답변을 주셔서 감사합니다.
nimgrg

@flexaddicted : 안녕하세요, 추가 한 슬라이드는 다음과 같이 말합니다. "자체 좌표 공간에서 B의 가운데보기 : bounds.size.width / 2 + origin.x"-왜 이런가요? 제목 이 자체 좌표 공간에 있다고 말하면 bounds.size.width / 2 + bounds.origin.x ?? 그렇지 않습니까?

134

이 질문에는 이미 좋은 대답이 있지만 더 많은 그림으로 보충하고 싶습니다. 내 대답은 여기에 있습니다.

프레임을 기억할 수 있도록 벽에 액자가 있다고 생각 합니다. 벽의 어느 곳으로나 사진을 옮길 수있는 것처럼 뷰 프레임의 좌표계는 수퍼 뷰입니다. (벽 = 슈퍼 뷰, 프레임 = 뷰)

바운드를 기억할 수 있도록 농구장의 바운드를 생각 합니다 . 농구는 뷰 경계의 좌표 시스템이 뷰 자체 내에있는 것처럼 코트 내 어딘가에 있습니다. (court = view, basketball / players =보기 내부의 내용)

프레임과 마찬가지로 view.center 도 수퍼 뷰의 좌표에 있습니다.

프레임 대 바운드-예 1

노란색 사각형은보기의 프레임을 나타냅니다. 녹색 사각형은 뷰의 경계를 나타냅니다. 두 이미지의 빨간색 점은 좌표계 내에서 프레임의 원점 또는 경계를 나타냅니다.

Frame
    origin = (0, 0)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

여기에 이미지 설명을 입력하십시오


실시 예 2

Frame
    origin = (40, 60)  // That is, x=40 and y=60
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

여기에 이미지 설명을 입력하십시오


실시 예 3

Frame
    origin = (20, 52)  // These are just rough estimates.
    width = 118
    height = 187

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

여기에 이미지 설명을 입력하십시오


실시 예 4

이것은보기의 전체 내용이보기의 경계에 잘리지 않는 것처럼 보이기 때문에보기 2의 경우를 제외하고는 예 2와 동일합니다.

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (0, 0)
    width = 80
    height = 130

여기에 이미지 설명을 입력하십시오


실시 예 5

Frame
    origin = (40, 60)
    width = 80
    height = 130

Bounds 
    origin = (280, 70)
    width = 80
    height = 130

여기에 이미지 설명을 입력하십시오

다시 한 번 더 자세한 내용 은 여기 를 참조 하십시오 .


2
감사합니다. 프레임과 바운드 차이의 매우 명확한 그림입니다. 당신의 노력에 진심으로 감사드립니다.
Mohd Haider

하나의 짧고 간결한 답변으로보고 싶은 모든 것. 감사!
Matt Chuang

대박! 예를 들어 3 : 나는 그것을 얻지 못한다. 프레임 원점을 조금만 움직였을 때 이미지의 회전이 어떻게 변경됩니까?
Honey

@ asma22, 예제 3에서는 이미지를 회전 할 때 프레임이 변경되지만 경계는 변경되지 않음을 보여 주려고했습니다. 더 자세한 답변을 참조하십시오 .
Suragch

89

이 이미지는 프레임, 경계 등을 이해하는 데 가장 도움이됩니다.

여기에 이미지 설명을 입력하십시오

또한 frame.size != bounds.size이미지가 회전 할 때 주의하십시오 .


14
천 단어의 가치가있는 그림.
Narendra Kamma

3
가장 좋은 설명
Ratikanta Patra

@Erben Mo : 안녕하세요. 추가 한 슬라이드에 "자체 좌표 공간에서 B의 중간보기는 bounds.size.width / 2 + origin.x"입니다. 왜 이런 경우입니까? 제목 이 자체 좌표 공간에 있다고 말하면 bounds.size.width / 2 + bounds.origin.x ?? 그렇지 않습니까?

1
이 이미지의 출처는 무엇입니까? 링크?
David

1
iTunesU가 여기에 그것은 물론 스탠포드의 CS193p에서의 @ 데이비드 : www.stanford.edu/class/cs193p/cgi-bin/drupal/downloads-2013-fall은
preynolds

3

의 관점에서 생각하면 CALayer모든 것이 더 명확 하다고 생각합니다 .

프레임은 실제로 뷰 또는 레이어의 고유 한 속성이 아니며, 경계, 위치 ( UIView및 중심) 및 변환 에서 계산 된 가상 속성 입니다.

기본적으로 레이어 / 뷰 레이아웃이이 세 가지 속성 (및 anchorPoint)에 의해 실제로 결정되는 방식이며이 세 가지 속성 중 하나는 변형 변경으로 범위가 변경되지 않는 등 다른 속성은 변경되지 않습니다.


2

이 게시물에 대한 자세한 설명과 함께 좋은 답변이 있습니다. WWDC 2011 비디오에서 Frame, Bounds, Center, Transform, Bounds Origin의 의미를 시각적으로 나타내는 또 다른 설명이 있습니다 .4 : 22에서 20:10까지 UIKit 렌더링 이해


0

위의 답변을 읽은 후 여기에 해석을 추가합니다.

온라인으로 탐색한다고 가정하면 웹 브라우저frame웹 페이지를 표시 할 위치와 크기를 결정합니다. 브라우저의 스크롤러bounds.origin웹 페이지의 어느 부분을 표시할지 결정합니다. bounds.origin이해하기 어렵다. 배우는 가장 좋은 방법은 Single View Application을 생성하고 이러한 매개 변수를 수정하여 하위 뷰가 어떻게 변경되는지 확인하는 것입니다.

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

UIView *view1 = [[UIView alloc] initWithFrame:CGRectMake(100.0f, 200.0f, 200.0f, 400.0f)];
[view1 setBackgroundColor:[UIColor redColor]];

UIView *view2 = [[UIView alloc] initWithFrame:CGRectInset(view1.bounds, 20.0f, 20.0f)];
[view2 setBackgroundColor:[UIColor yellowColor]];
[view1 addSubview:view2];

[[self view] addSubview:view1];

NSLog(@"Old view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"Old view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));

// Modify this part.
CGRect bounds = view1.bounds;
bounds.origin.x += 10.0f;
bounds.origin.y += 10.0f;

// incase you need width, height
//bounds.size.height += 20.0f;
//bounds.size.width += 20.0f;

view1.bounds = bounds;

NSLog(@"New view1 frame %@, bounds %@, center %@", NSStringFromCGRect(view1.frame), NSStringFromCGRect(view1.bounds), NSStringFromCGPoint(view1.center));
NSLog(@"New view2 frame %@, bounds %@, center %@", NSStringFromCGRect(view2.frame), NSStringFromCGRect(view2.bounds), NSStringFromCGPoint(view2.center));
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.