Criando elementos de interface programaticamente usando o PureLayout (parte 1)

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

imagem

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

imagem

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.

imagem

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:

imagem

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.

imagem

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:

imagem

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:

imagem

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á:

imagem

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

imagem

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:

imagem

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:

imagem

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:

imagem

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:

imagem

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.

Source: https://habr.com/ru/post/pt444854/


All Articles