코코아 : 프레임과 경계의 차이점은 무엇입니까?


587

UIView와 그 서브 클래스는 모든 속성을 가지고 framebounds. 차이점이 뭐야?



나를 위해 가장 간결한 설명은 다음과 같습니다. videos.raywenderlich.com/courses/99-scroll-view-school/lessons/…
Vlad

1
2:30 비디오에 대해 간결한 것은 없습니다. 2:30보다 한두 문장 빨리 읽을 수 있습니다.
dsjoerg

나를 위해 내가 이런 식으로 생각하면 훨씬 더 명확합니다 : 프레임 = 경계 및 위치
Serg

답변:


902

경계 의 AN 의 UIView는 은 IS 직사각형 자체 좌표계 (0,0)에 대해, 위치 (x, y) 및 크기 (폭, 높이)로 표현.

프레임 의 AN 의 UIView는 은 IS 사각형 이 포함 된 수퍼 상대 위치 (x, y)의 크기 (폭, 높이)로 표현.

따라서 슈퍼 뷰의 25,25 (x, y)에 100x100 (너비 x 높이) 크기의 뷰가 있다고 가정하십시오. 다음 코드는이 뷰의 경계와 프레임을 인쇄합니다.

// This method is in the view controller of the superview
- (void)viewDidLoad {
    [super viewDidLoad];

    NSLog(@"bounds.origin.x: %f", label.bounds.origin.x);
    NSLog(@"bounds.origin.y: %f", label.bounds.origin.y);
    NSLog(@"bounds.size.width: %f", label.bounds.size.width);
    NSLog(@"bounds.size.height: %f", label.bounds.size.height);

    NSLog(@"frame.origin.x: %f", label.frame.origin.x);
    NSLog(@"frame.origin.y: %f", label.frame.origin.y);
    NSLog(@"frame.size.width: %f", label.frame.size.width);
    NSLog(@"frame.size.height: %f", label.frame.size.height);
}

이 코드의 출력은 다음과 같습니다.

bounds.origin.x: 0
bounds.origin.y: 0
bounds.size.width: 100
bounds.size.height: 100

frame.origin.x: 25
frame.origin.y: 25
frame.size.width: 100
frame.size.height: 100

따라서 두 경우 모두 경계 또는 프레임을 보든 관계없이 뷰의 너비와 높이가 동일하다는 것을 알 수 있습니다. 다른 점은 뷰의 x, y 위치입니다. 경계의 경우 이러한 좌표는 뷰 자체에 상대적이므로 x 및 y 좌표는 0,0입니다. 그러나 프레임 x 및 y 좌표는 상위 뷰 내에서 뷰의 위치를 ​​기준으로합니다 (이전에는 25,25에 있음).

도있다 훌륭한 프리젠 테이션 UIViews을 다룹니다. 프레임과 경계의 차이를 설명 할뿐만 아니라 시각적 인 예를 보여주는 슬라이드 1-20을 참조하십시오.


37
따라서 경계의 x, y는 객체 자체의 위치 때문에 항상 0,0이 아닙니다 ... 아니면 그렇지 않은 시나리오를 줄 수 있습니까?
mk12

5
내가 아는 한, 경계의 원점은 항상 0,0입니다.
shek

77
실제로 bounds.origin은 0,0 이외의 것일 수 있습니다. 원점을 이동 / 번역하려면 setBoundsOrigin :을 사용하십시오. 자세한 내용은 "Cocoa 용 프로그래밍 안내서"의 "View Geometry"를 참조하십시오.
Meltemi

127
UIScrollView는 경계가 뷰 내에서 다른 내용 영역을 표시하도록 이동할 수있는 예입니다.
Brad Larson

92
작은 팁-NSStringFromCGRect를 사용하면 rect를 로그하는 데 시간을 절약 할 수 있습니다.
beryllium

645

짧은 답변

프레임 = 부모 뷰의 좌표계를 사용하는 뷰의 위치 및 크기

  • 중요 : 뷰를 부모에 배치

경계 = 자체 좌표계를 사용하여 뷰의 위치 및 크기

  • 중요 :보기의 컨텐츠 또는 하위보기를 자체 내에 배치

자세한 답변

프레임을 기억할 수 있도록 벽에 액자가 있다고 생각 합니다. 액자는보기의 경계와 같습니다. 벽에 원하는 곳 어디든 사진을 걸 수 있습니다. 같은 방식으로 부모 뷰 내부에 원하는 위치에 뷰를 넣을 수도 있습니다 (슈퍼 뷰라고도 함). 부모 뷰는 벽과 같습니다. iOS에서 좌표계의 원점은 왼쪽 상단입니다. 뷰 프레임의 xy 좌표를 (0, 0)으로 설정하여 슈퍼 뷰의 원점을 볼 수 있습니다. 이는 벽의 가장 왼쪽 상단에 사진을 걸어 놓는 것과 같습니다. 오른쪽으로 이동하려면 x를 높이고 아래로 이동하면 y가 증가합니다.

내가 바운드를 기억하는 것을 돕기 위해 , 나는 때때로 농구가 바운드에서 넘어지는 농구 코트를 생각 합니다 . 당신은 농구 코트 전체에 공을 드리블하지만, 법원 자체가 어디에 있는지는 실제로 신경 쓰지 않습니다. 체육관에있을 수도 있고, 고등학교 외부에 있거나 집 앞에있을 수도 있습니다. 중요하지 않습니다. 당신은 단지 농구를 원합니다. 같은 방식으로 뷰 경계의 좌표계는 뷰 자체에만 관심이 있습니다. 상위 뷰에서 뷰의 위치에 대해서는 아무것도 모릅니다. 경계의 원점 (기본적으로 (0, 0))은 뷰의 왼쪽 상단입니다. 이 견해에 대한 모든 견해는이 점과 관련하여 제시됩니다. 농구를 코트의 왼쪽 앞쪽 모서리로 가져가는 것과 같습니다.

이제 프레임과 경계를 비교하려고 할 때 혼란이 생깁니다. 그러나 실제로 처음에는 나쁘지 않습니다. 이해를 돕기 위해 그림을 사용합시다.

프레임 대 바운드

왼쪽의 첫 번째 그림에는 부모보기의 왼쪽 상단에있는보기가 있습니다. 노란색 사각형은보기의 프레임을 나타냅니다. 오른쪽에 우리는 다시보기를 볼 수 있지만 이번에는 부모보기가 표시되지 않습니다. 경계가 부모 뷰에 대해 알지 못하기 때문입니다. 녹색 사각형은 뷰의 경계를 나타냅니다. 두 이미지 의 빨간색 점 은 프레임 의 원점 을 나타냅니다 .

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

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

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

따라서 그림과 프레임과 경계는 동일합니다. 그것들이 다른 예를 보자.

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

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

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

따라서 프레임의 xy 좌표를 변경하면 부모 뷰에서 프레임이 이동한다는 것을 알 수 있습니다. 그러나 뷰 자체의 내용은 여전히 ​​똑같이 보입니다. 한계는 다른 것이 무엇인지 전혀 모른다.

지금까지 프레임과 경계의 너비와 높이는 정확히 동일했습니다. 그러나 항상 그런 것은 아닙니다. 뷰를 시계 방향으로 20도 회전하면 어떻게되는지보십시오. (회전은 변환을 사용하여 수행됩니다. 자세한 내용은 설명서 와 이러한 보기레이어 예제 를 참조하십시오.)

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

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

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

경계가 여전히 같다는 것을 알 수 있습니다. 그들은 여전히 ​​어떤 일이 일어 났는지 모른다! 그러나 프레임 값이 모두 변경되었습니다.

이제 프레임과 경계의 차이를 보는 것이 조금 더 쉽습니다. 그렇지 않습니까? 아마도 프레임과 경계를 이해하지 못하는 기사 는 뷰 프레임을 다음과 같이 정의합니다.

... 부모 좌표계와 관련하여 해당 뷰에 적용된 모든 변형을 포함하여 해당 뷰의 가장 작은 경계 상자입니다.

뷰를 변환하면 프레임이 정의되지 않습니다. 실제로 위의 이미지에서 회전 된 녹색 경계 주위에 그린 노란색 프레임은 실제로 존재하지 않습니다. 즉, 회전, 크기 조정 또는 다른 변형을 수행하는 경우 더 이상 프레임 값을 사용하지 않아야합니다. 그래도 범위 값을 사용할 수 있습니다. Apple 문서는 경고합니다.

중요 사항 : 보기의 transform특성에 ID 변환이 포함되어 있지 않으면 해당보기의 프레임이 정의되지 않아 자동 크기 조정 동작의 결과도 나타납니다.

자동 크기 조정에 대해서는 오히려 불행한 일이지만 ... 할 수있는 일이 있습니다.

Apple 문서는 다음과 같이 말합니다.

transform뷰 의 속성을 수정할 때 뷰의 중심점을 기준으로 모든 변형이 수행됩니다.

따라서 변환이 완료된 후 부모에서 뷰를 이동해야하는 경우 view.center좌표 를 변경하여 볼 수 있습니다 . 마찬가지로 frame, center부모 뷰의 좌표 시스템을 사용합니다.

자, 회전을 없애고 경계에 집중합시다. 지금까지 경계 원점은 항상 (0, 0)에 머물 렀습니다. 하지만 꼭 그럴 필요는 없습니다. 뷰에 큰 서브 뷰가 너무 커서 한 번에 모두 표시 할 수 없으면 어떻게됩니까? 우리는 그것을 UIImageView큰 이미지로 만들 것 입니다. 여기 위에서 다시 두 번째 그림이 있지만 이번에는 뷰 하위 뷰의 전체 내용이 어떻게 표시되는지 확인할 수 있습니다.

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

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

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

이미지의 왼쪽 위 모서리 만 뷰의 경계 안에 들어갈 수 있습니다. 이제 경계의 원점 좌표를 변경하면 어떻게되는지보십시오.

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

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

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

수퍼 뷰에서 프레임이 이동하지 않았지만 경계 사각형의 원점이 뷰의 다른 부분에서 시작하기 때문에 프레임 내부의 내용이 변경되었습니다. 이것은 a의 기본 개념 UIScrollView이며 하위 클래스입니다 (예 : a UITableView). 자세한 설명은 UIScrollView 이해를 참조하십시오 .

프레임 사용시기 및 경계 사용시기

frame상위 뷰에서 뷰의 위치를 ​​관련시키기 때문에 너비를 변경하거나 뷰와 상위 뷰의 상단 사이의 거리를 찾는 등 외부 변경을 할 때 사용합니다 .

뷰 내에서 사물을 그리거나 하위 뷰를 배열하는 것과 같이 안쪽으로 변경 하는 bounds경우를 사용하십시오 . 또한 일부 transfomation을 수행 한 경우 경계를 사용하여 뷰의 크기를 가져옵니다.

추가 연구를위한 기사 :

애플 문서

관련 StackOverflow 질문

기타 자료

자신을 연습

위의 기사를 읽는 것 외에도 테스트 앱을 만드는 데 많은 도움이됩니다. 비슷한 것을 시도하고 싶을 수도 있습니다. ( 이 비디오 과정 에서 아이디어를 얻었 지만 불행히도 무료는 아닙니다.)

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

다음은 참조 용 코드입니다.

import UIKit

class ViewController: UIViewController {


    @IBOutlet weak var myView: UIView!

    // Labels
    @IBOutlet weak var frameX: UILabel!
    @IBOutlet weak var frameY: UILabel!
    @IBOutlet weak var frameWidth: UILabel!
    @IBOutlet weak var frameHeight: UILabel!
    @IBOutlet weak var boundsX: UILabel!
    @IBOutlet weak var boundsY: UILabel!
    @IBOutlet weak var boundsWidth: UILabel!
    @IBOutlet weak var boundsHeight: UILabel!
    @IBOutlet weak var centerX: UILabel!
    @IBOutlet weak var centerY: UILabel!
    @IBOutlet weak var rotation: UILabel!

    // Sliders
    @IBOutlet weak var frameXSlider: UISlider!
    @IBOutlet weak var frameYSlider: UISlider!
    @IBOutlet weak var frameWidthSlider: UISlider!
    @IBOutlet weak var frameHeightSlider: UISlider!
    @IBOutlet weak var boundsXSlider: UISlider!
    @IBOutlet weak var boundsYSlider: UISlider!
    @IBOutlet weak var boundsWidthSlider: UISlider!
    @IBOutlet weak var boundsHeightSlider: UISlider!
    @IBOutlet weak var centerXSlider: UISlider!
    @IBOutlet weak var centerYSlider: UISlider!
    @IBOutlet weak var rotationSlider: UISlider!

    // Slider actions
    @IBAction func frameXSliderChanged(sender: AnyObject) {
        myView.frame.origin.x = CGFloat(frameXSlider.value)
        updateLabels()
    }
    @IBAction func frameYSliderChanged(sender: AnyObject) {
        myView.frame.origin.y = CGFloat(frameYSlider.value)
        updateLabels()
    }
    @IBAction func frameWidthSliderChanged(sender: AnyObject) {
        myView.frame.size.width = CGFloat(frameWidthSlider.value)
        updateLabels()
    }
    @IBAction func frameHeightSliderChanged(sender: AnyObject) {
        myView.frame.size.height = CGFloat(frameHeightSlider.value)
        updateLabels()
    }
    @IBAction func boundsXSliderChanged(sender: AnyObject) {
        myView.bounds.origin.x = CGFloat(boundsXSlider.value)
        updateLabels()
    }
    @IBAction func boundsYSliderChanged(sender: AnyObject) {
        myView.bounds.origin.y = CGFloat(boundsYSlider.value)
        updateLabels()
    }
    @IBAction func boundsWidthSliderChanged(sender: AnyObject) {
        myView.bounds.size.width = CGFloat(boundsWidthSlider.value)
        updateLabels()
    }
    @IBAction func boundsHeightSliderChanged(sender: AnyObject) {
        myView.bounds.size.height = CGFloat(boundsHeightSlider.value)
        updateLabels()
    }
    @IBAction func centerXSliderChanged(sender: AnyObject) {
        myView.center.x = CGFloat(centerXSlider.value)
        updateLabels()
    }
    @IBAction func centerYSliderChanged(sender: AnyObject) {
        myView.center.y = CGFloat(centerYSlider.value)
        updateLabels()
    }
    @IBAction func rotationSliderChanged(sender: AnyObject) {
        let rotation = CGAffineTransform(rotationAngle: CGFloat(rotationSlider.value))
        myView.transform = rotation
        updateLabels()
    }

    private func updateLabels() {

        frameX.text = "frame x = \(Int(myView.frame.origin.x))"
        frameY.text = "frame y = \(Int(myView.frame.origin.y))"
        frameWidth.text = "frame width = \(Int(myView.frame.width))"
        frameHeight.text = "frame height = \(Int(myView.frame.height))"
        boundsX.text = "bounds x = \(Int(myView.bounds.origin.x))"
        boundsY.text = "bounds y = \(Int(myView.bounds.origin.y))"
        boundsWidth.text = "bounds width = \(Int(myView.bounds.width))"
        boundsHeight.text = "bounds height = \(Int(myView.bounds.height))"
        centerX.text = "center x = \(Int(myView.center.x))"
        centerY.text = "center y = \(Int(myView.center.y))"
        rotation.text = "rotation = \((rotationSlider.value))"

    }

}

경계의 너비와 높이가 중복 된 것처럼 보이고 "원본"속성이 충분했을 것입니다 (Flash와 마찬가지로).
Ian Warburton

"보기 내에서 사물을 그리거나 하위 뷰를 배열하는 것과 같이"에 경계를 사용하십시오. 두 개의 버튼이있는 viewController가있는 경우 viewController의 '바운드'를 사용하여 버튼을 배치해야합니까?! 나는 항상보기의 프레임을 사용했습니다 ...
Honey

@Honey, 나는 작년에 Android에서 일한 이래로 iOS 기술에 조금 녹슬 었습니다. View Controller의 루트보기가 화면을 채우므로 프레임과 경계가 같아야합니다.
Suragch

5
만든 github.com/maniramezan/FrameVsBounds.git을 이해하는 더 나은 도움말을 여기에 주어진 예제 응용 프로그램을 기반으로 REPO boundsframe뷰의.
manman

1
@IanWarburton 뷰가 회전 될 때 경계의 너비와 높이가 프레임의 너비와 높이와 일치하지 않으므로 중복되지 않습니다.
Edward Brey

43

아래 코드를 실행하십시오

- (void)viewDidLoad {
    [super viewDidLoad];
    UIWindow *w = [[UIApplication sharedApplication] keyWindow];
    UIView *v = [w.subviews objectAtIndex:0];

    NSLog(@"%@", NSStringFromCGRect(v.frame));
    NSLog(@"%@", NSStringFromCGRect(v.bounds));
}

이 코드의 출력은 다음과 같습니다.

케이스 장치 방향이 세로

{{0, 0}, {768, 1024}}
{{0, 0}, {768, 1024}}

케이스 장치 방향은 가로

{{0, 0}, {768, 1024}}
{{0, 0}, {1024, 768}}

분명히, 당신은 프레임과 경계의 차이를 볼 수 있습니다


2
이것은 더 이상 사실이 아니다 (iOS 8)
Julian Król


13

프레임 과의 UIView를 정의하는 직사각형 의 수퍼 대하여 .

RECT 경계 되도록 정의 값의 범위 NSView의 좌표계입니다.

즉,이 사각형의 모든 것은 실제로 UIView에 표시됩니다.


10

frame 은 수퍼 뷰의 좌표계에서 뷰의 원점 (왼쪽 상단)과 뷰의 크기입니다. 이것은 프레임 원점, 경계를 변경하여 수퍼 뷰에서 뷰를 변환한다는 것을 의미 합니다 는 그 크기와 원점입니다 자체 좌표계이므로 기본적으로 경계 원점은 (0,0)입니다.

대부분의 경우 프레임과 경계가 합동이지만 프레임 ((140,65), (200,250)) 및 경계 ((0,0), (200,250))의 뷰가 있고 뷰가 기울어 진 경우 오른쪽 하단에 서 있도록 경계는 여전히 ((0,0), (200,250))이지만 프레임은 아닙니다.

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

프레임은 뷰를 캡슐화 / 서라운드하는 가장 작은 사각형이므로 사진과 같이 프레임은 ((140,65), (320,320)이됩니다.

또 다른 차이점은 예를 들어 범위가 ((0,0), (200,200)) 인 superView가 있고이 superView에 프레임이 ((20,20), (100,100)) 인 subView가 있고 superView 범위를 변경 한 경우 ((20,20), (200,200))이면 subView 프레임은 여전히 ​​((20,20), (100,100))이지만 슈퍼 뷰 좌표계가 (20, 20).

나는 이것이 누군가를 돕기를 바랍니다.


마지막 단락과 관련하여 : subView frame은 그것과 관련이 superView있습니다. superView범위를 변경하면 subView원점이 그것과 일치 하지 않습니다 superView.
staticVoidMan

5

SuperView를 기준으로 프레임을 구성하고 NSView를 기준으로 경계를 설정합니다.

예 : X = 40, Y = 60. 또한 3 개의 뷰가 포함되어 있습니다.이 다이어그램은 명확한 아이디어를 보여줍니다.

틀

범위


4

5 센트를 추가하겠습니다.

프레임 은 뷰의 상위 뷰에서 상위 뷰 내에 배치하는 데 사용됩니다.

바운드 는 뷰 자체에서 자체 컨텐츠를 배치하기 위해 사용됩니다 (스크롤 뷰가 스크롤하는 동안). clipsToBounds 도 참조하십시오 . 경계를 사용하여 뷰의 내용을 확대 / 축소 할 수도 있습니다.

유추 :
프레임 ~ TV 화면
경계 ~ 카메라 (확대, 이동, 회전)


2

위의 답변은 경계와 프레임의 차이점을 잘 설명했습니다.

경계 : 자체 좌표계에 따른 뷰 크기 및 위치.

프레임 : SuperView를 기준으로 한 뷰 크기 및 위치입니다.

그러면 경계의 경우 X, Y가 항상 "0"이된다는 혼동이 있습니다. 사실이 아닙니다 . UIScrollView 및 UICollectionView에서도 이해할 수 있습니다.

경계의 x, y가 0이 아닌
경우 UIScrollView가 있다고 가정합니다. 페이지 매김을 구현했습니다. UIScrollView는 3 페이지이며 ContentSize의 너비는 화면 너비의 3 배입니다 (ScreenWidth가 320이라고 가정). 높이는 일정합니다 (200으로 가정).

scrollView.contentSize = CGSize(x:320*3, y : 200)

세 개의 UIImageView를 subView로 추가하고 프레임 의 x 값을 자세히 살펴보십시오.

let imageView0 = UIImageView.init(frame: CGRect(x:0, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
let imageView1 :  UIImageView.init( frame: CGRect(x:320, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
let imageView2 :  UIImageView.init(frame: CGRect(x:640, y: 0 , width : scrollView.frame.size.width, height : scrollView.frame.size.height))
scrollView.addSubview(imageView0)
scrollView.addSubview(imageView0)
scrollView.addSubview(imageView0)
  1. 페이지 0 : ScrollView가 0 페이지 인 경우 경계는 (x : 0, y : 0, 너비 : 320, 높이 : 200)입니다.

  2. 1 페이지 : 스크롤하여 1 페이지로 이동합니다.
    이제 경계는 (x : 320, y : 0, 너비 : 320, 높이 : 200) 입니다. 자체 좌표계와 관련하여 말했음을 기억하십시오. 이제 ScrollView의 "Visible Part"는 320에서 "x"를 갖습니다. imageView1의 프레임을보십시오.

  3. 페이지 2 : 스크롤하여 페이지 2로 이동 경계 : (x : 640, y : 0, 너비 : 320, 높이 : 200) 다시 imageView2의 프레임을 살펴보십시오

UICollectionView의 경우에도 동일합니다. collectionView를 보는 가장 쉬운 방법은 그것을 스크롤하고 경계를 인쇄 / 기록하는 것입니다.


2

위의 모든 답변은 정확하며 이것이 내가 취하는 것입니다.

프레임과 경계를 구별하려면 CONCEPTS 개발자는 다음을 읽어야합니다.

  1. 수퍼 뷰 (상위 뷰 하나)에 대해 = FRAME에 포함됩니다.
  2. 자체 좌표계를 기준으로 하위 뷰 위치 결정 = BOUNDS

"바운드"는 좌표가 설정된 뷰의 위치라는 인상을주기 때문에 혼동됩니다. 그러나 이들은 관계가 있으며 프레임 상수에 따라 조정됩니다.

아이폰 화면


1

프레임과 경계의 차이를 보여주는 그림이 하나 더 있습니다. 이 예에서 :

  • View B 의 하위 견해입니다 View A
  • View B 로 이동 x:60, y: 20
  • View B 회전했다 45 degrees

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


0

프레임 대 바운드

  • X : 0, Y : 0, 너비 : 400, 높이 : 400에서 뷰를 만들면 프레임과 경계가 동일합니다.
  • 해당 뷰를 X : 400으로 이동하면 해당 프레임에 해당 변경 사항이 반영되지만 경계는 적용되지 않습니다. 경계는 뷰 자체 공간과 관련이 있으며 내부적으로 뷰에는 아무런 변화가 없습니다.
  • 뷰를 회전 시키거나 확대하는 등의 뷰를 변형하면 프레임이이를 반영하도록 변경되지만 뷰가 내부적으로 관련되어있는 한 경계는 변경되지 않습니다.
  • 경계를 변경하면 경계 사각형의 원점이 뷰의 다른 부분에서 시작하기 때문에 프레임 내부의 내용이 변경됩니다.

-1

프레임 = 부모 뷰의 좌표계를 사용하는 뷰의 위치 및 크기

경계 = 자체 좌표계를 사용하여 뷰의 위치 및 크기

뷰는 프레임 사각형과 경계 사각형의 두 사각형을 사용하여 크기와 위치를 추적합니다. 프레임 사각형은 슈퍼 뷰의 좌표계를 사용하여 슈퍼 뷰에서 뷰의 위치와 크기를 정의합니다. 경계 사각형은 원점 및 배율을 포함하여 뷰의 내용을 그릴 때 사용되는 내부 좌표계를 정의합니다. 그림 2-1은 프레임 사각형 (왼쪽)과 경계 사각형 (오른쪽)의 관계를 보여줍니다.”

간단히 말해서 프레임은 뷰에 대한 수퍼 뷰의 아이디어이고 범위는 뷰 자체의 아이디어입니다. 각 뷰마다 하나씩 여러 좌표계를 갖는 것은 뷰 계층의 일부입니다.


그림 2-1은 어디에 있습니까?
Alexander Mayatsky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.