이러한 속성을 올바른 방법으로 사용하는 방법을 알고 싶습니다.
내가 이해하는 것처럼, frame
내가 만들고있는보기의 컨테이너에서 사용할 수 있습니다. 컨테이너 뷰를 기준으로 뷰 위치를 설정합니다. 또한 해당 뷰의 크기를 설정합니다.
또한 center
내가 만드는거야 뷰의 컨테이너에서 사용할 수 있습니다. 이 속성은 컨테이너를 기준으로 뷰의 위치를 변경합니다.
마지막으로 bounds
뷰 자체와 관련이 있습니다. 뷰의 드로어 블 영역을 변경합니다.
frame
과 의 관계에 대한 자세한 정보를 제공 할 수 있습니까 bounds
? 무엇에 대한 clipsToBounds
과 masksToBounds
특성?
답변
내가 묻는 질문은 여러 번 보였으므로 자세한 답변을 드리겠습니다. 더 정확한 내용을 추가하려면 자유롭게 수정하십시오.
먼저 질문에 대한 요약 : 프레임, 경계 및 중심과 관계.
프레임 보기 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
size
이 frame
적용되며 그 반대의 경우도 마찬가지입니다. 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)
있지만 view2
의 frame
origin
시작부터 (20.0, 20.0)
일치 한다고 말합니다 .
CGRect frame = view1.bounds;
frame.origin.x += 20.0f;
frame.origin.y += 20.0f;
view1.bounds = frame;
의 내부 위치를 origin
나타내지 만 중심 위치를 나타냅니다 .view
superview
bounds
마지막으로 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));
답변
