2013-07-21 10 views
5

Sto aggiungendo un UIView a UIScrollView e vincolandolo in modo che riempia lo spazio orizzontale, ad eccezione di alcuni margini. Il mio vincolo visivo si presenta così:UIView non obbedisce ai vincoli di autolayout in UIScrollView

@"|-16-[theLineView]-16-|" 

ho fatto la vista di un pixel ad alta in modo che apparirà come una linea, e la pose tra due etichette di testo:

@"V:[someOtherStuff]-[aTextLabel]-[theLineView]-[anotherLabel]" 

Tuttavia, sto trovando che la larghezza della linea si espande solo fino alla larghezza dell'etichetta più lunga sopra/sotto di essa.

Perché dovrebbe essere?

P.S Ho letto questo http://developer.apple.com/library/ios/#technotes/tn2154/_index.html

enter image description here

Codice

Ecco la totalità del codice di vista del regolatore da un progetto di test che presenta questo problema sulla sim iPad.

- (void)viewDidLoad 

{ [super viewDidLoad];

self.scrollView = [[UIScrollView alloc] init]; 
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO; 
self.scrollView.backgroundColor = [UIColor greenColor]; 
[self.view addSubview:self.scrollView]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"|[scrollView]|" 
                   options:0 
                   metrics:0 
                    views:@{@"scrollView":self.scrollView}]]; 
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|" 
                    options:0 
                    metrics:0 
                    views:@{@"scrollView":self.scrollView}]]; 

self.line1 = [[UIView alloc] init]; 
self.line2 = [[UIView alloc] init]; 
self.label1 = [[UILabel alloc] init]; 
self.label2 = [[UILabel alloc] init]; 
self.label3 = [[UILabel alloc] init]; 

for (UILabel *label in @[self.label1, self.label2, self.label3]) 
{ 
    label.text = @"I am a label and I am long enough that I can be multiline on an iphone but single on ipad"; 
} 

for (UIView *view in @[self.line1, self.line2, self.label1, self.label2, self.label3]) 
{ 
    view.translatesAutoresizingMaskIntoConstraints = NO; 
    view.backgroundColor = [UIColor redColor]; 
    [self.scrollView addSubview:view]; 
} 

//horizontal layout - all views/labels should fill the horizontal space expect for margin 
for (UIView *view in @[self.line1, self.line2, self.label1, self.label2, self.label3]) 
{ 
    NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"|-16-[view]-16-|" 
                    options:0 
                    metrics:0 
                    views:@{@"view":view}]; 
    [self.scrollView addConstraints:constraints]; 
} 

//vertical layout - stack em up 
[self.scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[lab1]-[line1(==1)]-[lab2]-[line2(==1)]-[lab3]-|" 
                    options:0 
                    metrics:0 
                    views:@{@"lab1":self.label1, @"line1":self.line1, @"lab2":self.label2, @"line2":self.line2, @"lab3":self.label3}]]; 

}

+0

Il tuo 1px 'UIView' ha altri vincoli su di esso? – Yazid

+0

[guarda] la stessa vista di [theLineView]? Avete qualche impostazione delle opzioni di allineamento nel parametro opzioni? – rdelmar

+0

Nessun altro vincolo o nulla nel parametro opzioni. Vedrò se riesco a riprodurre in un progetto di test. Sì, quelle visualizzazioni sono le stesse, corretto lo snippet. –

risposta

6

UIScrollView riduce automaticamente per adattarsi i punti di vista al suo interno. È necessario impostare la larghezza assolutamente da qualche parte.

tattica consigliata:

  1. Completamente fixiate lo ScrollView all'interno del suo genitore-view con i vincoli (iniziali, finali, in alto, in basso).
  2. Creare un UIView all'interno di UIScrollView e inserire tutto ciò che è necessario al suo interno.
  3. Impostare i vincoli in modo che l'UIView funga da vista del contenuto (questo significa che è abbastanza grande da includere tutti gli elementi). Utilizza molto le dimensioni del contenuto intrinseco, la resistenza agli strizzacervelli e il concatenamento di elementi con vincoli. Il layout risultante deve essere ben definito e unico (questo significa che se dovessi rimuovere tutti i vincoli all'esterno, il layout funzionerebbe ancora).
  4. Connetti i limiti di UIView con il loro superview (che è la visualizzazione del contenuto reale di UIScrollView, NON di UIScrollView!).

Se lo si fa in Interface-Builder (è possibile), è necessario ricontrollare i vincoli ogni volta che si tocca qualcosa in quella scena. E al tatto intendo "selezionare" non solo "modificare".

+0

Non ha funzionato per me, come impostare l'UIView per riempire l'intera larghezza della vista di scorrimento? – AndiDog

+0

Come ho detto: il contentView SEMPRE riempie la scrollView completa, perché scrollView si riduce. Devi impostare la larghezza all'interno. Nel tuo esempio, cambiando il formato da "| -16- [visualizza] -16- |" a "| -16- [visualizza (288)] - 16- |" dovrebbe darti un buon risultato –

+3

Questo funziona. Il numero 4 è l'approccio migliore secondo me, poiché è semplice ed evita qualsiasi numero magico (il che significa che supporta la rotazione, ecc.). –

2

Trovato una soluzione di lavoro che dovrebbe funzionare anche per il vostro caso. Vedi here.

2

Espansione al numero 4 della risposta di Patric Schenke; poiché la dimensione del contenuto di scrollView è fluida, il blocco di una vista interna ai suoi bordi non funziona per determinare la larghezza della vista. Il tuo pin sinistro funzionerà, ma entrambi non lo faranno. Calcolare la larghezza della vista in base al livello successivo del contenitore è la strada da percorrere.Finché il tuo self.scrollView è bloccato a livello del suo contenitore (che io chiamo containerView), questa linea di codice realizzerà ciò che desideri. Aggiungere questa riga al vostro for ciclo per i vincoli orizzontali:

// Pin view's width to match the scrollView container's width 
// -32 constant offset for margins 
[containerView addConstraint: 
    [NSLayoutConstraint constraintWithItem:view 
           attribute:NSLayoutAttributeWidth 
           relatedBy:NSLayoutRelationEqual 
            toItem:containerView 
           attribute:NSLayoutAttributeWidth 
           multiplier:1.0f 
           constant:-32]]; 
0

Ho trovato un modo semplice vincolo-based per raggiungere questo obiettivo (non ho ancora testato il grado di fragilità di questa soluzione):

[email protected]"H:|-16-[view]-16-|"... // (your original constraint) 

[self.scrollView addConstraint: 
    [NSLayoutConstraint constraintWithItem:view 
           attribute:NSLayoutAttributeCenterX 
           relatedBy:NSLayoutRelationEqual 
            toItem:self.scrollView 
           attribute:NSLayoutAttributeCenterX 
           multiplier:1.0f 
           constant:0.0f]]; 

Questo allunga view completamente verso l'altro lato della vista. Questo probabilmente non è l'ideale per il contenuto che scorre in orizzontale, ma dovrebbe funzionare in verticale.

Mi rendo conto che questo è più di un anno dopo, ma è più semplice per il caso di utilizzo a scorrimento monodimensionale rispetto alle risposte di patric.schenke (che sono buone e più robuste).

Problemi correlati