누구나 UIButton의 제목에 밑줄을 긋는 방법을 제안 할 수 있습니까? 사용자 정의 유형의 UIButton이 있고 제목에 밑줄을 표시하고 싶지만 인터페이스 빌더는 옵션을 제공하지 않습니다.
버튼의 글꼴 옵션을 선택할 때 인터페이스 빌더에서 없음, 단일, 이중, 색상을 선택하는 옵션을 제공하지만 버튼의 제목에 대한 변경 사항은 없습니다.
도움을 주셔서 감사합니다.
누구나 UIButton의 제목에 밑줄을 긋는 방법을 제안 할 수 있습니까? 사용자 정의 유형의 UIButton이 있고 제목에 밑줄을 표시하고 싶지만 인터페이스 빌더는 옵션을 제공하지 않습니다.
버튼의 글꼴 옵션을 선택할 때 인터페이스 빌더에서 없음, 단일, 이중, 색상을 선택하는 옵션을 제공하지만 버튼의 제목에 대한 변경 사항은 없습니다.
도움을 주셔서 감사합니다.
답변:
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://www.youtube.com/watch?v=5-ZnV3jQd9I
setTitle
텍스트 로 사용할 수 있다는 것을 의미 합니다. 저에게 밑줄을 그리는 커스텀 버튼을 만드는 것은 다소 이국적입니다 (하나의 앱이 완성 되어도 iOS에 익숙하지 않을 수도 있습니다).
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];
기여 문자열로 매우 간단합니다.
설정된 속성으로 사전을 작성하고 속성이 지정된 문자열에 적용하십시오. 그런 다음 uibutton에서 타당한 문자열을 uilabel의 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)
}
}
Nick의 대답은이 작업을 수행하는 훌륭하고 빠른 방법입니다.
drawRect
그림자 에 대한 지원을 추가했습니다 .
버튼 제목에 텍스트 아래에 그림자가 있으면 Nick의 답변이 고려되지 않습니다.
그러나 그림자의 높이만큼 밑줄을 아래로 이동할 수 있습니다.
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;
경계가 변경되면 버튼이 다시 그려집니다.
둘째, 원래 코드는 버튼에 한 줄의 텍스트 만 있고 (내 버튼은 회전 할 때 두 줄로 줄 바꿈) 밑줄은 텍스트의 마지막 줄에만 나타납니다. 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-인터페이스 빌더 참조
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)
}
Xcode 10.3에서 2019 년 9 월 현재 작동하는 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()
를 걸어 해당 제목에 밑줄을 표시하십시오.
밑줄이 그어진 버튼을 계속 누르고 있으면 어떻게 처리 할 수 있습니까? 이 경우 버튼의 텍스트 색상은 강조 표시된 색상에 따라 변경되지만 선은 원래 색상으로 유지됩니다. 정상 상태의 버튼 텍스트 색상이 검은 색이면 밑줄에도 검은 색이 표시됩니다. 버튼의 강조된 색상은 흰색입니다. 버튼을 계속 누르고 있으면 버튼 텍스트 색상이 검은 색에서 흰색으로 변경되지만 밑줄 색상은 검은 색으로 유지됩니다.
Nick 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의 답변에 대한 스위프트 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")
}
}