iOS 使用 Autolayout 以编程方式修复 UIScrollView 中子视图的位置

Posted

技术标签:

【中文标题】iOS 使用 Autolayout 以编程方式修复 UIScrollView 中子视图的位置【英文标题】:iOS programmatically fix the position of a subview within UIScrollView with Autolayout 【发布时间】:2014-05-28 18:29:54 【问题描述】:

我有一个包含 UIScrollView 的 UIView。 UIScrollView 包含一个 MKMapView 子视图和它正下方的占位符子视图。我想将 MKMapView 固定到屏幕顶部,并允许占位符子视图滑过它并覆盖它。

Apple 表示现在可以使用 Autolayout 完成此操作,但它似乎对我不起作用。下面的代码正确显示了 UIScrollView 及其子视图,但地图仍然与其他所有内容一起滚动。我是否遗漏了一些非常明显的东西?

https://developer.apple.com/LIBRARY/ios/technotes/tn2154/_index.html

请注意,您可以通过在视图和滚动视图的子树之外的视图(例如滚动视图的超级视图)之间创建约束,使滚动视图的子视图看起来浮动(不滚动)在其他滚动内容之上.

UIView .m 文件:

- (id)initWithFrame:(CGRect)frame

    self = [super initWithFrame:frame];
    if (self) 

        // Create scroll view and add to view
        UIScrollView *scrollView = [[UIScrollView alloc] init];
        [scrollView setBackgroundColor: [UIColor clearColor]];
        [scrollView setShowsVerticalScrollIndicator:NO];
        [scrollView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self addSubview:scrollView];

        // Create map view and add to scroll view
        mapView = [[MKMapView alloc] init];
        mapView.showsPointsOfInterest = NO;
        mapView.translatesAutoresizingMaskIntoConstraints = NO;
        [scrollView addSubview:mapView];

        // Create a placeholder image to scroll over map view
        UIImageView *randomPlaceholderStuff = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"stuff.png"]];
        [dividingLine setTranslatesAutoresizingMaskIntoConstraints:NO];
        [scrollView addSubview:dividingLine];


        // Layouts
        NSDictionary *viewArranging = NSDictionaryOfVariableBindings(scrollView, tourMap, randomPlaceholderStuff);

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[scrollView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:viewArranging]];

        [self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[scrollView]|"
                                                                     options:0
                                                                     metrics:0
                                                                       views:viewArranging]];

        UIView *referenceSuperView = scrollView.superview;

        [referenceSuperView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mapView(320)]|"
                                                                           options:0
                                                                           metrics:0
                                                                             views:viewArranging]];

        [referenceSuperView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[mapView(320)]"
                                                                           options:0
                                                                           metrics:0
                                                                             views:viewArranging]];

        [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-334-[randomPlaceholderStuff]|"
                                                                           options:0
                                                                           metrics:0
                                                                             views:viewArranging]];

        [scrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[randomPlaceholderStuff(320)]|"
                                                                           options:0
                                                                           metrics:0
                                                                             views:viewArranging]];

    
    return self;


@end

编辑:

jrturton 的回答很到位。这是最终工作的代码:

[self addConstraint:[NSLayoutConstraint constraintWithItem:mapView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:scrollView.superview attribute:NSLayoutAttributeTop multiplier:1.0 constant:0.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem:mapView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:scrollView.superview attribute:NSLayoutAttributeWidth multiplier:1.0 constant:0.0]];

[self addConstraint:[NSLayoutConstraint constraintWithItem:mapView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:320.0]];

【问题讨论】:

【参考方案1】:

你不能用视觉格式语言做你正在尝试的事情。 | 字符将始终被解释为视图的直接超级视图,因此您不会创建您认为的约束。

您需要使用更长的方法 (constraintWithItem...) 来创建单独的约束,其中 item1 是您的浮动视图,而 item2 是滚动视图的超级视图。

【讨论】:

【参考方案2】:

您可以通过将子视图添加/移动到滚动视图的超级视图来在UIScrollView 上添加浮动子视图,例如:

将您的按钮放置/设置在滚动视图上(不在滚动视图内),如此处快照所示。并且还针对滚动视图的超级视图设置按钮约束(位置)。

这里是参考。每个视图的位置层次结构快照。

【讨论】:

以上是关于iOS 使用 Autolayout 以编程方式修复 UIScrollView 中子视图的位置的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式创建 AutoLayout 约束 (IOS) Xcode 7.0.1

以编程方式设置 AutoLayout 大小类?

如何使用大于或等于编程 iOS AutoLayout 约束而不使布局模糊?

使用 UIScrollView 和 AutoLayout 以编程方式创建控制器无法正确调整视图大小

如何以编程方式设置 UIScrollView 以使用 autoLayout 水平滚动

使用 AutoLayout 以编程方式将 UILabel 添加到 ScrollView (swift)