【问题标题】:How to set subviews with AutoLayout in UIScrollView programmatically?如何以编程方式在 UIScrollView 中使用 AutoLayout 设置子视图?
【发布时间】:2014-03-22 23:24:14
【问题描述】:

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

我已经创建了 TKScroller 作为 UIView 的子类,我使用 Some Mode 和 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];
}

现在我正在获取任何子视图,

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

编辑

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

我的Source Code is here,请帮帮我。 谢谢你。抱歉语法不好。

【问题讨论】:

  • “不正确的结果”是什么意思?
  • @AncAinu:pageControl 消失了。
  • 首先,如果您以编程方式执行AutoLayout,我建议您使用use this great Framework,这将使您的生活更加轻松,您的代码也更加可读;)
  • @AncAinu:感谢您的建议,我不想为此使用其他一些课程。请问你能帮我目前的工具,我只是缺少一些东西。
  • 旋转设备时,您是否看到调试控制台中显示任何信息?例如。无法同时满足约束。通常调试控制台会给你一些关于为什么视图没有正确显示的提示。此外,您应该在子视图上设置 translatesAutoresizingMaskIntoConstraints = NO

标签: ios iphone uiscrollview autolayout nslayoutconstraint


【解决方案1】:

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

你应该做一个UIView并且只有一个,你添加为你的UIScrollView的子视图。

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

这里详细解释了一切:Apple iOS Technical Note TN2154

【讨论】:

  • 是的,我正在这样做,我有UIView &gt; UIScrollview,并且在滚动视图中我也在添加一个视图,并且在参考链接中只有一个视图,我必须将多个视图添加到 uiscrollview。
  • 这不是我在你的代码中读到的,你在for 语句中做了[scrollView addSubview:subview];,所以你在UIScrollView 中添加了很多视图
  • 在参考链接中他们使用了 NSLayoutConstraintconstraintsWithVisualFormat ,在我的情况下我无法做到,所以我使用了其他 NSLayoutConstraint 方式。
  • 我必须在 uiscrollview 中添加视图,因为我想要像 iPhone Photos 应用程序这样的功能,但使用 pagecontrol.. 所以告诉我如何在不向滚动视图添加子视图的情况下实现画廊 + 页面控制功能。跨度>
  • 也许你可以仔细阅读我的回答...我解释你需要做UIScrollView &gt; UIView &gt; UIView[](your photos)。如果我是你,我会做一个UICollectionView启用水平滚动和分页,它应该以更简单的方式做你想做的事;)(但我从来没有尝试过水平UICollectionView我承认)
【解决方案2】:

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

替代方案

设置约束你可以只设置子视图的框架并在滚动视图中设置它,并且基于方向你可以改变滚动视图的子视图的框架。

你的 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);
}

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

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

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

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

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

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

【讨论】:

  • 感谢重播,但我需要用哪种方法写NSNotificationCenterobserver?
  • 你说它是自定义类,所以在它的init 方法中正确,你实现了那个方法吗??
  • 是的,我写过-(id)initWithFrame:(CGRect)frame array:(NSMutableArray *)array mode:(ScrollerMode)mode方法,
  • 并确保你删除了这个观察者。
  • 如果您为此编写代码将非常感谢,
【解决方案3】:

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

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

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

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

            }

        }

【讨论】:

  • 此布局适用于水平布局还是垂直布局的视图?
【解决方案4】:

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

self.autoresizingMask = UIViewAutoresizingFlexibleWidth;

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

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

【讨论】:

  • 这只是为了向后兼容(并使用setTranslatesAutoresizingMaskIntoConstraints:NO),但我认为这不是OP想要的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-15
  • 1970-01-01
  • 2014-08-09
  • 1970-01-01
相关资源
最近更新 更多