Pergunta

UIView e suas subclasses todos têm a frame propriedades e bounds. Qual é a diferença?

Foi útil?

Solução

O limites de um UIView é o rectângulo , expressa como uma posição (x, y) e o tamanho (largura, altura) em relação ao seu próprio sistema de coordenadas (0,0).

O quadro de um UIView é o rectângulo , expressa como uma posição (x, y) e o tamanho (largura, altura) em relação ao superview está contido dentro.

Assim, imaginar uma vista que tem um tamanho de 100x100 (largura x altura) posicionado no 25,25 (x, y) da sua superview. As seguintes impressões de código fora limites e quadro deste vista:

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

E a saída desse código é:

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

Assim, podemos ver que em ambos os casos, a largura ea altura da vista é o mesmo, independentemente de que estamos olhando para os limites ou quadro. O que é diferente é o x, y posicionamento da vista. No caso dos limites, as coordenadas x e y são em 0,0 como estas coordenadas são em relação à vista em si. No entanto, a estrutura de coordenadas x e y são em relação à posição da vista dentro da vista principal (que anteriormente foi dito que a 25,25).

Há também um grande apresentação que cobre UIViews. Veja os slides 1-20 que não só explicar a diferença entre os quadros e barrancos, mas também mostram exemplos visuais.

Outras dicas

Resposta Curta

moldura = a localização de um ponto de vista e tamanho usando o vista principal é sistema de coordenadas

  • Importante para: colocar o ponto de vista do pai

limites = a localização de um ponto de vista e tamanho usando o seu próprio sistema de coordenadas

  • Importante para: colocar conteúdo ou subviews da vista dentro de si

resposta detalhada

Para me ajudar a lembrar quadro , penso em um quadro de imagem em uma parede . O quadro de imagem é como a fronteira de um ponto de vista. Eu posso pendurar a qualquer imagem que eu quero na parede. Da mesma forma, eu posso colocar um em qualquer lugar vista eu quero dentro de uma vista pai (também chamado de superview). A vista principal é como a parede. A origem do sistema de coordenadas no iOS é o canto superior esquerdo. Podemos colocar a nossa visão na origem do superview definindo coordenadas-x y do quadro vista a (0, 0), que é como pendurar a nossa imagem no canto muito superior esquerdo da parede. Para movê-lo direito, aumento x, para movê-lo para baixo aumento y.

Para me ajudar a lembrar limites , penso em uma quadra de basquete , onde às vezes o basquete começa batido fora dos limites . Você está driblando a bola por toda a quadra de basquete, mas você realmente não me importo onde o próprio tribunal é. Poderia ser em um ginásio, ou fora em uma escola secundária, ou na frente de sua casa. Não importa. Você só quer jogar basquete. Da mesma forma, o sistema de coordenadas para limites de uma vista só se preocupa com o próprio ponto de vista. Ele não sabe nada sobre onde a vista está localizado na vista principal. origem dos limites (ponto (0, 0), por padrão) é o canto superior esquerdo, do ponto de vista. Quaisquer subviews que esta visão tem são definidos em relação a este ponto. É como tirar a bola para o canto frontal esquerdo do tribunal.

Agora, a confusão vem quando você tentar comparar quadro e limites. Ele realmente não é tão ruim quanto parece à primeira, embora. Vamos usar algumas fotos para nos ajudar a entender.

Quadro vs Bounds

Na primeira foto à esquerda temos uma visão que está localizado na parte superior esquerda da sua vista principal. O retângulo amarelo representa moldura da vista. À direita vemos a vista novamente, mas desta vez o ponto de vista dos pais não é mostrado. Isso porque os limites não sei sobre a vista principal. O retângulo verde representa limites da vista. O Red Dot em ambas as imagens representa o origem do quadro ou limites.

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

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

enter descrição da imagem aqui

Assim, o quadro e limites eram exatamente o mesmo em que a imagem. Vamos olhar um exemplo onde eles são diferentes.

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

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

enter descrição da imagem aqui

Assim você pode ver que a mudança das coordenadas-x y do quadro movimenta na vista principal. Mas o conteúdo da própria visão ainda parece exatamente o mesmo. Os limites não têm idéia de que tudo é diferente.

Até agora, a largura ea altura de tanto o quadro e os limites tenham sido exatamente o mesmo. Isso nem sempre é verdade, no entanto. Olhe o que acontece se rodar a vista 20 graus no sentido horário. (A rotação é feita usando transformações. Veja o documentação e estes vista e layer exemplos para mais informações.)

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

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

enter descrição da imagem aqui

Você pode verque os limites ainda são os mesmos. Eles ainda não sabem nada aconteceu! Os valores de quadro têm tudo mudou, no entanto.

Agora é um pouco mais fácil de ver a diferença entre frame e barrancos, não é? O artigo Você Provavelmente não compreende quadros e limites define uma moldura vista como

... caixa delimitadora a menor de que a visão em relação a ela de pais sistema de coordenadas, incluindo quaisquer transformações aplicadas a essa vista.

É importante notar que, se você transformar uma vista, em seguida, o quadro torna-se indefinido. Então, na verdade, o quadro amarelo que eu desenhei em torno dos limites verdes giradas na imagem acima nunca realmente existe. Isso significa que se você girar, redimensionar ou fazer alguma outra transformação, então você não deve usar os valores de quadro mais. Você ainda pode usar os valores limites, porém. Os docs da Apple alertam:

Importante: Se a propriedade transform de uma vista não contém transformar a identidade, o quadro de que a visão é indefinido e por isso são o resultados dos seus comportamentos redimensionamento automático.

Em vez infeliz sobre o redimensionamento automático .... Há algo que você pode fazer, no entanto.

O estado docs Apple:

Ao modificar a propriedade transform do seu ponto de vista, tudo as transformações são executadas em relação ao ponto central do view.

Então, se você precisa mover uma visão em torno do pai depois de uma transformação tem sido feito, você pode fazê-lo alterando as coordenadas view.center. Como frame, center usa o sistema de coordenadas da vista principal.

Ok, vamos nos livrar da nossa rotação e foco nos limites. Até agora, a origem limites manteve-se sempre em (0, 0). Ele não tem, no entanto. E se a nossa visão tem uma grande subexibição que é muito grande para mostrar tudo de uma vez? Vamos torná-lo um UIImageView com uma imagem grande. Aqui é a nossa segunda imagem de cima de novo, mas desta vez podemos ver o que todo o conteúdo do subexibição do nosso ponto de vista seria semelhante.

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

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

enter descrição da imagem aqui

Apenas o canto esquerdo superior da imagem pode caber dentro dos limites da vista. Agora veja o que acontece se mudarmos coordenadas de origem dos limites.

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

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

enter descrição da imagem aqui

O quadro não mudou no superview mas o conteúdo dentro do quadro mudou porque a origem dos limites retângulo começa em uma parte diferente da vista. Esta é a idéia por trás de um UIScrollView e é subclasses (por exemplo, um UITableView). Consulte Entendimento UIScrollView para mais explicações.

Quando usar o quadro e quando usar limites

Desde frame relaciona a localização de uma vista na sua opinião pai, você usá-lo quando você está fazendo exterior muda , como mudar a sua largura ou encontrar a distância entre o ponto de vista ea parte superior do seu ponto de vista dos pais.

Use o bounds quando você está fazendo interior muda , como desenhar coisas ou arranjar subviews dentro da visão. Além disso, use os limites para obter o tamanho da vista se você tiver feito alguma transformações do sobre ele.

Artigos para futuras pesquisas:

docs da Apple

perguntas StackOverflow Relacionados

Outros recursos

Practice-se

Além de ler os artigos acima, isso me ajuda muito a fazer um aplicativo de teste. Você pode querer tentar fazer algo similar. (Eu tive a idéia de este vídeo curso mas, infelizmente, não é livre.)

enter descrição da imagem aqui

Aqui está o código para sua referência:

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

    }

}

tentar executar o código abaixo

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

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

A saída desse código é:

a orientação do dispositivo caso é Retrato

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

orientação do dispositivo caso é Paisagem

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

Obviamente, você pode ver a diferença entre o quadro e limites

O quadro é o retângulo que define o UIView com relação ao seu superview .

O limites rect é o intervalo de valores que definem que sistema de coordenadas de NSView.

i. nada neste rectângulo vai realmente mostrar no UIView.

quadro é a origem (canto superior esquerdo) e tamanho da visualização no sistema de coordenadas sua super de vista, isso significa que você traduzir a visão em sua super vista alterando a origem quadro, limites , por outro lado é o tamanho ea origem em seu próprio sistema de coordenadas, então por padrão a origem limites é (0,0).

na maioria das vezes o quadro e limites são congruentes, mas se você tem uma visão do quadro ((140,65), (200,250)) e limites ((0,0), (200,250)), por exemplo, eo vista foi inclinado para que ele está em seu canto inferior direito, então os limites ainda será ((0,0), (200,250)), mas o quadro não é.

enter descrição da imagem aqui

a moldura será o menor retângulo que encapsula / rodeia o ponto de vista, de modo que o quadro (como na foto) será ((140,65), (320,320)).

Outra diferença é, por exemplo, se você tem um Superview cujos limites é ((0,0), (200,200)) e este Superview tem uma subexibição cuja estrutura é ((20,20), (100,100)) e você mudou o superview limita a ((20,20), (200200)), então o quadro subexibição será ainda ((20,20), (100100)), mas por offseted (20,20), porque o seu sistema de coordenadas foi superview offseted pela (20,20).

Espero que isso ajude alguém.

Quadro seu parente à sua SuperView enquanto Bounds em relação à sua NSView.

Exemplo:. X = 40, Y = 60.Also contém 3 mostra Views.This diagrama que ideia clara

frame

BOUNDS

As respostas acima foram muito bem explicado a diferença entre Bounds e Frames.

Bounds:. Uma visão tamanho e localização de acordo com o seu próprio sistema de coordenadas

Quadro:. Um tamanho de vista e localização em relação à sua SuperView

Em seguida, há uma confusão que em caso de Bounds o X, Y será sempre "0". Isto não é verdade . Isso pode ser entendido em UIScrollView e UICollectionView também.

Quando x limites, y não são 0.
Vamos supor que temos um UIScrollView. Temos implementado paginação. O UIScrollView tem 3 páginas e largura de seu contentSize é três vezes Tela Largura (assumir ScreenWidth é 320). A altura é constante (assumir 200).

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

Adicione três UIImageViews como subviews e manter um olhar atento sobre o x valor do quadro

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. Page 0: Quando o ScrollView está em 0 página do Bounds será (x, y: 0: 0, largura: 320, altura: 200)

  2. Page 1: Scroll e passar para a página 1.
    Agora, os limites serão (x: 320, y: 0, largura: 320, altura: 200) Lembra que dissemos em relação ao seu próprio sistema de coordenadas. Então, agora a "parte visível" do nosso ScrollView tem a sua "x" no 320. Olhe para o quadro de imageView1.

  3. Page 2: Scroll e ir para a página 2 limites: (x: 640, y: 0, largura: 320, altura: 200) Mais uma vez dar uma olhada no quadro de imageView2

Mesmo para o caso de UICollectionView. A maneira mais fácil de olhar para CollectionView é deslocá-lo e imprimir / log seus limites e você vai ter a idéia.

Todas as respostas acima estão corretas e esta é a minha opinião sobre isso:

Para diferenciar entre quadros e barrancos CONCEITOS desenvolvedor deve ler-se:

  1. em relação ao superview (uma vista pai) que está contido dentro QUADRO =
  2. em relação ao seu próprio sistema de coordenadas, determina a sua localização subexibição = BOUNDS

"limites" é desconcertante, porque dá a impressão de que as coordenadas são a posição da visão para a qual ele está definido. Mas estes são nas relações e ajustado de acordo com as constantes do quadro.

tela do iPhone

= moldura localização e o tamanho de uma vista usando o sistema de coordenadas da vista pai

limites = localização e tamanho de uma vista utilizando o seu próprio sistema de coordenadas

Uma visão rastreia seu tamanho e localização utilizando dois retângulos: um retângulo quadro e um retângulo limites. O rectângulo quadro define localização e tamanho da vista no superview usando os SuperView do sistema de coordenadas. Os limites retângulo define o interior do sistema de coordenadas que são usados ??quando desenho o conteúdo da vista, incluindo a origem e escamação. Figura 2-1 mostra a relação entre o rectângulo quadro, no lado esquerdo, e os limites rectângulo, sobre a direita.”

Em suma, o quadro é a idéia de superview de um ponto de vista, e os limites é a própria ideia da vista. Ter múltiplos sistemas, uma para cada vista, coordenada é parte da hierarquia de vista.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top