在 Superview 中更改子视图的框架

Posted

技术标签:

【中文标题】在 Superview 中更改子视图的框架【英文标题】:Change Frame of Subview in Superview 【发布时间】:2018-10-01 20:29:54 【问题描述】:

我有一个 ViewController,它在 viewDidLoad 中添加 UIViewSpeciesImageView 作为子视图,并在 viewWillLayoutSubviews 中设置约束。

SpeciesImageView 没有 nib 文件。当我们在 viewDidLoad 中创建speciesImageView 时,它会调用SpeciesImageView 类中的initWithFrame

在手机旋转之前,它可以正常工作(横向和纵向)。我尝试将约束设置为speciesImageView.frame.size.width,但这不起作用,因为当方向改变时不会调用initWithFrame,因此speciesImageView 的高度/宽度保持不变。

另一方面,使用screenRect 不会改变UIView 的实际大小,它会改变它在超级视图中的大小。所以换句话说,我还没有找到一种方法来改变实际speciesImageView 在方向改变时的大小。

由于我不知道的原因,当您将其旋转回原始位置时,它会完全混乱。

- (void)viewDidLoad


    self.tabBarController.tabBar.hidden=YES;
    self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
    self.navigationController.navigationBar.hidden = NO;
    //self.navigationController.navigationBar.translucent = YES;


    UIImage *plantinfo;
    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_ios_6_1) 
        plantinfo = [UIImage imageNamed:@"plantinfo_frame.png"];
     else 
        plantinfo = [UIImage imageNamed:@"plantinfo.png"];
    

    UIBarButtonItem *tempButton = [[UIBarButtonItem alloc] initWithImage:plantinfo
                                                                   style:UIBarButtonItemStylePlain
                                                                  target:self
                                                                  action:@selector(toggleText:)];
    self.navigationItem.rightBarButtonItem = tempButton;
    [tempButton release];
    self.title = theSpecies.scientificName;
    //[self.navigationItem.backBarButtonItem setTitle:@""];
    self.navigationItem.backBarButtonItem.title = @"";


    infoViewSegmentedControl.backgroundColor = [UIColor blackColor];
    webView.backgroundColor = [UIColor blackColor];
    _activityIndicator.hidden = YES;

    [webView setOpaque:YES];
    webView.delegate = self;
    // Do double justification
    [webView loadhtmlString:[self formatHTML:theSpecies] baseURL:nil];
    showingInfoView = NO;

    //
    //  Resize containerView, infoview according to iphone 5 screen size.
    //

    infoView.autoresizingMask = UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
    CGPoint screenOrigin = [[UIScreen mainScreen] bounds].origin;
    CGSize viewSize = [[UIScreen mainScreen] bounds].size;
    CGPoint origin = infoView.frame.origin;

    CGRect statusBarFrame = [[UIApplication sharedApplication] statusBarFrame];

    if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) 
        infoView.frame = CGRectMake(screenOrigin.x,
                                    screenOrigin.y + statusBarFrame.size.height,
                                    viewSize.width,
                                    viewSize.height - origin.y - statusBarFrame.size.height);

        speciesImageView = [[SpeciesImageView alloc]
                            initWithFrame:CGRectMake(screenOrigin.x,
                                                     screenOrigin.y,
                                                     viewSize.width,
                                                     viewSize.height)];
     else 
        infoView.frame = CGRectMake(screenOrigin.x,
                                    screenOrigin.y,
                                    viewSize.width,
                                    viewSize.height - origin.y - statusBarFrame.size.height);

        speciesImageView = [[SpeciesImageView alloc]
                            initWithFrame:CGRectMake(screenOrigin.x,
                                                     screenOrigin.y,
                                                     viewSize.width,
                                                     viewSize.height - statusBarFrame.size.height)];
    

    speciesImageView.delegate = self;
    [containerView addSubview:speciesImageView];

    managedObjectContext = [(LeafletAppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
    [self parseImageURLArray];


-(void)viewWillLayoutSubviews
    if(speciesImageView.window != nil)
        CGRect screenRect = [[UIScreen mainScreen] bounds];
        speciesImageView.translatesAutoresizingMaskIntoConstraints = NO;
        NSLayoutConstraint *widthConst = [NSLayoutConstraint
                                          constraintWithItem:speciesImageView
                                          attribute:NSLayoutAttributeWidth
                                          relatedBy:NSLayoutRelationEqual
                                          toItem:nil
                                          attribute:NSLayoutAttributeNotAnAttribute
                                          multiplier:1.0
                                          constant:screenRect.size.width];

        NSLayoutConstraint *heightConst = [NSLayoutConstraint
                                           constraintWithItem:speciesImageView
                                           attribute:NSLayoutAttributeHeight
                                           relatedBy:NSLayoutRelationEqual
                                           toItem:nil
                                           attribute:NSLayoutAttributeNotAnAttribute
                                           multiplier:1.0
                                           constant:screenRect.size.height];

        NSLayoutConstraint *rightConstraint = [NSLayoutConstraint
                                               constraintWithItem:speciesImageView
                                               attribute:NSLayoutAttributeCenterX
                                               relatedBy:NSLayoutRelationEqual
                                               toItem:self.view
                                               attribute:NSLayoutAttributeCenterX
                                               multiplier:1.0
                                               constant:0.0];


        NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint
                                                constraintWithItem:speciesImageView
                                                attribute:NSLayoutAttributeBottom
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self.view
                                                attribute:NSLayoutAttributeBottom
                                                multiplier:1.0
                                                constant:0.0];
        [self.view addConstraints:@[widthConst, heightConst, bottomConstraint, rightConstraint]];
    


- (id)initWithFrame:(CGRect)frame


    if (self = [super initWithFrame:frame])
    
        imageScrollView = [[UIScrollView alloc] initWithFrame:frame];
        imageScrollView.delegate = self;
        imageScrollView.backgroundColor = [UIColor blackColor];
        [self addSubview:imageScrollView];

        imageScrollView.translatesAutoresizingMaskIntoConstraints = NO;


        NSLayoutConstraint *widthConst = [NSLayoutConstraint constraintWithItem:imageScrollView attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:imageScrollView.frame.size.width];

        NSLayoutConstraint *heightConst = [NSLayoutConstraint constraintWithItem:imageScrollView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:imageScrollView.frame.size.height];


        NSLayoutConstraint *rightConstraint = [NSLayoutConstraint
                                               constraintWithItem:imageScrollView
                                               attribute:NSLayoutAttributeRight
                                               relatedBy:NSLayoutRelationEqual
                                               toItem:self
                                               attribute:NSLayoutAttributeRight
                                               multiplier:1.0
                                               constant:0.0];


        NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint
                                                constraintWithItem:imageScrollView
                                                attribute:NSLayoutAttributeTop
                                                relatedBy:NSLayoutRelationEqual
                                                toItem:self
                                                attribute:NSLayoutAttributeTop
                                                multiplier:1.0
                                                constant:0.0];
        [self addConstraints:@[widthConst, heightConst, bottomConstraint, rightConstraint]];
    
    return self;

【问题讨论】:

如果你希望图像视图的宽度被屏幕宽度改变你应该设置左右superView的约束而不是它的宽度约束 【参考方案1】:

如果您希望您的视图调整为超级视图的大小, 那么你需要这样的东西(将边距设置为你喜欢的任何东西):

CGFloat margin = 0;

NSString * visualFormatH = [NSString stringWithFormat:@"|-(%f)-[speciesImageView]-(%f)-|", margin, margin];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatH
                                                                           options:0
                                                                           metrics:Nil
                                                                             views:@@"speciesImageView": speciesImageView]];
NSString * visualFormatV = [NSString stringWithFormat:@"V:|-(%f)-[speciesImageView]-(%f)-|", margin, margin];
[self.containerView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatV
                                                                           options:0
                                                                           metrics:Nil
                                                                             views:@@"speciesImageView": speciesImageView]];

现在,speciesImageView 将在 superview 框架发生变化时调整其框架。

这是一个通用示例:

- (void)viewDidLoad 
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.

UIView * sampleView = [UIView new];
sampleView.backgroundColor = [UIColor redColor];
sampleView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:sampleView];


CGFloat margin = 0;

NSString * visualFormatH = [NSString stringWithFormat:@"|-(%f)-[sampleView]-(%f)-|", margin, margin];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatH
                                                                       options:0
                                                                       metrics:Nil
                                                                         views:@@"sampleView": sampleView]];
NSString * visualFormatV = [NSString stringWithFormat:@"V:|-(%f)-[sampleView]-(%f)-|", margin, margin];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:visualFormatV
                                                                       options:0
                                                                       metrics:Nil
                                                                         views:@@"sampleView": sampleView]];


 

Auto Layout Getting Started

Auto Layout Visual Format Documentation

【讨论】:

我是否在 SpeciesImageViewClass 的 viewWillLayoutSubviews 中执行此操作? 您可以在 viewDidLoad 中将speciesImageView 添加到它的superView 后立即执行此操作 我将speciesImageView添加到容器视图中,这不是它的父视图 我不知道上述原因是不是这个解决方案对我不起作用的原因 containerView 是否有适当的约束?它的框架变化正确吗?

以上是关于在 Superview 中更改子视图的框架的主要内容,如果未能解决你的问题,请参考以下文章

UIView 在其 Superview 内移动

从其 superView 中删除 UIView 并将其框架扩展到全屏

添加删除的子视图 Swift 3 iOS

iOS Autolayout如何在superview中拉伸子视图

从 Superview 中删除子视图

无法从 superview-Xcode6 中删除子视图