【问题标题】:Positioning a UILabel directly beneath another UILabel将 UILabel 直接定位在另一个 UILabel 下方
【发布时间】:2013-03-26 08:12:40
【问题描述】:

我对@9​​87654323@ 做了一个补充,它会根据正在读入的文本自动调整UILabel 的大小(我有一个显示引文的简单应用程序,所以有些是几个词,有些是几个句子)。在quote 标签下方,我还有一个author 标签,(奇怪的是)其中包含引用的作者。

我正在尝试将 author 标签直接放置在 quote 标签下方(例如,其 y 坐标将是 quote 标签的 y 坐标加上 quote 标签的 height .我看到的是在两个标签之间放置了一些空间,这取决于引用的长度,改变大小。较小的引号有更多的空间,而较长的引号有更少的空间。这是我的快速图表看到:

请注意红色和蓝色框之间的差距(我使用layer.borderColor/borderWidth 设置,以便我可以在应用程序中看到它们),报价越短,差距越大。

如果有人可以筛选下面的代码并帮助我指出导致差异的确切原因,我将不胜感激。据我所知,author 标签应该始终比quote 标签的y + height 值低35 像素。

只是为了确认一下:在 Interface Builder 中,一切都已正确连接,等等。引用的内容很好,其他一切正常,所以它已经连接,这不是问题。

澄清一下,我的问题是:为什么标签之间的间隙会根据引用的长度而变化,我怎样才能正确获得稳定、可设置的 35 像素间隙?

这是我用来定位标签的代码:

// Fill and format Quote Details
_quoteLabel.text = [NSString stringWithFormat:@"\"%@\"", _selectedQuote.quote];
_authorLabel.text = _selectedQuote.author;
[_quoteLabel setFont: [UIFont fontWithName: kScriptFont size: 28.0f]];
[_authorLabel setFont: [UIFont fontWithName: kScriptFontAuthor size: 30.0f]];

// Automatically resize the label, then center it again.
[_quoteLabel sizeToFitMultipleLines];
[_quoteLabel setFrame: CGRectMake(11, 11, 298, _quoteLabel.frame.size.height)];

// Position the author label below the quote label, however high it is.
[_authorLabel setFrame: CGRectMake(11, 11 + _quoteLabel.frame.size.height + 35, _authorLabel.frame.size.width, _authorLabel.frame.size.height)];

这是我对sizeToFitMultipleLines 的自定义方法:

- (void) sizeToFitMultipleLines
{
    if (self.adjustsFontSizeToFitWidth) {
        CGFloat adjustedFontSize = [self.text fontSizeWithFont: self.font constrainedToSize: self.frame.size minimumFontSize: self.minimumScaleFactor];
        self.font = [self.font fontWithSize: adjustedFontSize];
    }
    [self sizeToFit];
}

这是我的fontSizeWithFont:constrainedToSize:minimumFontSize: 方法:

- (CGFloat) fontSizeWithFont: (UIFont *) font constrainedToSize: (CGSize) size minimumFontSize: (CGFloat) minimumFontSize
{
    CGFloat fontSize = [font pointSize];
    CGFloat height = [self sizeWithFont: font constrainedToSize: CGSizeMake(size.width, FLT_MAX) lineBreakMode: NSLineBreakByWordWrapping].height;
    UIFont *newFont = font;

    // Reduce font size while too large, break if no height (empty string)
    while (height > size.height && height != 0 && fontSize > minimumFontSize) {
        fontSize--;
        newFont = [UIFont fontWithName: font.fontName size: fontSize];
        height = [self sizeWithFont: newFont constrainedToSize: CGSizeMake(size.width, FLT_MAX) lineBreakMode: NSLineBreakByWordWrapping].height;
    };

    // Loop through words in string and resize to fit
    for (NSString *word in [self componentsSeparatedByCharactersInSet: [NSCharacterSet whitespaceAndNewlineCharacterSet]]) {
        CGFloat width = [word sizeWithFont: newFont].width;
        while (width > size.width && width != 0 && fontSize > minimumFontSize) {
            fontSize--;
            newFont = [UIFont fontWithName: font.fontName size: fontSize];
            width = [word sizeWithFont: newFont].width;
        }
    }
    return fontSize;
}

【问题讨论】:

  • 红框和蓝框从何而来?它们是标签的框架吗?另外,CGRectGetMaxY() 等是一个不错的功能,你应该看看。
  • 在您的示例代码中,您只需调整字体大小以适合标签,但您在哪里定义 _quoteLabel.frame.size.height
  • @DavidRönnqvist 红色和蓝色框是使用标签本身的layer.borderColor/borderWidth 设置的,因此它们准确地显示了标签的框架。
  • @xapslock 我没有明确设置高度,我计算了适合标签中文本所需的字体大小,然后sizeToFit
  • @DavidRönnqvist 将author 的Y 坐标设置为CGRectGetMaxY() 会使其与quote 重叠,而不是直接位于其下方。根据报价的大小,它的重叠量也不同,所以我认为这是同一个问题。

标签: ios objective-c nsstring uilabel sizetofit


【解决方案1】:

在您调用 size 以适应两个标签后,计算它们的框架之间的距离并相应地更改它们:

[quoteLabel sizeToFit];
[authorLabel sizeToFit];

float distance = authorLabel.frame.origin.y - quoteLabel.frame.size.height;
float difference = distance - 35;

authorLabel.frame = CGRectMake(authorLabel.frame.origin.x,(authorLabel.frame.origin.y - difference),authorLabel.frame.size.width,authorLabel.frame.size.height);

间隙发生变化的原因是,当您调用 sizeToFit 时,引用标签框架会根据其内容改变其高度。

更新

鉴于最近cmets的发展,我认为你有3种可能:

  • 调整空格而不是单词的大小,使字符串 实际上正确地适合框架
  • 以某种方式访问​​ UILabel 的 CTFramesetter 以查看实际情况 框架,当一切都说完了,就相当于
  • 制作你自己的 UIView 子类来处理核心文本的绘制 绘制 rect 方法(在你的情况下应该很容易),因为毕竟你 试图给 UILabel 一个不适合的行为

【讨论】:

  • 恐怕这根本不起作用,这与我所看到的没有任何区别。 distancedifference 浮点数始终分别报告为 4611,无论我选择多长的引用。
  • 如果您不考虑字体大小,也会发生同样的事情吗?
  • 这是个好问题.. 检查.. 不,当我注释掉对sizeToFitMultipleLines 的调用时,author 位于quote 下方几个像素处的稳定位置。
  • 您的最小字体大小是多少?我还看到您将 minimumScaleFactor 作为最小字体大小传递:最小字体大小 = 最小比例因子 * 正常大小。
  • 另外,我不知道这是否与您的问题有关,但是如果您调整字体大小,为什么两个屏幕截图的字体大小相同?默认报价标签高度是多少?它比第一个屏幕截图中的标签短还是高?
【解决方案2】:

它可能正在移动到您想要的位置,但随后自动布局约束或弹簧/支柱正在移动它。

编辑:
我的第一个想法(我排除了,因为您说单词周围的框是标签框。在后来的 cmets 中,您说这不是实际的屏幕截图,而只是它的表示形式,所以它仍然可能是正确的)是你做错了:

[_quoteLabel sizeToFitMultipleLines];
[_quoteLabel setFrame: CGRectMake(11, 11, 298, _quoteLabel.frame.size.height)];

在第一行中,您正在调整文本的大小以适应标签的当前宽度,然后在第二行中转身并更改标签的宽度。所以最有可能发生的事情是您正在调整标签的尺寸以适应更小的宽度,这使得它变高了。然后,您使标签比以前更宽,文本扩展以适应更宽的标签,在实际文本下方留下一个空白区域,尽管框架没有改变。这使得标签之间的空间正好为 35,但顶部标签的文本不会一直到其框架的底部,因此空白空间超出了您的要求。基本上,你有这个:

*************
* text text *
* text text *
*           *
*           *
*           *
*************

*************
* text text *
*************

如果是这种情况,那么您可以通过先设置宽度来修复它,如下所示:

// You could put anything for the 200 height since you will be changing it in the next line anyway.
[_quoteLabel setFrame: CGRectMake(11, 11, 298, 200];  
[_quoteLabel sizeToFitMultipleLines];

【讨论】:

  • @Inafziger 我已经确认,并且整个故事板的自动布局已关闭,所以恐怕不是这样:(
  • 那么弹簧和支柱呢? (自动调整大小?)
  • @Inafziger 根本没有,完全禁用了。
  • @Inafziger 在sizeToFitMultipleLines 之后调用setFrame 的原因是如果调整大小导致其宽度变窄,则将其重新定位在视图的中心(水平方向)。我已经颠倒了这两行代码,但恐怕没有任何区别。
【解决方案3】:

我最终通过使用单个UILabel 和带有NSAttributedString 的CoreText 解决了这个问题。有点逃避,但它有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-17
    相关资源
    最近更新 更多