web-dev-qa-db-fra.com

Comment définir des sous-vues avec AutoLayout dans UIScrollView par programme?

Je crée une application avec UiScrollview et UIPagectontrol en utilisant Autolayout par programme, pour

J'ai créé TKScroller comme sous-classe d'UIView, je l'initialise en utilisant Some Mode et Array.

TKScroller.m

-(void)setData{

[self layoutIfNeeded];
CGRect mainFrame=self.frame;


[self layoutIfNeeded];
CGRect mainFrame=self.frame;
UIView *lastview;
NSMutableArray* manualConstraints = [NSMutableArray array];

for (int i=0; i<arrayData.count ; i++)
{
    CGRect frame;
    frame.Origin.x = scrollView.frame.size.width * i;
    frame.Origin.y = 0;
    frame.size = scrollView.frame.size;

    UIView *subview = [UIView new];

    subview.backgroundColor = [self getRandomColor];
    [scrollView addSubview:subview];

    if (i==0)
    {

        NSLayoutConstraint* b1_top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:5];
        [manualConstraints addObject:b1_top];

        NSLayoutConstraint* b1_left = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeLeading multiplier:1 constant:5];
        [manualConstraints addObject:b1_left];

        NSLayoutConstraint* b1_right = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTrailing multiplier:1 constant:-5];
        [manualConstraints addObject:b1_right];
        NSLayoutConstraint* b1_bottom = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:-10];
        [manualConstraints addObject:b1_bottom];

        [subview layoutIfNeeded];
        [scrollView addConstraints:manualConstraints];
        lastview=subview;
    }
    else{

        NSLayoutConstraint* b1_top = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:5];
        [manualConstraints addObject:b1_top];

        NSLayoutConstraint* b1_left = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:lastview attribute:NSLayoutAttributeLeading multiplier:1 constant:5];
        [manualConstraints addObject:b1_left];

        NSLayoutConstraint* b1_right = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTrailing multiplier:1 constant:-5];
        [manualConstraints addObject:b1_right];
        NSLayoutConstraint* b1_bottom = [NSLayoutConstraint constraintWithItem:subview attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:scrollView attribute:NSLayoutAttributeTop multiplier:1 constant:-10];
        [manualConstraints addObject:b1_bottom];

        [subview layoutIfNeeded];
        [scrollView addConstraints:manualConstraints];
        lastview=subview;

    }
}

scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * arrayData.count, mainFrame.size.height/2);

self.pageControl.currentPage = 0;
self.pageControl.numberOfPages = arrayData.count;

 pageControlBeingUsed = NO;
}

-(UIColor *)getRandomColor{
    int r = arc4random() % 255;
    int g = arc4random() % 255;
    int b = arc4random() % 255;
    return [UIColor colorWithRed:(r/255.0) green:(g/255.0) blue:(b/255.0) alpha:1.0];
}

En ce moment je reçois des sous-vues,

mais si je change d'orientation, cela donnera un résultat incorrect. Alors, comment puis-je donner NSLayoutConstraint pour les sous-vues de scrollview? 

MODIFIER

Après avoir ajouté NSLayoutConstraint, les sous-vues ne sont pas affichées. Il me manque juste une contrainte, corrigez-moi s'il vous plaît dans la définition dynamique des contraintes.

Mon Code source est ici, Aidez-moi, s'il vous plaît… .. Merci. Et désolé pour la mauvaise grammaire.

12
user203108

Voici une réponse SO a expliqué comment procéder avec la mise en page automatique, explique-t-il parfaitement. Ici, il y a des champs de texte à la verticale. Mais dans votre cas, vous devez définir des contraintes de vues horizontales.

Alternative

Plutôt que de définir des contraintes, vous pouvez définir uniquement le cadre de la sous-vue et le définir dans Scrollview. Et en fonction de l'orientation, vous pouvez modifier les cadres des sous-vues de la scrolview.

Votre méthode setData comme,

-(void)setData{

    [self layoutIfNeeded];
    CGRect mainFrame=scrollView.frame;
    CGRect frame;
    for (int i=0; i<arrayData.count ; i++)
    {
        CGRect frame;
        frame.Origin.x = scrollView.frame.size.width * i;
        frame.Origin.y = 0;
        frame.size = scrollView.frame.size;

        frame.Origin=CGPointMake(0, 0);
        UIView *subview = [[UIView alloc]initWithFrame:frame];
        subview.backgroundColor = [self getRandomColor];
        [scrollView addSubview:subview];
    }
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * arrayData.count, mainFrame.size.height/2);
}

Maintenant, vous utilisez NSNotificationCenter, vous pouvez recevoir une notification lorsque l'orientation du périphérique est modifiée. Dans cette méthode de sélecteur, appelez votre méthode setData,

[[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(setData)
                                                 name:UIDeviceOrientationDidChangeNotification
                                               object:nil];

Maintenant, dans votre méthode setData, vous devez supprimer toutes les sous-vues, car lorsque l'appareil change d'orientation, il ajoute de nouvelles vues à votre vue à défilement. Supprimez donc toutes les sous-vues de la vue de défilement avant de définir son cadre.

        [scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];

Assurez-vous de retirer l'observateur de votre classe, comme

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
7
Toseef Khilji

Dans mon expérience avec AutoLayout (que j'utilise aussi par programme). Vous ne devez pas ajouter de vues directement à votre UIScrollView.

Vous devez faire une UIViewet un seul, que vous ajoutez comme sous-vue de votre UIScrollView.

Une fois que cela est fait, vous pouvez ajouter toutes vos sous-vues à cette UIView.

Tout est expliqué en détail ici: Note technique Apple iOS TN2154

10
AncAinu

Je sais que le problème a été résolu. et j’espère que cette solution pourra aider certaines personnes, je la poste donc.

Le code ci-dessous sert à ajouter le scrollview à uiviewcontroller

  self.scrollView = UIScrollView()
    self.scrollView.backgroundColor = UIColor.greenColor()
    self.scrollView.setTranslatesAutoresizingMaskIntoConstraints(false)
    self.scrollView.scrollEnabled=true
    self.scrollView.pagingEnabled = true
    self.view.addSubview(self.scrollView)

    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["scrollView":self.scrollView]))

    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["scrollView":self.scrollView]))

Après avoir ajouté la vue de défilement et ajouté les sous-vues/images comme ceci (ceci est un exemple pour les images affichées en taille réelle comme dans l'application de photos)

var prev:UIImgeView?

        for var index = 0; index < self.images.count; ++index {
            var iview = UIImgeView()
            iview.setTranslatesAutoresizingMaskIntoConstraints(false)
            self.scrollView.addSubview(iview)
            var image = self.images.objectAtIndex(index) as UIImage
            iview.image = image
            if (index == 0){
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[iview(==scrollView)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"scrollView":self.scrollView]))
                prev = iview

            }
            else{
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[prev][iview(==prev)]", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"prev":prev!]))
                prev = iview
            }
            self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[iview(==scrollView)]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["iview":iview,"scrollView":self.scrollView]))

            if (index == self.images.count-1){
                self.scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[prev]|", options: NSLayoutFormatOptions(0), metrics: nil, views: ["prev":prev!]))

            }

        }
5
sateesh

Si vous souhaitez que votre TKScroller soit fixé au centre et que l'orientation de l'assistance soit modifiée, vous pouvez simplement insérer le code suivant dans votre init

self.autoresizingMask = UIViewAutoresizingFlexibleWidth;

et vous devrez peut-être vérifier toutes vos sous-vues de TKScroller. Si vous n'aimez pas la taille automatique, vous pouvez définir (l'un des trois)

self.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
self.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin;
0
Baoyu