如何使用带循环的 cgrect 垂直(而不是水平)添加 uiview objective c

How to add uiviews vertically (not horizontally) using cgrect with a loop objective c

我一直在尝试垂直而不是水平添加 uiview(换句话说,在一列中而不是在一行中),但我认为我没有正确理解代码。我可以改变和改变事情,我明白发生了什么,但我似乎无法垂直放置这些 uiviews。我已经尝试了数百种不同的东西,我正在阅读 cgrect,但我仍然找不到该做什么。如果有人能指出正确的方向,我将不胜感激。

 - (void) generateChat
    {
    int xcounter = 0;
    int longest = 0;
    _chatListRect.backgroundColor= [UIColor whiteColor];
    NSArray *commaChat01 = @[@"test 01",@"test 02",@"test 03",@"test 04"];
    for (NSString* str in commaChat01){
        
         CGSize result = [[UIScreen mainScreen]bounds].size;
         CGFloat
          x= 0.0, xt = 0.0,
          y= 0.0, yt = 0.0,
          w= 0.0, wt = 0.0,
          h= 0.0, ht = 0.0;
        
       if (result.width >= 0  && result.width <= 1500){
           x = 15; xt = 7.5;
           y = 10; yt = 7.5;
           w = 75; wt = 65;
           h = 75; ht = 75;
       }
             
        UIView *testview =[[UIView alloc]initWithFrame:CGRectMake((xcounter*(x+w))+x, y, w,h)];
    UIView *labelrect = [[UIView alloc]initWithFrame:CGRectMake(yt, xt, wt, ht)];
 
          testview.backgroundColor = UIColor.redColor;
        labelrect.backgroundColor = UIColor.blueColor;
          [testview.layer setCornerRadius:2.0f];
          [testview.layer setBorderColor:[UIColor lightGrayColor].CGColor];
          [testview.layer setBorderWidth:0.0f];
          UILabel *testlabel = [[UILabel alloc]initWithFrame:labelrect.bounds];
          testlabel.adjustsFontSizeToFitWidth = true;
         [testlabel setFont:[UIFont fontWithName:@"HelveticaNeue-Medium" size:20]];
          testlabel.textAlignment = NSTextAlignmentCenter;
          [self.view layoutIfNeeded];
          NSString *line1 = str;
           
           testlabel.text = line1;
           [labelrect addSubview:testlabel];
           [testview addSubview:labelrect];
           [_chatListRect addSubview:testview];
           xcounter = xcounter+1;
}
    longest =xcounter;
  xcounter =0;
    if (longest < xcounter){longest = xcounter;}

           _chatListRect.contentSize = CGSizeMake(100*longest,500);
                     
}

你知道bounds和frame的区别吗?在定位视图时,它们并没有什么不同——它们是天壤之别。

相应地,设置每个视图的中心以将它们精确定位在其父视图中,没有限制或奇怪:

https://developer.apple.com/documentation/uikit/uiview/1622627-center

否则,调用其父 UIView 的 setNeedsDisplay 方法。

如果不是那样,请在 UIView animateWithDuration:animations: 块参数中执行与子视图相关的代码。

情侣笔记...

首先,主要问题是您递增 x 而不是 y,因此您得到的是“水平列表”而不是“垂直列表”。

其次 - 这与您的其他(已删除)问题更相关 - 如果您有不同的高度标签...

每次通过你的循环,你想要增加 y 标签(或视图)的高度加上 常量 垂直间距值。

因此,如果您有 4 个不同长度的标签,并且 word-wrapping 最终高度为:

80, 40, 30, 30

你从 y = 20 开始,你想要 20-points 的垂直间距,你的帧的 y 值将是:

y = 20;

y += 80 + 20;

y += 40 + 20;

y += 30 + 20;

y += 30 + 20;

所以,这是您的代码的修改版本...我将其简化为仅使用标签,但如果您将标签嵌入“包含”视图中,则同样的过程将适用:

_chatListRect.backgroundColor = [UIColor whiteColor];

NSArray *commaChat01 = @[
    @"test 01 - long enough that this label will almost certainly need to wrap onto multiple lines.",
    @"test 02 - short",
    @"test 03 - longer string",
    @"test 04 - longer, and will probably need to wrap",
    @"test 05 - short",
    @"test 06 - longer, and will probably need to wrap",
    @"test 07 - short",
    @"test 08 - long enough that this label will almost certainly need to wrap onto multiple lines.",
    @"test 09 - short",
    @"test 10 - longer string",
    @"test 11 - longer, and will probably need to wrap",
    @"test 12 - short",
    @"test 13 - short",
    @"test 14 - short",
    @"test 15 - longer, and will probably need to wrap",
    @"test 16 - short",
];

CGSize result = [[UIScreen mainScreen]bounds].size;

// we want the first label 20-points from the top
CGFloat y = 20.0;

// we want 20-points vertical spacing between labels
CGFloat vSpacing = 20.0;

// we want the labels to start 15-points from the left
CGFloat x = 15.0;

// we want the same "padding" (15-points) on the right as the left
//  so max width for the labels is
CGFloat maxWidth = result.width - 30.0;

// to get the width of the widest label
CGFloat widest = 0;

for (NSString* str in commaChat01) {
    
    // create the label
    UILabel *testlabel = [UILabel new];
    
    // set label font properties
    [testlabel setFont:[UIFont fontWithName:@"HelveticaNeue-Medium" size:20]];
    testlabel.textAlignment = NSTextAlignmentCenter;
    testlabel.backgroundColor = UIColor.cyanColor;
    
    // we want the text to wrap if needed
    testlabel.numberOfLines = 0;

    // set label text
    testlabel.text = str;
    
    // calculate label size restricted to maxWidth
    CGSize labelSize = [testlabel sizeThatFits:CGSizeMake(maxWidth, CGFLOAT_MAX)];

    // set the label frame
    testlabel.frame = CGRectMake(x, y, labelSize.width, labelSize.height);
    
    // add label to _chatListRect
    [_chatListRect addSubview:testlabel];
    
    // increment y by label Height plus Spacing
    y += testlabel.frame.size.height + vSpacing;
    
    widest = MAX(widest, testlabel.frame.size.width);
}

// content size
//  Width = widest label plus left-indent
//  Height = y (which has been incremented each time through the loop)
_chatListRect.contentSize = CGSizeMake(widest + 15.0, y) ;

如果您仔细阅读该代码并检查注释,希望您能理解。

但是...如果您正在构建“聊天应用程序”,您几乎 肯定 想要使用 UITableViewUICollectionView。如果一个聊天线程收到数百条 back-and-forth 条消息,您真的不想添加数百个子视图和标签。