Come creare la percentuale della larghezza totale utilizzando il layout automatico?


114

Devo creare tre colonne dinamiche, ciascuna con una percentuale fissa della larghezza totale. Non terzi, ma valori diversi. Ad esempio, l'illustrazione seguente mostra tre colonne: la prima ha una larghezza del 42%, la seconda è del 25% e la terza è del 33%.

Per un 600 pixel attraverso il viewcontroller, sarebbero rispettivamente 252, 150 e 198 pixel.

Tuttavia, per qualsiasi dimensione di visualizzazione successiva (ad es. IPhone 4 orizzontale (960 di larghezza) o iPad 2 verticale (768 di larghezza), vorrei che le percentuali relative fossero le stesse (non le larghezze dei pixel citate sopra).

C'è un modo per farlo usando Storyboard (cioè senza codice)? Posso farlo facilmente nel codice, ma il mio obiettivo è inserire il maggior numero possibile di questa logica di visualizzazione nello Storyboard.

inserisci qui la descrizione dell'immagine

Risposte:


205

Se, come dici, sai come farlo in codice, allora sai già come farlo nello storyboard. Sono esattamente gli stessi vincoli, ma li stai creando visivamente piuttosto che in codice.

  1. Seleziona sia una vista che la relativa superview.

  2. Scegli Editor -> Pin -> Widths Allo stesso modo per vincolare la larghezza in modo che sia uguale alla larghezza della superview (in realtà la finestra di dialogo a comparsa "pin" nella parte inferiore dell'area di disegno funziona meglio qui).

  3. Modificare il vincolo e impostare il moltiplicatore sulla frazione desiderata, ad esempio 0,42. E così anche per le altre visualizzazioni.


9
Assicurati che la vista che stai vincolando appaia nel "primo elemento" del Vincolo di larghezze uguali e non la larghezza della superview, altrimenti stai rendendo la larghezza della tua sottoview multipli della larghezza della superview. Quando si trascina il controllo da una sottoview a una superview per applicare un vincolo di uguale larghezza, questi sono sempre invertiti, il che mi sembra controintuitivo.
memmons

Ah - per "farlo in codice" intendevo qualcosa di più come "manualmente, senza vincoli o autolayout".
Jeffrey Berthiaume

Bella risposta. Sono sorpresa che IB non fornisca un modo per farlo senza modificare il vincolo.
wcochran

Ho provato ad applicarlo nel mio UITableViewCell e tutto era grigio. Ho dovuto incorporare tutte le mie viste in una nuova vista e selezionare la larghezza uguale dalla mia etichetta a questa nuova vista. Spero che sia d'aiuto.
nano

6
Novità in Xcode7: se vuoi allineare le viste in modo uniforme, usa la nuova "Vista pila".
Bijan

15

Quando Apple ha introdotto UIStackView, ha reso il lavoro molto semplice.

Metodo 1: utilizzo di Nib / StoryBoard:

Devi solo aggiungere tre viste nel generatore di interfacce e incorporarle in stackview

Xcode ► Editor ► Incorpora in ► StackView

inserisci qui la descrizione dell'immagine

Seleziona stackView e dai vincoli con leading, trailing, top e uguale altezza con safeArea

Fare clic sull'area di ispezione degli attributi e impostare StackView orizzontale e la distribuzione per riempire proporzionalmente

[ inserisci qui la descrizione dell'immagine3

Dare il vincolo di tre viste con principale, finale, superiore, inferiore con i rispettivi lati. inserisci qui la descrizione dell'immagine

Metodo 2: a livello di codice:

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

Produzione:

Funziona con paesaggio e ritratto

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Progetto demo - https://github.com/janeshsutharios/UIStackView-with-constraints

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


4

Penso che questo possa essere spiegato in modo più dettagliato in modo che possa essere applicato più facilmente a qualsiasi numero di visualizzazioni che richiedono layout a percentuale fissa all'interno di una superview.

Vista più a sinistra

  • Ancorato a SuperView.Leading
  • Definisce la sua percentuale fissa come moltiplicatore su SuperView.Height

Viste intermedie

  • Definisce la sua percentuale fissa come moltiplicatore su SuperView.Height
  • Lo blocca leftalla destra del vicino

Vista più a destra

  • Non definisce una percentuale fissa (è il resto della visualizzazione disponibile)
  • Lo blocca leftalla destra del vicino
  • Pin il suo rightaSuperView.Trailing

Tutte le viste

  • Definisci le loro altezze non fisse ancorando a Top Layout Guide.Tope Top Layout Guide.bottom. Nella risposta sopra, si nota che questo può essere fatto anche impostando l'altezza uguale alla vista vicina.
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.