2013-07-16 6 views
6

Ho un UIScrollView con 2 subviews. Vorrei che una sottoview fosse "leading-aligned" (left-aligned) dove il suo leading edge si allineava con il leading edge della scrollview. Mi piacerebbe che l'altra sottoview fosse "allineata alla fine" (allineata a destra) dove il suo bordo posteriore si allinea con il bordo finale della scrollview.La sottoview non allineerà il bordo posteriore al suo padre UIScrollView

Per qualche motivo, l'autolayout mantiene inaspettatamente la seconda sottoview allineata alla fine, al di fuori dei limiti della scrollview, sul lato principale (a sinistra) dell'altro subview, in modo tale che il bordo finale della sottodirectory si allinea con il bordo principale della scrollview.

Sto provando a farlo a livello di programmazione. Il codice è sotto Sto usando 2 etichette per le 2 sottoview. L'etichetta "alpha" è correttamente allineata, ma l'etichetta "beta" non è allineata alla fine, come dovrebbe essere.

Questo succede anche se provo ad usare gli allineamenti sinistro e destro invece che all'inizio e alla fine. L'etichetta allineata a destra viene visualizzata nella stessa posizione errata dell'etichetta allineata alla fine.

Ho letto le note di rilascio di iOS 6 e le risposte qui e altrove molte volte e non sono sicuro del perché ciò stia accadendo.

Nel controller della vista:


- (void) viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Create and configure the scroll view. 
    UIScrollView * scrollView = [[UIScrollView alloc] init]; 
    [scrollView setTranslatesAutoresizingMaskIntoConstraints:NO]; 

    // For debugging. 
    [scrollView setClipsToBounds:NO]; 
    scrollView.layer.borderColor = [UIColor redColor].CGColor; 
    scrollView.layer.borderWidth = 1.0; 

    [[self view] addSubview:scrollView]; 

    // Layout scrollview. 

    // Horizontal: leading edge to superview's leading edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeLeading 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeLeading 
                 multiplier:1.0 
                  constant:20.0]]; 

    // Horizontal: trailing edge to superview's trailing edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeTrailing 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeTrailing 
                 multiplier:1.0 
                  constant:-20.0]]; 

    // Vertical: top edge to superview's top edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeTop 
                 multiplier:1.0 
                  constant:20.0]]; 

    // Vertical: bottom edge to superview's bottom edge, with indent. 
    [self.view addConstraint:[NSLayoutConstraint constraintWithItem:scrollView 
                  attribute:NSLayoutAttributeBottom 
                  relatedBy:NSLayoutRelationEqual 
                  toItem:self.view 
                  attribute:NSLayoutAttributeBottom 
                 multiplier:1.0 
                  constant:-20.0]]; 

    // Create and configure first label which should be leading-aligned with scrollview. 
    UILabel * labelAlpha = [[UILabel alloc] init]; 
    [labelAlpha setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [labelAlpha setText:@"Alpha"]; 
    [scrollView addSubview:labelAlpha]; 

    // Layout first label. 

    // Horizontal: leading edge to scrollview's leading edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha 
                  attribute:NSLayoutAttributeLeading 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeLeading 
                  multiplier:1.0 
                  constant:0.0]]; 

    // Vertical: top edge to scrollview's top edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelAlpha 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  multiplier:1.0 
                  constant:0.0]]; 


    // Create and configure second label which should be trailing-aligned with scrollview. 
    UILabel * labelBeta = [[UILabel alloc] init]; 
    [labelBeta setTranslatesAutoresizingMaskIntoConstraints:NO]; 
    [labelBeta setText:@"Beta"]; 
    [scrollView addSubview:labelBeta]; 

    // Layout second label. 

    // Horizontal: trailing edge to scrollview's trailing edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta 
                  attribute:NSLayoutAttributeTrailing 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTrailing 
                  multiplier:1.0 
                  constant:0.0]]; 
    // Vertical: top edge to scrollview's top edge. 
    [scrollView addConstraint:[NSLayoutConstraint constraintWithItem:labelBeta 
                  attribute:NSLayoutAttributeTop 
                  relatedBy:NSLayoutRelationEqual 
                   toItem:scrollView 
                  attribute:NSLayoutAttributeTop 
                  multiplier:1.0 
                  constant:0.0]]; 

} 

Per riferimento, l'uscita dal recursiveDescription di vista del controller della vista esegue il backup del disallineamento:

2013-07-15 22:04:23.892 Middleman[5669:907] <UIView: 0x20872960; frame = (0 0; 320 480); transform = [0, -1, 1, 0, 0, 0]; autoresize = RM+BM; layer = <CALayer: 0x20871e60>> 
    | <UIScrollView: 0x208718a0; frame = (20 20; 440 280); gestureRecognizers = <NSArray: 0x20871f20>; layer = <CALayer: 0x208728e0>; contentOffset: {0, 0}> 
    | | <UILabel: 0x20872ab0; frame = (0 0; 44 21); text = 'Alpha'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20872b90>> 
    | | <UILabel: 0x208730e0; frame = (-36 0; 36 21); text = 'Beta'; clipsToBounds = YES; userInteractionEnabled = NO; layer = <CALayer: 0x20873170>> 
+0

Ho lo stesso identico problema (anche se sto usando strumenti C# MonoTouch invece di obj-c). Sto creando esempi molto semplici usando viste create a livello di codice e non riesco a farle allineare sul lato destro di UIScrollView usando l'autolayout. Hai avuto fortuna a capirlo? – Camputer

risposta

0

si può provare a utilizzare il corretto allineamento del testo e imposta anche il vincolo di larghezza dell'etichetta. Altrimenti la dimensione dell'etichetta è adatta al contenuto.

CGFloat width = CGRectGetWidth(self.view.frame)-40.0; 
labelBeta.preferredMaxLayoutWidth = width; //required for multi line wrapping 
[scrollView addConstraints: 
    [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[labelBeta(width)]|" 
              options:0 metrics:@{@"width":@(width)} 
               views:NSDictionaryOfVariableBindings(labelBeta)]]; 
+0

E se volessi allineare a destra qualcos'altro oltre ad un UILabel (ad es., Una vista immagine)? – Camputer

6

Ho affrontato lo stesso problema e alla fine ho trovato una soluzione. Nota che non sto usando l'obiettivo C, sto usando MonoTouch (C#), ma il principio dovrebbe essere lo stesso.

Il problema è il modo in cui AutoLayout risolve i vincoli per un UIScrollView. Per molte altre viste, l'esecuzione automatica utilizza l'allineamento della vista rect, che in molti casi coincide con il fotogramma della vista. In UIScrollView, tuttavia, sembra utilizzare la dimensione (ad esempio, la larghezza) del frame se il vincolo è centrato (ad esempio, centerX), motivo per cui la mia sottoview è centrata normalmente all'interno di UIScrollView, ma quando si aggiungono vincoli per allineare a destra un sottoview usa il contentSize width/height. Il problema è che la larghezza contentSize era 0 nel mio caso (solo lo scorrimento verticale), quindi allineare a destra significava semplicemente allineare a una casella di larghezza 0, che io perché ho visto la mia sottoview sul bordo sinistro.

Normalmente, avrei risolto contentSize anche con i vincoli, ma in questo caso, solo l'altezza contentSize era diverso da zero poiché stavo scorrendo verticalmente. Ho provato ad aggiungere vincoli nella vista di scorrimento per ottenere anche la larghezza contentSize da impostare correttamente, ma l'unico modo ho potuto fare questo (pur mantenendo i vincoli necessari per la mia pagina) è stato quello di effettuare le seguenti operazioni:

  1. Inserire un UIView "vuoto" come figlio di scrollView.
  2. impostare la larghezza di questo UIView alla larghezza del più alto contenitore di livello View (sopra ScrollView) utilizzando vincoli
  3. Applicare un vincolo alla ScrollView tale che il suo bordo destro deve essere maggiore o uguale al bordo destro della mia UIView vuoto (simile al vincolo utilizzato per impostare il contenuto verticale Dimensione per lo scorrimento della pagina).

Ora, la larghezza del contenuto del mio UIScrollView è impostata correttamente e le cose sono allineate al bordo destro come previsto.

+0

Come si trova il contenutoSize? – Gerald

1

La mia soluzione a questo è quella di inserire una sorta di helperView (ad esempio UIView, UITableView) in UIScrollView e applicare 6 vincoli alla helperView:

- equal width to scrollView 
- equal height to scrollView 
- 0 leading space to scrollView 
- 0 trailing space to scrollView 
- 0 top space to scrollView 
- 0 bottom space to scrollView 

È quanto possibile allineare altre viste bambino di ScrollView verso i bordi helperView .

Problemi correlati