2013-03-05 15 views
8

मैं वर्तमान में टेक्स्ट की कई पंक्तियों को प्रदर्शित करने के लिए UILabel का उपयोग कर रहा हूं। लाइन ब्रेक अधिकांश को NSLineBreakByWordWrapping पर सेट किया गया है, इसलिए लेबल स्वचालित रूप से लाइन ब्रेक लगाता है। मैं कैसे पता लगा सकता हूं कि उन लाइन ब्रेक कहां हैं? असल में, मैं प्रत्येक \n ब्रेक के साथ एक स्ट्रिंग वापस करना चाहता हूं।UILabel पता लाइन ब्रेक

+2

+1 अच्छा प्रश्न –

उत्तर

3

यहाँ मेरी लाइन का पता लगाने के लिए चारों ओर काम के अंदर UILabel

- (int)getLengthForString:(NSString *)str fromFrame:(CGRect)frame withFont:(UIFont *)font 
{ 
    int length = 1; 
    int lastSpace = 1; 
    NSString *cutText = [str substringToIndex:length]; 
    CGSize textSize = [cutText sizeWithFont:font constrainedToSize:CGSizeMake(frame.size.width, frame.size.height + 500)]; 
    while (textSize.height <= frame.size.height) 
    { 
     NSRange range = NSMakeRange (length, 1); 
     if ([[str substringWithRange:range] isEqualToString:@" "]) 
     { 
      lastSpace = length; 
     } 
     length++; 
     cutText = [str substringToIndex:length]; 
     textSize = [cutText sizeWithFont:font constrainedToSize:CGSizeMake(frame.size.width, frame.size.height + 500)]; 
    } 
    return lastSpace; 
} 


-(NSString*) getLinebreaksWithString:(NSString*)labelText forWidth:(CGFloat)lblWidth forPoint:(CGPoint)point 
{ 
    //Create Label 
    UILabel *label = [[UILabel alloc] init]; 
    label.text = labelText; 
    label.numberOfLines = 0; 
    label.lineBreakMode = NSLineBreakByWordWrapping; 

    //Set frame according to string 
    CGSize size = [label.text sizeWithFont:label.font 
         constrainedToSize:CGSizeMake(lblWidth, MAXFLOAT) 
          lineBreakMode:UILineBreakModeWordWrap]; 
    [label setFrame:CGRectMake(point.x , point.y , size.width , size.height)]; 

    //Add Label in current view 
    [self.view addSubview:label]; 

    //Count the total number of lines for the Label which has NSLineBreakByWordWrapping line break mode 
    int numLines = (int)(label.frame.size.height/label.font.leading); 

    //Getting and dumping lines from text set on the Label 
    NSMutableArray *allLines = [[NSMutableArray alloc] init]; 

    BOOL shouldLoop = YES; 
    while (shouldLoop) 
    { 
     //Getting length of the string from rect with font 
     int length = [self getLengthForString:labelText fromFrame:CGRectMake(point.x, point.y, size.width, size.height/numLines) withFont:label.font] + 1;   

     [allLines addObject:[labelText substringToIndex:length]]; 

     labelText = [labelText substringFromIndex:length]; 
     if(labelText.length<length) 
      shouldLoop = NO; 
    } 

    [allLines addObject:labelText]; 
    //NSLog(@"\n\n%@\n",allLines); 

    return [allLines componentsJoinedByString:@"\n"]; 
} 

टूट जाता है का उपयोग कैसे करें

NSString *labelText = @"We are what our thoughts have made us; so take care about what you think. Words are secondary. Thoughts live; they travel far."; 

NSString *stringWithLineBreakChar = [self getLinebreaksWithString:labelText forWidth:200 forPoint:CGPointMake(15, 15)]; 
NSLog(@"\n\n%@",stringWithLineBreakChar); 

तुम बस के लिए आवश्यक getLinebreaksWithString पैरामीटर सेट करने की जरूरत है और आप करेंगे है प्रत्येक "\ n" ब्रेक के साथ एक स्ट्रिंग प्राप्त करें।

उत्पादन Result of NSLog and Simulator

+0

यह काम किया। हालांकि कुछ तारों पर मुझे "अगर ([[str substringWithRange: range] isEqualToString: @" "]) " वापसी "बिना अपवाद अपवाद 'NSRangeException' के कारण ऐप को समाप्त करना, कारण: '- [__ एनएससीएफस्ट्रिंग सबस्ट्रिंग विथेंज:] : सीमाओं से बाहर रेंज या इंडेक्स ' – morcutt

+0

क्या आप केवल उन नमूना स्ट्रिंग को त्रुटि के कारण पोस्ट कर सकते हैं? हो सकता है कि मैं –

+0

@ भार्गई को समझ सकूं, कल मैंने इसे आरएसएस फ़ीड के साथ परीक्षण किया और अभी तक एक ही त्रुटि को पुन: पेश नहीं किया है। अगली बार ऐसा होता है, मैं इसे पोस्ट करूंगा। तुम्हारी सहायता सराहनीय है! – morcutt

0

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

func wordWrapFormattedStringFor(string: String) -> String { 
    // Save label state 
    let labelHidden = label.isHidden 
    let labelText = label.text 

    // Set text to current label and size it to fit the content 
    label.isHidden = true 
    label.text = string 
    label.sizeToFit() 
    label.layoutIfNeeded() 

    // Prepare array with indexes of all whitespace characters 
    let whitespaceIndexes: [String.Index] = { 
     let whitespacesSet = CharacterSet.whitespacesAndNewlines 
     var indexes: [String.Index] = [] 

     string.unicodeScalars.enumerated().forEach { i, unicodeScalar in 
      if whitespacesSet.contains(unicodeScalar) { 
       let index = string.index(string.startIndex, offsetBy: i) 
       indexes.append(index) 
      } 
     } 

     // We want also the index after the last character so that when we make substrings later we include also the last word 
     // This index can only be used for substring to this index (not from or including, since it points to \0) 
     let index = string.index(string.startIndex, offsetBy: string.characters.count) 
     indexes.append(index) 

     return indexes 
    }() 

    var reformattedString = "" 

    let boundingSize = CGSize(width: label.bounds.width, height: CGFloat.greatestFiniteMagnitude) 
    let attributes = [NSFontAttributeName: font] 

    var runningHeight: CGFloat? 
    var previousIndex: String.Index? 

    whitespaceIndexes.forEach { index in 
     let string = string.substring(to: index) 
     let stringHeight = string.boundingRect(with: boundingSize, options: .usesLineFragmentOrigin, attributes: attributes, context: nil).height 

     var newString: String = { 
      if let previousIndex = previousIndex { 
       return string.substring(from: previousIndex) 
      } else { 
       return string 
      } 
     }() 

     if runningHeight == nil { 
      runningHeight = stringHeight 
     } 

     if runningHeight! < stringHeight { 
      // Check that we can create a new index with offset of 1 and that newString does not contain only a whitespace (for example if there are multiple consecutive whitespaces) 
      if newString.characters.count > 1 { 
       let splitIndex = newString.index(newString.startIndex, offsetBy: 1) 
       // Insert a new line between the whitespace and rest of the string 
       newString.insert("\n", at: splitIndex) 
      } 
     } 

     reformattedString += newString 

     runningHeight = stringHeight 
     previousIndex = index 
    } 

    // Restore label 
    label.text = labelText 
    label.isHidden = labelHidden 

    return reformattedString 
} 

Image - Comparison of output string with label text.

यह समाधान मेरे मामले में वास्तव में अच्छी तरह से काम किया, आशा है कि यह मदद करता है।

संबंधित मुद्दे