【问题标题】:NSTextField (multiline) grow horizontally after filling all linesNSTextField(多行)填充所有行后水平增长
【发布时间】:2017-06-16 08:38:07
【问题描述】:

我有多行 NSTexField,用于显示静态文本,在每次显示窗口时可能具有不同的长度。这个 NSTextField 有一个高度约束,将其限制为两行。

我想设置行为,NSTextField 只会水平增长这么多,它会填满这两条水平线。 现在,当我将水平压缩阻力设置得更高时,文本字段宽度会增长很多,以在一行上显示所有文本。这是否可能仅通过使用自动布局约束来实现,还是我必须以某种方式计算 nstextfield 宽度?

我尝试在 superview 中重载“布局”方法。但它没有像我预期的那样工作。

- (void)layout
{
    [self solveLayoutForView:self];
}

- (void)solveLayoutForView:(NSView*)view
{
    for (NSView* subView in [view subviews])
    {
        if (subView.subviews.count)
            [self solveLayoutForView:subView];
        else
        {
            NSLayoutConstraint* height = [subView constraintForAttribute:NSLayoutAttributeHeight];

            if (height && height.constant > 17 && [subView isKindOfClass:[NSTextField class]]) // seems like multiline nstextfield
            {
                NSTextField* textField = (NSTextField*)subView;

                textField.preferredMaxLayoutWidth = 0;
                [super layout];
                textField.preferredMaxLayoutWidth = NSWidth([textField alignmentRectForFrame:textField.frame]);
                [super layout];
            }
        }
    }
}

【问题讨论】:

    标签: cocoa autolayout width nstextfield


    【解决方案1】:

    我最终自己计算了它。 我在 NSTextField 的子类中重载了 setStringValue。 如果我需要跳过此计算,“PreferGrowingHorizo​​ntally”是一个子类属性(例如:如果我希望它水平增长)

    - (void)setStringValue:(NSString *)stringValue
    {
        BOOL changed = ![self.stringValue isEqualToString:stringValue] ? YES : NO;
    
        [super setStringValue:stringValue];
    
        if (stringValue.length && changed)
        {
            if (self.frame.size.height > 17 && self.preferGrowingHorizontally)
                [self compensateWidth];
        }
    }
    
    - (void)compensateWidth
    {
        float requiredHeight = FLT_MAX;
        int widthCompensation = 0;
    
        while (requiredHeight > self.frame.size.height)
            requiredHeight = [self heightForStringDrawing:self.stringValue Font:self.font Width:self.frame.size.width + widthCompensation++];
    
        if (--widthCompensation)
        {
            NSLayoutConstraint* width = [self constraintForAttribute:NSLayoutAttributeWidth];
            if (width)
                width.constant = self.frame.size.width + widthCompensation;
    
            NSLog(@"requiredHeight: %f width compensation: %d for textField: %@", requiredHeight, widthCompensation, self.stringValue);
        }
    }
    
    - (float)heightForStringDrawing:(NSString*)myString Font:(NSFont*)myFont Width:(float)myWidth
    {
        NSTextStorage *textStorage = [[[NSTextStorage alloc] initWithString:myString] autorelease];
        NSTextContainer *textContainer = [[[NSTextContainer alloc] initWithContainerSize:NSMakeSize(myWidth, FLT_MAX)] autorelease];
    
        NSLayoutManager *layoutManager = [[[NSLayoutManager alloc] init] autorelease];
        [layoutManager addTextContainer:textContainer];
        [textStorage addLayoutManager:layoutManager];
        [textStorage addAttribute:NSFontAttributeName value:myFont
                            range:NSMakeRange(0, [textStorage length])];
        [textContainer setLineFragmentPadding:0.0];
        textContainer.lineBreakMode = NSLineBreakByWordWrapping;
    
        (void) [layoutManager glyphRangeForTextContainer:textContainer];
        return [layoutManager usedRectForTextContainer:textContainer].size.height;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-02-05
      • 1970-01-01
      • 1970-01-01
      • 2014-06-25
      • 1970-01-01
      • 2013-03-13
      相关资源
      最近更新 更多