J'ai le problème suivant: j'ai créé une classe UIView
personnalisée et sa présentation dans le fichier XIB
. Supposons que la taille de ma vue personnalisée sous XIB soit de 150 x 50. J'ai activé sizeClasses
(wAny hAny) et AutoLayout
. Dans les métriques simulées, j'ai défini Size = Freeform
, Status Bar = None
, tous other = Inferred
.
Le code de ma classe UIView
personnalisée ressemble à ceci:
#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
Dans ma UIViewController
où je veux ajouter cette coutume UIView
, j'ai créé le pseudo UIView (taille que j'ai définie dans Interface Builder) où je veux ajouter mes CustomView
et j'aimerais que ma CustomView
corresponde aux limites de mon conteneur). vue.
J'essaie de faire ça comme ça:
_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]];
Mais pas de chance. Supposons que ma vue conteneur soit de 300 x 100, lorsque j'y ajoute ma UIView
personnalisée, ma vue personnalisée est encore de 150 x 50.
J'ai essayé de travailler sans vue conteneur - pour ajouter mon objet personnalisé UIView
directement à self.view de ma UIViewController
et définir sa largeur et sa hauteur avec:
autoLayout
contraintesinitWithFrame
lors de l'initialisation de ma UIView
personnaliséemais encore une fois - pas de chance. La vue personnalisée est toujours de 150 x 50.
Quelqu'un peut-il m'expliquer comment puis-je {ajouter par programme ma UIView
personnalisée faite dans XIB
et la redimensionner à l'aide de contraintes autoLayout
?
Merci d'avance.
_ {Edit # 1: Erreur lorsque j'essaie d'exécuter le code d'Andrea sur mon 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: Ca marche!} _
Après @Andrea ajouté:
view.translatesAutoresizingMaskIntoConstraints = NO;
dans son:
- (void) stretchToSuperView:(UIView*) view;
méthode, tout fonctionne comme prévu.
Merci à @Andrea.
Je suppose que le problème principal est que vous n'utilisez pas la mise en page automatique lorsque vous ajoutez votre xib dans la vue du contenu.
Après avoir ajouté la sous-vue dans vos méthodes init, veuillez appeler cette méthode en passant la vue de la xib:
- (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];
}
}
[MODIFIER]
Votre code de configuration devrait ressembler à ça:
- (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];
}
}
Faites attention à l'intérieur de la vue étendue, j'ai ajouté view.translatesAutoresizingMaskIntoConstraints = NO;
[EDIT 2]
Je vais essayer de développer ma réponse comme demandé. Avec autolayout, lorsque vous ajoutez une vue sans définir de contraintes, autolayout convertit automatiquement les masques de redimensionnement automatique en contraintes, dont la propriété par défaut est UIViewAutoresizingNone
, ce qui signifie de ne pas redimensionner automatiquement.
Votre vue XIB a été ajoutée à son parent sans contraintes et sans possibilité de redimensionnement automatique, conservant ainsi sa taille d'origine. Puisque vous voulez que votre vue soit redimensionnée en conséquence, vous avez deux choix:
Ce que vous allez faire par la suite consiste à ajouter des contraintes à la vue (hébergeant la vue XIB) dans sa vue d'ensemble, mais il n'y avait aucune contrainte entre XIB et son parent. Autolayout ne sait donc pas comment redimensionner la vue XIB.
Chaque vue dans une hiérarchie de vues doit avoir ses propres contraintes.
J'espère que cela aide à mieux comprendre.
Dans votre code, vous devriez avoir quelque chose comme ça:
Tout d’abord, une variable IBOutlet
à la contrainte de largeur que vous voulez modifier, soit dans le viewController, soit dans votre CustomView
(je ne sais pas vraiment où vous avez la logique pour calculer la valeur de la contrainte).
@property (nonatomic, weak) IBOutlet NSLayoutConstraint *widthConstraint;
Ensuite, dans la méthode à mettre à jour la valeur constante, vous obtiendrez quelque chose comme ceci:
-(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
}
J'espère que cela fonctionne pour toi. Bonne chance!
Fonction Swift 4.0 pour étirer la vue:
Extrait de code:
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)
}
}
Remarque: Appelez simplement la fonction avec un argument comme sous-vue.
Cela m'aide à résoudre le problème de résolution de .xib dans Swift 4.0.