¿Cómo crear un porcentaje del ancho total usando el diseño automático?

114

Necesito crear tres columnas dinámicas, cada una con un porcentaje fijo del ancho total. No tercios, sino valores diferentes. Por ejemplo, la siguiente ilustración muestra tres columnas: la primera tiene un 42% de ancho, la segunda un 25% de ancho y la tercera un 33% de ancho.

Para un controlador de vista de 600 píxeles, serían 252, 150 y 198 píxeles respectivamente.

Sin embargo, para cualquier tamaño de pantalla posterior (es decir, iPhone 4 horizontal (960 ancho) o iPad 2 vertical (768 ancho), me gustaría que los porcentajes relativos fueran los mismos (no los anchos de píxeles citados anteriormente).

¿Hay alguna manera de hacer esto usando Storyboards (es decir, sin código)? Puedo hacer esto fácilmente en código, pero mi objetivo es poner la mayor cantidad posible de esta lógica de visualización en el Storyboard.

ingrese la descripción de la imagen aquí

Jeffrey Berthiaume
fuente

Respuestas:

205

Si, como dices, sabes cómo hacerlo en código, entonces ya sabes cómo hacerlo en el guión gráfico. Son exactamente las mismas restricciones, pero las está creando visualmente en lugar de en código.

  1. Seleccione tanto una vista como su supervista.

  2. Elija Editor -> Pin -> Widths Equality para restringir el ancho para que sea igual al ancho de la supervista (en realidad, el cuadro de diálogo emergente "pin" en la parte inferior del lienzo funciona mejor aquí).

  3. Edite la restricción y establezca el multiplicador en la fracción deseada, por ejemplo, 0,42. Y lo mismo ocurre con las otras vistas.

mate
fuente
9
Asegúrese de que la vista que está restringiendo aparezca en el "primer elemento" de la Restricción de anchos iguales y no en el ancho de la supervista; de lo contrario, está haciendo que el ancho de la subvista sea múltiplo del ancho de la supervista. Al arrastrar el control de una subvista a una supervista para aplicar una restricción de igual ancho, siempre se invierte, lo que me parece contradictorio.
memmons
Ah, al "hacerlo en código" me refería a algo más como "manualmente, sin restricciones ni diseño automático".
Jeffrey Berthiaume
Buena respuesta. Me sorprende que IB no proporcione una forma de hacer esto sin editar la restricción.
wcochran
Intenté aplicar esto en mi UITableViewCell y todo estaba en gris. Tuve que incrustar todas mis vistas en una nueva vista y seleccionar el Ancho igualmente de mi etiqueta a esta nueva vista. Espero eso ayude.
nano
6
Nuevo en Xcode7: Si desea alinear las vistas por igual, use la nueva "Vista de pila".
Bijan
15

Cuando Apple presentó UIStackView , el trabajo fue mucho más fácil.

Método 1: Uso de Nib / StoryBoard:

Solo tiene que agregar tres vistas en el generador de interfaces e incrustarlas en la vista de pila

Xcode ► Editor ► Insertar en ► StackView

ingrese la descripción de la imagen aquí

Seleccione stackView y proporcione una restricción con altura inicial, final, superior e igual con safeArea

Haga clic en el área del inspector de atributos y establezca StackView horizontal y la distribución para llenar proporcionalmente

[ ingrese la descripción de la imagen aquí3

Dar restricción de tres vistas con anterior, posterior, superior, inferior con los respectivos lados. ingrese la descripción de la imagen aquí

Método 2: programáticamente:

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
    }
}

Salida:

Funciona con paisaje y retrato

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

Proyecto de demostración: https://github.com/janeshsutharios/UIStackView-with-constraints

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

Jack
fuente
4

Creo que esto se puede explicar con más detalle para que se pueda aplicar más fácilmente a cualquier número de vistas que requieran diseños de porcentaje fijo dentro de una supervista.

Vista más a la izquierda

  • Anclado a SuperView.Leading
  • Define su porcentaje fijo como un multiplicador en el SuperView.Height

Vistas intermedias

  • Define su porcentaje fijo como un multiplicador en el SuperView.Height
  • Fija su lefta la derecha de su vecino

Vista más a la derecha

  • No define un porcentaje fijo (es el resto de la vista disponible)
  • Fija su lefta la derecha de su vecino
  • Pines es rightaSuperView.Trailing

Todas las vistas

  • Defina sus alturas no fijas anclando a Top Layout Guide.Topy Top Layout Guide.bottom. En la respuesta anterior, se observa que esto también se puede hacer estableciendo la misma altura a la vista vecina.
JuJoDi
fuente