【问题标题】:Auto-expanding a UIView and CGPath to fit Core Text自动扩展 UIView 和 CGPath 以适应核心文本
【发布时间】:2012-05-12 03:25:29
【问题描述】:

我一直在寻找这个问题的答案,虽然有很多关于这个话题的东西似乎没有什么能回答这个问题,至少对我来说不是。

我在情节提要中有一个固定大小的自定义 UIView(在原型单元格中)。我为它继承了 UIView 并重写了 drawRect 方法。它基本上把一个格式化的字符串放在一起,然后我像这样绘制它:

// now for the actual drawing
CGContextRef context = UIGraphicsGetCurrentContext();

CGContextSetShadowWithColor(context, 
                            CGSizeMake(0, 1), 
                            0,  
                            [UIColor whiteColor].CGColor);

CGMutablePathRef path = CGPathCreateMutable(); //1
CGPathAddRect(path, NULL, self.bounds );

// flip the coordinate system
CGContextSetTextMatrix(context, CGAffineTransformIdentity);
CGContextTranslateCTM(context, 0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CTFramesetterRef framesetter =
CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef)stringToDraw); //3

CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);


CTFrameDraw(frame, context); //4

这很好并且有效,如果我将默认大小设置得足够大,它将处理多行文本。

CGPath 使用所有 UIView,这很好/理想。

我想保持 CGPath 的宽度固定,但我希望扩展高度以容纳基本上无限量的文本,现在它只是被切断(由于路径/视图不够大,无法包含它)

我尝试使用 CTFramesetterSuggestFrameSizeWithConstraints 无济于事。有人可以帮我开发一些代码来实现我需要做的事情吗?

【问题讨论】:

    标签: iphone ios uiview core-text cgpath


    【解决方案1】:

    知道要绘制的字符串和要使用的字体,您总是可以从中获取边界

    CGSize boundingSize = CGSizeMake(self.bounds.size.width, CGFLOAT_MAX);
    CGSize requiredSize = [yourText sizeWithFont:yourFont
                               constrainedToSize:boundingSize
                                   lineBreakMode:UILineBreakModeWordWrap];
    CGFloat requiredHeight = requiredSize.height;
    

    你在那里得到了高度,可以在其他地方重复使用......

    【讨论】:

    • 感谢@nicolasthenoz,虽然我需要它扩展以适应的另一个原因是因为我计划在文本之后/下方放置其他元素。此外,我的表格单元格也会扩大到超出文本所需的范围。
    • sizeWithFont 无法与 CoreText 一起使用,至少在所有情况下都不会。
    【解决方案2】:

    这是您尝试执行的操作,请注意,这使用 CoreText API,并且会返回正确的高度,这与错误的 sizeWithFont 答案不同。

    // Measure the height required to display the attr string given a known width.
    // This logic returns a height without an upper bound. Not thread safe!
    
    - (NSUInteger) measureHeightForWidth:(NSUInteger)width
    {
      NSAssert(self.isDoneAppendingText == TRUE, @"isDoneAppendingText");
    
      NSAssert(self.attrString, @"attrString");
    
      CFMutableAttributedStringRef attrString = self.attrString;
      CFRange stringRange = self.stringRange;
    
      CGFloat measuredHeight = 1.0f;
    
      // Create the framesetter with the attributed string.
    
      CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString(attrString);
    
      if (framesetter) {
        CFRange fitRange;
        CGSize constraints = CGSizeMake(width, CGFLOAT_MAX); // width, height : CGFLOAT_MAX indicates unconstrained
    
        CGSize fontMeasureFrameSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, stringRange, (CFDictionaryRef)NULL, constraints, &fitRange);
    
        // Note that fitRange is ignored here, we only care about the measured height
    
        measuredHeight = fontMeasureFrameSize.height;
    
        CFRelease(framesetter);
      }
    
      return (NSUInteger) ceil(measuredHeight);
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多