Mon*_*urd 102 iphone cocoa-touch core-graphics objective-c ios
我想要的只是在我的白色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]);
}
Run Code Online (Sandbox Code Playgroud)
我只是有一种唠叨的感觉,我忽略了一种更简单的方法.也许通过重写"drawTextInRect",但我似乎无法让drawTextInRect屈服于我的意志,尽管专心地盯着它并且皱眉真的很难.
kpr*_*vas 164
我能够通过覆盖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;
}
Run Code Online (Sandbox Code Playgroud)
Axe*_*min 104
更简单的解决方案是使用属性字符串,如下所示:
let strokeTextAttributes: [NSAttributedStringKey : Any] = [
NSAttributedStringKey.strokeColor : UIColor.black,
NSAttributedStringKey.foregroundColor : UIColor.white,
NSAttributedStringKey.strokeWidth : -2.0,
]
myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes)
Run Code Online (Sandbox Code Playgroud)
let strokeTextAttributes: [NSAttributedString.Key : Any] = [
.strokeColor : UIColor.black,
.foregroundColor : UIColor.white,
.strokeWidth : -2.0,
]
myLabel.attributedText = NSAttributedString(string: "Foo", attributes: strokeTextAttributes)
Run Code Online (Sandbox Code Playgroud)
在一个UITextField可以设置defaultTextAttributes和attributedPlaceholder为好.
请注意,在这种情况下NSStrokeWidthAttributeName 必须是负数,即只有内部轮廓有效.

Lac*_*zar 24
在阅读了接受的答案以及对它的两个更正和Axel Guilmin的答案之后,我决定在Swift中编译一个适合我的整体解决方案:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
您可以将此自定义UILabel类添加到Interface Builder中的现有标签,并通过添加用户定义的运行时属性来更改边框的厚度及其颜色,如下所示:

结果:

答案的实现存在一个问题.使用笔划绘制文本的字符字形宽度与绘制没有笔划的文本略有不同,这会产生"未中心"的结果.可以通过在填充文本周围添加不可见的笔划来修复它.
更换:
CGContextSetTextDrawingMode(c, kCGTextFill);
self.textColor = textColor;
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
Run Code Online (Sandbox Code Playgroud)
有:
CGContextSetTextDrawingMode(context, kCGTextFillStroke);
self.textColor = textColor;
[[UIColor clearColor] setStroke]; // invisible stroke
self.shadowOffset = CGSizeMake(0, 0);
[super drawTextInRect:rect];
Run Code Online (Sandbox Code Playgroud)
我不是百分百肯定,如果这是真正的交易,因为我不知道是否self.textColor = textColor;有相同的效果[textColor setFill],但它应该工作.
披露:我是THLabel的开发者.
我刚刚发布了一个UILabel子类,它允许在文本和其他效果中使用大纲.你可以在这里找到它:https://github.com/tobihagemann/THLabel
这不会创建一个轮廓本身,但它会在文本周围留下阴影,如果你使阴影半径足够小,它可能类似于轮廓.
label.layer.shadowColor = [[UIColor blackColor] CGColor];
label.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
label.layer.shadowOpacity = 1.0f;
label.layer.shadowRadius = 1.0f;
Run Code Online (Sandbox Code Playgroud)
我不知道它是否与旧版本的iOS兼容..
无论如何,我希望它有所帮助......
import Foundation
import UIKit
public class OutlinedText: UILabel{
internal var mOutlineColor:UIColor?
internal var mOutlineWidth:CGFloat?
@IBInspectable var outlineColor: UIColor{
get { return mOutlineColor ?? UIColor.clear }
set { mOutlineColor = newValue }
}
@IBInspectable var outlineWidth: CGFloat{
get { return mOutlineWidth ?? 0 }
set { mOutlineWidth = newValue }
}
override public func drawText(in rect: CGRect) {
let shadowOffset = self.shadowOffset
let textColor = self.textColor
let c = UIGraphicsGetCurrentContext()
c?.setLineWidth(outlineWidth)
c?.setLineJoin(.round)
c?.setTextDrawingMode(.stroke)
self.textColor = mOutlineColor;
super.drawText(in:rect)
c?.setTextDrawingMode(.fill)
self.textColor = textColor
self.shadowOffset = CGSize(width: 0, height: 0)
super.drawText(in:rect)
self.shadowOffset = shadowOffset
}
}
Run Code Online (Sandbox Code Playgroud)
通过将 UILabel 的自定义类设置为 OutlinedText,它可以完全在 Interface Builder 中实现。然后,您将能够从“属性”窗格中设置轮廓的宽度和颜色。
如果你的目标是这样的:
以下是我实现它的方法:我添加了一个新的label自定义类作为子视图到我当前的 UILabel (受到此答案的启发)。
只需将其复制并粘贴到您的项目中即可:
extension UILabel {
func addTextOutline(usingColor outlineColor: UIColor, outlineWidth: CGFloat) {
class OutlinedText: UILabel{
var outlineWidth: CGFloat = 0
var outlineColor: UIColor = .clear
override public func drawText(in rect: CGRect) {
let shadowOffset = self.shadowOffset
let textColor = self.textColor
let c = UIGraphicsGetCurrentContext()
c?.setLineWidth(outlineWidth)
c?.setLineJoin(.round)
c?.setTextDrawingMode(.stroke)
self.textAlignment = .center
self.textColor = outlineColor
super.drawText(in:rect)
c?.setTextDrawingMode(.fill)
self.textColor = textColor
self.shadowOffset = CGSize(width: 0, height: 0)
super.drawText(in:rect)
self.shadowOffset = shadowOffset
}
}
let textOutline = OutlinedText()
let outlineTag = 9999
if let prevTextOutline = viewWithTag(outlineTag) {
prevTextOutline.removeFromSuperview()
}
textOutline.outlineColor = outlineColor
textOutline.outlineWidth = outlineWidth
textOutline.textColor = textColor
textOutline.font = font
textOutline.text = text
textOutline.tag = outlineTag
sizeToFit()
addSubview(textOutline)
textOutline.frame = CGRect(x: -(outlineWidth / 2), y: -(outlineWidth / 2),
width: bounds.width + outlineWidth,
height: bounds.height + outlineWidth)
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
yourLabel.addTextOutline(usingColor: .red, outlineWidth: 6)
Run Code Online (Sandbox Code Playgroud)
它也适用于 aUIButton及其所有动画:
yourButton.titleLabel?.addTextOutline(usingColor: .red, outlineWidth: 6)
Run Code Online (Sandbox Code Playgroud)