ios - UILabel के भीतर टेक्स्ट को लंबवत रूप से संरेखित करें




cocoa-touch uikit (20)

  1. नया टेक्स्ट सेट करें:

    myLabel.text = @"Some Text"
  2. लाइनों की maximum number 0 (स्वचालित) पर सेट करें:

    myLabel.numberOfLines = 0
  3. लेबल के फ्रेम को अधिकतम आकार में सेट करें:

    myLabel.frame = CGRectMake(20,20,200,800)
  4. कॉल आकार को फ्रेम आकार को कम करने के लिए sizeToFit करें ताकि सामग्री बस फिट हो:

    [myLabel sizeToFit]

लेबल फ्रेम अब आपके पाठ को फिट करने के लिए पर्याप्त उच्च और चौड़ा है। ऊपरी बाएं अपरिवर्तित होना चाहिए। मैंने इसे केवल शीर्ष बाएं संरेखित पाठ के साथ परीक्षण किया है। अन्य संरेखणों के लिए, आपको फ्रेम को बाद में संशोधित करना पड़ सकता है।

इसके अलावा, मेरे लेबल में शब्द रैपिंग सक्षम है।

मेरे पास टेक्स्ट की दो पंक्तियों के लिए एक UILabel । कभी-कभी, जब पाठ बहुत छोटा होता है, तो यह पाठ लेबल के ऊर्ध्वाधर केंद्र में प्रदर्शित होता है।

मैं UILabel के शीर्ष पर हमेशा टेक्स्ट को लंबवत कैसे संरेखित करूं?


Subclass UILabel और ड्राइंग आयत को बाधित करें, इस तरह:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];
}

मैंने न्यूलाइन पैडिंग से जुड़े समाधान की कोशिश की और कुछ मामलों में गलत व्यवहार में भाग गया। मेरे अनुभव में, numberOfLines साथ गड़बड़ के ऊपर ड्रॉइंग रेक्ट को बाधित करना आसान है।

पीएस आप आसानी से UIViewContentMode का समर्थन करने की कल्पना कर सकते हैं:

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];

    if (self.contentMode == UIViewContentModeTop) {
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }
    else if (self.contentMode == UIViewContentModeBottom) {
        rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }

    [super drawTextInRect:rect];
}

अगर किसी के लिए यह किसी भी मदद की बात है, तो मुझे एक ही समस्या थी, लेकिन UITextView का उपयोग करने के लिए UILabel का उपयोग करने से स्विच करके बस समस्या को हल करने में सक्षम था। मैं सराहना करता हूं कि यह सभी के लिए नहीं है क्योंकि कार्यक्षमता थोड़ा अलग है।

यदि आप UITextView का उपयोग करने के लिए स्विच करते हैं, तो आप सभी स्क्रॉल व्यू गुणों के साथ-साथ उपयोगकर्ता इंटरैक्शन सक्षम भी बंद कर सकते हैं ... इससे इसे लेबल की तरह कार्य करने के लिए मजबूर किया जाएगा।


अनुकूली यूआई (आईओएस 8 या उसके बाद) के लिए, यूआईएलएबल का वर्टिकल संरेखण स्टोरीबार्ड से गुणों को noOfLines = 0` बदलना है और

प्रतिबन्ध

  1. UILabel LefMargin, राइटमार्गिन और शीर्ष मार्जिन बाधाओं को समायोजित करना।

  2. Content Compression Resistance Priority For Vertical = 1000` के Content Compression Resistance Priority For Vertical बदलें ताकि वर्टिकल> क्षैतिज।

संपादित:

noOfLines=0

और वांछित परिणाम प्राप्त करने के लिए निम्नलिखित बाधाएं पर्याप्त हैं।


इसे पूरा करने के लिए एक तेज़ (और गंदे) तरीका है UILabel के लाइन ब्रेक मोड को "क्लिप" पर सेट करके और एक निश्चित मात्रा में न्यूलाइन जोड़ना।

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

यह समाधान सभी के लिए काम नहीं करेगा - विशेष रूप से, यदि आप अभी भी अपनी स्ट्रिंग के अंत में "..." दिखाना चाहते हैं, तो यह आपके द्वारा दिखाए जा रहे लाइनों की संख्या से अधिक है, तो आपको एक का उपयोग करना होगा कोड के लंबे बिट्स - लेकिन कई मामलों के लिए यह आपको प्राप्त करेगा जो आपको चाहिए।


ऊपर दिए गए उत्तर की तरह, लेकिन यह बिल्कुल सही नहीं था, या कोड में थप्पड़ मारना आसान था इसलिए मैंने इसे थोड़ा सा साफ़ कर दिया। इस एक्सटेंशन को या तो अपने .h और .m फ़ाइल में जोड़ें या केवल उस क्रियान्वयन के ऊपर पेस्ट करें जिसका आप इसका उपयोग करना चाहते हैं:

#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end


@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i<= newLinesToPad; i++)
    {
        self.text = [self.text stringByAppendingString:@" \n"];
    }
}

- (void)alignBottom
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i< newLinesToPad; i++)
    {
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
    }
}
@end

और फिर उपयोग करने के लिए, अपना टेक्स्ट लेबल में रखें, और उसके बाद इसे संरेखित करने के लिए उचित विधि को कॉल करें:

[myLabel alignTop];

या

[myLabel alignBottom];

किसी को भी इसे पढ़ने के लिए क्योंकि आपके लेबल के अंदर का पाठ लंबवत केंद्रित नहीं है, ध्यान रखें कि कुछ फ़ॉन्ट प्रकार समान रूप से डिज़ाइन नहीं किए गए हैं। उदाहरण के लिए, यदि आप ज़ैपफिनो आकार 16 के साथ एक लेबल बनाते हैं, तो आप देखेंगे कि पाठ लंबवत रूप से केंद्रित नहीं है।

हालांकि, हेल्वैटिका के साथ काम करने से लंबवत आपके पाठ को केंद्रित किया जाएगा।


कोई उपद्रव कोई अव्यवस्था नहीं

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

कोई मुसब्बर नहीं, कोई उद्देश्य-सी नहीं, कोई झगड़ा नहीं, लेकिन स्विफ्ट 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

मुझे पता चला है कि इस प्रश्न पर उत्तर अब थोड़ी देर के हैं, इसलिए ऑटो लेआउट प्रशंसकों के लिए इसे जोड़ना।

ऑटो लेआउट इस मुद्दे को बहुत छोटा बनाता है। मान लें कि हम UIView *view में लेबल जोड़ रहे हैं, निम्न कोड यह पूरा करेगा:

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];

लेबल की ऊंचाई स्वचालित रूप से गणना की जाएगी (इसके intrinsicContentSize का उपयोग करके) और लेबल view के शीर्ष पर क्षैतिज रूप से किनारे पर स्थित होगा।


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

- (void) customInit {
    // Setup label
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.label.numberOfLines = 0;
    self.label.lineBreakMode = UILineBreakModeWordWrap;
    self.label.textAlignment = UITextAlignmentCenter;

    // Add the label as a subview
    self.autoresizesSubviews = YES;
    [self addSubview:self.label];
}

और फिर जब मैं अपने लेबल का पाठ बदलना चाहता था ...

- (void) updateDisplay:(NSString *)text {
    if (![text isEqualToString:self.label.text]) {
        // Calculate the font size to use (save to label's font)
        CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
        self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
        CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
            self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
            textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        }
        // In cases where the frame is still too large (when we're exceeding minimum font size),
        // use the views size
        if (textSize.height > self.frame.size.height) {
            textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
        }

        // Draw 
        self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
        self.label.text = text;
    }
    [self setNeedsDisplay];
}

उम्मीद है कि किसी की मदद करता है!


मैंने उपरोक्त कई विधियों का उपयोग किया है, और बस मैंने उपयोग किए गए त्वरित और गंदे दृष्टिकोण को जोड़ना चाहते हैं:

myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];

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

क्योंकि कभी-कभी पर्याप्त अच्छा पर्याप्त होता है


मैंने यहां सुझाव दिए और एक दृश्य बनाया जो यूआईएलएबल को लपेट सकता है और इसे आकार देगा और लाइनों की संख्या निर्धारित करेगा ताकि यह शीर्ष गठबंधन हो। बस एक उपनाम के रूप में एक UILabel डाल दिया:

@interface TopAlignedLabelContainer : UIView
{
}

@end

@implementation TopAlignedLabelContainer

- (void)layoutSubviews
{
    CGRect bounds = self.bounds;

    for (UILabel *label in [self subviews])
    {
        if ([label isKindOfClass:[UILabel class]])
        {
            CGSize fontSize = [label.text sizeWithFont:label.font];

            CGSize textSize = [label.text sizeWithFont:label.font
                                     constrainedToSize:bounds.size
                                         lineBreakMode:label.lineBreakMode];

            label.numberOfLines = textSize.height / fontSize.height;

            label.frame = CGRectMake(0, 0, textSize.width,
                 fontSize.height * label.numberOfLines);
        }
    }
}

@end

विस्तार समाधान का जिक्र करना:

for(int i=1; i< newLinesToPad; i++) 
    self.text = [self.text stringByAppendingString:@"\n"];

द्वारा प्रतिस्थापित किया जाना चाहिए

for(int i=0; i<newLinesToPad; i++)
    self.text = [self.text stringByAppendingString:@"\n "];

प्रत्येक अतिरिक्त नई लाइन में अतिरिक्त स्थान की आवश्यकता है, क्योंकि आईफोन UILabels के पीछे की गाड़ी रिटर्न को अनदेखा किया जा रहा है :(

इसी तरह, alignBottom को @" \[email protected]%" के स्थान पर @" \[email protected]%" साथ भी अपडेट किया जाना चाहिए (चक्र प्रारंभ करने के लिए "int (int i = 0 ..." के लिए भी बदला जाना चाहिए)।

निम्नलिखित एक्सटेंशन मेरे लिए काम करता है:

// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [self.text stringByAppendingString:@"\n "];
}

- (void)alignBottom {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
@end

फिर [yourLabel alignTop]; कॉल करें [yourLabel alignTop]; या [yourLabel alignBottom]; प्रत्येक आपके लेबल लेबल असाइनमेंट के बाद।


FXLabel (github पर) label.contentMode . label.contentMode को UIViewContentModeTop सेट करके बॉक्स से बाहर करता है। यह घटक मेरे द्वारा नहीं बनाया गया है, लेकिन यह एक घटक है जिसका मैं अक्सर उपयोग करता हूं और इसमें कई सुविधाएं हैं, और अच्छी तरह से काम करने लगती हैं।


UILabel बजाय आप UITextField उपयोग कर सकते हैं जिसमें लंबवत संरेखण विकल्प है:

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

स्टोरीबोर्ड समाधान: StackView में Label को एम्बेड StackView और स्टैकव्यू के Axis को Horizontal , स्टोरीबोर्ड से Attribute Inspector में Top Alignment करना सबसे सरल और आसान तरीका है।


मुझे पता है कि यह एक पुरानी पोस्ट है लेकिन पाठ को लंबवत रूप से संरेखित करना एक बड़ी समस्या है (कम से कम मेरे लिए यह है) और मुझे लगा कि मुझे इस समाधान को साझा करना चाहिए क्योंकि मुझे खुद को नहीं मिला।

DrawRect का उपयोग करना मेरी राय में थोड़ा महंगा है। UILabel को लंबवत रूप से संरेखित करने का उचित तरीका UILabel का उपयोग नहीं करना है। UITextView (multiline UITextField) का उपयोग करें और इस तरह की सामग्री प्रॉपर्टी का निरीक्षण करें:

- (UITextView*)textView{
     if(!_textView){
        UIEdgeInsets insets = UIEdgeInsetsMake(0, 50, 0, 5);
        CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
        _textView = [[UITextView alloc]initWithFrame:UIEdgeInsetsInsetRect(frame, insets)];
        _textView.delegate = self;
        _textView.scrollEnabled = YES;
        _textView.bounces = YES;
        _textView.backgroundColor = [UIColor whiteColor];
        [_textView setUserInteractionEnabled:NO];
        [_textView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
    }
    return _textView;
}

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary *)change context:(void *)context {
UITextView *tv = object;

CGFloat height = [tv bounds].size.height;
CGFloat contentheight;

#ifdef __IPHONE_7_0
    contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;
#else
    contentheight = [tv contentSize].height;
#endif

    switch(self.verticalAlignment) {
        case VerticalAlignmentBottom:{
            CGFloat topCorrect = ([tv bounds].size.height - contentheight);
            topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
        break;
        case VerticalAlignmentMiddle:{
            CGFloat topCorrect = (height - contentheight * [tv zoomScale])/2.0;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
            break;
        case VerticalAlignmentTop:{
            tv.contentOffset = (CGPoint){.x = 0, .y = 0 };
        }
            break;
        default:
            break;
    }
}

असल में यहां क्या हो रहा है, हम उस कक्षा को सेट करते हैं जो हम पर्यवेक्षक के रूप में हैं, सामग्री को देखकर NSKeyValueObservingOptionNew के विकल्प के साथ आकार बदलें, इसलिए जब भी सामग्री बदलती है, -(void)observeValueForKeyPath:ofObject:change:context:तो कॉल किया जाएगा और फिर आप उचित रूप से टेक्स्ट को संरेखित करने के लिए ऑफसेट आकार की गणना कर सकते हैं ।

मैं इसके लिए क्रेडिट नहीं ले सकता, मूल विचार here से आया था । लेकिन, यह समाधान आईओएस 7 पर काम नहीं करता है। कुछ घंटों के लिए एसओ के आसपास घूमने के बाद, मुझे यह पता चला: आईओएस 7 लंबवत संरेखण फिक्स । कुंजी लाइन हैcontentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height; ।आईओएस 7 में किसी कारण से, सामग्री प्राप्त करना आकार की ऊंचाई काम नहीं करती है लेकिन यह इसे ठीक करती है। दो समाधानों में से कोई भी अपने आप पर काम नहीं करता था, लेकिन थोड़ी सी झुकाव के बाद, मैं उपरोक्त समाधान को एक साथ संश्लेषित करने में सक्षम था।


यदि अपना खुद का कस्टम व्यू बनाना एक विकल्प है, तो आप ऐसा कुछ कर सकते हैं:

- (void)drawRect:(CGRect)rect
{
    CGRect bounds = self.bounds;
    [self.textColor set];
    [self.text drawInRect:bounds
                 withFont:self.font
            lineBreakMode:UILineBreakModeTailTruncation
                alignment:self.textAlignment];
}

UILabel लंबवत पाठ संरेखण में संभव नहीं है। लेकिन, आप sizeWithFont:विधि का उपयोग कर लेबल की ऊंचाई को गतिशील रूप से बदल सकते हैं NSString, और बस अपनी एक्स और वाई को अपनी इच्छानुसार सेट कर सकते हैं।

आप उपयोग कर सकते हैं UITextField। यह सामग्री वर्टिकल एलाइनमेंट peoperty का समर्थन करता है क्योंकि यह एक उप-वर्ग है UIControluserInteractionEnabledउपयोगकर्ता को टेक्स्ट टाइप करने से रोकने के लिए आपको इसे NO पर सेट करना होगा।


जब तक आप किसी भी जटिल कार्य कर रही है नहीं कर रहे हैं, तब तक आप उपयोग कर सकते हैं UITextViewके बजाय UILabels

स्क्रॉल अक्षम करें।

यदि आप टेक्स्ट को पूरी तरह से उपयोगकर्ता sizeToFitऔर sizeThatFits:विधियों को प्रदर्शित करना चाहते हैं





text-alignment