ios 如何以编程方式在 UIScrollView 中使用 AutoLayout 设置子视图?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21934558/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:32:23  来源:igfitidea点击:

How to set subviews with AutoLayout in UIScrollView programmatically?

iosiphoneuiscrollviewautolayoutnslayoutconstraint

提问by

I am creating app with UiScrollview and UIPagectontrol using Autolayout Programmatically, for

我正在以编程方式使用 Autolayout 创建带有 UiScrollview 和 UIPagectontrol 的应用程序,用于

I have Created TKScrolleras subclass of UIView, I am init it using Some Mode and Array.

我已经创建了 TKScroller作为 UIView 的子类,我使用 Some Mode 和 Array 初始化它。

TKScroller.m

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];
}

Right now i am getting any subviews,

现在我收到任何子视图,

but if i change orientation it will give incorrect result, So how can i give NSLayoutConstraintfor subviews of scrollview ?

但是如果我改变方向它会给出不正确的结果,那么我怎么能给出NSLayoutConstraint滚动视图的子视图呢?

EDIT

编辑

After adding NSLayoutConstraintsubviews are not shown. I am just missing some constraint , please correct me in setting constraints dynamically.

添加NSLayoutConstraint子视图后不显示。我只是缺少一些约束,请在动态设置约束时纠正我。

My Source Code is here, Please Help Me. Thank you. And Sorry for bad grammar.

我的源代码在这里,请帮助我。谢谢你。对不起,语法不好。

采纳答案by Toseef Khilji

Here is a SO answerhas explained how to do this with auto layout, he has explain perfectly , In here there is vertically textfields are there But in your case it is you have to set Horizontal views constraints.

Here is a SO answer解释了如何使用自动布局来做到这一点,他解释得很好,在这里有垂直文本字段,但在您的情况下,您必须设置水平视图约束。

Alternative

选择

Rather that setting constraints you can set just frame of the subview and set it in Scrollview, And based on orientation you can change frames of the scrolview's subviews.

而不是设置约束,您可以只设置子视图的框架并将其设置在 Scrollview 中,并且根据方向,您可以更改滚动视图子视图的框架。

Your setData Method like,

你的 setData 方法就像,

-(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);
}

Now you using NSNotificationCenter you can get notify when device orientation chaged, so in this selector method of it call your setDatamethod,

现在你使用 NSNotificationCenter 你可以在设备方向改变时得到通知,所以在它的这个选择器方法中调用你的setData方法,

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

Now in you setData method you need remove all subviews because when device changes Orientation it will add new views to your scrollview, so remove all subview from Scrollview before setting its frame,

现在在您的 setData 方法中,您需要删除所有子视图,因为当设备更改方向时,它将向您的滚动视图添加新视图,因此在设置其框架之前从 Scrollview 中删除所有子视图,

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

Make sure you are removing observer from your class like,

确保您正在从班级中删除观察者,例如,

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

回答by AncAinu

In my experience with AutoLayout(that I use programmatically too). You should not add views directly to your UIScrollView.

根据我的经验AutoLayout(我也以编程方式使用)。您不应将视图直接添加到您的UIScrollView.

You should do one UIViewand only one, that you add as subview of your UIScrollView.

您应该UIView只做一项,将其添加为UIScrollView.

Once this is done, you can add all of your subviews to this UIView.

完成后,您可以将所有子视图添加到此UIView.

Everything is explained in detail here : Apple iOS Technical Note TN2154

一切都在这里详细解释:Apple iOS 技术说明 TN2154

回答by sateesh

I know that the problem has been solved. and i hope that this solution my help for some people so i am posting it.

我知道问题已经解决了。我希望这个解决方案对某些人有帮助,所以我发布了它。

Below code is for adding the scrollview to the uiviewcontroller

下面的代码用于将滚动视图添加到 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]))

After added the scrollview and add the subviews/images like this(this is an example for images showing in full size of scrollview like in photos app )

添加滚动视图并添加这样的子视图/图像后(这是在照片应用程序中以全尺寸滚动视图显示图像的示例)

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!]))

            }

        }

回答by Baoyu

If you want your TKScroller fixed to the center and support orientation changes, you can simply put the following code in your init

如果您希望您的 TKScroller 固定在中心并支持方向更改,您可以简单地将以下代码放入您的 init

self.autoresizingMask = UIViewAutoresizingFlexibleWidth;

and you may need to check all your subview's of TKScroller. If you don't like autosize , you can set (one of the three)

并且您可能需要检查 TKScroller 的所有子视图。如果你不喜欢 autosize ,你可以设置(三个之一)

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