Рамка, границы и центр UIView

Я хотел бы знать, как правильно использовать эти свойства.

как я понимаю, frame может использоваться из контейнера представления, которое я создаю. Он задает положение представления относительно представления контейнера. Он также устанавливает размер этого представления.

и center можно использовать из контейнера представления, которое я создаю. Это свойство изменяет положение представления относительно его контейнера.

наконец, bounds относительно представления себя. Он изменяет область рисования для вида.

можете ли вы дать больше информации о взаимоотношениях между frame и bounds? Как насчет clipsToBounds и masksToBounds свойства?

7 ответов


поскольку вопрос, который я задал, был замечен много раз, я дам подробный ответ на него. Не стесняйтесь изменять его, если вы хотите добавить более правильный контент.

сначала резюме по вопросу: фрейм, границы и центр и их отношения.

рама вида frame (CGRect) - это положение его прямоугольника в superviewсистема координат. По умолчанию он начинается в левом верхнем углу.

границы A вид 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

Примечание: эти отношения не распространяется, если вид повернут. Для получения дополнительной информации, я предлагаю вам взглянуть на следующее Изображение взято из На Кухне на основе Стэнфорда CS193p конечно. Кредиты идет к @Rhubarb.

Frame, bounds and center

с помощью 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 subview как вставка первого. Рисунок подпанель требуется знать 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 ' s 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 ' s положение в его 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]));

относительное изображение.

enter image description here

это вместо того, что произойдет, если я изменю [self view] границы следующие.

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

относительное изображение.

enter image description here

здесь вы говорите [self view] что его верхний левый угол теперь находится в позиции (30.0, 20.0), но так как view1начало кадра начинается с (30.0, 20.0), они совпадут.

дополнительная литература (для обновления с другими ссылками, если вы хотите)

о clipsToBounds (источник Apple doc)

значение да подпанелей, обрезается до границ из приемника. Если установлено значение NO, подвиды, фреймы которых выходят за рамки видимые границы приемника не обрезаются. Значение по умолчанию НЕТ.

другими словами, если вид frame is (0, 0, 100, 100) и его подвидом является (90, 90, 30, 30), вы увидите только часть этого подвида. Этот последнее не будет превышать границ родительского представления.

masksToBounds эквивалентно clipsToBounds. Вместо UIView это свойство применяется к CALayer. Под капотом, clipsToBounds звонки masksToBounds. Для дальнейших ссылок взгляните на как связь между clipsToBounds наследник UIView и masksToBounds CALayer это?.


этот вопрос уже есть хороший ответ, но я хочу дополнить его еще несколько фотографий. мой полный ответ здесь.

, чтобы помочь мне вспомнить рама, Я думаю о рама для картины на стене. Так же, как изображение может быть перемещено в любом месте на стене, система координат кадра вида является супервизором. (wall=superview, frame=view)

, чтобы помочь мне вспомнить границы, Я думаю о границы баскетбольной площадки. Баскетбол находится где-то внутри площадки, так же как система координат границ вида находится внутри самого вида. (корт=вид, баскетбол / игроки=содержимое внутри вида)

как рама, вид.центр также находится в координатах superview.

Frame vs Bounds-Пример 1

желтый прямоугольник представляет рамку вида. Зеленый прямоугольник представляет границы вида. Красная точка в обоих изображениях представлено начало кадра или границы в пределах их систем координат.

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

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

enter image description here


Пример 2

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

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

enter image description here


Пример 3

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

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

enter image description here


Пример 4

это то же самое, что и Пример 2, за исключением того, что на этот раз все содержимое представления показано так, как оно выглядело бы, если бы оно не было обрезано до границ вид.

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

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

enter image description here


Пример 5

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

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

enter image description here

еще раз, смотрите здесь для моего ответа с более подробной информацией.


Я нашел это изображение наиболее полезным для понимания рамки, границы и т. д.

enter image description here

Также обратите внимание, что frame.size != bounds.size при повороте изображения.


  • свойство frame содержит прямоугольник frame, который задает размер и расположение представления в системе координат супервизора.
  • свойство bounds содержит прямоугольник bounds, который задает размер представления (и его источник содержимого) в собственной локальной системе координат представления.
  • свойство center содержит известную центральную точку представления в системе координат супервизора.

Я думаю, если вы думаете, что это с точки зрения CALayer, все более ясно.

Frame на самом деле не является отдельным свойством представления или слоя вообще, это виртуальное свойство, вычисленное из границ, позиции (UIViewцентр) и преобразование.

Итак, в основном, как макеты слоя / представления действительно решаются этими тремя свойствами (и точкой привязки), и любое из этих трех свойств не изменит никакого другого свойства, например изменение преобразования не меняет границ.


есть очень хорошие ответы с подробным объяснением этого поста. Я просто хотел бы сослаться на то, что есть еще одно объяснение с визуальным представлением значения фрейма, границ, Центра, преобразования, происхождения границ в WWDC 2011 video Понимание Рендеринга UIKit начиная с @4:22 до 20:10


после прочтения вышеуказанных ответов, здесь добавив мои интерпретации.

предположим, просмотр в интернете,браузер ваш frame, который решает, где и как большой, чтобы показать веб-страницы. скроллер браузер-это ваш bounds.origin это решает, какая часть веб-страницы будет показана. bounds.origin - это трудно понять. Лучший способ узнать-создать приложение с одним представлением, попытаться изменить эти параметры и посмотреть, как изменяются подвиды.

- (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));