Comment créer un pourcentage de largeur totale en utilisant la mise en page automatique?

114

J'ai besoin de créer trois colonnes dynamiques, chacune avec un pourcentage fixe de la largeur totale. Pas des tiers, mais des valeurs différentes. Par exemple, l'illustration suivante montre trois colonnes: la première étant de 42% de large, la seconde de 25% de large et la troisième de 33% de large.

Pour un contrôleur de vue de 600 pixels, ce serait respectivement 252, 150 et 198 pixels.

Cependant, pour toutes les tailles d'affichage ultérieures (c'est-à-dire iPhone 4 paysage (960 de large) ou iPad 2 portrait (768 de large), je voudrais que les pourcentages relatifs soient les mêmes (pas les largeurs de pixels citées ci-dessus).

Existe-t-il un moyen de faire cela en utilisant des Storyboards (c'est-à-dire sans code)? Je peux le faire facilement dans le code, mais mon objectif est de mettre autant de logique d'affichage que possible dans le Storyboard.

entrez la description de l'image ici

Jeffrey Berthiaume
la source

Réponses:

205

Si, comme vous le dites, vous savez comment le faire dans le code, alors vous savez déjà comment le faire dans le storyboard. Ce sont exactement les mêmes contraintes, mais vous les créez visuellement plutôt que dans le code.

  1. Sélectionnez à la fois une vue et sa supervision.

  2. Choisissez Editeur -> Épingler -> Largeurs égales pour contraindre la largeur à être égale à la largeur de la vue supervisée (en fait, la boîte de dialogue contextuelle "épingle" au bas du canevas fonctionne mieux ici).

  3. Modifiez la contrainte et réglez le multiplicateur sur la fraction souhaitée, par exemple 0,42. Et il en va de même pour les autres points de vue.

mat
la source
9
Assurez-vous que la vue que vous contraignez apparaît dans le "premier élément" de la contrainte de largeurs égales et non dans la largeur de la vue supervisée, sinon vous rendez la largeur de votre sous-vue multiple de la largeur de la vue supervisée. Lorsque vous faites glisser le contrôle d'une sous-vue vers une vue supervisée pour appliquer une contrainte de largeur égale, celles-ci sont toujours inversées, ce qui me semble contre-intuitif.
memmons
Ah - par "le faire dans le code", je voulais dire quelque chose de plus comme "manuellement, sans contraintes ni mise en page automatique".
Jeffrey Berthiaume
Bonne réponse. Je suis surpris qu'IB ne fournisse pas un moyen de le faire sans modifier la contrainte.
wcochran
J'ai essayé d'appliquer cela dans mon UITableViewCell et tout était grisé. J'ai dû intégrer toutes mes vues dans une nouvelle vue et sélectionner la largeur égale de mon étiquette à cette nouvelle vue. J'espère que ça aide.
nano
6
Nouveau dans Xcode7: si vous souhaitez aligner les vues de manière égale, utilisez la nouvelle "vue de pile".
Bijan
15

En introduisant UIStackView, Apple a rendu le travail beaucoup plus facile.

Méthode 1: Utilisation de Nib / StoryBoard:

Vous devez simplement ajouter trois vues dans le générateur d'interface et les intégrer dans stackview

Xcode ► Editor ► Incorporer dans ► StackView

entrez la description de l'image ici

Sélectionnez stackView et donnez une contrainte avec des hauteurs de début, de fin, de haut et d'égale avec safeArea

Cliquez sur la zone de l'inspecteur d'attributs et définissez StackView horizontalement et distribution pour remplir proportionnellement

[ entrez la description de l'image ici3

Donner la contrainte de trois vues avec des côtés de début, de fin, de haut et de bas avec les côtés respectifs. entrez la description de l'image ici

Méthode 2: par programmation:

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

Production:

Fonctionne avec paysage et portrait

entrez la description de l'image ici entrez la description de l'image ici

Projet de démonstration - https://github.com/janeshsutharios/UIStackView-with-constraints

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

Jack
la source
4

Je pense que cela peut être expliqué plus en détail afin qu'il puisse être plus facilement appliqué à n'importe quel nombre de vues nécessitant des mises en page à pourcentage fixe dans un superview.

Vue la plus à gauche

  • Ancré à SuperView.Leading
  • Définit son pourcentage fixe comme un multiplicateur sur le SuperView.Height

Vues intermédiaires

  • Définit son pourcentage fixe comme un multiplicateur sur le SuperView.Height
  • Épingle leftà droite de son voisin

Vue la plus à droite

  • Ne définit pas de pourcentage fixe (c'est le reste de la vue disponible)
  • Épingle leftà droite de son voisin
  • Épingle rightàSuperView.Trailing

Toutes les vues

  • Définissez leurs hauteurs non fixes en les ancrant à Top Layout Guide.Topet Top Layout Guide.bottom. Dans la réponse ci-dessus, il est à noter que cela peut également être fait en définissant une hauteur égale à la vue voisine.
JuJoDi
la source