【问题标题】:UITextView exclusionPaths bottom rightUITextView excludePaths 右下角
【发布时间】:2015-07-21 17:26:09
【问题描述】:

我正在尝试为消息做一些 whatsapp 之类的操作,以使单元格根据 contentsize 调整大小并在右下角显示日期...问题是我不知道排除的矩形位置路径,因为文本是动态的,我有这样的东西,但仅适用于多行,但不适用于单行:

NSString *txt=@"I'm writing ";//a text renderer using Core Text, and I discovered I’ll need to wrap text around objects (such as is done in any DTP program). I couldn’t find any easy answers as to how to do this in the documentation, so having finally got it working I’ll share what I did. To lay out text in a custom shape in Core Text, you can pass a CGPath in when you create your CTFramesetterRef. Originally this only supported rectangular paths, but now it supports fully custom paths. My first thought was to see if I could subtract the region to wrap around from the path for my frame’s border, and pass the result in to Core Text as a path. It turns out firstly that subtracting one path from another in Core Graphics is not trivial. However, if you simply add two shapes to the same path, Core Graphics can use a winding rule to work out which areas to draw. Core Text, at least as of iOS 4.2, can also use this kind of algorithm. This will work for many cases: if you can guarantee that your object to be wrapped will be fully inside the frame (and not overlapping the edge), just go ahead and add its border to the same path as your frame, and Core"; // Text will do the rest.";

txtText.text=txt;

CGSize textFrame = [txtText sizeThatFits:CGSizeMake(235, MAXFLOAT)];

UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(textFrame.width-35, textFrame.height-20, 35, 20)];
txtText.textContainer.exclusionPaths = @[imgRect];

textFrame = [txtText sizeThatFits:CGSizeMake(235, MAXFLOAT)];

//int frameWidth=375;

txtText.frame=CGRectIntegral(CGRectMake(10, 10, textFrame.width, textFrame.height));
lblHour.frame=CGRectIntegral(CGRectMake(textFrame.width-35, textFrame.height-15, 35, 20));

viewCanvasAround.frame=CGRectIntegral(CGRectMake(50, 100, textFrame.width+20, textFrame.height+20));

【问题讨论】:

  • 嗨@Catalin,您找到合适的解决方案了吗?
  • 不,还没有,就这样@adnako
  • 一个聪明人告诉我使用 NSAttributed 字符串,它的尾部有一个透明矩形,其大小与时间视图框架相同。效果很好。
  • 分享代码并将其标记为答案然后@adnako

标签: ios iphone uitableview uitextview


【解决方案1】:

我也有同样的问题。我添加了带有大小的 textAttachment 属性字符串。您将设置估计的最大尺寸。单行也没有问题。 (对不起,我英语不好。)

这是示例代码。

var text: String! {
    didSet {

        let font = UIFont.systemFont(ofSize: 13);
        let att = NSMutableAttributedString.init(string: text, attributes: [NSAttributedString.Key.foregroundColor : UIColor.black,
                                                                            NSAttributedString.Key.font : font]);
        let attachment = NSTextAttachment.init(data: nil, ofType: nil);
        var size = extraSize;
        size.height = font.lineHeight;
        attachment.bounds = CGRect.init(origin: CGPoint.init(), size: size);

        att.append(NSAttributedString.init(attachment: attachment));

        textView.attributedText = att;
    }
}

【讨论】:

    【解决方案2】:

    我的同事在 actor.im 中找到了一个很好的解决方案。 https://github.com/actorapp/actor-platform/blob/master/actor-sdk/sdk-core-ios/ActorSDK/Sources/Controllers/Content/Conversation/Cell/AABubbleTextCell.swift#L312

        let container = YYTextContainer(size: CGSizeMake(maxTextWidth, CGFloat.max))
    
        textLayout = YYTextLayout(container: container, text: attributedText)!
    
        // print("Text Layouted")
    
        // Measuring text and padded text heights
        let textSize = textLayout.textBoundingSize
    
        if textLayout.lines.count == 1 {
            if textLayout.textBoundingSize.width < maxTextWidth - timeWidth {
                //
                // <line_0> <date>
                //
                bubbleSize = CGSize(width: textSize.width + timeWidth, height: textSize.height)
            } else {
    
                //
                // <line_________0>
                //           <date>
                //
                bubbleSize = CGSize(width: textSize.width, height: textSize.height + 16)
            }
        } else {
            let maxWidth = textSize.width
            let lastLine = textLayout.lines.last!.width
            if lastLine + timeWidth < maxWidth {
                //
                // <line_________0>
                // <line_________1>
                // ..
                // <line_n>  <date>
                //
                bubbleSize = textSize
            } else if lastLine + timeWidth < maxTextWidth {
                //
                // |------------------|
                // <line______0>
                // <line______1>
                // ..
                // <line______n> <date>
                //
                bubbleSize = CGSize(width: max(lastLine + timeWidth, maxWidth), height: textSize.height)
            } else {
                //
                // <line_________0>
                // <line_________1>
                // ..
                // <line_________n>
                //           <date>
                //
                bubbleSize = CGSize(width: max(timeWidth, maxWidth), height: textSize.height + 16)
            }
        }
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题(对我来说是右上角的一个按钮),我有办法解决它:

      - (void)viewWillLayoutSubviews {
          [super viewWillLayoutSubviews];
          [self updateTextExclusionPaths];
      }
      
      - (void)updateTextExclusionPaths {
          // Remove old exclusionPaths to calculate right rects of new
          textView.textContainer.exclusionPaths = @[];
          // Force textView to layout the text without exclusionPaths
          [textView.layoutManager glyphRangeForTextContainer:textView.textContainer];
      
          /// Because of some specifics of my implementation I had a problem with wrong frame of my button. So I calculated it manually
          // Calculate new exclusionPaths
          CGRect buttonFrameInTextView = [superViewOfTextView convertRect:button.frame toView:textView];
      
          // Calculate textView.text size without any exclusionPaths to calculate right button frame
          CGSize textViewSize = [textView sizeThatFits:CGSizeMake(textView.frame.size.width, CGFLOAT_MAX)];
          // Update Y position of button
          buttonFrameInTextView.origin.y = size.height - buttonFrameInTextView.size.height;
      
          // Add new exclusionPaths
          UIBezierPath *buttonRectBezierPath = [UIBezierPath bezierPathWithRect:buttonFrameInTextView];
          textView.textContainer.exclusionPaths = @[ buttonRectBezierPath ];
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-12-22
        • 2021-08-21
        • 1970-01-01
        • 1970-01-01
        • 2018-03-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多