【问题标题】:How to set NSString's background cornerRadius on iOS7iOS7上如何设置NSString的背景角半径
【发布时间】:2014-03-18 10:06:29
【问题描述】:

我想在 iOS7 上设置 NSString 的背景角半径。 但是,NSString 没有层...

请告诉我,如何在 iOS7 上设置 NSString 的背景角半径?

示例

【问题讨论】:

    标签: objective-c background cornerradius


    【解决方案1】:

    伊曼纽尔的 swift 代码:

    class TagLayoutManager : NSLayoutManager {
    
    override func fillBackgroundRectArray(rectArray: UnsafePointer<CGRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: UIColor) {
    
        let cornerRadius:CGFloat = 3.0
        let path = CGPathCreateMutable()
    
        if rectCount == 1 || (rectCount == 2 && (CGRectGetMaxX(rectArray[1]) < CGRectGetMaxX(rectArray[0]))) {
    
            CGPathAddRect(path, nil, CGRectInset(rectArray[0], cornerRadius, cornerRadius))
            if rectCount == 2 {
                CGPathAddRect(path, nil, CGRectInset(rectArray[1], cornerRadius, cornerRadius))
            }
    
        } else {
                let lastRect = rectCount - 1
    
                CGPathMoveToPoint(path, nil, CGRectGetMinX(rectArray[0]) + cornerRadius, CGRectGetMaxY(rectArray[0]) + cornerRadius);
    
                CGPathAddLineToPoint(path, nil, CGRectGetMinX(rectArray[0]) + cornerRadius, CGRectGetMinY(rectArray[0]) + cornerRadius);
                CGPathAddLineToPoint(path, nil, CGRectGetMaxX(rectArray[0]) - cornerRadius, CGRectGetMinY(rectArray[0]) + cornerRadius);
    
                CGPathAddLineToPoint(path, nil, CGRectGetMaxX(rectArray[0]) - cornerRadius, CGRectGetMinY(rectArray[lastRect]) - cornerRadius);
                CGPathAddLineToPoint(path, nil, CGRectGetMaxX(rectArray[lastRect]) - cornerRadius, CGRectGetMinY(rectArray[lastRect]) - cornerRadius);
    
                CGPathAddLineToPoint(path, nil, CGRectGetMaxX(rectArray[lastRect]) - cornerRadius, CGRectGetMaxY(rectArray[lastRect]) - cornerRadius);
                CGPathAddLineToPoint(path, nil, CGRectGetMinX(rectArray[lastRect]) + cornerRadius, CGRectGetMaxY(rectArray[lastRect]) - cornerRadius);
    
                CGPathAddLineToPoint(path, nil, CGRectGetMinX(rectArray[lastRect]) + cornerRadius, CGRectGetMaxY(rectArray[0]) + cornerRadius);
    
                CGPathCloseSubpath(path);
            }
    
            color.set()
    
            let ctx = UIGraphicsGetCurrentContext()
            CGContextSetLineWidth(ctx, cornerRadius * 2.0)
            CGContextSetLineJoin(ctx, .Round)
    
            CGContextAddPath(ctx, path)
    
            CGContextDrawPath(ctx, .FillStroke)
        }
    
    }
    

    【讨论】:

      【解决方案2】:

      更新到 Swift 3.1 Emmanuel 的 swift 代码更新到 3.1 版

      class TagLayoutManager: NSLayoutManager {
      
      override func fillBackgroundRectArray(_ rectArray: UnsafePointer<CGRect>, count rectCount: Int, forCharacterRange charRange: NSRange, color: UIColor) {
      
          let cornerRadius:CGFloat = 5
          let path = CGMutablePath.init()
      
      
      
      
          if rectCount == 1 || (rectCount == 2 && (rectArray[1].maxX < rectArray[0].maxX)) {
      
              path.addRect(rectArray[0].insetBy(dx: cornerRadius, dy: cornerRadius))
      
              if rectCount == 2 {
                  path.addRect(rectArray[1].insetBy(dx: cornerRadius, dy: cornerRadius))
              }
      
          } else {
      
              let lastRect = rectCount - 1
      
              path.move(to: CGPoint(x: rectArray[0].minX + cornerRadius, y: rectArray[0].maxY + cornerRadius))
      
              path.addLine(to: CGPoint(x: rectArray[0].minX + cornerRadius, y: rectArray[0].minY + cornerRadius))
              path.addLine(to: CGPoint(x: rectArray[0].maxX - cornerRadius, y: rectArray[0].minY + cornerRadius))
      
              path.addLine(to: CGPoint(x: rectArray[0].maxX - cornerRadius, y: rectArray[lastRect].minY - cornerRadius))
              path.addLine(to: CGPoint(x: rectArray[lastRect].maxX - cornerRadius, y: rectArray[lastRect].minY - cornerRadius))
      
              path.addLine(to: CGPoint(x: rectArray[lastRect].maxX - cornerRadius, y: rectArray[lastRect].maxY - cornerRadius))
              path.addLine(to: CGPoint(x: rectArray[lastRect].minX + cornerRadius, y: rectArray[lastRect].maxY - cornerRadius))
      
              path.addLine(to: CGPoint(x: rectArray[lastRect].minX + cornerRadius, y: rectArray[0].maxY + cornerRadius))
      
              path.closeSubpath()
      
          }
      
          color.set()
      
          let ctx = UIGraphicsGetCurrentContext()
          ctx!.setLineWidth(cornerRadius * 2.0)
          ctx!.setLineJoin(.round)
      
          ctx!.setAllowsAntialiasing(true)
          ctx!.setShouldAntialias(true)
      
          ctx!.addPath(path)
          ctx!.drawPath(using: .fillStroke)
      }
      }
      

      【讨论】:

      • 没有解释的代码不是一个好的答案。请阅读此how-to-answer
      • 好的。如文章标题所述,该代码只是将之前的 Swift 2.x 代码更新为 Swift 3.1。
      【解决方案3】:

      作为@Emmanuel 解决方案的补充,添加

      CGContextSetAllowsAntialiasing(ctx, YES);
      CGContextSetShouldAntialias(ctx, YES);
      

      会让它看起来更好。

      【讨论】:

        【解决方案4】:

        您可以通过使用带有NSLayoutManager 子类的UITextView 来覆盖-fillBackgroundRectArray:count:forCharacterRange:color:。 只是一个小例子:

        @implementation ViewController
        - (void)viewDidLoad
        {
            [super viewDidLoad];
        
            // setup text handling
            NSTextStorage *textStorage = [[NSTextStorage alloc] initWithString:@"Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda."];
        
            // use our subclass of NSLayoutManager
            MyLayoutManager *textLayout = [[MyLayoutManager alloc] init];
        
            [textStorage addLayoutManager:textLayout];
        
            NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:self.view.bounds.size];
        
            [textLayout addTextContainer:textContainer];
            UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(0,20,self.view.bounds.size.width,self.view.bounds.size.height-20)
                                                       textContainer:textContainer];
            [self.view addSubview:textView];
        
            // set some background color to our text
            [textView.textStorage setAttributes:[NSDictionary dictionaryWithObject:[UIColor blueColor] forKey:NSBackgroundColorAttributeName] range:NSMakeRange(22, textView.text.length - 61)];
        }
        @end
        
        @interface MyLayoutManager : NSLayoutManager
        @end
        
        - (void)fillBackgroundRectArray:(const CGRect *)rectArray count:(NSUInteger)rectCount forCharacterRange:(NSRange)charRange color:(UIColor *)color
        {
             CGFloat halfLineWidth = 4.; // change this to change corners radius
        
             CGMutablePathRef path = CGPathCreateMutable();
        
             if (rectCount == 1
                 || (rectCount == 2 && (CGRectGetMaxX(rectArray[1]) < CGRectGetMinX(rectArray[0])))
                )
            {
                // 1 rect or 2 rects without edges in contact
        
                 CGPathAddRect(path, NULL, CGRectInset(rectArray[0], halfLineWidth, halfLineWidth));
                 if (rectCount == 2)
                    CGPathAddRect(path, NULL, CGRectInset(rectArray[1], halfLineWidth, halfLineWidth));
            }
             else
            {
                // 2 or 3 rects
                 NSUInteger lastRect = rectCount - 1;
        
                 CGPathMoveToPoint(path, NULL, CGRectGetMinX(rectArray[0]) + halfLineWidth, CGRectGetMaxY(rectArray[0]) + halfLineWidth);
        
                 CGPathAddLineToPoint(path, NULL, CGRectGetMinX(rectArray[0]) + halfLineWidth, CGRectGetMinY(rectArray[0]) + halfLineWidth);
                 CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(rectArray[0]) - halfLineWidth, CGRectGetMinY(rectArray[0]) + halfLineWidth);
        
                 CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(rectArray[0]) - halfLineWidth, CGRectGetMinY(rectArray[lastRect]) - halfLineWidth);
                 CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(rectArray[lastRect]) - halfLineWidth, CGRectGetMinY(rectArray[lastRect]) - halfLineWidth);
        
                 CGPathAddLineToPoint(path, NULL, CGRectGetMaxX(rectArray[lastRect]) - halfLineWidth, CGRectGetMaxY(rectArray[lastRect]) - halfLineWidth);
                 CGPathAddLineToPoint(path, NULL, CGRectGetMinX(rectArray[lastRect]) + halfLineWidth, CGRectGetMaxY(rectArray[lastRect]) - halfLineWidth);
        
                 CGPathAddLineToPoint(path, NULL, CGRectGetMinX(rectArray[lastRect]) + halfLineWidth, CGRectGetMaxY(rectArray[0]) + halfLineWidth);
        
                 CGPathCloseSubpath(path);
            }
        
            [color set]; // set fill and stroke color
        
             CGContextRef ctx = UIGraphicsGetCurrentContext();
             CGContextSetLineWidth(ctx, halfLineWidth * 2.);
             CGContextSetLineJoin(ctx, kCGLineJoinRound);
        
             CGContextAddPath(ctx, path);
             CGPathRelease(path);
        
             CGContextDrawPath(ctx, kCGPathFillStroke);
        }
        @end
        

        【讨论】:

        • 所以@Emmanuel 有什么办法可以使用attributedText 上的属性而不是NSTextStorage?我尝试将 MyLayoutManager 设置到我的 UITextView 上,但它仍然在背景上有硬角,这一定意味着它不尊重属性文本属性中的属性......
        • 有什么方法可以为文本字段完成此操作吗?
        • uilabel 有什么解决方案吗?
        【解决方案5】:

        NSString 只是定义了一个文本字符串。它没有定义如何呈现的属性。为了在屏幕上显示文本,通常使用UILabelUITextView。但是,对于您在示例中显示的选择行为,您需要自己绘制。它还会更改所选文本的文本颜色,因此您需要自己处理。

        如果您创建了一个自定义UIView 以允许您绘制蓝色选择区域,您可以将其放在UILabel 后面,您可以使用NSAttributedString 来设置标签的文本,其中“选择" 文本是白色而不是黑色。这可能是最简单的方法。

        【讨论】:

        • 不是我,但可能是因为您的答案没有考虑到 attributed 字符串,这些字符串中存储了某种视觉呈现信息。
        【解决方案6】:

        NSString 没有。 NSAttributedString 有一个可以使用的 backgroundColor 属性,但如果没有自定义渲染,您将无法为选择的文本片段设置角半径。

        所以你需要编写一个自定义 UIView 来呈现你的文本

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-07-13
          • 1970-01-01
          • 1970-01-01
          • 2020-03-24
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多