IOS 7 में UITextView ऊंचाई के साथ UITableViewCell?


121

मैं iOS 7 में UITextView के साथ UITableViewCell की ऊंचाई की गणना कैसे कर सकता हूं?

मुझे इसी तरह के सवालों पर बहुत सारे उत्तर मिले, लेकिन sizeWithFont:हर समाधान में भाग लेते हैं और इस विधि को हटा दिया जाता है!

मुझे पता है कि मुझे उपयोग करना है - (CGFloat)tableView:heightForRowAtIndexPath:लेकिन मैं अपने टेक्स्ट व्यू को पूरे पाठ को प्रदर्शित करने के लिए कितनी ऊंचाई की गणना करता हूं?

जवाबों:


428

सबसे पहले, यह नोट करना बहुत महत्वपूर्ण है, कि UITextView और UILabel के बीच एक बड़ा अंतर है जब यह आता है कि पाठ कैसे प्रस्तुत किया जाता है। न केवल UITextView में सभी सीमाओं पर इनसेट हैं, बल्कि इसके अंदर का टेक्स्ट लेआउट भी थोड़ा अलग है।

इसलिए, sizeWithFont:UITextViews के लिए जाने के लिए एक बुरा तरीका है।

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

निम्नलिखित iOS 7 और पुराने संस्करणों दोनों के लिए समान रूप से काम करेगा और जैसे अभी किसी भी तरीके को शामिल नहीं किया गया है, जो कि पदावनत हैं।


सरल उपाय

- (CGFloat)textViewHeightForAttributedText: (NSAttributedString*)text andWidth: (CGFloat)width {
    UITextView *calculationView = [[UITextView alloc] init];
    [calculationView setAttributedText:text];
    CGSize size = [calculationView sizeThatFits:CGSizeMake(width, FLT_MAX)];
    return size.height;
}

यह फ़ंक्शन ए NSAttributedStringऔर वांछित चौड़ाई को ए के रूप में ले जाएगा CGFloatऔर आवश्यक ऊंचाई वापस कर देगा


विस्तृत समाधान

चूँकि मैंने हाल ही में कुछ ऐसा ही किया है, मुझे लगा कि मैं अपने द्वारा जुड़े हुए मुद्दों के साथ कुछ समाधान भी साझा करूँगा। मुझे उम्मीद है कि यह किसी की मदद करेगा।

यह गहराई में कहीं अधिक है और निम्नलिखित को कवर करेगा:

  • बेशक: किसी UITableViewCellपूर्ण की सामग्री को प्रदर्शित करने के लिए आवश्यक आकार के आधार पर ऊंचाई निर्धारित करनाUITextView
  • पाठ परिवर्तनों के जवाब में (और पंक्ति के ऊंचाई परिवर्तनों को चेतन करें)
  • कर्सर को दृश्य क्षेत्र के अंदर रखते हुए और संपादन करते UITextViewसमय रिसायपर पर पहला रेस्पोंडर रखेंUITableViewCell

यदि आप एक स्थिर तालिका दृश्य के साथ काम कर रहे हैं या आपके पास केवल ज्ञात संख्या है UITextView, तो आप संभावित रूप से चरण 2 को बहुत सरल बना सकते हैं।

1. सबसे पहले, ऊँचाई को लिखें। RowAtIndexPath:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    // check here, if it is one of the cells, that needs to be resized
    // to the size of the contained UITextView
    if (  )             
        return [self textViewHeightForRowAtIndexPath:indexPath];
    else
    // return your normal height here:
            return 100.0;           
}

2. उस फ़ंक्शन को परिभाषित करें जो आवश्यक ऊंचाई की गणना करता है:

अपने उपवर्ग में एक उदाहरण चर के रूप NSMutableDictionaryमें (इस उदाहरण में कहा जाता है textViews) जोड़ें UITableViewController

इस शब्दकोष का उपयोग व्यक्ति को संदर्भों को संग्रहीत करने के लिए UITextViewsकरें:

(और हाँ, indexPaths शब्दकोशों के लिए मान्य कुंजी हैं )

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    
    // Do you cell configuring ...

    [textViews setObject:cell.textView forKey:indexPath];
    [cell.textView setDelegate: self]; // Needed for step 3

    return cell;
}

यह फ़ंक्शन अब वास्तविक ऊँचाई की गणना करेगा:

- (CGFloat)textViewHeightForRowAtIndexPath: (NSIndexPath*)indexPath {
    UITextView *calculationView = [textViews objectForKey: indexPath];
    CGFloat textViewWidth = calculationView.frame.size.width;
    if (!calculationView.attributedText) {
        // This will be needed on load, when the text view is not inited yet
        
        calculationView = [[UITextView alloc] init];
        calculationView.attributedText = // get the text from your datasource add attributes and insert here
        textViewWidth = 290.0; // Insert the width of your UITextViews or include calculations to set it accordingly
    }
    CGSize size = [calculationView sizeThatFits:CGSizeMake(textViewWidth, FLT_MAX)];
    return size.height;
}

3. संपादन करते समय आकार बदलने में सक्षम करें

अगले दो कार्यों के लिए, यह महत्वपूर्ण है, कि प्रतिनिधि UITextViewsआपके लिए निर्धारित है UITableViewController। यदि आपको प्रतिनिधि के रूप में कुछ और चाहिए, तो आप वहां से संबंधित कॉल करके या उपयुक्त NSNotificationCenter हुक का उपयोग करके इसके चारों ओर काम कर सकते हैं।

- (void)textViewDidChange:(UITextView *)textView {

    [self.tableView beginUpdates]; // This will cause an animated update of
    [self.tableView endUpdates];   // the height of your UITableViewCell

    // If the UITextView is not automatically resized (e.g. through autolayout 
    // constraints), resize it here

    [self scrollToCursorForTextView:textView]; // OPTIONAL: Follow cursor
}

4. एडिटिंग के दौरान कर्सर का पालन करें

- (void)textViewDidBeginEditing:(UITextView *)textView {
    [self scrollToCursorForTextView:textView];
}

यह UITableViewस्क्रॉल को कर्सर की स्थिति में कर देगा, अगर यह यूआईटेबल व्यू के दृश्यमान के अंदर नहीं है:

- (void)scrollToCursorForTextView: (UITextView*)textView {
    
    CGRect cursorRect = [textView caretRectForPosition:textView.selectedTextRange.start];
    
    cursorRect = [self.tableView convertRect:cursorRect fromView:textView];
    
    if (![self rectVisible:cursorRect]) {
        cursorRect.size.height += 8; // To add some space underneath the cursor
        [self.tableView scrollRectToVisible:cursorRect animated:YES];
    }
}

5. इनसेट्स को सेट करके, दिखाई देने वाली रेक्ट को एडजस्ट करें

संपादन करते समय, आपके हिस्से UITableViewकीबोर्ड द्वारा कवर किए जा सकते हैं। यदि टेबलव्यू इनसेट्स को समायोजित नहीं किया scrollToCursorForTextView:गया है, तो यह टेबलव्यू के निचले भाग में होने पर, आपके कर्सर को स्क्रॉल नहीं कर पाएगा।

- (void)keyboardWillShow:(NSNotification*)aNotification {
    NSDictionary* info = [aNotification userInfo];
    CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
    
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, kbSize.height, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
}

- (void)keyboardWillHide:(NSNotification*)aNotification {
    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:0.35];
    UIEdgeInsets contentInsets = UIEdgeInsetsMake(self.tableView.contentInset.top, 0.0, 0.0, 0.0);
    self.tableView.contentInset = contentInsets;
    self.tableView.scrollIndicatorInsets = contentInsets;
    [UIView commitAnimations];
}

और अंतिम भाग:

आपके दृश्य के अंदर लोड किया गया, कीबोर्ड परिवर्तन के लिए सूचनाओं के लिए साइन अप करें NSNotificationCenter:

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

कृपया मुझे इतना लंबा जवाब देने के लिए, पागल मत होना। हालांकि इस सवाल का जवाब देने के लिए सभी की जरूरत नहीं है, मेरा मानना ​​है कि ऐसे अन्य लोग हैं जो सीधे संबंधित मुद्दों के लिए सहायक होंगे।


अपडेट करें:

जैसा कि डेव हूपर्ट ने बताया, मैं rectVisibleफ़ंक्शन को शामिल करना भूल गया :

- (BOOL)rectVisible: (CGRect)rect {
    CGRect visibleRect;
    visibleRect.origin = self.tableView.contentOffset;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size = self.tableView.bounds.size;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
    
    return CGRectContainsRect(visibleRect, rect);
}

इसके अलावा, मैंने देखा, कि scrollToCursorForTextView:अभी भी मेरी परियोजना में एक TextFields के लिए एक सीधा संदर्भ शामिल है। यदि आपको bodyTextViewनहीं मिलने की समस्या है, तो फ़ंक्शन के अद्यतन संस्करण की जांच करें।


1
वह कोड बिल्कुल अच्छा काम कर रहा है! यह सब कुछ आकार देता है! लेकिन, मेरे TextView को हमेशा 30px की ऊंचाई मिलती है! क्या ऐसी सेटिंग हैं जिन्हें मुझे सेट करने की अनुमति नहीं है, या क्या कुछ ऐसा है जिसकी मुझे यूआईटेक्स्ट व्यू में अनुमति नहीं है?
MyJBMe

1
यह समाधान कॉपी और पेस्ट पर काम नहीं करता है यदि पाठ बड़ा है, कोई विचार?
वाइकिंग्स

2
@ टिम बोदित, आपका समाधान काम करता है, धन्यवाद! लेकिन मुझे लगता है कि आपको टिप्पणी पर ध्यान देना चाहिए, कि attributedTextफ़ॉन्ट, रंग और पाठ संरेखण को निर्दिष्ट किए बिना असाइन करने से NSAttributedString विशेषताओं के डिफ़ॉल्ट मानों की सेटिंग टेक्स्टव्यू तक हो जाती है। मेरे मामले में यह एक ही पाठ के लिए टेक्स्टव्यू की विभिन्न ऊंचाइयों को प्राप्त करने का कारण बनता है।
अलेक्जेंडर

4
यह मेरे सभी समय पसंदीदा स्टैक ओवरफ्लो उत्तरों में से एक है - धन्यवाद!
रिचर्ड वेनटेबल

3
@TimBodeit: मैं iOS8 पर यह काम नहीं कर पा रहा हूं। कृपया मुझे बताएं कि यह कैसे तय किया जा सकता है।
अरुण गुप्ता

37

SizeWithFont को बदलने के लिए एक नया फ़ंक्शन है, जो कि बाउंडिंग है।

मैंने अपनी परियोजना में निम्नलिखित फ़ंक्शन को जोड़ा, जो iOS7 पर नए फ़ंक्शन का उपयोग करता है और पुराने iOS पर 7. से कम है। यह मूल रूप से साइंटैक्स के समान सिंटैक्स है:

    -(CGSize)text:(NSString*)text sizeWithFont:(UIFont*)font constrainedToSize:(CGSize)size{
        if(IOS_NEWER_OR_EQUAL_TO_7){
            NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                              font, NSFontAttributeName,
                                              nil];

            CGRect frame = [text boundingRectWithSize:size
                                              options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                           attributes:attributesDictionary
                                              context:nil];

            return frame.size;
        }else{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            return [text sizeWithFont:font constrainedToSize:size];
#pragma clang diagnostic pop
        }
    }

आप अपनी परियोजना में अपनी उपसर्ग। Pch फ़ाइल में उस IOS_NEWER_OR_EQUAL_TO_7 को जोड़ सकते हैं:

#define IOS_NEWER_OR_EQUAL_TO_7 ( [ [ [ UIDevice currentDevice ] systemVersion ] floatValue ] >= 7.0 )

मेरे UITextViews अभी भी बहुत अच्छी तरह से स्केल नहीं करते हैं और जब पाठ 3 पंक्तियों तक फैल जाता है, तो स्क्रॉल करने योग्य हो जाता है; pastebin.com/Wh6vmBqh
मार्टिन डे कीजर

दूसरा रिटर्न स्टेटमेंट एक्सकोड में एक डिप्रेसेशन चेतावनी भी फेंकता है।
मार्टिन डी कीइजर

क्या आप पाठ के परिकलित आकार में UIFxtView का आकार भी सेलफ़ॉररौटएंडइंडेक्सथ में सेट कर रहे हैं? इसके अलावा, आपको दूसरी वापसी में चेतावनी के बारे में चिंता नहीं करनी चाहिए क्योंकि यह केवल तब उपयोग किया जाता है जब ऐप को iOS6 डिवाइस पर चलाया जाता है जिसमें फ़ंक्शन को पदावनत नहीं किया जाता है।
manecosta

क्या आप इस फ़ंक्शन का उपयोग करने का एक सरल उदाहरण प्रदान कर सकते हैं?
जोरायर

@manecosta Apple के दस्तावेज़ीकरण में कहा गया है कि आपको 'सीविल' करना होगा: iOS 7 और बाद में, यह विधि आंशिक आकार (लौटे CGRect के आकार के घटक में) को लौटा देती है; दृश्यों को आकार देने के लिए लौटे आकार का उपयोग करने के लिए, आपको छत फ़ंक्शन का उपयोग करके इसके मूल्य को निकटतम उच्च पूर्णांक तक ले जाना चाहिए।
HpTerm

9

यदि आप UITableViewAutomaticDimension का उपयोग कर रहे हैं तो मेरे पास वास्तव में सरल (iOS 8 केवल) समाधान है। मेरे मामले में यह एक स्थिर तालिका दृश्य है, लेकिन मुझे लगता है कि आप इसे गतिशील प्रोटोटाइप के लिए अनुकूलित कर सकते हैं ...

मेरे पास टेक्स्ट-व्यू की ऊंचाई के लिए एक बाधा आउटलेट है और मैंने इस तरह निम्नलिखित तरीके लागू किए हैं:

// Outlets

@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *textViewHeight;


// Implementation

#pragma mark - Private Methods

- (void)updateTextViewHeight {
    self.textViewHeight.constant = self.textView.contentSize.height + self.textView.contentInset.top + self.textView.contentInset.bottom;
}

#pragma mark - View Controller Overrides

- (void)viewDidLoad {
    [super viewDidLoad];
    [self updateTextViewHeight];
}

#pragma mark - TableView Delegate & Datasource

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 80;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

#pragma mark - TextViewDelegate

- (void)textViewDidChange:(UITextView *)textView {
    [self.tableView beginUpdates];
    [self updateTextViewHeight];
    [self.tableView endUpdates];
}

लेकिन याद रखें : पाठ दृश्य स्क्रॉल करने योग्य होना चाहिए, और आपको अपनी बाधाओं को ऐसे सेट करना होगा कि वे स्वचालित आयाम के लिए काम करें:

  • सेल में सभी दृश्य एक दूसरे के संबंध में तय हाइट्स के साथ सेट करें (पाठ दृश्य ऊंचाई सहित, जिसे आप प्रोग्राम में बदलेंगे)
  • शीर्ष सबसे अधिक दृश्य में शीर्ष रिक्ति है और नीचे के अधिकांश दृश्य में सुपर दृश्य में सबसे नीचे स्पेस है;

सबसे बुनियादी सेल उदाहरण है:

  • टेक्स्टव को छोड़कर सेल में कोई अन्य विचार नहीं है
  • पाठ दृश्य के सभी पक्षों के चारों ओर मार्जिन और पाठ दृश्य के लिए पूर्वनिर्धारित ऊँचाई की कमी।

1
पाठ दृश्य को स्क्रॉल करने योग्य नहीं होना चाहिए
अक्षत झवेरी

मैं हर समय अद्यतन के तहत एक ही आकार प्राप्त कर रहा हूँ। लगता है कि सामग्री का आकार गलत है। स्क्रॉल करना अक्षम है।
Dvole

5

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

IOS 6 और उसके बाद के संस्करण में सब कुछ काम कर रहा है, लेकिन iOS 7 में टेक्स्ट व्यू में टेक्स्ट को पूरी तरह से नहीं दिखाया जा सकता है, हालांकि frameटेक्स्ट व्यू का आकार वास्तव में रिसाइज है। (मैं उपयोग नहीं कर रहा हूं Auto Layout)। यह कारण होना चाहिए कि आईओएस 7 TextKitमें है और पाठ की स्थिति को इसके द्वारा नियंत्रित किया NSTextContainerजाता है UITextView। तो मेरे मामले में मुझे someTextViewआईओएस 7 में इसे सही तरीके से काम करने के लिए एक लाइन जोड़ने की आवश्यकता है ।

    if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
        someTextView.textContainer.heightTracksTextView = YES;
    }

जैसा कि प्रलेखन ने कहा, वह संपत्ति क्या है:

नियंत्रित करता है कि क्या रिसीवर अपने बाउंडिंग आयत की ऊंचाई को समायोजित करता है जब उसका टेक्स्ट व्यू रिसाइज़ होता है। डिफ़ॉल्ट मूल्य: नहीं।

यदि यह डिफ़ॉल्ट मान के साथ छोड़ देते हैं, के बाद का आकार बदलने frameके someTextView, के आकारtextContainer , नतीजा यह है कि केवल पाठ का आकार बदलने से पहले क्षेत्र में प्रदर्शित किया जा सकता करने के लिए अग्रणी नहीं बदला है।

और हो सकता है कि scrollEnabled = NOमामले को एक से अधिक होने पर सेट करने की आवश्यकता हो textContainer, ताकि पाठ एक textContainerसे दूसरे में वापस आ जाए।


4

यहाँ एक और उपाय है जिसका उद्देश्य सरलता और त्वरित प्रोटोटाइप है :

सेट अप:

  1. प्रोटोटाइप कोशिकाओं के साथ तालिका।
  2. प्रत्येक कोशिका में गतिशील आकार होता है UITextView w / अन्य सामग्री होती है।
  3. प्रोटोटाइप कोशिकाओं के साथ जुड़े हुए हैं TableCell.h
  4. UITableViewके साथ जुड़ा हुआ है TableViewController.h

उपाय:

(1) इसमें जोड़ें TableViewController.m:

 // This is the method that determines the height of each cell.  
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 
{
    // I am using a helper method here to get the text at a given cell.
    NSString *text = [self getTextAtIndex:indexPath];

    // Getting the height needed by the dynamic text view.
    CGSize size = [self frameForText:text sizeWithFont:nil constrainedToSize:CGSizeMake(300.f, CGFLOAT_MAX)];

    // Return the size of the current row.
    // 80 is the minimum height! Update accordingly - or else, cells are going to be too thin.
    return size.height + 80; 
}

// Think of this as some utility function that given text, calculates how much 
// space would be needed to fit that text.
- (CGSize)frameForText:(NSString *)text sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
{
    NSDictionary *attributesDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                                          font, NSFontAttributeName,
                                          nil];
    CGRect frame = [text boundingRectWithSize:size
                                      options:(NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading)
                                   attributes:attributesDictionary
                                      context:nil];

    // This contains both height and width, but we really care about height.
    return frame.size;
}

// Think of this as a source for the text to be rendered in the text view. 
// I used a dictionary to map indexPath to some dynamically fetched text.
- (NSString *) getTextAtIndex: (NSIndexPath *) indexPath
{
    return @"This is stubbed text - update it to return the text of the text view.";
}

(2) इसमें जोड़ें TableCell.m:

// This method will be called when the cell is initialized from the storyboard
// prototype. 
- (void)awakeFromNib
{
    // Assuming TextView here is the text view in the cell. 
    TextView.scrollEnabled = YES;
}

स्पष्टीकरण:

तो यहाँ क्या हो रहा है: प्रत्येक पाठ दृश्य ऊर्ध्वाधर और क्षैतिज बाधाओं द्वारा तालिका कोशिकाओं की ऊँचाई के लिए बाध्य है - इसका मतलब है कि जब तालिका सेल की ऊँचाई बढ़ती है, तो पाठ दृश्य इसके आकार में भी वृद्धि करता है। मैंने सेल में दिए गए टेक्स्ट को फिट करने के लिए टेक्स्ट व्यू की आवश्यक ऊंचाई की गणना करने के लिए @ manecosta के कोड के एक संशोधित संस्करण का उपयोग किया। तो इसका मतलब है कि वर्णों की X संख्या के साथ एक पाठ दिया गया है, frameForText:एक आकार लौटाएगा जिसके पास एक संपत्ति होगी जो size.heightपाठ दृश्य की आवश्यक ऊंचाई से मेल खाती है।

अब, वह सब बना हुआ है जो आवश्यक टेक्स्ट दृश्य की ऊंचाई से मेल खाने के लिए सेल की ऊँचाई को अद्यतन करता है। और यह हासिल किया है heightForRowAtIndexPath:। जैसा कि टिप्पणियों में उल्लेख किया गया है, चूंकि size.heightपाठ दृश्य के लिए केवल ऊंचाई है और संपूर्ण सेल नहीं है, इसलिए इसमें कुछ ऑफसेट जोड़े जाने चाहिए। उदाहरण के मामले में, यह मान 80 था।


यह 'dream.dream' किसके लिए है?
MyJBMe

@MyJBMe खेद है कि मेरे अपने प्रोजेक्ट का हिस्सा था - मैंने तदनुसार कोड अपडेट किया है। dream.dreamवह पाठ था जिसे मैं पाठ दृश्य में प्रस्तुत कर रहा था।
जोरायर

3

यदि आप ऑटोलेयूट का उपयोग कर रहे हैं तो एक तरीका यह है कि ऑटोलेयूट इंजन को आपके लिए आकार की गणना करने दें। यह सबसे कुशल दृष्टिकोण नहीं है, लेकिन यह बहुत सुविधाजनक है (और यकीनन सबसे सटीक)। यह और अधिक सुविधाजनक हो जाता है क्योंकि सेल लेआउट की जटिलता बढ़ती है - जैसे अचानक आपके पास सेल में दो या अधिक टेक्स्ट / फ़ील्ड हैं।

मैंने ऑटो लेआउट का उपयोग करते हुए टेबलव्यू कोशिकाओं को आकार देने के लिए एक पूर्ण नमूने के साथ एक समान प्रश्न का उत्तर दिया, यहां:

ऑटोलयूट के साथ सभी साक्षात्कारों को फिट करने के लिए सुपरवाइज का आकार कैसे बदलें?


1

पूर्ण सुचारू समाधान इस प्रकार है।

सबसे पहले, हमें textView के साथ सेल क्लास की आवश्यकता है

@protocol TextInputTableViewCellDelegate <NSObject>
@optional
- (void)textInputTableViewCellTextWillChange:(TextInputTableViewCell *)cell;
- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell;
@end

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@property (nonatomic) CGFloat lastRelativeFrameOriginY;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextWillChange:)]) {
        [self.delegate textInputTableViewCellTextWillChange:self];
    }
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {
    if ([self.delegate respondsToSelector:@selector(textInputTableViewCellTextDidChange:)]) {
        [self.delegate textInputTableViewCellTextDidChange:self];
    }
}

अगला, हम इसका उपयोग TableViewController में करते हैं

@interface SomeTableViewController () <TextInputTableViewCellDelegate>
@end

@implementation SomeTableViewController

. . . . . . . . . . . . . . . . . . . .

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    TextInputTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: TextInputTableViewCellIdentifier forIndexPath:indexPath];
    cell.delegate = self;
    cell.minLines = 3;
    . . . . . . . . . .  
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return UITableViewAutomaticDimension;
}

- (void)textInputTableViewCellWillChange:(TextInputTableViewCell *)cell {
    cell.lastRelativeFrameOriginY = cell.frame.origin.y - self.tableView.contentOffset.y;
}

- (void)textInputTableViewCellTextDidChange:(TextInputTableViewCell *)cell {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = cell.frame.origin.y - cell.lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [cell.textView caretRectForPosition:cell.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:cell.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;
    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end
  • यहाँ minLinestextView के लिए न्यूनतम ऊंचाई निर्धारित करने की अनुमति देता है (UITableViewAutomaticDimension के साथ AutoLayout द्वारा न्यूनतम ऊंचाई का विरोध करने के लिए)।

  • moveRowAtIndexPath:indexPath: उसी IndexPath के साथ tableViewCell ऊँचाई पुनः गणना और पुनः लेआउट शुरू होती है।

  • performWithoutAnimation: साइड-इफ़ेक्ट को हटाता है (टाइप करते समय नई लाइन शुरू करने पर टेबल व्यू कंटेंट ऑफ़ जंपिंग)।

  • सेल अपडेट के दौरान relativeFrameOriginY(नहीं contentOffsetY!) को संरक्षित करना महत्वपूर्ण है क्योंकि contentSizeवर्तमान सेल से पहले कोशिकाओं को अप्रत्याशित तरीके से ऑटोलैट पथरी द्वारा बदल दिया जा सकता है। यह लंबे शब्दों को टाइप करते समय सिस्टम हाइफ़नेशन पर दृश्य कूदता है।

  • ध्यान दें कि आपको संपत्ति सेट नहीं करनी चाहिए estimatedRowHeight ! निम्नलिखित काम नहीं करता है

    self.tableView.estimatedRowHeight = UITableViewAutomaticDimension;

    केवल tableViewDelegate पद्धति का उपयोग करें।

================================================== ========================

यदि कोई tableView और tableViewCell के बीच कमजोर बंधन के खिलाफ बुरा नहीं मानता है और tableViewCell से tableView के ज्यामिति को अपडेट कर रहा है, तो TextInputTableViewCellऊपर वर्ग को अपग्रेड करना संभव है :

@interface TextInputTableViewCell : UITableViewCell
@property (nonatomic, weak) id<TextInputTableViewCellDelegate> delegate;
@property (nonatomic, weak) UITableView *tableView;
@property (nonatomic, readonly) UITextView *textView;
@property (nonatomic) NSInteger minLines;
@end


#import "TextInputTableViewCell.h"

@interface TextInputTableViewCell () <UITextViewDelegate> {
    NSLayoutConstraint *_heightConstraint;
    CGFloat _lastRelativeFrameOriginY;
}
@property (nonatomic) UITextView *textView;
@end

@implementation TextInputTableViewCell

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
        self.selectionStyle = UITableViewCellSelectionStyleNone;

        _textView = [UITextView new];
        _textView.translatesAutoresizingMaskIntoConstraints = NO;
        _textView.delegate = self;
        _textView.scrollEnabled = NO;
        _textView.font = CELL_REG_FONT;
        _textView.textContainer.lineFragmentPadding = 0.0;
        _textView.textContainerInset = UIEdgeInsetsZero;
        [self.contentView addSubview:_textView];

        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];
        [self.contentView addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-[view]-|" options:nil metrics:nil views:@{@"view": _textView}]];

        _heightConstraint = [NSLayoutConstraint constraintWithItem: _textView
                         attribute: NSLayoutAttributeHeight
                         relatedBy: NSLayoutRelationGreaterThanOrEqual
                         toItem: nil
                         attribute: NSLayoutAttributeNotAnAttribute
                         multiplier: 0.0
                         constant: (_textView.font.lineHeight + 15)];
        _heightConstraint.priority = UILayoutPriorityRequired - 1;
        [_textView addConstraint:_heightConstraint];
    }
    return self;
}

- (void)prepareForReuse {
    [super prepareForReuse];    
    self.minLines = 1;
    self.tableView = nil;
}

- (void)setMinLines:(NSInteger)minLines {
    _heightConstraint.constant = minLines * _textView.font.lineHeight + 15;
}

- (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {

    _lastRelativeFrameOriginY = self.frame.origin.y - self.tableView.contentOffset.y;
    return YES;
}

- (void)textViewDidChange:(UITextView *)textView {

    NSIndexPath *indexPath = [self.tableView indexPathForCell:self];
    if (indexPath == nil) return;

    [UIView performWithoutAnimation:^{
        [self.tableView moveRowAtIndexPath:indexPath toIndexPath:indexPath];
    }];

    CGFloat contentOffsetY = self.frame.origin.y - _lastRelativeFrameOriginY;
    self.tableView.contentOffset = CGPointMake(self.tableView.contentOffset.x, contentOffsetY);

    CGRect caretRect = [self.textView caretRectForPosition:self.textView.selectedTextRange.start];
    caretRect = [self.tableView convertRect:caretRect fromView:self.textView];

    CGRect visibleRect = self.tableView.bounds;
    visibleRect.origin.y += self.tableView.contentInset.top;
    visibleRect.size.height -= self.tableView.contentInset.top + self.tableView.contentInset.bottom;

    BOOL res = CGRectContainsRect(visibleRect, caretRect);
    if (!res) {
        caretRect.size.height += 5;
        [self.tableView scrollRectToVisible:caretRect animated:NO];
    }
}
@end

1
  1. अपने UITextView के पीछे UILabel रखो।
  2. इस उत्तर का उपयोग करें: https://stackoverflow.com/a/36054679/6681462 आपके द्वारा बनाए गए UILabel पर
  3. उन्हें वही अड़चन और फोंट दें
  4. उन्हें एक ही पाठ सेट करें;

आपके सेल की ऊंचाई UILabel की सामग्री द्वारा गणना की जाएगी, लेकिन सभी पाठ TextField द्वारा दिखाए जाएंगे।


0
UITextView *txtDescLandscape=[[UITextView alloc] initWithFrame:CGRectMake(2,20,310,2)];

    txtDescLandscape.editable =NO;
    txtDescLandscape.textAlignment =UITextAlignmentLeft;
    [txtDescLandscape setFont:[UIFont fontWithName:@"ArialMT" size:15]];
    txtDescLandscape.text =[objImage valueForKey:@"imgdescription"];
    txtDescLandscape.text =[txtDescLandscape.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    [txtDescLandscape sizeToFit];
    [headerView addSubview:txtDescLandscape];

    CGRect txtViewlandscpframe = txtDescLandscape.frame;
    txtViewlandscpframe.size.height = txtDescLandscape.contentSize.height;
    txtDescLandscape.frame = txtViewlandscpframe;

मुझे लगता है कि इस तरह आप अपने टेक्स्ट व्यू की ऊंचाई को गिन सकते हैं और फिर उस ऊंचाई के अनुसार अपने टेबलव्यू सेल का आकार बदल सकते हैं ताकि आप सेल पर पूरा टेक्स्ट दिखा सकें


0

स्विफ्ट संस्करण

func textViewHeightForAttributedText(text: NSAttributedString, andWidth width: CGFloat) -> CGFloat {
    let calculationView = UITextView()
    calculationView.attributedText = text
    let size = calculationView.sizeThatFits(CGSize(width: width, height: CGFloat.max))
    return size.height
}

0

यदि आप UITableViewCellआंतरिक ऊंचाई के आधार पर स्वचालित रूप से समायोजित करना चाहते हैं UITextView। मेरा उत्तर यहाँ देखें: https://stackoverflow.com/a/45890087/1245231

समाधान काफी सरल है और iOS 7 के बाद से काम करना चाहिए। सुनिश्चित करें कि StoryBoard में अंदर के लिए Scrolling Enabledविकल्प बंद हैUITextViewUITableViewCell

फिर आपके UITableViewController के दृश्य में () tableView.rowHeight = UITableViewAutomaticDimensionऔर tableView.estimatedRowHeight > 0जैसे सेट करें :

override func viewDidLoad() {
    super.viewDidLoad()

    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 44.0
}

बस। UITableViewCellआंतरिक UITextViewऊंचाई के आधार पर स्वचालित रूप से ऊँचाई समायोजित की जाएगी ।


-2

IOS 8 और इसके बाद के संस्करण के लिए आप उपयोग कर सकते हैं

your_tablview.estimatedrowheight= minheight तुम्हें चाहिए

your_tableview.rowheight=UItableviewautomaticDimension
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.