谁能建议如何在 UIButton 的标题下划线?我有一个自定义类型的 UIButton,我希望标题带有下划线,但 Interface Builder 没有提供任何这样做的选项。
在 Interface Builder 中,当您为按钮选择字体选项时,它提供了选择无、单、双、颜色的选项,但这些都没有对按钮上的标题进行任何更改。
任何帮助表示赞赏。
要使用界面生成器来下划线,必须:
将其更改为归因
突出显示属性检查器中的文本
右键单击,选择字体,然后下划线
https://i.stack.imgur.com/yfYRv.png
其他人制作的视频 https://www.youtube.com/watch?v=5-ZnV3jQd9I
从 iOS6 开始,现在可以使用 NSAttributedString 以更灵活的方式执行下划线(以及任何其他属性字符串支持):
NSMutableAttributedString *commentString = [[NSMutableAttributedString alloc] initWithString:@"The Quick Brown Fox"];
[commentString addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0, [commentString length])];
[button setAttributedTitle:commentString forState:UIControlStateNormal];
注意:将此添加为另一个答案 - 因为它与我之前的解决方案完全不同。
编辑:奇怪的是(至少在 iOS8 中)你必须在第一个字符下划线,否则它不起作用!
因此,作为一种解决方法,将第一个字符设置为清晰的颜色下划线!
// underline Terms and condidtions
NSMutableAttributedString* tncString = [[NSMutableAttributedString alloc] initWithString:@"View Terms and Conditions"];
// workaround for bug in UIButton - first char needs to be underlined for some reason!
[tncString addAttribute:NSUnderlineStyleAttributeName
value:@(NSUnderlineStyleSingle)
range:(NSRange){0,1}];
[tncString addAttribute:NSUnderlineColorAttributeName value:[UIColor clearColor] range:NSMakeRange(0, 1)];
[tncString addAttribute:NSUnderlineStyleAttributeName
value:@(NSUnderlineStyleSingle)
range:(NSRange){5,[tncString length] - 5}];
[tncBtn setAttributedTitle:tncString forState:UIControlStateNormal];
UIUnderlinedButton.h
@interface UIUnderlinedButton : UIButton {
}
+ (UIUnderlinedButton*) underlinedButton;
@end
UIUnderlinedButton.m
@implementation UIUnderlinedButton
+ (UIUnderlinedButton*) underlinedButton {
UIUnderlinedButton* button = [[UIUnderlinedButton alloc] init];
return [button autorelease];
}
- (void) drawRect:(CGRect)rect {
CGRect textRect = self.titleLabel.frame;
// need to put the line at top of descenders (negative value)
CGFloat descender = self.titleLabel.font.descender;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// set to same colour as text
CGContextSetStrokeColorWithColor(contextRef, self.titleLabel.textColor.CGColor);
CGContextMoveToPoint(contextRef, textRect.origin.x, textRect.origin.y + textRect.size.height + descender);
CGContextAddLineToPoint(contextRef, textRect.origin.x + textRect.size.width, textRect.origin.y + textRect.size.height + descender);
CGContextClosePath(contextRef);
CGContextDrawPath(contextRef, kCGPathStroke);
}
@end
drawRect
。这可以通过将按钮设置为重绘来解决,如下所示:myButton.contentMode = UIViewContentModeRedraw;
强制按钮在边界更改时重绘。
setTitle
方法:objective-c - (void)setTitle:(NSString *)title forState:(UIControlState)state { [super setTitle:title forState:state]; [self setNeedsDisplay]; }
您可以在界面构建器本身中执行此操作。
选择属性检查器将标题类型从普通更改为属性
https://i.stack.imgur.com/kM4YA.png
设置适当的字体大小和文本对齐方式
https://i.stack.imgur.com/aBcfS.png
然后选择标题文本并将字体设置为下划线
https://i.stack.imgur.com/j7kc7.png
属性字符串非常简单
创建具有设置属性的字典并应用于属性字符串。然后你可以将属性字符串设置为 uibutton 中的 attibutedtitle 或 uilabel 中的属性文本。
NSDictionary *attrDict = @{NSFontAttributeName : [UIFont
systemFontOfSize:14.0],NSForegroundColorAttributeName : [UIColor
whiteColor]};
NSMutableAttributedString *title =[[NSMutableAttributedString alloc] initWithString:@"mybutton" attributes: attrDict];
[title addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0,[commentString length])]; [btnRegLater setAttributedTitle:title forState:UIControlStateNormal];
commentString
是什么;你是从@NickH247 的答案中复制过来的吗?
这是我的函数,适用于 Swift 1.2。
func underlineButton(button : UIButton, text: String) {
var titleString : NSMutableAttributedString = NSMutableAttributedString(string: text)
titleString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: NSMakeRange(0, count(text.utf8)))
button.setAttributedTitle(titleString, forState: .Normal)
}
更新 Swift 3.0 扩展:
extension UIButton {
func underlineButton(text: String) {
let titleString = NSMutableAttributedString(string: text)
titleString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSMakeRange(0, text.characters.count))
self.setAttributedTitle(titleString, for: .normal)
}
}
截至 2019 年 9 月在 Xcode 10.3 中运行的 Swift 5.0 版本:
extension UIButton {
func underlineText() {
guard let title = title(for: .normal) else { return }
let titleString = NSMutableAttributedString(string: title)
titleString.addAttribute(
.underlineStyle,
value: NSUnderlineStyle.single.rawValue,
range: NSRange(location: 0, length: title.count)
)
setAttributedTitle(titleString, for: .normal)
}
}
要使用它,首先使用 button.setTitle("Button Title", for: .normal)
设置按钮标题,然后调用 button.underlineText()
使该标题带有下划线。
尼克的回答是一个很好的、快速的方法。
我在 drawRect
中添加了对阴影的支持。
如果您的按钮标题在文本下方有阴影,尼克的回答没有考虑到:
https://i.stack.imgur.com/e618S.png
但是您可以将下划线向下移动阴影的高度,如下所示:
CGFloat descender = self.titleLabel.font.descender;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
CGFloat shadowHeight = self.titleLabel.shadowOffset.height;
descender += shadowHeight;
然后你会得到这样的东西:
https://i.stack.imgur.com/8y3hS.png
对于 Swift 3,可以使用以下扩展:
extension UIButton {
func underlineButton(text: String) {
let titleString = NSMutableAttributedString(string: text)
titleString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.styleSingle.rawValue, range: NSMakeRange(0, text.characters.count))
self.setAttributedTitle(titleString, for: .normal)
}
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
CGRect textRect = self.titleLabel.frame;
// need to put the line at top of descenders (negative value)
CGFloat descender = self.titleLabel.font.descender;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
UIColor *colr;
// set to same colour as text
if (self.isHighlighted || self.isSelected) {
colr=self.titleLabel.highlightedTextColor;
}
else{
colr= self.titleLabel.textColor;
}
CGContextSetStrokeColorWithColor(contextRef, colr.CGColor);
CGContextMoveToPoint(contextRef, textRect.origin.x, textRect.origin.y + textRect.size.height + descender);
CGContextAddLineToPoint(contextRef, textRect.origin.x + textRect.size.width, textRect.origin.y + textRect.size.height + descender);
CGContextClosePath(contextRef);
CGContextDrawPath(contextRef, kCGPathStroke);
}
//Override this to change the underline color to highlighted color
-(void)setHighlighted:(BOOL)highlighted
{
[super setHighlighted:highlighted];
// [self setNeedsDisplay];
}
扩展@Nick H247 的答案,我遇到了一个问题,首先当按钮在旋转时调整大小时下划线没有重绘;这可以通过将按钮设置为重绘来解决,如下所示:
myButton.contentMode = UIViewContentModeRedraw;
当边界改变时,这会强制按钮重绘。
其次,原始代码假设您在按钮中只有 1 行文本(我的按钮在旋转时换行为 2 行),并且下划线仅出现在文本的最后一行。可以修改 drawRect 代码以首先计算按钮中的行数,然后在每一行而不是底部添加下划线,如下所示:
- (void) drawRect:(CGRect)rect {
CGRect textRect = self.titleLabel.frame;
// need to put the line at top of descenders (negative value)
CGFloat descender = self.titleLabel.font.descender;
CGContextRef contextRef = UIGraphicsGetCurrentContext();
// set to same colour as text
CGContextSetStrokeColorWithColor(contextRef, self.titleLabel.textColor.CGColor);
CGSize labelSize = [self.titleLabel.text sizeWithFont:self.titleLabel.font
constrainedToSize:self.titleLabel.frame.size
lineBreakMode:UILineBreakModeWordWrap];
CGSize labelSizeNoWrap = [self.titleLabel.text sizeWithFont:self.titleLabel.font forWidth:self.titleLabel.frame.size.width lineBreakMode:UILineBreakModeMiddleTruncation ];
int numberOfLines = abs(labelSize.height/labelSizeNoWrap.height);
for(int i = 1; i<=numberOfLines;i++) {
// Original code
// CGContextMoveToPoint(contextRef, textRect.origin.x, textRect.origin.y + textRect.size.height + descender + PADDING);
//
// CGContextAddLineToPoint(contextRef, textRect.origin.x + textRect.size.width, textRect.origin.y + textRect.size.height + descender);
CGContextMoveToPoint(contextRef, textRect.origin.x, textRect.origin.y + (labelSizeNoWrap.height*i) + descender + PADDING);
CGContextAddLineToPoint(contextRef, textRect.origin.x + textRect.size.width, textRect.origin.y + (labelSizeNoWrap.height*i) + descender);
CGContextClosePath(contextRef);
CGContextDrawPath(contextRef, kCGPathStroke);
}
}
希望这段代码对其他人有帮助!
迅速
func underlineButton(button : UIButton) {
var titleString : NSMutableAttributedString = NSMutableAttributedString(string: button.titleLabel!.text!)
titleString.addAttribute(NSUnderlineStyleAttributeName, value: NSUnderlineStyle.StyleSingle.rawValue, range: NSMakeRange(0, button.titleLabel!.text!.utf16Count))
button.setAttributedTitle(titleString, forState: .Normal)}
您可以使用此代码在按钮中添加带间距的下划线。
当我试图从界面生成器中绘制下划线时。它看起来像下图。
1 - 界面生成器参考
https://i.stack.imgur.com/NLaxr.png
在使用下面的代码后,我得到了我想要的结果。
2 - 使用描述的代码
https://i.stack.imgur.com/wN333.png
public func setTextUnderline()
{
let dummyButton: UIButton = UIButton.init()
dummyButton.setTitle(self.titleLabel?.text, for: .normal)
dummyButton.titleLabel?.font = self.titleLabel?.font
dummyButton.sizeToFit()
let dummyHeight = dummyButton.frame.size.height + 3
let bottomLine = CALayer()
bottomLine.frame = CGRect.init(x: (self.frame.size.width - dummyButton.frame.size.width)/2, y: -(self.frame.size.height - dummyHeight), width: dummyButton.frame.size.width, height: 1.0)
bottomLine.backgroundColor = self.titleLabel?.textColor.cgColor
self.layer.addSublayer(bottomLine)
}
当我们按住一个带下划线的按钮时,将如何处理这种情况?在这种情况下,按钮的文本颜色会根据突出显示的颜色而变化,但线条保持原始颜色。假设如果正常状态下的按钮文本颜色为黑色,则其下划线也将具有黑色。该按钮的突出显示颜色为白色。按住按钮将按钮文本颜色从黑色更改为白色,但下划线颜色保持黑色。
我相信这是 XCode 字体编辑器中的一些错误。如果您使用界面生成器,则必须将标题从普通更改为属性,打开 TextEdit 创建带下划线的文本并复制粘贴到 XCode 中的文本框
尼克 H247 的回答,但 Swift 方法:
import UIKit
class UnderlineUIButton: UIButton {
override func drawRect(rect: CGRect) {
super.drawRect(rect)
let textRect = self.titleLabel!.frame
var descender = self.titleLabel?.font.descender
var contextRef: CGContextRef = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(contextRef, self.titleLabel?.textColor.CGColor);
CGContextMoveToPoint(contextRef, textRect.origin.x, textRect.origin.y + textRect.size.height + descender!);
CGContextAddLineToPoint(contextRef, textRect.origin.x + textRect.size.width, textRect.origin.y + textRect.size.height + descender!);
CGContextClosePath(contextRef);
CGContextDrawPath(contextRef, kCGPathStroke);
}
}
func underline(text: String, state: UIControlState = .normal, color:UIColor? = nil) {
var titleString = NSMutableAttributedString(string: text)
if let color = color {
titleString = NSMutableAttributedString(string: text,
attributes: [NSForegroundColorAttributeName: color])
}
let stringRange = NSMakeRange(0, text.characters.count)
titleString.addAttribute(NSUnderlineStyleAttributeName,
value: NSUnderlineStyle.styleSingle.rawValue,
range: stringRange)
self.setAttributedTitle(titleString, for: state)
}
@NickH247's 答案的 Swift 3 版本,带有自定义下划线颜色、线宽和间隙:
import Foundation
class UnderlinedButton: UIButton {
private let underlineColor: UIColor
private let thickness: CGFloat
private let gap: CGFloat
init(underlineColor: UIColor, thickness: CGFloat, gap: CGFloat, frame: CGRect? = nil) {
self.underlineColor = underlineColor
self.thickness = thickness
self.gap = gap
super.init(frame: frame ?? .zero)
}
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let textRect = titleLabel?.frame,
let decender = titleLabel?.font.descender,
let context = UIGraphicsGetCurrentContext() else { return }
context.setStrokeColor(underlineColor.cgColor)
context.move(to: CGPoint(x: textRect.origin.x, y: textRect.origin.y + textRect.height + decender + gap))
context.setLineWidth(thickness)
context.addLine(to: CGPoint(x: textRect.origin.x + textRect.width, y: textRect.origin.y + textRect.height + decender + gap))
context.closePath()
context.drawPath(using: .stroke)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
setTitle
与属性文本一起使用。对我来说,创建自定义按钮来绘制下划线有点异国情调(即使完成了一个应用程序,我可能还是 iOS 新手)。