Подчеркивание текста в UIButton

Может ли кто-нибудь предложить, как подчеркнуть название UIButton? У меня есть UIButton типа Custom, и я хочу, чтобы заголовок был выделен, но Interface Builder не предоставляет никакой возможности для этого.

В интерфейсе Builder, когда вы выбираете параметр шрифта для кнопки, он предоставляет возможность выбора «Нет», «Одинарный», «Двойной», «Цвет», но ни один из них не вносит никаких изменений в заголовок на кнопке.

Любая помощь оценивается.

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 

Чтобы использовать конструктор интерфейса для подчеркивания, необходимо:

  • Измените его на атрибут
  • Выделите текст в инспекторе атрибутов
  • Щелкните правой кнопкой мыши, выберите «Шрифт», а затем «Подчеркните»

Подчеркивание с использованием IB

Видео другого человека сделало 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]; 

Это очень просто с атрибутной строкой

Создает словарь с установленными атрибутами и применяется к атрибутной строке. Затем вы можете установить атрибутную строку как attibutedtitle в uibutton или attribitedtext в 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]; 

Вы можете сделать это в самом интерфейсе.

  1. Выберите инспектор атрибутов
  2. Измените тип заголовка с простого на атрибут

введите описание изображения здесь

  1. Установите соответствующий размер шрифта и выравнивание текста

введите описание изображения здесь

  1. Затем выберите текст заголовка и установите шрифт как подчеркнутый

введите описание изображения здесь

Вот моя функция, работает в 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) } 

UPDATE Расширение 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) } } 

Ответ Ника – отличный и быстрый способ сделать это.

Я добавил поддержку в drawRect для теней.

Ответ Ника не учитывает, имеет ли название вашей кнопки тень под текстом:

введите описание изображения здесь

Но вы можете перемещать подчеркивание вниз по высоте тени следующим образом:

 CGFloat descender = self.titleLabel.font.descender; CGContextRef contextRef = UIGraphicsGetCurrentContext(); CGFloat shadowHeight = self.titleLabel.shadowOffset.height; descender += shadowHeight; 

Тогда вы получите что-то вроде этого:

введите описание изображения здесь

Для 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; 

Это заставляет кнопку перерисовывать, когда границы меняются.

Во-вторых, исходный код предполагал, что у вас есть только одна строка текста (моя кнопка обертывается до 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); } } 

Надеюсь, этот код поможет кому-то еще!

Как будет обрабатываться случай, когда мы удерживаем нажатой кнопку? В этом случае цвет текста кнопки изменяется в соответствии с выделенным цветом, но остается строка исходного цвета. Скажем, если цвет текста кнопки в нормальном состоянии черный, то его подчеркивание также будет иметь черный цвет. Цвет подсветки кнопки белый. Нажатие кнопки нажатие меняет цвет текста кнопки с черного на белый, но цвет подчеркивания остается черным.

Я считаю, что это ошибка в редакторе шрифтов в XCode. Если вы используете построитель интерфейсов, вам нужно изменить заголовок из Plain в Attributed, откройте TextEdit, создайте подчеркнутый текст и скопируйте-вставьте в текстовое поле в XCode

В быстрых

 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)} 

Ответ Ника 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); } } 

Вы можете использовать этот код для добавления подчеркивания с интервалом в кнопке.

  • Когда я попытался сделать подчеркивание из конструктора интерфейса. Это похоже на изображение ниже.

1 – Ссылка на построитель интерфейса

  • И после использования ниже кода я достиг результата, которого я хотел.

2 – с использованием описанного кода

 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) } 

Swift 3 для ответа @ NickH247 с пользовательским цветом подчеркивания, шириной линии и разрывом:

 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") } } 
 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) } 
  • Форматирование JSON в C #?
  • Значение двойного значения в формате Java в виде суммы в долларах
  • Ограничьте два-два десятичных знака
  • что такое идентификаторы формата scanf ("% * s") и scanf ("% * d")?
  • Как я могу String.Format объект TimeSpan с пользовательским форматом в .NET?
  • Что означает {0}, когда он найден в строке в C #?
  • строковый формат для intptr_t и uintptr_t
  • формат даты в c #
  • Как отобразить вывод данных float с 2 десятичными знаками в Java?
  • Удаление повторяющихся элементов с помощью XSLT
  • VBA: преобразовать текст в число
  • Давайте будем гением компьютера.