Eu sei que muitas pessoas já me perguntaram toneladas sobre isso, mas mesmo com as respostas não consigo fazer funcionar.
Quando estou lidando com restrições no storyboard, é fácil, mas no código eu tenho dificuldade. Procuro, por exemplo, ter uma visão que fique do lado direito e tenha a altura da tela de acordo com a orientação da tela. Este é o meu código:
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 748)];
myView.backgroundColor = [UIColor redColor];
[self.view addSubview:myView];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|"
options:0 metrics:nil
views:NSDictionaryOfVariableBindings(myView)]];
Não satisfaz algumas restrições. Eu não vejo o que está errado. Além disso, por que não posso usar uma propriedade como em self.myView
vez de uma variável local como myView
?
objective-c
ios
constraints
autolayout
pierre23
fonte
fonte
myView
? (3) O que évivi
(como perguntou ACB)? (4) Você tem uma propriedademyView
declaradaself
?Respostas:
Ao usar Layout automático no código, a configuração do quadro não faz nada. Portanto, o fato de você ter especificado uma largura de 200 na vista acima não significa nada quando você define restrições nela. Para que o conjunto de restrições de uma visualização não seja ambíguo, são necessárias quatro coisas: uma posição x, uma posição y, uma largura e uma altura para qualquer estado dado.
Atualmente, no código acima, você tem apenas dois (altura, em relação à supervisualização e posição y, em relação à supervisualização). Além disso, você tem duas restrições necessárias que podem entrar em conflito, dependendo de como as restrições da visão geral da visualização são configuradas. Se a supervisualização tivesse uma restrição necessária que especifica que sua altura seja um valor menor que 748, você receberá uma exceção de "restrições insatisfatórias".
O fato de você definir a largura da visualização antes de definir as restrições não significa nada. Ele nem mesmo levará em consideração o quadro antigo e calculará um novo quadro com base em todas as restrições que especificou para essas visualizações. Ao lidar com autolayout no código, normalmente apenas crio uma nova visualização usando
initWithFrame:CGRectZero
ou simplesmenteinit
.Para criar o conjunto de restrições necessário para o layout que você descreveu verbalmente em sua pergunta, você precisaria adicionar algumas restrições horizontais para limitar a largura e a posição x, a fim de fornecer um layout totalmente especificado:
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=748)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]];
A descrição verbal desse layout é a seguinte, começando com a restrição vertical:
Se você simplesmente quiser que a visualização preencha toda a altura da supervisualização sem restringir a altura da supervisualização, então você simplesmente omite o
(>=748)
parâmetro no texto de formato visual. Se você acha que o(>=748)
parâmetro é necessário para dar a ele uma altura - você não acha neste caso: fixando a visualização nas bordas da supervisualização usando a sintaxe de barra (|
) ou barra com espaço (|-
,-|
), você está atribuindo um y à sua visualização -position (fixando a vista em uma única aresta), e uma posição y com altura (fixando a vista em ambas as arestas), satisfazendo assim seu conjunto de restrições para a vista.Em relação à sua segunda pergunta:
Usando
NSDictionaryOfVariableBindings(self.myView)
(se você tiver uma configuração de propriedade para myView) e alimentando-a em seu VFL para usarself.myView
em seu texto VFL, você provavelmente obterá uma exceção quando o autolayout tentar analisar seu texto VFL. Tem a ver com a notação de ponto nas chaves do dicionário e com o sistema que tenta usarvalueForKeyPath:
. Veja aqui uma pergunta e resposta semelhantes .fonte
Oi, tenho usado muito esta página para restrições e "como fazer". Levei uma eternidade para chegar ao ponto de perceber que precisava:
myView.translatesAutoresizingMaskIntoConstraints = NO;
para fazer este exemplo funcionar. Obrigado Userxxx, Rob M. e especialmente larsacus pela explicação e código aqui, foi inestimável.
Aqui está o código completo para que os exemplos acima sejam executados:
UIView *myView = [[UIView alloc] init]; myView.backgroundColor = [UIColor redColor]; myView.translatesAutoresizingMaskIntoConstraints = NO; //This part hung me up [self.view addSubview:myView]; //needed to make smaller for iPhone 4 dev here, so >=200 instead of 748 [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[myView(>=200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]]; [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[myView(==200)]-|" options:NSLayoutFormatDirectionLeadingToTrailing metrics:nil views:NSDictionaryOfVariableBindings(myView)]];
fonte
Versão rápida
Atualizado para Swift 3
Este exemplo mostrará dois métodos para adicionar programaticamente as seguintes restrições, da mesma forma que faria no Interface Builder:
Largura e altura
Centro no recipiente
Código padrão
override func viewDidLoad() { super.viewDidLoad() // set up the view let myView = UIView() myView.backgroundColor = UIColor.blue myView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(myView) // Add constraints code here (choose one of the methods below) // ... }
Método 1: estilo âncora
// width and height myView.widthAnchor.constraint(equalToConstant: 200).isActive = true myView.heightAnchor.constraint(equalToConstant: 100).isActive = true // center in container myView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true myView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
Método 2: Estilo NSLayoutConstraint
// width and height NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 200).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil, attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: 100).isActive = true // center in container NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerX, multiplier: 1, constant: 0).isActive = true NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.centerY, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.centerY, multiplier: 1, constant: 0).isActive = true
Notas
NSLayoutConstraint
estilo, no entanto, está disponível apenas no iOS 9, portanto, se você oferece suporte ao iOS 8, ainda deve usar oNSLayoutConstraint
estilo.fonte
Com relação à sua segunda pergunta sobre propriedades, você pode usar
self.myView
apenas se você declarou como uma propriedade em classe. ComomyView
é uma variável local, você não pode usá-la dessa forma. Para obter mais detalhes sobre isso, eu recomendo que você leia a documentação da apple em Propriedades Declaradas ,fonte
por que não posso usar uma propriedade como em
self.myView
vez de uma variável local como myView?tente usar:
NSDictionaryOfVariableBindings(_view)
ao invés de
self.view
fonte
Observe também que, no iOS9, podemos definir restrições programaticamente "mais concisas e mais fáceis de ler" usando subclasses da nova classe auxiliar NSLayoutAnchor .
Um exemplo do doc:
[self.cancelButton.leadingAnchor constraintEqualToAnchor:self.saveButton.trailingAnchor constant: 8.0].active = true;
fonte