UIButton में अंडरलाइनिंग टेक्स्ट


143

क्या कोई सुझाव दे सकता है कि UIButton के शीर्षक को कैसे रेखांकित किया जाए? मेरे पास कस्टम प्रकार का एक UIButton है, और मैं चाहता हूं कि शीर्षक को रेखांकित किया जाए, लेकिन इंटरफ़ेस बिल्डर ऐसा करने का कोई विकल्प प्रदान नहीं करता है।

इंटरफ़ेस बिल्डर में जब आप एक बटन के लिए फ़ॉन्ट विकल्प का चयन करते हैं, तो यह कोई नहीं, एकल, डबल, रंग का चयन करने का विकल्प प्रदान करता है, लेकिन इनमें से कोई भी बटन पर शीर्षक में कोई बदलाव नहीं प्रदान करता है।

किसी भी मदद की सराहना की।


1
आप UITextView को इस प्रश्न के लिंक के रूप में
यूटैक्सट्यूड के

जवाबों:


79

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

1
शायद उतने समय पर नहीं जितना आपको जरूरत थी!
निक एच 247

4
धन्यवाद, मैंने इसे इस प्रकार से कॉल किया: यूआईबूटन * बीटीएन = [यूआईउंडरइल्डबटन बटनवाइप टाइप: यूआईबूटनटाइप टाइप कस्टम];
hb922

2
कोड अच्छी तरह से काम करता है, लेकिन मैंने देखा कि जब रोटेशन पर आकार नहीं बदला drawRectजाता है , तो अंडरलाइन सिकुड़ता / बढ़ता नहीं था, जो रोटेशन पर नहीं बुलाए जाने के कारण होता है । यह आपके बटन को फिर से redraw की तरह सेट करके हल किया जा सकता है: myButton.contentMode = UIViewContentModeRedraw;जो बटन को सीमा बदलने के लिए फिर से शुरू करने के लिए मजबूर करता है।
15

4
आप इस setTitleतरह से विधि को भी ओवरराइड कर सकते हैं :objective-c - (void)setTitle:(NSString *)title forState:(UIControlState)state { [super setTitle:title forState:state]; [self setNeedsDisplay]; }
Kirualex

379

इंटरफ़ेस बिल्डर को रेखांकित करने के लिए, एक को निम्न करना होगा:

  • इसे जिम्मेदार ठहराया है
  • गुण निरीक्षक में पाठ को हाइलाइट करें
  • राइट क्लिक करें, फ़ॉन्ट चुनें और फिर रेखांकित करें

IB का उपयोग करके रेखांकित करें

वीडियो किसी और ने बनाया https://www.youtube.com/watch?v=5-ZnV3jQd9I


2
अच्छा सवाल @ new2ios शायद कोई और जानता हो
finneycanhelp

1
मैं नया सवाल पूछूंगा, @finneycanhelp। मुझे उम्मीद है कि Xcode 6.3 में अधिक आसान तरीका होगा। मेरा मतलब है कि मैं हो सकता है कि मैं आपके समाधान को सेट कर सकूं और फिर setTitleजिम्मेदार पाठ के साथ उपयोग कर सकूं। मेरे लिए अंडरलाइन ड्रॉ करने के लिए कस्टम बटन बनाना थोड़ा विदेशी है (हो सकता है कि मैं अभी भी iOS के लिए नया हूं, यहां तक ​​कि एक ऐप भी पूरा कर चुका हूं)।
new2ios

2
finneydonehelped! इसके लिए धन्यवाद! फोंट पॉपअप संवाद पर कोई प्रभाव नहीं पड़ा, यह पता नहीं लगा सका। राइट-क्लिक सही है।
IMFletcher

2
इस तरह की सरल चीजों के लिए इंटरफ़ेस बिल्डर उपयोगकर्ताओं के लिए अच्छा जवाब जो कोड में काम करते समय बहुत कम हैं। धन्यवाद! (Y)
रंडिका विशमन

1
IOS डेवलपर्स सिर्फ एक बहुत ही साधारण मुद्दे के लिए एक बहुत लंबा कोड लिखना क्यों पसंद करते हैं?
mr5

129

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];

9
बस इस बात का ध्यान रखें कि जब आप इसे इस तरह से करते हैं, तो आपको रंग के लिए विशेषता भी जोड़ना चाहिए, क्योंकि शीर्षक शीर्षक पाठ आपके द्वारा सेट किए गए रंग का उपयोग नहीं करेगा जैसे कि setTitleColor: forState:
daveMac

2
रंग पर सिर के लिए बहुत बढ़िया और धन्यवाद @daveMac। उन लोगों के लिए जो इसकी विशेषता को नहीं जानते हैं: NSForegroundColorAttributeName
रयान क्रू

इस तरीके में बटन अंडरलाइन टेक्स्ट की किसी भी विधि के करीब है ताकि अंडरलाइन की y स्थिति बदल सके?
इलेश पी

49

आप इसे इंटरफ़ेस बिल्डर में ही कर सकते हैं।

  1. विशेषता निरीक्षक का चयन करें
  2. शीर्षक प्रकार को सादे से एट्रिब्यूट में बदलें

यहाँ छवि विवरण दर्ज करें

  1. उपयुक्त फ़ॉन्ट आकार और पाठ संरेखण सेट करें

यहाँ छवि विवरण दर्ज करें

  1. फिर शीर्षक पाठ का चयन करें और फ़ॉन्ट को रेखांकित करें

यहाँ छवि विवरण दर्ज करें


28

यह जिम्मेदार स्ट्रिंग के साथ बहुत सरल है

सेट विशेषताओं के साथ एक शब्दकोश बनाता है और जिम्मेदार स्ट्रिंग पर लागू होता है। फिर आप यूआईबटन में एट्रीब्यूटेडिटल के रूप में या स्ट्रिंग को यूलेबेल में एट्रिब्यूटेडटेक्ट के रूप में जिम्मेदार स्ट्रिंग सेट कर सकते हैं।

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 के उत्तर से कॉपी किया है?
मायने-मायने

21

यहां मेरा कार्य है, स्विफ्ट 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)
}

अद्यतन स्विफ्ट 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)
    }
}

13

निक का जवाब ऐसा करने का एक शानदार, त्वरित तरीका है।

मैंने drawRectछाया के लिए समर्थन जोड़ा ।

यदि आपके बटन का शीर्षक पाठ के नीचे छाया है, तो निक के उत्तर पर ध्यान नहीं दिया जाता है:

यहाँ छवि विवरण दर्ज करें

लेकिन आप इस तरह से छाया की ऊंचाई से नीचे जा सकते हैं:

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

फिर आपको कुछ इस तरह मिलेगा:

यहाँ छवि विवरण दर्ज करें


self.titleLabel.font.descender; इसे iOS 3.0
KING

5

स्विफ्ट 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)
    }
}

4
// 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];
}

3

@Nick H247 द्वारा उत्तर पर विस्तार करते हुए, मैंने एक ऐसे मुद्दे का अनुभव किया, जहां रोटेशन पर बटन के आकार बदलने पर सबसे पहले रेखांकित किया गया था; यह आपके बटन को फिर से सेट करने के लिए हल किया जा सकता है जैसे:

myButton.contentMode = UIViewContentModeRedraw; 

यह बटन को बदलने के लिए मजबूर करता है जब सीमा बदल जाती है।

दूसरे, मूल कोड ने माना कि आपके पास बटन में केवल 1 पंक्ति का पाठ था (मेरा बटन रोटेशन पर 2 रेखाओं तक लपेटता है) और रेखांकित केवल पाठ की अंतिम पंक्ति पर दिखाई देता है। ड्राअर कोड को पहले बटन में लाइनों की संख्या की गणना करने के लिए संशोधित किया जा सकता है, फिर नीचे की बजाय हर लाइन पर एक रेखांकन डालते हैं, जैसे:

 - (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);

}


}

उम्मीद है कि यह कोड किसी और की मदद करे!


3

स्विफ्ट में

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

3

आप इस कोड का उपयोग बटन में रिक्ति के साथ अंडरलाइन जोड़ने के लिए कर सकते हैं।

  • जब मैंने इंटरफ़ेस बिल्डर से एक अंडरलाइन खींचने की कोशिश की। यह नीचे की छवि की तरह दिखता है।

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

इस कोड स्निपेट के लिए धन्यवाद, जो कुछ सीमित, तत्काल सहायता प्रदान कर सकता है। एक उचित व्याख्या यह दर्शाती है कि यह समस्या का एक अच्छा समाधान क्यों है, यह दिखाते हुए इसके दीर्घकालिक मूल्य में बहुत सुधार करेगा , और यह भविष्य के पाठकों को अन्य, समान प्रश्नों के साथ और अधिक उपयोगी बना देगा। कृपया कुछ स्पष्टीकरण जोड़ने के लिए अपने उत्तर को संपादित करें, जिसमें आपके द्वारा की गई धारणाएँ शामिल हैं।
टोबे स्पाइट

3

Xcode 10.3 में सितंबर 2019 तक काम करने वाली स्विफ्ट 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()उस शीर्षक को रेखांकित करने के लिए कॉल करें ।


1
मैं iOS 10.3.1 के पुराने संस्करणों पर इस काम की पुष्टि कर सकता हूं, Xcode 10.3 Mojave पर पुराने से अधिक सिमुलेटरों का समर्थन नहीं करता है, जहां तक ​​मैं जागरूक हूं।
मैक्स डेसिआटोव

2

जब हम एक बटन दबाए रखेंगे, तो मामला कैसे संभालेगा? उस स्थिति में बटन का टेक्स्ट कलर हाइलाइटेड कलर के अनुसार बदल जाता है लेकिन ओरिजिनल कलर का ही लाइन रहता है। बता दें कि अगर सामान्य अवस्था में बटन टेक्स्ट का रंग काला है तो इसके अंडरलाइन में भी काला रंग होगा। बटन का हाइलाइट किया गया रंग सफेद है। बटन दबाए जाने से बटन टेक्स्ट का रंग काले से सफेद हो जाता है, लेकिन अंडरलाइन रंग काला रहता है।


2
यदि बटन हाइलाइट और चयनित है, तो आप परीक्षण कर सकते हैं और तदनुसार रंग सेट कर सकते हैं। यकीन नहीं होता है कि अगर redraw को स्वचालित रूप से अनुरोध किया जाएगा, यदि आपको सेट ओवरलेक्टेड / setHighlighted को ओवरराइड करने की आवश्यकता नहीं है और सुपर और [self setNeedsDisplay] को कॉल करें
Nick H247

2

मेरा मानना ​​है कि यह XCode में फ़ॉन्ट संपादक में कुछ बग है। यदि आप इंटरफ़ेस बिल्डर का उपयोग कर रहे हैं, तो आपको प्लेन से एटिट्यूड में शीर्षक बदलना होगा, TextEdit को अंडरकोड टेक्स्ट और कॉपी-पेस्ट को XCode में टेक्स्टबॉक्स में बनाएं।


2

निक H247 का जवाब लेकिन स्विफ्ट दृष्टिकोण:

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

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

1

कस्टम अंडरलाइन रंग, लिनिविड और गैप के साथ @ 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")
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.