如何使用带有循环目标 c 的 cgrect 垂直(而不是水平)添加 uiviews

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

提问人:John 提问时间:1/14/2022 最后编辑:WillekeJohn 更新时间:3/13/2022 访问量:80

问:

我一直在尝试垂直而不是水平添加uiviews(换句话说,在一列而不是一行中),但我认为我没有正确理解代码。我可以改变和改变事情,我明白发生了什么,但我似乎无法垂直放置这些 uiview。我已经尝试了数百种不同的东西,我正在阅读 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);
                     
}
Objective-C UIVie查看原文

评论

1赞 Larme 1/14/2022
CGRectMake((xcounter*(x+w))+x, y, w,h),则您只修改原点 x。这就是为什么你最终拥有水平并排视图的原因。只需在纸上用轴画出它,您就会更好地理解或平均坐标......
1赞 Cy-4AH 1/14/2022
可以代替吗?UIStackView
0赞 John 1/14/2022
@Larme谢谢你的帮助。是的,我试过修改 y,但我没有运气。我试过把 +y 和 +x 拿走,但代码不再正确。我尝试将 x+w 更改为 y+h,但没有奏效。
1赞 John 1/14/2022
@Cy-4AH:我也会看看。谢谢你的建议。

答:

0赞 James Bush 1/16/2022 #1

你知道边界和框架的区别吗?在定位视图时,它们并没有细微的不同——它们是天壤之别。

因此,设置每个视图的中心,以将它们精确地放置在其上视图中,而不受限制或奇怪:

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

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

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

0赞 DonMag 3/13/2022 #2

几张纸条...

首先,主要问题是你正在递增而不是 ,所以你得到的是一个“水平列表”而不是“垂直列表”。xy

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

每次循环时,您都希望按标签(或视图)的高度加上恒定的垂直间距值递增。y

因此,如果您有 4 个不同长度的标签,并且换行的高度为:

80, 40, 30, 30

从,并且需要垂直间距,则帧的值为:y = 2020-pointsy

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

评论

0赞 John 3/15/2022
@DonMag哇谢谢。我试图重写最后一个问题以使其更清晰,这就是我删除它的原因。但你在这里的答案,正是我所需要的。我一直在绞尽脑汁,试图弄清楚如何获得具有可变标签高度的 Y 位置。我还没有尝试过你的代码,但它看起来像我需要的。我现在要试试。非常感谢。我真的很感激。
0赞 John 3/15/2022
@DonMag 绝对令人惊叹。它就像一个魅力!我真的花了几个星期的时间!再次感谢你。