2015-03-23 12 views
12

Ho il seguente problema: Ho creato una classe personalizzata UIView e il suo layout nel file XIB. Diciamo che la dimensione della mia vista personalizzata in XIB è 150 x 50. Ho abilitato sizeClasses (wAny hAny) e AutoLayout. In Metriche simulate ho impostato Size = Freeform, Status Bar = None, tutto other = Inferred.Ridimensiona a livello di codice Uiview personalizzato da XIB

codice della mia classe personalizzata UIView si presenta così:

#import "CustomView.h" 

@implementation CustomView 

#pragma mark - Object lifecycle 

- (id)initWithFrame:(CGRect)frame { 
    self = [super initWithFrame:frame]; 

    if (self) { 
     [self setup]; 
    } 

    return self; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder { 
    self = [super initWithCoder:aDecoder]; 

    if (self) { 
     [self setup]; 
    } 

    return self; 
} 

#pragma mark - Private & helper methods 

- (void)setup { 
    if (self.subviews.count == 0) { 
     [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil]; 
     self.bounds = self.view.bounds; 
     [self addSubview:self.view]; 
    } 
} 

@end 

Nel mio UIViewController dove voglio aggiungere questa usanza UIView, ho fatto UIView manichino (che taglia ho impostato in Interface Builder) dove ho voglio aggiungere il mio CustomView e Mi piacerebbe che il mio CustomView soddisfi i limiti della mia vista container.

io sto cercando di fare che in questo modo:

_vCustomView = [[CustomView alloc] init]; 
_vCustomView.translatesAutoresizingMaskIntoConstraints = NO; 
[_vContainer addSubview:_vCustomView]; 

[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeLeft multiplier:1.0 constant:0.0]]; 
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeRight multiplier:1.0 constant:0.0]]; 
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]]; 
[_vContainer addConstraint:[NSLayoutConstraint constraintWithItem:_vCustomView attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:_vContainer attribute:NSLayoutAttributeBottom multiplier:1.0 constant:0.0]]; 

ma senza fortuna. Supponiamo che la vista del contenitore sia 300 x 100, quando aggiungo la mia personalizzata UIView ad essa, , la mia visualizzazione personalizzata è ancora 150 x 50.

ho cercato di lavorare senza vista container - aggiungere il mio oggetto personalizzato UIView direttamente al self.view della mia UIViewController e impostare la sua larghezza e altezza con:

  • autoLayout vincoli
  • utilizzando initWithFrame quando inizializzare la mia custom UIView

ma ancora una volta - senza fortuna. visualizzazione personalizzata è sempre di 150 x 50.

Qualcuno può spiegare a me come posso programmazione aggiungere il mio personalizzato UIView fatto in XIB e ridimensionarlo utilizzando autoLayout vincoli?

Molte grazie in anticipo.

Modifica # 1: errore che ottengo quando si tenta di eseguire il codice di Andrea sul mio CustomView

Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x17489b760 V:[UIView:0x17418d820(91)]>", 
    "<NSLayoutConstraint:0x170c9bf80 V:|-(0)-[CustomView:0x1741da7c0] (Names: '|':CustomView:0x1741da8b0)>", 
    "<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0)>", 
    "<NSLayoutConstraint:0x170c9be90 V:|-(0)-[CustomView:0x1741da8b0] (Names: '|':UIView:0x17418d820)>", 
    "<NSLayoutConstraint:0x170c9bee0 CustomView:0x1741da8b0.bottom == UIView:0x17418d820.bottom>", 
    "<NSAutoresizingMaskLayoutConstraint:0x170c9dba0 h=--& v=--& CustomView:0x1741da7c0.midY == + 25.0>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x170c9bfd0 V:[CustomView:0x1741da7c0]-(0)-| (Names: '|':CustomView:0x1741da8b0)> 

Edit # 2: Funziona!

Dopo @Andrea aggiunto:

view.translatesAutoresizingMaskIntoConstraints = NO; 

nel suo:

- (void) stretchToSuperView:(UIView*) view; 

metodo, tutto funziona come mi aspettavo.

Grazie a @Andrea.

+0

Stai chiamando 'layoutIfNeeded' dopo aver apportato le modifiche ai vincoli? Potresti postare il codice dove cambi la larghezza e l'altezza? Inoltre, se la vista ha un'altezza e una larghezza vincoli nello storyboard, l'aggiunta dei vincoli al 'contentView' farà in modo che i vincoli si bloccino, perché saranno in conflitto. –

+0

@CatalinaT. La ringrazio per la risposta. Non ho chiamato layoutIfNeeded, ma ora ci ho provato, non ha apportato alcuna modifica. _vContainer è una vista fittizia che si trova al centro del mio schermo. La mia idea è di aggiungere il mio CustomView a quella vista fittizia e che il mio CustomView ha le stesse dimensioni come vista fittizia. Ecco perché ho scritto 4 vincoli sopra dove sto dicendo che il mio CustomView dovrebbe essere allineato con tutti e quattro i lati della vista fittizia. Indirettamente, sto impostando la larghezza e l'altezza di CustomView in questo modo. Ma, nessuna fortuna. CustomView ha sempre le stesse dimensioni del suo XIB (150 x 50). – uerceg

risposta

16

Immagino che il problema principale è che non si utilizza il layout automatico quando si aggiunge il tuo xib nella visualizzazione del contenuto.
Dopo aver aggiunto la visualizzazione secondaria in voi init metodi si prega di chiamare quel metodo, passando la vista della XI ter:

- (void) stretchToSuperView:(UIView*) view { 
    view.translatesAutoresizingMaskIntoConstraints = NO; 
    NSDictionary *bindings = NSDictionaryOfVariableBindings(view); 
    NSString *formatTemplate = @"%@:|[view]|"; 
    for (NSString * axis in @[@"H",@"V"]) { 
     NSString * format = [NSString stringWithFormat:formatTemplate,axis]; 
     NSArray * constraints = [NSLayoutConstraint constraintsWithVisualFormat:format options:0 metrics:nil views:bindings]; 
     [view.superview addConstraints:constraints]; 
    } 

} 

[EDIT]
Il codice di installazione dovrebbe essere simile che:

- (void)setup { 
    if (self.subviews.count == 0) { 
     [[NSBundle mainBundle] loadNibNamed:@"CustomView" owner:self options:nil]; 
     self.bounds = self.view.bounds; 
     [self addSubview:self.view]; 
     [self stretchToSuperView:self.view]; 
    } 
} 

Prestare attenzione che all'interno vista allungata ho aggiunto view.translatesAutoresizingMaskIntoConstraints = NO;
[EDIT 2]
Cercherò di elaborare la mia risposta come richiesto. Utilizzando l'autolayout, quando si aggiunge una vista senza vincoli di impostazione, l'autolayout converte automaticamente le maschere di autoresizing in vincoli, la cui proprietà predefinita è UIViewAutoresizingNone che significa non autorizzare.
La vista XIB è stata aggiunta al relativo genitore senza vincoli e senza la possibilità di autorizzare, mantenendo così le sue dimensioni originali. Dal momento che si desidera che l'immagine per ridimensionare di conseguenza per la vostra vista che aveva due scelte:

  • Modificare le maschere ridimensionamento automatico della vostra vista XI ter larghezza e l'altezza flessibile, ma hanno bisogno in base al formato genitore o non si avrà un full cover
  • Aggiungi alcuni vincoli che vincolano le due viste in modo da modificarle in base alle modifiche principali. E raggiungi questo detto tra la vista XIB e la sua vista genitore, lo spazio tra il trailing/leading e il top/botton è 0. È come se mettessi della colla sui loro bordi. Per fare questo è necessario impostare la maschera di ridimensionamento dell'autotranslate in vincolo su NO, oppure si possono avere alcuni conflitti durante la registrazione nel log.

Quello che state facendo tardi è l'aggiunta di vincoli per la vista (che ospita la vista XIB) per la sua superview, ma non c'erano vincoli tra la XIB ed il suo genitore, quindi AutoLayout non sa come ridimensionare la vista XIB.
Ogni vista in una gerarchia di viste dovrebbe avere i propri vincoli.
Spero che questo aiuti a capire meglio.

+0

Ho scritto _vCustomView.translatesAutoresizingMaskIntoConstraints = NO; prima ho aggiunto il mio CustomView in un contenitore fittizio. Non è abbastanza per poter utilizzare i vincoli di autolayout sul mio oggetto CustomView a livello di programmazione? In seguito, ho provato con questi 4 vincoli per rendere la mia CustomView adatta alla vista del contenitore fittizio, ma come detto - senza fortuna. Ho provato a chiamare il metodo dopo aver aggiunto il mio oggetto CustomView al contenitore fittizio e impostando i suoi quattro vincoli, ma senza fortuna - lo stesso risultato. CustomView è ancora 150 x 50 e non grande come un contenitore fittizio (come penso che dovrebbe essere). – uerceg

+0

Sto parlando di quel metodo '- (void) setup' dopo aver aggiunto lo xib come una subview call quella che ho postato. È la tua vista xib che manca i vincoli. – Andrea

+0

Controlla la mia modifica # 1. – uerceg

1

Nel codice si dovrebbe avere qualcosa di simile:

In primo luogo, un IBOutlet per il vincolo di larghezza si vuole il cambiamento, sia nel viewController o in CustomView (io non so davvero dove si ha la logica per calcolare il valore del vincolo).

@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint; 

Poi, nel metodo si desidera aggiornare il valore costante, avrete qualcosa di simile:

-(void)updateWidth { 
    [self.widthConstraint setConstant:newConstant]; 
    [self.view layoutIfNeeded]; // self.view must be an ancestor of the view 

    //If you need the changes animated, call layoutIfNeeded in an animation block 
} 

Spero che questo funziona per voi. In bocca al lupo!

+0

Andrea mi ha aiutato con la sua risposta, ma molte grazie anche a voi per la disponibilità ad aiutare. I migliori saluti. – uerceg

+0

Soluzione semplice ed elegante per me, grazie! – inix

0

Swift funzione 4.0 per allungare alla visualizzazione super:

Snippet di codice:

static public func stretchToSuperView(view:UIView) 
    { 
     view.translatesAutoresizingMaskIntoConstraints = false 
     var d = Dictionary<String,UIView>() 
     d["view"] = view 
     for axis in ["H","V"] { 
      let format = "\(axis):|[view]|" 
      let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: NSLayoutFormatOptions(rawValue: 0), metrics: [:], views: d) 
      view.superview?.addConstraints(constraints) 
     } 
    } 

Nota: Basta chiamare la funzione con un argomento come visualizzazione secondaria.

Questo mi aiuta a risolvere il problema .xib resing in swift 4.0.