iOS
Layout automatico
Ricerca…
introduzione
Layout automatico calcola dinamicamente la dimensione e la posizione di tutte le viste nella gerarchia della vista, in base ai vincoli posti su tali viste. fonte
Sintassi
- NSLayoutConstraint (elemento: Qualsiasi, attributo: NSLayoutAttribute, relatedBy: NSLayoutRelation, toItem: Qualsiasi ?, attributo: NSLayoutAttribute, moltiplicatore: CGFloat, costante: CGFloat) // Crea una contraint a livello di codice
Impostazione dei vincoli a livello di codice
Esempio di codice Boilerplate
override func viewDidLoad() {
super.viewDidLoad()
let myView = UIView()
myView.backgroundColor = UIColor.blueColor()
myView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(myView)
// Add constraints code here
// ...
}
Negli esempi sotto lo Stile di ancoraggio è il metodo preferito su NSLayoutConstraint
Style, tuttavia è disponibile solo da iOS 9, quindi se stai supportando iOS 8, dovresti comunque utilizzare NSLayoutConstraint
Style.
pinning
Stile di ancoraggio
let margins = view.layoutMarginsGuide
myView.leadingAnchor.constraintEqualToAnchor(margins.leadingAnchor, constant: 20).active = true
- Oltre a
leadingAnchor
, ci sono anchetrailingAnchor
,topAnchor
ebottomAnchor
.
NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.LeadingMargin, multiplier: 1.0, constant: 20.0).active = true
- Oltre a
.Leading
c'è anche..Trailing
,.Top
e.Bottom
. - Oltre a
.LeadingMargin
c'è anche..TrailingMargin
,.TopMargin
e.BottomMargin
.
Stile di linguaggio in formato visivo
NSLayoutConstraint.constraintsWithVisualFormat("H:|-20-[myViewKey]", options: [], metrics: nil, views: ["myViewKey": myView])
Larghezza e altezza
Stile di ancoraggio
myView.widthAnchor.constraintEqualToAnchor(nil, constant: 200).active = true
myView.heightAnchor.constraintEqualToAnchor(nil, constant: 100).active = true
NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 200).active = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100).active = true
Stile di linguaggio in formato visivo
NSLayoutConstraint.constraintsWithVisualFormat("H:[myViewKey(200)]", options: [], metrics: nil, views: ["myViewKey": myView])
NSLayoutConstraint.constraintsWithVisualFormat("V:[myViewKey(100)]", options: [], metrics: nil, views: ["myViewKey": myView])
Centro nel contenitore
Stile di ancoraggio
myView.centerXAnchor.constraintEqualToAnchor(view.centerXAnchor).active = true
myView.centerYAnchor.constraintEqualToAnchor(view.centerYAnchor).active = true
NSLayoutConstraint Style
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0).active = true
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0).active = true
Stile di linguaggio in formato visivo
NSLayoutConstraint.constraintsWithVisualFormat("V:[viewKey]-(<=0)-[myViewKey]", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: ["myViewKey": myView, "viewKey": view])
NSLayoutConstraint.constraintsWithVisualFormat("H:[viewKey]-(<=0)-[myViewKey]", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: ["myViewKey": myView, "viewKey": view])
Come usare Auto Layout
Il layout automatico viene utilizzato per disporre le viste in modo che risultino perfette su qualsiasi dispositivo e orientamento. I vincoli sono le regole che dicono come dovrebbe essere stabilito tutto. Includono bordi di pinning, centratura e dimensioni di impostazione, tra le altre cose.
Il layout automatico è abilitato di default, ma puoi ricontrollarlo. Se fai clic su Main.storyboard nel Project Navigator e poi mostra la finestra di ispezione File. Assicurati che le Classi Auto Layout e Dimensioni siano selezionate:
I vincoli di layout automatici possono essere impostati in Interface Builder o nel codice. In Interface Builder trovi gli strumenti di Auto Layout in basso a destra. Facendo clic su di essi verranno visualizzate diverse opzioni per l'impostazione dei vincoli su una vista.
Se si desidera avere vincoli diversi per le diverse dimensioni o orientamenti dei dispositivi, è possibile impostarli in wAny hAny opzioni di classe di dimensioni che si trovano nella parte centrale inferiore.
Vincoli al centro
Seleziona il tuo pulsante (o qualsiasi altra vista che vuoi centrare) sullo storyboard . Quindi fare clic sul pulsante di allineamento in basso a destra. Selezionare Horizontally in Container
e Vertically in Container
. Fai clic su "Aggiungi 2 vincoli".
Se non fosse già perfettamente centrato, potrebbe essere necessario fare ancora una cosa. Fai clic sul pulsante "Aggiorna frame" che si trova a due a sinistra del pulsante "Incorpora nello stack" nella barra inferiore.
Puoi anche "aggiornare i fotogrammi se necessario" premendo insieme ⌘ + ⌥ + = (Comando + Opzione e uguale) dopo aver selezionato la vista, questo potrebbe far risparmiare un po 'di tempo.
Ora quando esegui la tua app dovrebbe essere centrata, indipendentemente dalla dimensione del dispositivo che stai utilizzando.
Un altro modo per centrare le viste usando Interface Builder è control-click-dragging. UILabel
voler centrare un UILabel
in una vista. Apri lo Document Outline
del Document Outline
nello storyboard facendo clic sul pulsante della barra laterale in basso a sinistra. Clicca e trascina dall'etichetta alla vista tenendo premuto ctrl (controllo), e dovrebbe apparire una linea blu:
Al rilascio, apparirà un menu di opzioni di vincolo:
Seleziona "Centra orizzontalmente nel contenitore" e "Centra verticalmente nel contenitore". Aggiorna i fotogrammi se necessario, e voilà! Un'etichetta centrata.
In alternativa, è possibile aggiungere i vincoli a livello di codice. Crea i vincoli e aggiungili agli elementi e alle viste dell'interfaccia utente desiderati come descritto nel seguente esempio, dove creiamo un pulsante e lo allineiamo al centro, in orizzontale e in verticale, alla sua superview:
Objective-C
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *yourButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 18)];
[yourButton setTitle:@"Button" forState:UIControlStateNormal];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:yourButton attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]]; //Align veritcally center to superView
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:yourButton attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1 constant:0]]; //Align horizontally center to superView
[self.view addSubview:yourButton]; //Add button to superView
}
veloce
override func viewDidLoad()
{
super.viewDidLoad()
let yourButton: UIButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 18))
yourButton.setTitle("Button", forState: .Normal)
let centerVertically = NSLayoutConstraint(item: yourButton,
attribute: .CenterX,
relatedBy: .Equal,
toItem: view,
attribute: .CenterX,
multiplier: 1.0,
constant: 0.0)
let centerHorizontally = NSLayoutConstraint(item: yourButton,
attribute: .CenterY,
relatedBy: .Equal,
toItem: view,
attribute: .CenterY,
multiplier: 1.0,
constant: 0.0)
NSLayoutConstraint.activateConstraints([centerVertically, centerHorizontally])
}
Viste spaziali in modo uniforme
È comune desiderare che due viste siano affiancate, centrate nella loro superview. La risposta comune fornita su Stack Overflow consiste nell'incorporare queste due viste in un UIView
e centrare l' UIView
. Questo non è necessario o raccomandato. Dai documenti UILayoutGuide :
Vi sono una serie di costi associati all'aggiunta di viste fittizie alla gerarchia della vista. Innanzitutto, c'è il costo di creare e mantenere la vista stessa. In secondo luogo, la vista fittizia è un membro completo della gerarchia della vista, il che significa che aggiunge un sovraccarico a tutte le attività eseguite dalla gerarchia. La cosa peggiore è che la vista fittizia invisibile può intercettare i messaggi destinati ad altre viste, causando problemi che sono molto difficili da trovare.
Puoi usare UILayoutGuide
per fare questo, invece di aggiungere i pulsanti a un UIView
non UIView
. Una UILayoutGuide
è essenzialmente uno spazio rettangolare che può interagire con Auto Layout. UILayoutGuide
una UILayoutGuide
sui lati sinistro e destro dei pulsanti e imposta la loro larghezza per essere uguale. Questo centrerà i pulsanti. Ecco come farlo nel codice:
Stile di linguaggio in formato visivo
view.addSubview(button1)
view.addSubview(button2)
let leftSpace = UILayoutGuide()
view.addLayoutGuide(leftSpace)
let rightSpace = UILayoutGuide()
view.addLayoutGuide(rightSpace)
let views = [
"leftSpace" : leftSpace,
"button1" : button1,
"button2" : button2,
"rightSpace" : rightSpace
]
// Lay the buttons and layout guides out horizontally in a line.
// Put the layout guides on each end.
NSLayoutConstraint.activateConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[leftSpace][button1]-[button2][rightSpace]|", options: [], metrics: nil, views: views))
// Now set the layout guides widths equal, so that the space on the
// left and the right of the buttons will be equal
leftSpace.widthAnchor.constraintEqualToAnchor(rightSpace.widthAnchor).active = true
Stile di ancoraggio
let leadingSpace = UILayoutGuide()
let trailingSpace = UILayoutGuide()
view.addLayoutGuide(leadingSpace)
view.addLayoutGuide(trailingSpace)
leadingSpace.widthAnchor.constraintEqualToAnchor(trailingSpace.widthAnchor).active = true
leadingSpace.leadingAnchor.constraintEqualToAnchor(view.leadingAnchor).active = true
leadingSpace.trailingAnchor.constraintEqualToAnchor(button1.leadingAnchor).active = true
trailingSpace.leadingAnchor.constraintEqualToAnchor(button2.trailingAnchor).active = true
trailingSpace.trailingAnchor.constraintEqualToAnchor(view.trailingAnchor).active = true
Sarà necessario aggiungere vincoli verticali anche a questo, ma questo centrerà i pulsanti nella vista senza aggiungere alcuna vista "fittizia"! Ciò salverà il sistema dal sprecare tempo della CPU nel visualizzare quelle viste "fittizie". Questo esempio utilizza i pulsanti, ma puoi scambiare i pulsanti per qualsiasi vista su cui vuoi applicare i vincoli.
Se stai supportando iOS 8 o versioni precedenti, il modo più semplice per creare questo layout è aggiungere viste fittizie nascoste. Con iOS 9 è possibile sostituire le viste fittizie con le guide di layout.
Nota: Interface Builder non supporta ancora le guide di layout (Xcode 7.2.1). Quindi se vuoi usarli devi creare i tuoi vincoli nel codice. Fonte .
UILabel dimensione intrinseca
Dobbiamo creare una vista che avrà un prefisso dell'immagine per un testo. il testo potrebbe essere di lunghezza variabile. Dobbiamo ottenere un risultato in cui Image + text è sempre al centro di una vista genitore.
Passo 1: Prima crea un progetto a vista singola e assegnagli un nome a tua scelta e apri la visualizzazione del pacco story board. Scorri una vista con delle dimensioni ragionevoli e imposta il suo colore di sfondo su giallo. Ho ridimensionato il mio viewcontroller a 3.5 ". la vista dovrebbe sembrare qualcosa del genere
Passo 2: Ora aggiungeremo dei vincoli alla vista gialla. Per cominciare aggiungeremo i vincoli di larghezza e altezza (Aspetta un attimo non abbiamo detto che la vista avrà larghezza dinamica? Ok ci torneremo più tardi) Aggiungi la i seguenti vincoli come nell'immagine qui sotto non infastidiscono con il valore della larghezza, qualsiasi valore andrà bene per la larghezza, basta tenerlo abbastanza grande in modo che possiamo aggiungere correttamente gli autolayout.
Dopo aver aggiunto questi due vincoli, vedrai che XCode ti sta dando degli errori come nell'immagine sottostante, li vediamo e li capiamo.
Abbiamo due errori (rosso significa errore) Come discusso sopra, rivisitiamo la parte dell'ambiguità
Vincoli mancanti: Necessità di vincoli per: posizione X: - Come discusso sopra abbiamo dato alla vista una larghezza e un'altezza in modo che i suoi "BOUNDS" siano definiti ma non abbiamo dato la sua origine quindi il suo "FRAME" non è definito. L'Autolayout non è in grado di determinare quale sarà la posizione X della nostra vista gialla
Vincoli mancanti: Necessità di vincoli per: Posizione Y: - Come discusso sopra abbiamo dato alla vista una larghezza e un'altezza in modo che i suoi "BOUNDS" siano definiti ma non abbiamo dato la sua origine in modo che il suo "FRAME" non sia definito. L'autolayout non è in grado di determinare quale sarà la posizione Y della nostra vista gialla Per risolvere questo problema dobbiamo dare un po 'di spazio all'autolayout per resettare X e Y. Poiché non possiamo impostare i fotogrammi, lo faremo in modalità autolayout. Aggiungere i seguenti vincoli come da immagine fornita qui di seguito lo spiegherò più tardi
Quello che abbiamo fatto è, abbiamo aggiunto un "Centro Verticale" e un "Centro Orizzontale" questi vincoli che indicano l'autolayout che la nostra vista gialla sarà sempre al centro Orizzontalmente: quindi X in determinato è con vincolo verticale e Y è determinato. potrebbe essere necessario regolare la cornice).
Passo 3: Ormai la nostra vista di base gialla è pronta. Aggiungeremo l'immagine del prefisso come sottoview della nostra vista gialla con i seguenti vincoli. Puoi scegliere qualsiasi immagine a tua scelta.
Dato che abbiamo fissato la dimensione per la nostra immagine di prefisso avremo un'altezza di larghezza fissa per questa vista. Aggiungere i vincoli e procedere al passaggio successivo.
Step4: aggiungi un UILabel come sottoview della nostra vista gialla e aggiungi i seguenti vincoli
Come puoi vedere ho dato solo vincoli relativi al nostro UILabel.I suoi 8 punti dall'immagine del prefisso e 0,0,0 in alto e in basso dalla vista gialla. Visto che vogliamo che la larghezza sia dinamica non daremo limiti di larghezza o altezza .
D: Perché ora non riceviamo errori, non abbiamo dato alcuna larghezza e altezza? Risposta: - Riceviamo un errore o un avvertimento solo quando il layout automatico non è in grado di risolvere qualsiasi cosa che è necessario per rendere una visualizzazione sullo schermo. La sua larghezza o origine. La nostra etichetta è relativa alla vista gialla e all'immagine del prefisso e ai relativi frame è ben definito l'autolayout è in grado di calcolare il frame della nostra etichetta.
Passo 5: Ora, se ricordiamo, realizzeremo che abbiamo dato una vista fissa a una vista gialla, ma vogliamo che sia dinamica dipendente dal testo della nostra etichetta. Quindi modificheremo il nostro vincolo di larghezza della vista gialla. Larghezza della vista gialla è necessario per risolvere l'ambiguità ma vogliamo che venga annullato in fase di esecuzione in base al contenuto di UILabel. Quindi selezioneremo la nostra vista gialla e andremo a Dimensione ispettore e ridurrà la priorità del vincolo di larghezza a 1 in modo che sia sovrascritta. Segui l'immagine qui sotto.
Passaggio 6: Vogliamo che UILabel si espanda in base al testo e spinga la nostra vista gialla. Così abbiamo ridotto la priorità della larghezza della vista gialla. Ora aumenteremo la priorità della resistenza alla compressione del testo della nostra UILabel. Vogliamo che la nostra vista riduca come bene, quindi aumenteremo la priorità di abbracciare i contenuti di UILabel. Segui l'immagine qui sotto
Come potete vedere abbiamo aumentato la priorità di abbraccio del contenuto a 500 e la priorità di resistenza alla compressione a 751, che supererà con successo la priorità 1 del vincolo di larghezza.
Ora costruisci e corri vedrai qualcosa come segue.
Come animare con Auto Layout
Senza il layout automatico, l'animazione si ottiene modificando il frame di una vista nel tempo. Con Auto Layout, i vincoli dettano il frame della vista, quindi devi animare i vincoli. Questa indiretta rende l'animazione più difficile da visualizzare.
Ecco i modi per animare con Auto Layout:
- Modificare la costante del vincolo dopo la creazione utilizzando chiamate periodiche (
CADisplayLink
,dispatch_source_t
,dispatch_after
,NSTimer
). Quindi chiamalayoutIfNeeded
per aggiornare il vincolo. Esempio:
Objective-C:
self.someConstraint.constant = 10.0;
[UIView animateWithDuration:0.25 animations:^{
[self.view layoutIfNeeded];
}];
Swift:
self.someConstraint.constant = 10.0
UIView.animate(withDuration: 0.25, animations: self.view.layoutIfNeeded)
- Modificare i vincoli e chiamare
[view layoutIfNeeded]
all'interno di un blocco di animazione. Questo interpola tra le due posizioni ignorando i vincoli durante l'animazione.
[UIView animateWithDuration:0.5 animations:^{
[view layoutIfNeeded];
}]
Cambia la priorità dei vincoli . Questa operazione richiede meno CPU rispetto all'aggiunta e alla rimozione dei vincoli.
Rimuovi tutti i vincoli e utilizza le maschere di autosizing . Per il successivo, è necessario impostare
view.translatesAutoresizingMaskIntoConstraints = YES
.Utilizzare i vincoli che non interferiscono con l'animazione prevista .
Usa una vista del contenitore . Posiziona la superview usando i vincoli. Quindi aggiungi una sottoview con i vincoli che non combattono l'animazione, ad esempio: un centro relativo alla superview. Questo scarica parte dei vincoli alla superview, in modo che non combattano l'animazione nella sottoview.
Animare i livelli invece le viste . Le trasformazioni di livello non attivano il layout automatico.
CABasicAnimation* ba = [CABasicAnimation animationWithKeyPath:@"transform"];
ba.autoreverses = YES;
ba.duration = 0.3;
ba.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.1, 1.1, 1)];
[v.layer addAnimation:ba forKey:nil];
Sostituisci layoutSubviews . Chiama
[super layoutSubviews]
e perfeziona i vincoli.Cambia il frame in viewDidLayoutSubviews . Layout automatico viene applicato in
layoutSubviews
, quindi una volta fatto, cambiarlo inviewDidLayoutSubviews
.Disattivare il layout automatico e impostare le visualizzazioni manualmente. Puoi fare questo sovrascrivendo
layoutSubviews
/layout
senza chiamare l'implementazione della super classe.
Suggerimento: se il genitore della vista animata non viene interpolato (ovvero, l'animazione salta dallo stato iniziale a quello finale), chiama layoutIfNeeded()
nella vista più profonda che è il genitore della vista animata (in altre parole , che non è influenzato dall'animazione). Non so esattamente perché funzioni.
Risolvi conflitto priorità UILabel
Problema : quando usi molte etichette in una vista, potresti ricevere un avvertimento :
Come possiamo risolvere questo avvertimento ?
Soluzione : calcoliamo e definiamo le priorità in ordine. Le priorità devono essere diverse dalle etichette. Significa che è importante avrà una priorità più alta. Ad esempio, nel mio caso, ho impostato le priorità verticali per le mie etichette in questo modo:
Ho impostato la massima priorità per la 1a etichetta e la più bassa per la 4a etichetta.
In un ViewController, penso che sia difficile vedere l'effetto di quelle priorità. Tuttavia, è molto chiaro con UITableViewCell + stima l'altezza della cella.
Spero che questo aiuto.
UILabel e dimensione Parentview in base al testo in UILabel
Guida passo passo: -
Passo 1: - Imposta il vincolo su UIView
- Leading. 2) In alto. 3) Trailing. (Dalla schermata principale)
Step 2: - Imposta vincolo su Label 1
- Leading 2) Top 3) Trailing (Dalla sua superview)
Passaggio 3: - Imposta il vincolo sull'etichetta 2
- Leading 2) Top 3) Trailing (Dalla sua superview)
Passo 4: - Più difficile dare un fondo a UILabel da UIView.
Passaggio 5: - (Facoltativo) Impostare il vincolo su UIButton
- Leading 2) Bottom 3) Trailing 4) Fixed Height (From mainview)
Produzione :-
Nota: - Assicurarsi di aver impostato Numero di righe = 0 nella proprietà Label.
Spero che questa informazione sia sufficiente per comprendere l'Autoresize UIView in base all'altezza di UILabel e Autoresize UILabel in base al testo.
Nozioni di base sul linguaggio Visual Format: vincoli nel codice!
HVFL è un linguaggio progettato per limitare gli elementi dell'interfaccia utente in modo semplice e rapido. In generale, VFL ha un vantaggio rispetto alla tradizionale personalizzazione dell'interfaccia utente in Interface Builder perché è molto più leggibile, accessibile e compatto.
Ecco un esempio di VFL, in cui tre UIViews sono vincolate da sinistra a destra, riempiendo superView.width
, con aGradeView
"H:|[bgView][aGradeView(40)][bGradeView(40)]|"
Ci sono due assi in cui possiamo limitare gli oggetti UI a, orizzontalmente e verticalmente.
Ogni riga di VFL inizia sempre con H:
o V:
Se nessuno dei due è presente, l'opzione predefinita è H:
Andando avanti, abbiamo una pipeline. |
Questo simbolo, o il tubo, si riferisce alla superview. Se osservi più da vicino lo snippet del codice VFL riportato sopra, noterai due di queste pipeline.
Questo significa le due estremità orizzontali del superview, il limite esterno e i confini esterni.
Poi vedrai alcune parentesi quadre, all'interno del primo set di parentesi quadre, abbiamo bgView
. Quando abbiamo parentesi quadre, si riferisce a un elemento dell'interfaccia utente, ora ti potresti chiedere come stabiliamo un collegamento tra il nome e l'effettivo elemento dell'interfaccia utente, forse uno sbocco?
Lo copro alla fine del post.
Se dai un'occhiata alla seconda coppia di parentesi quadre [aGradeView(50)]
, abbiamo alcune parentesi incapsulate all'interno, quando è presente, definisce la larghezza / altezza in base agli assi, che in questo caso è 50 pixel in larghezza.
Le prime parentesi quadre [bgView]
non hanno una larghezza esplicitamente definita, il che significa che si estenderà il più possibile.
Va bene, è tutto per le basi, più sulle cose avanzate in un altro esempio.
// 1. create views UIView *blueView = [[UIView alloc] init]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; // 2. forbid Autoresizing blueView.translatesAutoresizingMaskIntoConstraints = NO; redView.translatesAutoresizingMaskIntoConstraints = NO; // 3. make contraints // horizontal NSArray *blueH = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-20-[blueView]-20-|" options:NSLayoutFormatAlignAllLeft metrics:nil views:@{@"blueView" : blueView}]; [self.view addConstraints:blueH]; // vertical NSArray *blueVandRedV = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-20-[blueView(50)]-20-[redView(==blueView)]" options:NSLayoutFormatAlignAllTrailing metrics:nil views:@{@"blueView" : blueView, @"redView" : redView}]; [self.view addConstraints:blueVandRedV]; NSLayoutConstraint *redW = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0]; [self.view addConstraint:redW];
Utilizzo misto di layout automatico con layout non automatico
A volte potresti voler eseguire alcune azioni aggiuntive ai calcoli del layout automatico eseguiti da UIKit
stessa.
Esempio: quando hai un UIView
con maskLayer
, potresti dover aggiornare maskLayer
non appena Layout automatico cambia il frame
UIView
// CustomView.m
- (void)layoutSubviews {
[super layoutSubviews];
// now you can assume Auto Layout did its job
// you can use view's frame in your calculations
CALayer maskLayer = self.maskLayer;
maskLayer.bounds = self.bounds;
...
}
o se si desidera intraprendere qualche azione aggiuntiva su Auto Layout in ViewController
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// now you can assume all your subviews are positioned/resized correctly
self.customView.frame = self.containerView.frame;
}
Layout proporzionale
Vincolo creato come
NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.LeadingMargin, multiplier: 1.0, constant: 20.0)
o, dal punto di vista della matematica:
view.attribute * multiplier + constant (1)
È possibile utilizzare il moltiplicatore per creare un layout proporzionale per un fattore di dimensioni diverse.
Esempio:
Turquoise View (V1) è un quadrato con larghezza proporzionale della larghezza superview con rapporto 1: 1.1
Gary square (V2) è una sottoview di V1. Spazio inferiore impostato da costante = 60, Spazio finale impostato da moltiplicatore = 1.125 e costante = 0
Lo spazio finale è impostato in modo proporzionale, lo spazio inferiore impostato come costante.
Nota: se view.attribute è uguale a 0 (ad esempio spazio iniziale), la formula del vincolo (1) sarà uguale a 0. È necessario modificare il secondo elemento del vincolo o impostare il vincolo relativo al margine, per poter visualizzare.attributo! = 0.
NSLayoutConstraint: Contraints in code!
Quando stiamo lavorando su un framework, se i vincoli non sono troppo complessi, è meglio usare Interface Builder o NSLayoutConstraint nel codice per renderlo più piccolo, invece di importare Masonry o SnapKit.
- Objective-C
// 1. create views UIView *blueView = [[UIView alloc] init]; blueView.backgroundColor = [UIColor blueColor]; [self.view addSubview:blueView]; UIView *redView = [[UIView alloc] init]; redView.backgroundColor = [UIColor redColor]; [self.view addSubview:redView]; // 2. forbid Autoresizing blueView.translatesAutoresizingMaskIntoConstraints = NO; redView.translatesAutoresizingMaskIntoConstraints = NO; // 3. make contraints // 3.1 blueView NSLayoutConstraint *blueLeft = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:1 constant:20]; [self.view addConstraint:blueLeft]; NSLayoutConstraint *blueTop = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:1 constant:20]; [self.view addConstraint:blueTop]; NSLayoutConstraint *blueRight = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:-20]; [self.view addConstraint:blueRight]; NSLayoutConstraint *blueHeight = [NSLayoutConstraint constraintWithItem:blueView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:50]; [self.view addConstraint:blueHeight]; // 3.2 redView NSLayoutConstraint *redTop = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeBottom multiplier:1 constant:20]; [self.view addConstraint:redTop]; NSLayoutConstraint *redRight = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeRight multiplier:1 constant:-20]; [self.view addConstraint:redRight]; NSLayoutConstraint *redHeight = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeHeight multiplier:1 constant:0]; [self.view addConstraint:redHeight]; NSLayoutConstraint *redWidth = [NSLayoutConstraint constraintWithItem:redView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:blueView attribute:NSLayoutAttributeWidth multiplier:0.5 constant:0]; [self.view addConstraint:redWidth];