[objective-c] UIView 프레임, 경계 및 중심

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

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

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

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

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



답변

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

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

프레임 보기 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 간의 관계는 무엇입니까?를 참조하십시오. .


답변

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

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

바운드를 기억할 수 있도록 농구장의 바운드를 생각 합니다 . 농구는 뷰 경계의 좌표 시스템이 뷰 자체 내에있는 것처럼 코트 내 어딘가에 있습니다. (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

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

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


답변

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

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

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


답변

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

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

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


답변

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


답변

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

온라인으로 탐색한다고 가정하면 웹 브라우저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));


답변