objective-c ios uiview frame bounds

objective c - UIView marco, límites y centro



objective-c ios (7)

Me gustaría saber cómo usar estas propiedades de la manera correcta.

Según tengo entendido, el frame se puede utilizar desde el contenedor de la vista que estoy creando. Establece la posición de la vista en relación con la vista del contenedor. También establece el tamaño de esa vista.

También se puede usar el center desde el contenedor de la vista que estoy creando. Esta propiedad cambia la posición de la vista relativa a su contenedor.

Finalmente, los bounds son relativos a la vista en sí. Cambia el área de dibujo para la vista.

¿Puedes dar más información sobre la relación entre frame y bounds ? ¿Qué pasa con las propiedades clipsToBounds y masksToBounds ?


Creo que si lo piensas desde el punto de CALayer , todo está más claro.

El marco no es realmente una propiedad distinta de la vista o capa, es una propiedad virtual, calculada desde los límites, la posición (centro de UIView ) y la transformación.

Básicamente, la forma en que los diseños de capa / vista se deciden realmente por estas tres propiedades (y anchorPoint), y cualquiera de estas tres propiedades no cambiará ninguna otra propiedad, como cambiar la transformación no cambia los límites.


Dado que la pregunta que formulé se ha visto muchas veces, le daré una respuesta detallada. Siéntase libre de modificarlo si desea agregar más contenido correcto.

Primero un resumen de la pregunta: marco, límites y centro y sus relaciones.

Marco El marco de una vista ( CGRect ) es la posición de su rectángulo en el sistema de coordenadas de la vista superview . Por defecto comienza en la parte superior izquierda.

Límites Los límites de una vista ( CGRect ) expresan un rectángulo de vista en su propio sistema de coordenadas.

Centro Un center es un CGPoint expresado en términos del sistema de coordenadas de la vista y determina la posición del punto central exacto de la vista.

Tomadas de UIView + position, estas son las relaciones (no funcionan en código, ya que son ecuaciones informales) entre las propiedades anteriores:

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

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

  • frame.size = bounds.size

NOTA: Estas relaciones no se aplican si se giran las vistas. Para obtener más información, sugeriré que eche un vistazo a la siguiente imagen tomada de The Kitchen Drawer basada en el curso Stanford CS193p . Los créditos van para @Rhubarb .

El uso del frame permite reposicionar y / o redimensionar una vista dentro de su superview . Por lo general, se puede usar desde una superview , por ejemplo, cuando crea una subvista específica. Por ejemplo:

// 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];

Cuando necesita las coordenadas para dibujar dentro de una view , usualmente se refiere a los bounds . Un ejemplo típico podría ser dibujar dentro de una view una subvista como un recuadro de la primera. Dibujar la subvista requiere conocer los bounds de la supervisión. Por ejemplo:

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];

Diferentes comportamientos suceden cuando cambias los bounds de una vista. Por ejemplo, si cambia el size los bounds , el frame cambia (y viceversa). El cambio ocurre alrededor del center de la vista. Usa el código de abajo y mira qué pasa:

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

Además, si cambia el origin bounds , cambia el origin de su sistema de coordenadas interno. Por defecto, el origin está en (0.0, 0.0) (esquina superior izquierda). Por ejemplo, si cambia el origin de la view1 , puede ver (comentar el código anterior si lo desea) que ahora la esquina superior izquierda de la view1 toca la view1 . La motivación es bastante simple. Usted dice a view1 que su esquina superior izquierda ahora está en la posición (20.0, 20.0) pero que el origin frame view2 comienza en (20.0, 20.0) , coincidirán.

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

El origin representa la posición de la view dentro de su superview pero describe la posición del centro de los bounds .

Finalmente, los bounds y el origin no son conceptos relacionados. Ambos permiten derivar el frame de una vista (ver ecuaciones anteriores).

Caso de estudio de View1

Esto es lo que sucede cuando se utiliza el siguiente fragmento de código.

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

La imagen relativa.

Esto, en cambio, qué sucede si cambio los límites de [self view] como el siguiente.

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

La imagen relativa.

Aquí le dice a [self view] que su esquina superior izquierda ahora está en la posición (30.0, 20.0) pero que el origen del marco de view1 comienza en (30.0, 20.0), coincidirán.

Referencias adicionales (para actualizar con otras referencias si lo desea)

Acerca de clipsToBounds (fuente Apple doc)

Establecer este valor en SÍ hace que las subvistas se recorten a los límites del receptor. Si se establece en NO, las subvistas cuyos fotogramas se extienden más allá de los límites visibles del receptor no se recortan. El valor predeterminado es no.

En otras palabras, si el frame una vista es (0, 0, 100, 100) y su subvista es (90, 90, 30, 30) , solo verá una parte de esa subvista. Este último no excederá los límites de la vista principal.

masksToBounds es equivalente a clipsToBounds . En lugar de a UIView , esta propiedad se aplica a un CALayer . Bajo el capó, clipsToBounds llama a masksToBounds . Para obtener más referencias, consulte ¿Cómo es la relación entre los clips ToBounds de UIView y las máscaras ToBounds de CALayer? .


Después de leer las respuestas anteriores, aquí agregando mis interpretaciones.

Supongamos que navegando en línea, el navegador web es su frame que decide dónde y qué tamaño mostrar la página web. La bounds.origin del navegador son sus bounds.origin . El bounds.origin determina qué parte de la página web se mostrará. bounds.origin son difíciles de entender. La mejor manera de aprender es crear una aplicación de vista única, intentando modificar estos parámetros y ver cómo cambian las subvistas.

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


Encontré esta imagen más útil para entender el marco, los límites, etc.

También tenga en cuenta que frame.size != bounds.size cuando se gira la imagen.


Esta pregunta ya tiene una buena respuesta, pero quiero complementarla con algunas fotos más. Mi respuesta completa está aquí.

Para ayudarme a recordar el marco , pienso en un marco de imagen en una pared . Al igual que una imagen se puede mover a cualquier lugar de la pared, el sistema de coordenadas del marco de una vista es la vista de supervisión. (wall = superview, frame = view)

Para ayudarme a recordar límites , pienso en los límites de una cancha de básquetbol . El baloncesto está en algún lugar dentro de la cancha al igual que el sistema de coordenadas de los límites de la vista está dentro de la vista misma. (corte = vista, baloncesto / jugadores = contenido dentro de la vista)

Al igual que el marco, view.center también se encuentra en las coordenadas de la vista de supervisión.

Cuadro vs límites - Ejemplo 1

El rectángulo amarillo representa el marco de la vista. El rectángulo verde representa los límites de la vista. El punto rojo en ambas imágenes representa el origen del marco o los límites dentro de sus sistemas de coordenadas.

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

Ejemplo 2

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

Ejemplo 3

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

Ejemplo 4

Esto es lo mismo que en el ejemplo 2, excepto que esta vez se muestra todo el contenido de la vista, tal como se vería si no se recortara a los límites de la vista.

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

Ejemplo 5

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

Una vez más, ver aquí para mi respuesta con más detalles.


Hay muy buenas respuestas con una explicación detallada de este post. Solo quisiera referirme a que hay otra explicación con representación visual para el significado de Frame, Bounds, Center, Transform, Bounds Origin en WWDC 2011 Comprendiendo el UIKit Rendering a partir de @ 4: 22 hasta 20:10


  • La propiedad de marco contiene el rectángulo de marco, que especifica el tamaño y la ubicación de la vista en el sistema de coordenadas de su supervisión.
  • La propiedad de límites contiene el rectángulo de límites, que especifica el tamaño de la vista (y su origen de contenido) en el propio sistema de coordenadas local de la vista.
  • La propiedad central contiene el punto central conocido de la vista en el sistema de coordenadas de la vista previa.