【问题标题】:Vertically align text to top within a UILabel在 UILabel 中将文本垂直对齐到顶部
【发布时间】:2010-11-06 11:24:14
【问题描述】:

我有一个UILabel,其中有两行文本的空格。有时,当文本太短时,该文本会显示在标签的垂直中心。

如何垂直对齐文本以始终位于 UILabel 的顶部?

【问题讨论】:

标签: ios cocoa-touch uikit uilabel text-alignment


【解决方案1】:

您可以通过代码或简单地在情节提要上执行以下操作来解决该问题:

  1. UILabel 的行数设置为等于0
  2. UILabel 嵌入到UIView 中。
  3. 设置UIView 约束(顶部、右侧、左侧和底部)以占据UILabel 应增长到的最大空间。
  4. 然后将UILabel 设置为UIView 的顶部、右侧和左侧,并将约束设置为底部距离>= 0

【讨论】:

    【解决方案2】:

    斯威夫特 5

    这里是从左上角开始渲染文本,并保持可能调整的文本大小。

    final class TopAlignedLabel: UILabel {
      override func drawText(in rect: CGRect) {
        super.drawText(in: .init(
          origin: .zero, 
          size: textRect(
            forBounds: rect, 
            limitedToNumberOfLines: numberOfLines
          ).size
        ))
      }
    }
    

    【讨论】:

      【解决方案3】:

      使用textRect(forBounds:limitedToNumberOfLines:)

      class TopAlignedLabel: UILabel {
        override func drawText(in rect: CGRect) {
          let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
          super.drawText(in: textRect)
        }
      }
      

      【讨论】:

      • 你先生是神!
      • 这个答案应该得到方式更多的支持,因为它是迄今为止最好和最干净的解决方案!
      • 很好。它引导我走向正确的方向,使我的标签垂直居中。
      • 非常优雅的解决方案
      【解决方案4】:

      使用 Storyboard 的最简单方法:

      StackView中嵌入Label,并在Attribute Inspector中设置StackView的以下两个属性:

      1-AxisHorizontal

      2- AlignmentTop

      【讨论】:

      • 为了获得更好的结果,你可以这样做 StackView > View > UILabel,因为当你只是在 StackView 中嵌入 UILabel 时,StackView 会调整大小以适应 UILabel 到最小尺寸
      • UILabel 放入一些UIView 子类(普通UIView 通常就足够了)并让标签向下增长的好主意。谢谢!
      • 使用 Editor->Embed 菜单命令并选择标签,Xcode 会为您清除标签约束,然后您可以为 StackView 设置约束。这种方法最接近我发现它的“SwiftUI”布局方法。
      • 您不需要UIStackView,只需将UILabel 嵌入UIView 中即可。设置UIView 约束以占用UILabel 应该增长到的最大空间。然后将UILabel 设置为UIView 的顶部、右侧和左侧,并将约束也设置为底部距离>= 0
      【解决方案5】:

      SwiftUI

      在 SwiftUI 中,所有视图通常都是 sizeToFit 其内容,但如果显式使用frame 修饰符,则可以使用框架的alignment 参数:

      Text("Text")
          .background(Color.red)
          .frame(width: 100, height: 200, alignment: .top)
      

      另外,如果你使用任何一种Stack来排列你的视图,它们都有一个类似于框架的参数,称为alignment

      ZStack(alignment: .top) {
          Color.red
          Text("Text")
              .background(Color.red)
      }
      

      【讨论】:

        【解决方案6】:

        这是一个旧的解决方案,在 iOS >= 6 上使用自动布局

        我的解决方案:

        1. 自己拆分行(忽略标签换行设置)
        2. 自己画线(忽略标签对齐)
        
        @interface UITopAlignedLabel : UILabel
        
        @end
        
        
        @implementation UITopAlignedLabel
        
        #pragma mark Instance methods
        
        - (NSArray*)splitTextToLines:(NSUInteger)maxLines {
            float width = self.frame.size.width;
        
            NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            NSMutableArray* lines = [NSMutableArray array];
        
            NSMutableString* buffer = [NSMutableString string];    
            NSMutableString* currentLine = [NSMutableString string];
        
            for (NSString* word in words) {
                if ([buffer length] > 0) {
                    [buffer appendString:@" "];
                }
        
                [buffer appendString:word];
        
                if (maxLines > 0 && [lines count] == maxLines - 1) {
                    [currentLine setString:buffer];
                    continue;
                }
        
                float bufferWidth = [buffer sizeWithFont:self.font].width;
        
                if (bufferWidth < width) {
                    [currentLine setString:buffer];
                }
                else {
                    [lines addObject:[NSString stringWithString:currentLine]];
        
                    [buffer setString:word];
                    [currentLine setString:buffer];
                }
            }
        
            if ([currentLine length] > 0) {
                [lines addObject:[NSString stringWithString:currentLine]];
            }
        
            return lines;
        }
        
        - (void)drawRect:(CGRect)rect {
            if ([self.text length] == 0) {
                return;
            }
        
            CGContextRef context = UIGraphicsGetCurrentContext();
        
            CGContextSetFillColorWithColor(context, self.textColor.CGColor);
            CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);
        
            NSArray* lines = [self splitTextToLines:self.numberOfLines];
            NSUInteger numLines = [lines count];
        
            CGSize size = self.frame.size;
            CGPoint origin = CGPointMake(0.0f, 0.0f);
        
            for (NSUInteger i = 0; i < numLines; i++) {
                NSString* line = [lines objectAtIndex:i];
        
                if (i == numLines - 1) {
                    [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];            
                }
                else {
                    [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
                }
        
                origin.y += self.font.lineHeight;
        
                if (origin.y >= size.height) {
                    return;
                }
            }
        }
        
        @end
        

        【讨论】:

          【解决方案7】:
          1. 设置新文本:

            myLabel.text = @"Some Text"
            
          2. 将行的maximum number 设置为0(自动):

            myLabel.numberOfLines = 0
            
          3. 将标签的边框设置为最大尺寸:

            myLabel.frame = CGRectMake(20,20,200,800)
            
          4. 调用sizeToFit 以减小帧大小,使内容刚好适合:

            [myLabel sizeToFit]
            

          标签框现在的高度和宽度足以容纳您的文本。左上角应该保持不变。我只用左上对齐的文本对此进行了测试。对于其他对齐方式,您可能需要在之后修改框架。

          另外,我的标签启用了自动换行。

          【讨论】:

          • 这对我来说很好。我在 IB 中设置了我的 UILabel 的尺寸并将 numberOfLines 更改为 0,然后在设置名为 [myLabel sizeToFit] 的文本之后。
          • 在 Attr.督察
          • 行数超过1的情况下不起作用
          • 当你想要一个两行的标签时它不起作用,但是文本需要更多行。
          【解决方案8】:

          不要乱来,不要大惊小怪

          @interface MFTopAlignedLabel : UILabel
          
          @end
          
          
          @implementation MFTopAlignedLabel
          
          - (void)drawTextInRect:(CGRect) rect
          {
              NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
              rect.size.height = [attributedText boundingRectWithSize:rect.size
                                                      options:NSStringDrawingUsesLineFragmentOrigin
                                                      context:nil].size.height;
              if (self.numberOfLines != 0) {
                  rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
              }
              [super drawTextInRect:rect];
          }
          
          @end
          

          没有混乱,没有 Objective-c,没有大惊小怪,只有 Swift 3:

          class VerticalTopAlignLabel: UILabel {
          
              override func drawText(in rect:CGRect) {
                  guard let labelText = text else {  return super.drawText(in: rect) }
          
                  let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
                  var newRect = rect
                  newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height
          
                  if numberOfLines != 0 {
                      newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
                  }
          
                  super.drawText(in: newRect)
              }
          
          }
          

          斯威夫特 4.2

          class VerticalTopAlignLabel: UILabel {
          
              override func drawText(in rect:CGRect) {
                  guard let labelText = text else {  return super.drawText(in: rect) }
          
                  let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
                  var newRect = rect
                  newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height
          
                  if numberOfLines != 0 {
                      newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
                  }
          
                  super.drawText(in: newRect)
              }
          
          }
          

          【讨论】:

          • 快速版本对我有用,没有任何副作用!干得好!
          • 这可能是最好的答案,适用于所有场景。如果标签位于 UITableviewCell 中,则 sizeToFit 不起作用。干得好。
          • 亲爱的 Apple,让文本自动转到左上角应该不难。也就是说,@jasongregori 这里的答案很好。尝试了拥抱概念和最佳答案,并且没有为 CollectionViewCell 标签工作。 UILabel 的自定义类就是解决方案。
          • 对于那些不了解自定义类概念的人,请使用以下方法修复上述答案: 1. 在您的项目中创建一个新的 Swift 文件。 COMMAND + N. 2. 为自定义 UILabel 类插入下图所示的代码。 3. 不要忘记将 UIKit 导入到这个文件,否则你会在这段代码中看到到处都是红色的,从 XCode 开始没有将“UILabel”识别为类类型。 4. 另外不要忘记进入标签的身份检查器以切换自定义类并找到“VerticalTopAlignLabel”或您命名的任何名称。
          【解决方案9】:

          无法在UILabel 上设置垂直对齐,但您可以通过更改标签的框架来获得相同的效果。我已将标签设为橙色,以便您清楚地看到发生了什么。

          以下是快速简便的方法:

              [myLabel sizeToFit];
          


          如果您有一个包含超过一行的较长文本的标签,请将numberOfLines 设置为0(此处的零表示行数不受限制)。

              myLabel.numberOfLines = 0;
              [myLabel sizeToFit];
          


          加长版

          我将在代码中制作我的标签,以便您了解发生了什么。您也可以在 Interface Builder 中设置大部分内容。我的设置是一个基于视图的应用程序,带有我在 Photoshop 中制作的背景图像以显示边距(20 点)。标签是有吸引力的橙色,因此您可以看到尺寸的变化。

          - (void)viewDidLoad
          {
              [super viewDidLoad];
          
              // 20 point top and left margin. Sized to leave 20 pt at right.
              CGRect labelFrame = CGRectMake(20, 20, 280, 150);
              UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
              [myLabel setBackgroundColor:[UIColor orangeColor]];
          
              NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
              [myLabel setText:labelText];
          
              // Tell the label to use an unlimited number of lines
              [myLabel setNumberOfLines:0];
              [myLabel sizeToFit];
          
              [self.view addSubview:myLabel];
          }
          

          使用sizeToFit 的一些限制会影响居中或右对齐的文本。以下是发生的事情:

              // myLabel.textAlignment = NSTextAlignmentRight;
              myLabel.textAlignment = NSTextAlignmentCenter;
          
              [myLabel setNumberOfLines:0];
              [myLabel sizeToFit];
          

          标签的大小仍然是固定的左上角。您可以将原始标签的宽度保存在变量中并在sizeToFit 之后设置它,或者给它一个固定宽度来解决这些问题:

              myLabel.textAlignment = NSTextAlignmentCenter;
          
              [myLabel setNumberOfLines:0];
              [myLabel sizeToFit];
          
              CGRect myFrame = myLabel.frame;
              // Resize the frame's width to 280 (320 - margins)
              // width could also be myOriginalLabelFrame.size.width
              myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
              myLabel.frame = myFrame;
          


          请注意,sizeToFit 将遵循您的初始标签的最小宽度。如果您从 100 宽的标签开始并在其上调用 sizeToFit,它将返回一个 100(或稍小)宽的(可能非常高)标签。您可能希望在调整大小之前将标签设置为所需的最小宽度。

          其他一些注意事项:

          lineBreakMode 是否受到尊重取决于它的设置方式。 NSLineBreakByTruncatingTail(默认值)在sizeToFit 之后被忽略,其他两种截断模式(头部和中间)也是如此。 NSLineBreakByClipping 也被忽略。 NSLineBreakByCharWrapping 照常工作。框架宽度仍然变窄以适合最右边的字母。


          Mark Amery 修复了在 cmets 中使用自动布局的 NIB 和 Storyboard:

          如果您的标签作为使用自动布局的 ViewController 的 view 的子视图包含在 nib 或情节提要中,那么将您的 sizeToFit 调用放入 viewDidLoad 将不起作用,因为自动布局的大小和位置在调用viewDidLoad 之后的子视图将立即撤消sizeToFit 调用的效果。但是,从viewDidLayoutSubviews 内部调用sizeToFit 工作。


          我的原始答案(供后代/参考):

          这使用NSString方法sizeWithFont:constrainedToSize:lineBreakMode:计算适合字符串所需的帧高度,然后设置原点和宽度。

          使用您要插入的文本调整标签框架的大小。这样您就可以容纳任意数量的行。

          CGSize maximumSize = CGSizeMake(300, 9999);
          NSString *dateString = @"The date today is January 1st, 1999";
          UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
          CGSize dateStringSize = [dateString sizeWithFont:dateFont 
                  constrainedToSize:maximumSize 
                  lineBreakMode:self.dateLabel.lineBreakMode];
          
          CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);
          
          self.dateLabel.frame = dateFrame;
          

          【讨论】:

          • 你需要删除自动布局
          • 这里有一个简单的解决方法:stackoverflow.com/a/26632490/636559
          • 这个答案不必要地复杂,它使用的是“周围的词”。请参阅下面关于简单更改垂直内容拥抱优先级的建议。不需要任何代码...
          • [myLabel sizeToFit] 在 UITableViewCells 中不好用,因为这里的标签被重复使用,新文本可能不适合。
          • 您仍然可以使用 AutoLayout 和约束,但要确保 [height] 不会被固定。例如:设置 Left、Top 和 Right 等于 8px,但 Bottom 可以设置“大于或等于”8px。它会对 iOS 说,让我的 sizeToFit 为我的标签决定更好的高度。
          【解决方案10】:

          可以更灵活地为 Interface Builder 中的标签设置 height constraint,使用 IBOutlet 将其绑定到代码并更改该高度以在具体的垂直位置显示文本。中心和底部对齐示例:

          labelHeightConstraint.constant = centerAlignment ? 30 : 15
          layoutIfNeeded()
          

          【讨论】:

            【解决方案11】:

            我在我的应用程序中所做的是将 UILabel 的 line 属性设置为 0,并创建 UILabel 的底部约束并确保将其设置为 >= 0,如下图所示。

            【讨论】:

            • 我不知道为什么这不是公认的答案。比那个简单得多。不错的答案!
            • 是的!这就是我一直在寻找的。这应该是公认的答案。
            • 迄今为止最好的答案。谢谢! +1
            【解决方案12】:

            (截至 2018 年 3 月 7 日)

            斯威夫特 4

            let maxFrameHeight = 75
            
            myLabel = UILabel()
            myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: maxFrameHeight)
            myLabel.text = "my labels text displayed"
            myLabel.numberOfLines = 0
            
            myLabel.sizeToFit()
            let newFrameHeight = myLabel.frame.size.height
            let safeNewHeight = min(newFrameHeight, maxFrameHeight)
            
            myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: safeNewHeight)
            

            这将获得所需的结果,并确保 UILabel 的新高度不会超过您希望此标签的某个最大高度。

            【讨论】:

            • 效果很好,但是你必须设置numberOfLines = 0!
            【解决方案13】:

            这是 Swift 4.0 中的解决方案:

            func viewDidLoad() {
            
                super.viewDidLoad()
            
                // 20 point top and left margin. Sized to leave 20 pt at right.
                let labelFrame = CGRect(x: 20, y: 20, width: 280, height: 150)
                let myLabel = UILabel(frame: labelFrame)
                myLabel.backgroundColor = UIColor.orange
            
                let labelText = "I am the very model of a modern Major-General, 
                I've information vegetable, animal, and mineral"
                myLabel.text = labelText
            
                // Tell the label to use an unlimited number of lines
                myLabel.numberOfLines = 0
                myLabel.sizeToFit()
            
                view.addSubview(myLabel) // add label
            }
            

            【讨论】:

              【解决方案14】:

              这个问题的简单解决方案……

              在标签下方放置UIStackView

              然后使用 AutoLayout 将标签的垂直间距设置为零,并将顶部约束到之前的标签底部。标签不会增长,stackView 会。我喜欢的是堆栈视图是非渲染的。所以这并不是真正浪费时间渲染。即使它进行 AutoLayout 计算。

              虽然您可能需要使用 ContentHugging 和 Resistance,但这也很简单。

              我时不时地在谷歌上搜索这个问题并回到这里。这次我有一个我认为最简单的想法,而且我不认为这是糟糕的表现。 我必须说我只是在使用 AutoLayout,并不想费心计算帧。这只是......糟糕。

              【讨论】:

                【解决方案15】:

                对于 Swift 3...

                @IBDesignable class TopAlignedLabel: UILabel {
                    override func drawText(in rect: CGRect) {
                        if let stringText = text {
                            let stringTextAsNSString = stringText as NSString
                            let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
                                                                                            options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                                                                            attributes: [NSFontAttributeName: font],
                                                                                            context: nil).size
                            super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
                        } else {
                            super.drawText(in: rect)
                        }
                    }
                    override func prepareForInterfaceBuilder() {
                        super.prepareForInterfaceBuilder()
                        layer.borderWidth = 1
                        layer.borderColor = UIColor.black.cgColor
                    }
                }
                

                【讨论】:

                  【解决方案16】:

                  对于那些尝试解决此问题的自定义表格单元格的人,请将其添加到您的自定义表格单元格类中:

                  Swift 2.2:

                  override func layoutSubviews() {
                      labelName.sizeToFit()
                  }
                  

                  这解决了我的问题。

                  【讨论】:

                    【解决方案17】:

                    Swift 2.0:

                    在一个空的 Swift 文件中创建常量枚举值。

                    //  AppRef.swift
                    
                    import UIKit
                    import Foundation
                    
                    enum UILabelTextPositions : String {
                    
                     case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
                     case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
                     case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"
                    
                    }
                    

                    使用 UILabel 扩展:

                    创建一个空的 Swift 类并为其命名。添加以下内容

                    //  AppExtensions.swift
                    
                    import Foundation
                    import UIKit
                    
                    extension UILabel{ 
                     func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
                     {
                      let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)
                    
                      switch positionIdentifier
                      {
                      case "VerticalAlignmentTop":
                       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
                       break;
                    
                      case "VerticalAlignmentMiddle":
                       sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
                        rect.size.width, rect.size.height);
                       break;
                    
                      case "VerticalAlignmentBottom":
                       sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
                       break;
                    
                      default:
                       sampleLabel!.frame = bounds;
                       break;
                      }
                      return sampleLabel!
                    
                     }
                    }
                    

                    用法:

                    myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)
                    

                    【讨论】:

                      【解决方案18】:

                      很快,

                      let myLabel : UILabel!

                      使标签的文本适合屏幕并且位于顶部

                      myLabel.sizeToFit()

                      使您的标签字体适合屏幕宽度或特定宽度大小。

                      myLabel.adjustsFontSizeToFitWidth = YES

                      还有一些用于标签的 textAlignment :

                      myLabel.textAlignment = .center

                      myLabel.textAlignment = .left

                      myLabel.textAlignment = .right

                      myLabel.textAlignment = .Natural

                      myLabel.textAlignment = .Justified

                      【讨论】:

                      • 只是对 [myLabel sizeToFit] 旧语法的语法更改。谢谢!
                      【解决方案19】:

                      上面的方法我用过很多,只是想补充一下我用过的又快又脏的方法:

                      myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];
                      

                      确保字符串中换行符的数量会导致任何文本填满可用的垂直空间,并设置 UILabel 以截断任何溢出的文本。

                      因为有时候足够好就是足够好

                      【讨论】:

                      • 但是考虑到 iOS 设备的屏幕尺寸高度的变化,需要有一个可变数量的 '\n' 来解释 uilabel 变化的高度(这是可能的)。因此,从长远来看,这种方法并不是特别有用。
                      • 注意:“快速而肮脏的”不是“永远的完美解决方案”。只是说。
                      • @CodeRoadie 又快又脏对我有用,我在真正的答案中遇到了一些布局问题。我可以以“正确的方式”做到这一点,但感谢您为我节省了一些时间!
                      • @dGambit 请注意:“快且
                      • 我最近在使用UITextView 动态加载视图时学到的一点是,它可以调用dlopen 来支持文本输入。这可能会导致 UI 线程严重滞后,因此这种方法的性能要高得多!
                      【解决方案20】:

                      对于自适应 UI(iOS8 或更高版本),UILabel 的垂直对齐将通过更改属性从 StoryBoard 设置 noOfLines=0` 和

                      约束

                      1. 调整 UILabel LefMargin、RightMargin 和上边距约束。

                      2. 更改Content Compression Resistance Priority For Vertical=1000` 使 Vertical>Horizo​​ntal 。

                      已编辑:

                      noOfLines=0
                      

                      并且以下约束足以达到预期的效果。

                      【讨论】:

                      • 这太棒了。你能解释一下为什么垂直>水平做这项工作吗?谢谢。
                      【解决方案21】:

                      以防万一它对任何人有任何帮助,我遇到了同样的问题,但只需从使用 UILabel 切换到使用 UITextView 就能够解决问题。我很感激这并不适合所有人,因为功能有点不同。

                      如果您确实切换到使用UITextView,您可以关闭所有滚动视图属性以及启用用户交互...这将迫使它更像一个标签。

                      【讨论】:

                      • 不确定如果将许多 UILabel 转换为文本视图,这将如何影响性能。
                      • 该线程上的所有其他解决方案在 iOS 7 中对我不起作用(无论出于何种原因)。但只需使用 UITextView 就可以立即获得所需的结果。
                      • 这是一种变通方法,它仍然需要一些调整以使其看起来真实,但确实这是我见过的最简单的无代码解决方案,竖起大拇指。
                      • 我喜欢这个解决方案。当然,可能存在性能问题,例如,对于相对简单的视图上的简单标签,这非常适合我的需要(而且我没有注意到任何性能影响)
                      • 这种方法的一个小缺点是它会给文本引入额外的内在填充。一个快速的解决方法是引入一个负约束。
                      【解决方案22】:

                      只要你不做任何复杂的任务,你可以用UITextView代替UILabels

                      禁用滚动。

                      如果您希望文本完全显示,只需用户 sizeToFitsizeThatFits: 方法

                      【讨论】:

                        【解决方案23】:

                        FXLabel (on github) 通过将label.contentMode 设置为UIViewContentModeTop 开箱即用地执行此操作。这个组件不是我做的,但它是我经常使用的一个组件,有很多功能,而且看起来很好用。

                        【讨论】:

                          【解决方案24】:

                          你可以使用TTTAttributedLabel,它支持垂直对齐。

                          @property (nonatomic) TTTAttributedLabel* label;
                          <...>
                          
                          //view's or viewController's init method
                          _label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
                          

                          【讨论】:

                            【解决方案25】:

                            此代码可帮助您使文本与顶部对齐,并且使标签高度与文本内容固定。

                            以下代码的使用说明

                            isHeightToChange 默认为 true 使标签的高度自动与文本内容相同。 isHeightToChange 如果它为 false,则使文本与顶部对齐,而不降低标签的高度。

                            #import "DynamicHeightLable.h"
                            
                            @implementation DynamicHeightLable
                            @synthesize isHeightToChange;
                            - (id)initWithFrame:(CGRect)frame 
                            {
                                self = [super initWithFrame:frame];
                                if (self)
                                {
                                    // Initialization code.
                                    self.isHeightToChange=FALSE;//default
                            
                                }
                                return self;
                            }
                            - (void)drawTextInRect:(CGRect)rect
                            {
                                if(!isHeightToChange){
                                CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);
                            
                                CGFloat height = [self.text sizeWithFont:self.font
                                                       constrainedToSize:maximumLabelSize
                                                           lineBreakMode:self.lineBreakMode].height;
                                if (self.numberOfLines != 0) {
                                    height = MIN(height, self.font.lineHeight * self.numberOfLines);
                                }
                                rect.size.height = MIN(rect.size.height, height);
                                }
                                [super drawTextInRect:rect];
                            
                            }
                            - (void) layoutSubviews
                            {
                                [super layoutSubviews];
                                   if(isHeightToChange){
                                 CGRect ltempFrame = self.frame;
                                CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);
                            
                                CGFloat height = [self.text sizeWithFont:self.font
                                                       constrainedToSize:maximumLabelSize
                                                           lineBreakMode:self.lineBreakMode].height;
                                if (self.numberOfLines != 0) {
                                    height = MIN(height, self.font.lineHeight * self.numberOfLines);
                                }
                                ltempFrame.size.height = MIN(ltempFrame.size.height, height);
                            
                                ltempFrame.size.height=ltempFrame.size.height;
                                self.frame=ltempFrame;
                                   }
                            }
                            @end
                            

                            【讨论】:

                              【解决方案26】:

                              我发现这个问题的答案现在有点过时了,所以为那里的自动布局爱好者添加这个。

                              自动布局使这个问题变得非常简单。假设我们将标签添加到UIView *view,以下代码将完成此操作:

                              UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
                              [label setText:@"Some text here"];
                              [label setTranslatesAutoresizingMaskIntoConstraints:NO];
                              [view addSubview:label];
                              
                              [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
                              [view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];
                              

                              标签的高度将被自动计算(使用它的intrinsicContentSize)并且标签将被水平边对边放置在view的顶部。

                              【讨论】:

                                【解决方案27】:

                                我知道这是一篇旧帖子,但垂直对齐文本是一个大问题(至少对我来说是这样),我想我应该分享这个解决方案,因为我自己找不到。

                                在我看来,使用 drawRect 有点贵。让 UILabel 垂直对齐的正确方法是不使用 UILabel。使用 UITextView(多行 UITextField)并像这样观察 content 属性:

                                - (UITextView*)textView{
                                     if(!_textView){
                                        UIEdgeInsets insets = UIEdgeInsetsMake(0, 50, 0, 5);
                                        CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
                                        _textView = [[UITextView alloc]initWithFrame:UIEdgeInsetsInsetRect(frame, insets)];
                                        _textView.delegate = self;
                                        _textView.scrollEnabled = YES;
                                        _textView.bounces = YES;
                                        _textView.backgroundColor = [UIColor whiteColor];
                                        [_textView setUserInteractionEnabled:NO];
                                        [_textView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
                                    }
                                    return _textView;
                                }
                                
                                 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary *)change context:(void *)context {
                                UITextView *tv = object;
                                
                                CGFloat height = [tv bounds].size.height;
                                CGFloat contentheight;
                                
                                #ifdef __IPHONE_7_0
                                    contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;
                                #else
                                    contentheight = [tv contentSize].height;
                                #endif
                                
                                    switch(self.verticalAlignment) {
                                        case VerticalAlignmentBottom:{
                                            CGFloat topCorrect = ([tv bounds].size.height - contentheight);
                                            topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
                                            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
                                        }
                                        break;
                                        case VerticalAlignmentMiddle:{
                                            CGFloat topCorrect = (height - contentheight * [tv zoomScale])/2.0;
                                            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
                                            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
                                        }
                                            break;
                                        case VerticalAlignmentTop:{
                                            tv.contentOffset = (CGPoint){.x = 0, .y = 0 };
                                        }
                                            break;
                                        default:
                                            break;
                                    }
                                }
                                

                                基本上这里发生的事情是我们将我们所在的类设置为观察者,使用 NSKeyValueObservingOptionNew 选项查看 contentSize 属性,因此每次内容更改时,-(void)observeValueForKeyPath:ofObject:change:context: 将被调用,然后您可以计算偏移量大小以适当地对齐文本。

                                我不能相信这一点,最初的想法来自here。但是,此解决方案不适用于 iOS7。在 SO 上闲逛了几个小时后,我发现了这个:iOS 7 vertical alignment fix。那里的关键行是contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;。出于某种原因,在 iOS 7 中,获取 contentSize 高度不起作用,但可以修复它。这两种解决方案都不能单独工作,但经过一些修补后,我能够将上述解决方案综合在一起。

                                【讨论】:

                                  【解决方案28】:

                                  如果您使用自动布局,请在代码或 IB 中将垂直 contentHuggingPriority 设置为 1000。在 IB 中,您可能必须通过将其优先级设置为 1 然后删除它来移除高度限制。

                                  【讨论】:

                                    【解决方案29】:

                                    我已经为此苦苦挣扎了很长时间,我想分享我的解决方案。

                                    这将为您提供UILabel,它将自动将文本缩小到 0.5 比例并将文本垂直居中。这些选项在 Storyboard/IB 中也可用。

                                    [labelObject setMinimumScaleFactor:0.5];
                                    [labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
                                    

                                    【讨论】:

                                    • 它在所有提供的答案中表现得非常完美。谢谢@David Greco。除了这些属性,如果我们将 adjustsFontSizeToFitWidth 设置为 YES,那么文本将适合框架而不修改标签的框架。
                                    【解决方案30】:
                                    yourLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 2014-05-20
                                      • 2015-10-18
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2021-07-19
                                      相关资源
                                      最近更新 更多