Wie erstelle ich einen Prozentsatz der Gesamtbreite mit Autolayout?

113

Ich muss drei dynamische Spalten mit jeweils einem festen Prozentsatz der Gesamtbreite erstellen. Nicht Drittel, sondern unterschiedliche Werte. Die folgende Abbildung zeigt beispielsweise drei Spalten: Die erste ist 42% breit, die zweite 25% breit und die dritte 33% breit.

Bei einem 600-Pixel-Viewcontroller wären dies 252, 150 bzw. 198 Pixel.

Für alle nachfolgenden Anzeigegrößen (z. B. iPhone 4-Querformat (960 breit) oder iPad 2-Hochformat (768 breit) möchte ich jedoch, dass die relativen Prozentsätze gleich sind (nicht die oben angegebenen Pixelbreiten).

Gibt es eine Möglichkeit, dies mit Storyboards zu tun (dh ohne Code)? Ich kann dies problemlos im Code tun, aber mein Ziel ist es, so viel wie möglich von dieser Anzeigelogik in das Storyboard zu integrieren.

Geben Sie hier die Bildbeschreibung ein

Jeffrey Berthiaume
quelle

Antworten:

205

Wenn Sie, wie Sie sagen, wissen, wie man es im Code macht, dann wissen Sie bereits, wie man es im Storyboard macht. Es sind genau die gleichen Einschränkungen, aber Sie erstellen sie visuell und nicht im Code.

  1. Wählen Sie sowohl eine Ansicht als auch deren Übersicht aus.

  2. Wählen Sie Editor -> Pin -> Widths Equally, um die Breite so einzuschränken, dass sie der Breite der Übersicht entspricht (tatsächlich funktioniert das Popup-Dialogfeld "Pin" am unteren Rand der Leinwand hier am besten).

  3. Bearbeiten Sie die Einschränkung und setzen Sie den Multiplikator auf den gewünschten Bruch, z. B. 0,42. Und so auch für die anderen Ansichten.

matt
quelle
9
Stellen Sie sicher, dass die Ansicht, die Sie einschränken, im "ersten Element" der Einschränkung "Gleiche Breiten" und nicht in der Breite der Übersicht angezeigt wird. Andernfalls machen Sie die Breite Ihrer Unteransicht um ein Vielfaches der Breite der Ansicht. Wenn Sie das Steuerelement von einer Unteransicht in eine Übersicht ziehen, um eine Einschränkung mit gleicher Breite anzuwenden, werden diese immer umgekehrt, was mir kontraintuitiv erscheint.
Memmons
Ah - mit "im Code machen" meinte ich eher "manuell, ohne Einschränkungen oder Autolayout".
Jeffrey Berthiaume
Gute Antwort. Ich bin überrascht, dass IB keine Möglichkeit bietet, dies zu tun, ohne die Einschränkung zu bearbeiten.
wcochran
Ich habe versucht, dies in meiner UITableViewCell anzuwenden, und alles war grau. Ich musste alle meine Ansichten in eine neue Ansicht einbetten und die Breite Gleich von meiner Beschriftung zu dieser neuen Ansicht auswählen. Ich hoffe es hilft.
Nano
6
Neu in Xcode7: Wenn Sie Ansichten gleichermaßen ausrichten möchten, verwenden Sie die neue "Stapelansicht".
Bijan
14

Mit der Einführung von UIStackView durch Apple wurde die Arbeit erheblich vereinfacht.

Methode 1: Verwenden von Nib / StoryBoard:

Sie müssen nur drei Ansichten im Interface Builder hinzufügen und in die Stapelansicht einbetten

Xcode ► Editor ► In ► StackView einbetten

Geben Sie hier die Bildbeschreibung ein

Wählen Sie stackView aus und geben Sie mit safeArea eine Einschränkung für führende, nachfolgende, obere und gleiche Höhe an

Klicken Sie auf Attributinspektorbereich und legen Sie StackView horizontal und verteilt fest, um sie proportional zu füllen

[ Geben Sie hier die Bildbeschreibung ein3

Geben Sie die Beschränkung auf drei Ansichten mit führenden, nachfolgenden, oberen und unteren Ansichten mit den jeweiligen Seiten an. Geben Sie hier die Bildbeschreibung ein

Methode 2: Programmatisch:

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

Ausgabe:

Arbeitet mit Landschaft & Porträt

Geben Sie hier die Bildbeschreibung ein Geben Sie hier die Bildbeschreibung ein

Demo-Projekt - https://github.com/janeshsutharios/UIStackView-with-constraints

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

Jack
quelle
4

Ich denke, dies kann detaillierter erklärt werden, so dass es einfacher auf eine beliebige Anzahl von Ansichten angewendet werden kann, die feste prozentuale Layouts innerhalb einer Übersicht erfordern.

Ansicht ganz links

  • Verankert in SuperView.Leading
  • Definiert seinen festen Prozentsatz als Multiplikator auf dem SuperView.Height

Zwischenansichten

  • Definiert seinen festen Prozentsatz als Multiplikator auf dem SuperView.Height
  • Steckt es leftrechts vom Nachbarn fest

Ansicht ganz rechts

  • Definiert keinen festen Prozentsatz (dies ist der Rest der verfügbaren Ansicht)
  • Steckt es leftrechts vom Nachbarn fest
  • Pins sein rightzuSuperView.Trailing

Alle Ansichten

  • Definieren Sie ihre nicht festgelegten Höhen durch Verankern an Top Layout Guide.Topund Top Layout Guide.bottom. In der obigen Antwort wird angemerkt, dass dies auch durch Einstellen der gleichen Höhe für die benachbarte Ansicht erfolgen kann.
JuJoDi
quelle