Olá Habr! Apresento a você a tradução do artigo
Criando restrições de UIViews programaticamente usando o PureLayout de Aly Yaka.

Hoje vou orientá-lo na criação de uma interface de usuário de aplicativo móvel simples com código, sem usar storyboards ou NIBs. Não vou entrar em discussões sobre o que é melhor, porque tudo tem seus prós e contras, então
deixarei um link que aborda esse assunto .
Na segunda parte deste guia, criaremos alguns dos elementos da interface do usuário de aplicativos móveis mais usados com código, incluindo uma barra de navegação, exibição de tabela e células de tamanho dinâmico.
Revisão
Este tutorial foi escrito usando o Xcode 9 e o Swift 4. Suponho também que você esteja familiarizado com o Xcode, Swift e CocoaPods.
Sem mais delongas, vamos começar a criar nosso projeto: um simples aplicativo de cartão de contato. O objetivo deste artigo é ensinar como criar a interface do usuário do seu aplicativo no código e, portanto, ele não conterá nenhuma lógica em relação à funcionalidade do aplicativo, a menos que isso seja necessário para os fins deste guia.
Criando restrições programaticamente com o PureLayout
Configuração do projeto
Comece iniciando o Xcode -> "Criar um novo projeto do Xcode". Selecione "Aplicativo de exibição única" e clique em "Avançar".

Nomeie o projeto como desejar, decidi chamá-lo de ContactCard. Limpe todas as três opções abaixo e selecione Swift como sua linguagem de programação e clique em Avançar.

Selecione um local no seu computador para salvar o projeto. Desmarque a opção "Criar repositório Git no meu Mac".
Como não usaremos Storyboards ou NIBs neste projeto, exclua o “Main.storyboard”, que pode ser encontrado no Project Navigator:

Depois disso, clique no projeto no navegador do projeto e na guia "Geral", localize a seção com informações de implantação e exclua tudo o que está escrito na "Interface principal". É isso que informa ao Xcode qual arquivo do Storyboard deve ser carregado quando o aplicativo é iniciado, mas como acabamos de excluir o “Main.storyboard”, o Xcode não encontrará esse arquivo, o que causará a falha do aplicativo.

Criando um ViewController
Se você executar o aplicativo agora, uma tela preta será exibida, já que o aplicativo não possui mais uma fonte de interface do usuário, portanto, na próxima parte, criaremos. Abra "AppDelegate.swift" e dentro do
application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?)
, Cole este fragmento de código:
self.window = UIWindow(frame: UIScreen.main.bounds) let viewController = ViewController() self.window?.rootViewController = viewController self.window?.makeKeyAndVisible()
Esse código fornece uma janela para a interação do usuário com o aplicativo, que geralmente pode ser encontrada em "ViewController.swift". Para verificar rapidamente se tudo funciona, vá para "ViewController.swift" e, no método
viewDidLoad()
, insira a seguinte linha:
self.view.backgroundColor = .blue
Agora execute o aplicativo.
Para navegar entre arquivos no Xcode, use as teclas de atalho “⇧⌘O” e digite o nome do arquivo ou mesmo o fragmento de código que você está procurando, e uma lista de arquivos que você pode escolher aparecerá na tela.
Após iniciar o aplicativo, este deve ser o resultado na tela do seu simulador:

Obviamente, não usaremos esse azul nojento, portanto, apenas altere o plano de fundo para branco substituindo
.blue
por
.white
dentro de
viewDidLoad ()
.
Desenvolvimento de UI
Para criar nossa interface de usuário, usaremos uma
biblioteca que facilitará nossa vida. Para instalar o PureLayout, você deve primeiro abrir seu terminal e digitar cd, depois um espaço, arraste a pasta do projeto para o terminal e pressione "Enter". Agora execute os seguintes comandos dentro do terminal:
- pod init
- instalação do pod
Esta deve ser a saída do seu terminal após o segundo comando:

Depois disso, feche o Xcode, abra a pasta no Finder e você deverá encontrar "<nome do seu projeto> .xcworkspace". É isso que abriremos para acessar nosso aplicativo se precisarmos usar o CocoaPods. Agora encontre o arquivo chamado “PodFile” e escreva a seguinte linha sob a frase
use_frameworks!
pod “PureLayout”
Execute o
pod install
novamente no seu terminal e, em seguida, crie seu projeto pressionando “Command + B”.
Coffee break
Agora que tudo está configurado, vamos começar com o trabalho real. Vá para “ViewController.swift” e pegue uma xícara de café, porque é assim que o resultado final será:

Criar ImageView
Insira a linha
import PureLayout
import UIKit
para poder usar a biblioteca nesse arquivo. Então, sob a declaração de classe e fora de qualquer função, começamos criando a variável
Avatar ImageView
preguiçosa (preguiçosa) da seguinte maneira:
lazy var avatar: UIImageView = { let imageView = UIImageView(image: UIImage(named: "avatar.jpg")) imageView.autoSetDimensions(to: CGSize(width: 128.0, height: 128.0)) imageView.layer.borderWidth = 3.0 imageView.layer.borderColor = UIColor.lightGray.cgColor imageView.layer.cornerRadius = 64.0 imageView.clipsToBounds = true return imageView }()
Quanto à imagem, salve qualquer imagem na área de trabalho que você usará como avatar e arraste-a para o Xcode na pasta <Your Project Name>, que no meu caso é chamada de "ContactCard" e marque a caixa "Copiar itens, se necessário" .

Depois disso, escreva o nome deste arquivo junto com sua extensão na declaração UIImage em vez de "avatar.jpg".
Para aqueles que não sabem, variáveis preguiçosas são semelhantes às variáveis comuns, exceto que elas não são inicializadas (ou que algum espaço de memória é alocado) até que sejam necessárias ou chamadas pela primeira vez . Isso significa que variáveis preguiçosas não são inicializadas quando o controlador de exibição é inicializado, mas esperam um momento posterior quando elas são realmente necessárias, o que economiza energia de processamento e espaço de memória para outros processos. Isso é especialmente útil ao inicializar componentes da interface do usuário.
PureLayout em ação
Como você pode ver dentro da inicialização, a linha
imageView.autoSetDimensions (to: CGSize (width: 128.0, height: 128.0))
é PureLayout em ação. Em uma linha, definimos um limite para altura e largura do UIImageView, e todas as NSLayoutConstraints necessárias são criadas sem a necessidade de chamadas de função enormes. Se você estava lidando com a criação de restrições programaticamente, provavelmente já se apaixonou por esta maravilhosa biblioteca.
Para fazer essa imagem circular, definimos seu raio angular para metade da largura ou altura, que é de 64,0 pontos. Além disso, defina a propriedade
clipsToBounds
como
true
, que informa à imagem que ela deve recortar tudo o que estiver fora do raio que acabamos de definir.
Em seguida, passamos a criar um UIView que servirá como o topo da visualização por trás do avatar pintado de cinza. Declare a seguinte variável lenta para esta exibição:
lazy var upperView: UIView = { let view = UIView() view.autoSetDimension(.height, toSize: 128) view.backgroundColor = .gray return view }()
Adicionando subvisões
Antes de
func addSubviews ()
, vamos criar uma
func addSubviews ()
que adiciona as visualizações que acabamos de criar (e todas as outras que vamos criar) como subviews ao controlador de view:
func addSubviews() { self.view.addSubview(avatar) self.view.addSubview(upperView) }
Agora adicione a seguinte linha a
viewDidLoad (): self.addSubviews ()
Definir restrições
Para ter uma idéia de quão longe chegamos, vamos definir limites para esses dois tipos. Crie outra função chamada
func setupConstraints()
e insira as seguintes restrições:
func setupConstraints() { avatar.autoAlignAxis(toSuperviewAxis: .vertical) avatar.autoPinEdge(toSuperviewEdge: .top, withInset: 64.0) upperView.autoPinEdge(toSuperviewEdge: .left) upperView.autoPinEdge(toSuperviewEdge: .right) upperView.autoPinEdgesToSuperviewEdges(with: .zero, excludingEdge: .bottom) }
Agora, dentro do
viewDidLoad()
chame
setupConstraints()
, da seguinte maneira:
self.setupConstraints()
. Adicione isso DEPOIS de chamar
addSubviews()
. Esta deve ser a conclusão final:

Traga o avatar para a frente
Infelizmente, não é isso que eu gostaria de receber. Como você pode ver, nosso
upperView
está no topo do avatar. Isso se deve ao fato de termos adicionado um avatar como
upperView
-
upperView
antes do
upperView
e, como essas
upperView
-
upperView
estão localizadas de alguma forma na pilha, obtemos esse resultado. Para consertar isso, podemos simplesmente substituir essas duas linhas, mas há outro truque que quero lhe mostrar, a saber:
self.view.bringSubview (toFront: avatar)
.
Este método transferirá o avatar da parte inferior da pilha para o topo, então escolha o método que você mais gosta. Obviamente, para facilitar a leitura, é melhor adicionar sub-visões na ordem em que elas devem ser exibidas se elas se cruzarem, lembrando que as primeiras sub-visões adicionadas estarão na parte inferior da pilha e, portanto, quaisquer outras visualizações aparecerão em cima dela.
E é assim que deve realmente parecer:

Criar controle segmentado
Em seguida, criaremos um controle segmentado, que é uma barra cinza contendo três seções. Na verdade, é fácil criar um controle segmentado. Faça o seguinte:
lazy var segmentedControl: UISegmentedControl = { let control = UISegmentedControl(items: ["Personal", "Social", "Resumè"]) control.autoSetDimension(.height, toSize: 32.0) control.selectedSegmentIndex = 0 control.layer.borderColor = UIColor.gray.cgColor control.tintColor = .gray return control }()
Acredito que tudo esteja claro, a única diferença é que, após a inicialização, fornecemos uma matriz de strings, cada linha representa o cabeçalho de uma das seções desejadas. Também definimos
selectedSegmentIndex
como 0, que informa ao controle segmentado para selecionar / selecionar o primeiro segmento durante a inicialização. O resto é apenas um estilo para brincar.
Agora, vamos continuar e adicioná-lo como uma subview, inserindo a seguinte linha no final da função
addCubviews(): self.view.addSubview(segmentedControl)
e suas limitações serão as seguintes:
segmentedControl.autoPinEdge(toSuperviewEdge: .left, withInset: 8.0) segmentedControl.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0) segmentedControl.autoPinEdge(.top, to: .bottom, of: avatar, withOffset: 16.0)
Dizemos ao controle segmentado que queremos anexá-lo ao lado esquerdo da sua visão geral, no entanto, queremos aumentar um pouco o intervalo e não anexá-lo diretamente à borda da tela. Se você notar, eu uso a chamada grade de oito pontos, onde todas as distâncias e tamanhos são múltiplos de oito. Eu faço o mesmo no lado direito do controle segmentado. Quanto à última limitação, ele diz anexar um vértice à base do avatar com um intervalo de 16 pontos.
Após adicionar as limitações acima ao
func setupConstraints()
execute o código e verifique se ele se parece com isso:

Adicionando um botão
Agora passaremos para a última parte da interface do usuário do livro, que é um botão "Editar". Adicione a seguinte variável lenta:
lazy var editButton: UIButton = { let button = UIButton() button.setTitle("Edit", for: .normal) button.setTitleColor(.gray, for: .normal) button.layer.cornerRadius = 4.0 button.layer.borderColor = UIColor.gray.cgColor button.layer.borderWidth = 1.0 button.tintColor = .gray button.backgroundColor = .clear button.autoSetDimension(.width, toSize: 96.0) button.autoSetDimension(.height, toSize: 32.0) return button }()
Não se preocupe com o tamanho da inicialização, mas preste atenção em como eu defino o título e sua cor chamando as
button.setTitleColor
e
button.setTitleColor
. Por certas razões, não podemos definir o título de um botão acessando diretamente seu
titleLabel
, e isso ocorre porque existem estados diferentes para o botão e muitos se sentiriam à vontade com cabeçalhos / cores diferentes para estados diferentes.
Agora adicione o botão como uma subvisão, como o restante dos componentes, e adicione as seguintes restrições para que apareça onde deveria estar:
editButton.autoPinEdge(.top, to: .bottom, of: upperView, withOffset: 16.0) editButton.autoPinEdge(toSuperviewEdge: .right, withInset: 8.0)
Aqui, definimos apenas os limites direito e superior para o botão, porque atribuímos um tamanho a ele, ele não será expandido e nada mais será necessário. Agora execute o projeto para ver o resultado final:

Algumas notas recentes
Pratique, adicione quantos elementos de interface desejar. Crie visualizações de qualquer aplicativo que achar difícil. Comece simples e aumente gradualmente a dificuldade. Tente desenhar componentes da interface do usuário em um pedaço de papel para imaginar como eles se encaixam.
Na segunda parte, estendo este guia para criar uma barra de navegação, exibição de tabela e células de tamanho dinâmico no código.