Como criar porcentagem da largura total usando autolayout?

114

Preciso criar três colunas dinâmicas, cada uma com uma porcentagem fixa da largura total. Não terços, mas valores diferentes. Por exemplo, a ilustração a seguir mostra três colunas: a primeira com 42% de largura, a segunda com 25% de largura e a terceira com 33% de largura.

Para um controlador de visualização de 600 pixels, isso seria 252, 150 e 198 pixels, respectivamente.

No entanto, para quaisquer tamanhos de tela subsequentes (por exemplo, iPhone 4 paisagem (960 de largura) ou iPad 2 retrato (768 de largura), gostaria que as porcentagens relativas fossem as mesmas (não as larguras de pixel citadas acima).

Existe uma maneira de fazer isso usando Storyboards (ou seja, sem código)? Posso fazer isso facilmente no código, mas meu objetivo é colocar o máximo possível dessa lógica de exibição no Storyboard.

insira a descrição da imagem aqui

Jeffrey Berthiaume
fonte

Respostas:

205

Se, como você diz, você sabe como fazer em código, então já sabe como fazer no storyboard. São exatamente as mesmas restrições, mas você as está criando visualmente em vez de no código.

  1. Selecione uma visualização e sua supervisão.

  2. Escolha Editor -> Fixar -> Larguras Igualmente para restringir a largura para ser igual à largura da visualização (na verdade, a caixa de diálogo pop-up "fixar" na parte inferior da tela funciona melhor aqui).

  3. Edite a restrição e defina o Multiplicador para a fração desejada, por exemplo, 0,42. E o mesmo ocorre com as outras visualizações.

mate
fonte
9
Certifique-se de que a visualização que você está restringindo apareça no "primeiro item" da Restrição de larguras iguais e não na largura da supervisualização, caso contrário, você estará tornando a largura da sua subvisualização múltiplos da largura da supervisualização. Ao arrastar o controle de uma subvisualização para uma supervisualização para aplicar uma restrição de largura igual, essas são sempre invertidas, o que parece contra-intuitivo para mim.
memmons de
Ah - por "fazer em código" eu quis dizer algo mais como "manualmente, sem restrições ou autolayout".
Jeffrey Berthiaume
Boa resposta. Estou surpreso que o IB não forneça uma maneira de fazer isso sem editar a restrição.
wcochran
Tentei aplicar isso no meu UITableViewCell e tudo ficou cinza. Tive que incorporar todas as minhas visualizações em uma nova visualização e selecionar a largura igual de meu rótulo para esta nova visualização. Espero que ajude.
nano
6
Novo no Xcode7: Se você deseja alinhar as visualizações igualmente, use o novo "Stack View".
Bijan,
15

Quando a Apple apresenta o UIStackView, ele torna o trabalho muito mais fácil.

Método 1: Usando Nib / StoryBoard:

Você tem que apenas adicionar três visualizações no construtor de interface e incorporá-las ao stackview

Xcode ► Editor ► Incorporar em ► StackView

insira a descrição da imagem aqui

Selecione stackView e dê restrição com altura inicial, final, superior e igual com safeArea

Clique na área do inspetor de atributos e defina StackView horizontal e distribuição para preencher proporcionalmente

[ insira a descrição da imagem aqui3

Fornece a restrição de três vistas com os lados esquerdo, direito, superior e inferior. insira a descrição da imagem aqui

Método 2: programaticamente:

import UIKit
class StackViewProgramatically: UIViewController {
    var propotionalStackView: UIStackView!
    ///Initially defining three views
    let redView: UIView = {
        let view = UIView()//taking 42 % initially
        view.frame = CGRect(x: 0, y: 0, width: 42 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .red
        return view
    }()

    let greenView: UIView = {
        let view = UIView()//taking 42* initially
        view.frame = CGRect(x: 42 * UIScreen.main.bounds.width/100, y: 0, width: 25 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .green
        return view
    }()
    let blueView: UIView = {
        let view = UIView()//taking 33*initially
        view.frame = CGRect(x: 67 * UIScreen.main.bounds.width/100, y: 0, width: 33 * UIScreen.main.bounds.width/100, height: UIScreen.main.bounds.height)
        view.backgroundColor = .blue
        return view
    }()

    ///Changing UIView frame to supports landscape mode.
    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        DispatchQueue.main.async {
            self.redView.frame = CGRect(x: 0, y: 0, width: 42 * self.widthPercent, height: self.screenHeight)
            self.greenView.frame = CGRect(x: 42 * self.widthPercent, y: 0, width: 25 * self.widthPercent, height: self.screenHeight)
            self.blueView.frame = CGRect(x: 67 * self.widthPercent, y: 0, width: 33 * self.widthPercent, height: self.screenHeight)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        //Adding subViews to the stackView
        propotionalStackView = UIStackView()
        propotionalStackView.addSubview(redView)
        propotionalStackView.addSubview(greenView)
        propotionalStackView.addSubview(blueView)
        propotionalStackView.spacing = 0
        ///setting up stackView
        propotionalStackView.axis = .horizontal
        propotionalStackView.distribution = .fillProportionally
        propotionalStackView.alignment = .fill
        view.addSubview(propotionalStackView)
    }
}
//MARK: UIscreen helper extension
extension NSObject {

    var widthPercent: CGFloat {
        return UIScreen.main.bounds.width/100
    }

    var screenHeight: CGFloat {
        return UIScreen.main.bounds.height
    }
}

Resultado:

Funciona com paisagem e retrato

insira a descrição da imagem aqui insira a descrição da imagem aqui

Projeto de demonstração - https://github.com/janeshsutharios/UIStackView-with-constraints

https://developer.apple.com/videos/play/wwdc2015/218/

Jack
fonte
4

Acho que isso pode ser explicado com mais detalhes para que possa ser mais facilmente aplicado a qualquer número de visualizações que requeiram layouts de porcentagem fixa em uma supervisão.

Visão mais à esquerda

  • Ancorado em SuperView.Leading
  • Define sua porcentagem fixa como um multiplicador no SuperView.Height

Visualizações intermediárias

  • Define sua porcentagem fixa como um multiplicador no SuperView.Height
  • Fixa leftà direita do vizinho

Vista mais à direita

  • Não define uma porcentagem fixa (é o restante da visualização disponível)
  • Fixa leftà direita do vizinho
  • Fixa rightemSuperView.Trailing

Todas as visualizações

  • Defina suas alturas não fixas ancorando em Top Layout Guide.Tope Top Layout Guide.bottom. Na resposta acima, nota-se que isso também pode ser feito definindo uma altura igual à vista vizinha.
JuJoDi
fonte