如何使UILabel显示概述文本?

我想要的是我的白色UILabel文本的一个像素的黑色边框。

我使用下面的代码对UILabel进行了子类化,这些代码是我从一些切线相关的在线示例中笨拙地拼凑而成的。 它的工作原理非常非常缓慢(除了在模拟器上),我也无法让它垂直居中文本(所以我暂时将最后一行的y值硬编码)。 哈啊!

void ShowStringCentered(CGContextRef gc, float x, float y, const char *str) { CGContextSetTextDrawingMode(gc, kCGTextInvisible); CGContextShowTextAtPoint(gc, 0, 0, str, strlen(str)); CGPoint pt = CGContextGetTextPosition(gc); CGContextSetTextDrawingMode(gc, kCGTextFillStroke); CGContextShowTextAtPoint(gc, x - pt.x / 2, y, str, strlen(str)); } - (void)drawRect:(CGRect)rect{ CGContextRef theContext = UIGraphicsGetCurrentContext(); CGRect viewBounds = self.bounds; CGContextTranslateCTM(theContext, 0, viewBounds.size.height); CGContextScaleCTM(theContext, 1, -1); CGContextSelectFont (theContext, "Helvetica", viewBounds.size.height, kCGEncodingMacRoman); CGContextSetRGBFillColor (theContext, 1, 1, 1, 1); CGContextSetRGBStrokeColor (theContext, 0, 0, 0, 1); CGContextSetLineWidth(theContext, 1.0); ShowStringCentered(theContext, rect.size.width / 2.0, 12, [[self text] cStringUsingEncoding:NSASCIIStringEncoding]); } 

我只是有一种唠叨的感觉,我忽略了一个简单的方法来做到这一点。 也许通过重写“drawTextInRect”,但我似乎无法得到drawTextInRect弯曲我的意志,尽pipe专注地凝视着,真的很难皱眉。

我可以通过覆盖drawTextInRect来实现:

 - (void)drawTextInRect:(CGRect)rect { CGSize shadowOffset = self.shadowOffset; UIColor *textColor = self.textColor; CGContextRef c = UIGraphicsGetCurrentContext(); CGContextSetLineWidth(c, 1); CGContextSetLineJoin(c, kCGLineJoinRound); CGContextSetTextDrawingMode(c, kCGTextStroke); self.textColor = [UIColor whiteColor]; [super drawTextInRect:rect]; CGContextSetTextDrawingMode(c, kCGTextFill); self.textColor = textColor; self.shadowOffset = CGSizeMake(0, 0); [super drawTextInRect:rect]; self.shadowOffset = shadowOffset; } 

一个更简单的解决scheme是像这样使用一个Attributed String :

 let strokeTextAttributes = [ NSStrokeColorAttributeName : UIColor.blackColor(), NSForegroundColorAttributeName : UIColor.whiteColor(), NSStrokeWidthAttributeName : -1.0, ] myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes) 

Swift 4语法:

 let strokeTextAttributes: [NSAttributedStringKey : Any] = [ NSAttributedStringKey.strokeColor : UIColor.black, NSAttributedStringKey.foregroundColor : UIColor.white, NSAttributedStringKey.strokeWidth : -2.0, ] myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes) 

UITextField你也可以设置defaultTextAttributes和。

请注意, NSStrokeWidthAttributeName在这种情况下必须是负数 ,即只有内部轮廓工作。

带有使用属性文本大纲的UITextFields

在阅读了接受的答案和两个更正以及Axel Guilmin的回答之后,我决定在Swift中编写一个整体解决scheme,这适合我:

 import UIKit class UIOutlinedLabel: UILabel { var outlineWidth: CGFloat = 1 var outlineColor: UIColor = UIColor.whiteColor() override func drawTextInRect(rect: CGRect) { let strokeTextAttributes = [ NSStrokeColorAttributeName : outlineColor, NSStrokeWidthAttributeName : -1 * outlineWidth, ] self.attributedText = NSAttributedString(string: self.text ?? "", attributes: strokeTextAttributes) super.drawTextInRect(rect) } } 

您可以将此自定义UILabel类添加到Interface Builder中的现有标签,并通过添加用户定义的运行时属性来更改边框的厚度和颜色: 界面生成器设置

结果:

大红G与轮廓

答案的实现有一个问题。 用笔画绘制文本与绘制没有笔画的文本可能会产生“未经处理”的结果略有不同。 可以通过在填充文本周围添加一个不可见的笔画来修复它。

更换:

 CGContextSetTextDrawingMode(c, kCGTextFill); self.textColor = textColor; self.shadowOffset = CGSizeMake(0, 0); [super drawTextInRect:rect]; 

有:

 CGContextSetTextDrawingMode(context, kCGTextFillStroke); self.textColor = textColor; [[UIColor clearColor] setStroke]; // invisible stroke self.shadowOffset = CGSizeMake(0, 0); [super drawTextInRect:rect]; 

我不是100%确定,如果这是真正的交易,因为我不知道是否self.textColor = textColor;[textColor setFill]具有相同的效果,但它应该工作。

披露:我是THLabel的开发者。

我刚才发布了一个UILabel子类,它允许在文本和其他效果的轮廓。 你可以在这里find它: https : //github.com/tobihagemann/THLabel

这不会创build一个大纲本身,但它会在文本周围的阴影,如果你使阴影半径足够小,它可以像一个轮廓。

 label.layer.shadowColor = [[UIColor blackColor] CGColor]; label.layer.shadowOffset = CGSizeMake(0.0f, 0.0f); label.layer.shadowOpacity = 1.0f; label.layer.shadowRadius = 1.0f; 

我不知道它是否与旧版本的iOS兼容..

无论如何,我希望这有助于…

如果你想要复杂的animation,最好的方法是用程序化的方式把它的截图变成一个animation,而不是!

要获取视图的屏幕截图,您需要使用以下代码:

 UIGraphicsBeginImageContext(mainContentView.bounds.size); [mainContentView.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); 

mainContentView是你想截图的视图。 将viewImage添加到UIImageView并为其设置animation效果。

希望加快你的animation!

ñ

正如MuscleRumble所说,接受答案的边界有点偏离中心。 我可以通过设置笔触宽度为零而不是改变颜色来清除这个问题。

即replace:

 CGContextSetTextDrawingMode(c, kCGTextFill); self.textColor = textColor; self.shadowOffset = CGSizeMake(0, 0); [super drawTextInRect:rect]; 

有:

 CGContextSetTextDrawingMode(c, kCGTextFillStroke); self.textColor = textColor; CGContextSetLineWidth(c, 0); // set stroke width to zero self.shadowOffset = CGSizeMake(0, 0); [super drawTextInRect:rect]; 

我只是评论他的答案,但显然我不够“信誉”。

如果你想要的是我的白色UILabel文本周围的一个像素的黑色边框,

那么我认为你正在使问题比它更难…我不知道你应该使用“绘制矩形/ frameRect”函数,但它会很容易find。 这个方法只是示范了策略(让超类做这个工作!):

 - (void)drawRect:(CGRect)rect { [super drawRect:rect]; [context frameRect:rect]; // research which rect drawing function to use... } 

我发现主要答案的问题。 文本位置不一定要正确居中到子像素位置,以便轮廓可以在文本周围不匹配。 我使用下面的代码修复了它,它使用了CGContextSetShouldSubpixelQuantizeFonts(ctx, false)

 - (void)drawTextInRect:(CGRect)rect { CGContextRef ctx = UIGraphicsGetCurrentContext(); [self.textOutlineColor setStroke]; [self.textColor setFill]; CGContextSetShouldSubpixelQuantizeFonts(ctx, false); CGContextSetLineWidth(ctx, self.textOutlineWidth); CGContextSetLineJoin(ctx, kCGLineJoinRound); CGContextSetTextDrawingMode(ctx, kCGTextStroke); [self.text drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment]; CGContextSetTextDrawingMode(ctx, kCGTextFill); [self.text drawInRect:rect withFont:self.font lineBreakMode:NSLineBreakByWordWrapping alignment:self.textAlignment]; } 

这假定您将textOutlineColortextOutlineWidth定义为属性。

为什么不在Photoshop中创build一个1px的边框UIView,然后设置一个UIView的图像,并将其放在你的UILabel?

码:

 UIView *myView; UIImage *imageName = [UIImage imageNamed:@"1pxBorderImage.png"]; UIColor *tempColour = [[UIColor alloc] initWithPatternImage:imageName]; myView.backgroundColor = tempColour; [tempColour release]; 

这将节省你的子类的对象,这是相当简单的。

更何况如果你想做animation,它是内置到UIView类。

要在UILabel周围放置一个带有圆angular的边框,请执行以下操作:

 labelName.layer.borderWidth = 1; labelName.layer.borderColor = [[UIColor grayColor] CGColor]; labelName.layer.cornerRadius = 10; 

(不要忘记包含QuartzCore / QuartzCore.h)