डायनेमिक हाइट वाली पंक्तियों के साथ दृश्य-आधारित NSTableView


84

मेरे पास इसमें देखने-आधारित के साथ एक आवेदन NSTableViewहै। इस तालिका दृश्य के अंदर, मेरे पास ऐसी पंक्तियाँ हैं जिनमें ऐसी कोशिकाएँ हैं जिनमें NSTextFieldशब्द-आवरण सक्षम के साथ एक बहु-पंक्ति है । की पाठ्य सामग्री के आधार पर NSTextField, सेल को प्रदर्शित करने के लिए आवश्यक पंक्तियों का आकार अलग-अलग होगा।

मुझे पता है कि मैं NSTableViewDelegateविधि को लागू कर सकता हूं - tableView:heightOfRow:ऊंचाई वापस करने के लिए, लेकिन ऊँचाई का निर्धारण शब्द के आधार पर किया जाएगा, जिसका उपयोग किया गया है NSTextField। के रैपिंग शब्द NSTextFieldसमान रूप से कितने चौड़े NSTextFieldहै ... के आधार पर निर्धारित किया जाता है NSTableView

Soooo ... मुझे लगता है कि मेरा सवाल है ... इसके लिए एक अच्छा डिज़ाइन पैटर्न क्या है? ऐसा लगता है कि सब कुछ मैं कोशिश कर रहा हूँ हवाओं एक जटिल गड़बड़ हो रही है। चूँकि TableView को बाहर रखने के लिए कोशिकाओं की ऊँचाई के ज्ञान की आवश्यकता होती है ... और NSTextFieldशब्द रैप को निर्धारित करने के लिए इसे लेआउट के ज्ञान की आवश्यकता होती है ... और सेल को रैप को निर्धारित करने के लिए वर्ड रैप के ज्ञान की आवश्यकता होती है ... यह एक परिपत्र गड़बड़ है ... और यह मुझे पागल कर रहा है

सुझाव?

यदि यह मायने रखता है, तो अंतिम परिणाम में भी संपादन योग्य NSTextFieldsहोगा जो उनके भीतर पाठ को समायोजित करने के लिए आकार देगा। मेरे पास पहले से ही दृश्य स्तर पर यह काम कर रहा है, लेकिन टेबलव्यू अभी तक कोशिकाओं की ऊंचाइयों को समायोजित नहीं करता है। एक बार जब मैं ऊंचाई के मुद्दे पर काम कर noteHeightOfRowsWithIndexesChangedलेता हूं, तो मैं बताता हूं - मैं तालिका को ऊंचाई को देखने के लिए सूचित करने के लिए विधि का उपयोग करूंगा ... लेकिन यह तब भी प्रतिनिधि को ऊंचाई के लिए पूछने जा रहा है ... इसलिए, मेरा प्रश्न।

अग्रिम में धन्यवाद!


यदि दृश्य की चौड़ाई और ऊंचाई दोनों उनकी सामग्री के साथ बदल सकते हैं, तो उन्हें परिभाषित करना जटिल है क्योंकि आपको इसे पुनरावृत्त करना होगा (लेकिन तब आप कैश कर सकते हैं)। लेकिन आपके मामले में निरंतर चौड़ाई के लिए एक बदलती ऊंचाई है। यदि चौड़ाई ज्ञात है (यानी खिड़की या दृश्य की चौड़ाई के आधार पर), तो यहां कुछ भी जटिल नहीं है। मुझे याद आ रहा है कि चौड़ाई भिन्न क्यों है?
रोब नेपियर

केवल ऊंचाई सामग्री के साथ बदल सकती है। और मैंने उस समस्या को पहले ही हल कर दिया है। मेरे पास एक NSTextField उपवर्ग है जो समायोजित करता है यह स्वचालित रूप से ऊंचाई है। समस्या तालिका समायोजन के प्रतिनिधि के पास उस समायोजन के ज्ञान को प्राप्त करने में है, इसलिए यह तदनुसार ऊंचाई को अपडेट कर सकता है।
जीवा डेवो

@ जीवा: आश्चर्य है कि अगर आपने इसे अभी तक हल किया है।
जोशुआ नोजि

मैं कुछ ऐसा ही करने की कोशिश कर रहा हूं। मुझे एक NSTextField उपवर्ग का विचार पसंद है जो समायोजित करता है कि यह स्वयं की ऊंचाई है। कैसे के बारे में एक (प्रतिनिधि) ऊंचाई को बदलने की सूचना उस उपवर्ग में बदल जाती है और निगरानी करती है कि रूपरेखा के बारे में जानकारी प्राप्त करने के लिए कुछ उपयुक्त वर्ग (डेटा स्रोत, रूपरेखा प्रतिनिधि, ...) के साथ?
जॉन वेलमैन

एक अत्यधिक संबंधित प्रश्न, उत्तर के साथ जो मुझे यहाँ से अधिक मदद करता है: NSTableView Row Height NSStrings पर आधारित है
एशले

जवाबों:


132

यह मुर्गी और अंडे की समस्या है। तालिका को पंक्ति की ऊंचाई जानने की आवश्यकता है क्योंकि यह निर्धारित करता है कि किसी दिए गए दृश्य में झूठ कहाँ होगा। लेकिन आप चाहते हैं कि एक दृश्य पहले से ही आस-पास हो ताकि आप इसका उपयोग पंक्ति की ऊंचाई जानने के लिए कर सकें। तो, जो पहले आता है?

उत्तर NSTableCellViewकेवल दृश्य की ऊंचाई को मापने के लिए एक अतिरिक्त (या जो कुछ भी आप अपने "सेल व्यू" के रूप में उपयोग कर रहे हैं) को रखने के लिए है। में tableView:heightOfRow:प्रतिनिधि विधि, 'पंक्ति' और सेट के लिए अपने मॉडल का उपयोग objectValueपर NSTableCellView। फिर अपनी तालिका की चौड़ाई के लिए दृश्य की चौड़ाई सेट करें, और (हालांकि आप इसे करना चाहते हैं) उस दृश्य के लिए आवश्यक ऊंचाई का पता लगाएं। उस मान को लौटाओ।

noteHeightOfRowsWithIndexesChanged:प्रतिनिधि विधि से फोन न करें tableView:heightOfRow:या viewForTableColumn:row:! यह बुरा है, और मेगा-परेशानी का कारण होगा।

ऊंचाई को गतिशील रूप से अपडेट करने के लिए, फिर आपको क्या करना चाहिए, यह पाठ को बदलने (लक्ष्य / कार्रवाई के माध्यम से) पर प्रतिक्रिया देता है और उस दृश्य की अपनी गणना की गई ऊँचाई को पुनर्गणना करता है। अब, गतिशील रूप से NSTableCellViewऊँचाई (या जो भी दृश्य आप अपने "सेल दृश्य" के रूप में उपयोग कर रहे हैं) को न बदलें । तालिका को उस दृश्य के फ़्रेम को नियंत्रित करना होगा , और यदि आप इसे सेट करने का प्रयास करते हैं, तो आप टेबलव्यू से लड़ रहे होंगे। इसके बजाय, पाठ क्षेत्र के लिए अपने लक्ष्य / कार्रवाई में जहां आपने ऊंचाई की गणना की है, कॉल करें noteHeightOfRowsWithIndexesChanged:, जो तालिका को उस व्यक्तिगत पंक्ति का आकार बदलने देगा। मान लें कि आपके पास ऑटोसाइज़िंग मुखौटा सेटअप है, जो कि साक्षात्कारों पर सही है (यानी: साक्षात्कार NSTableCellView), चीजें ठीक होनी चाहिए! यदि नहीं, तो पहले चीज़ों को वैरिएबल रो हाइट के साथ प्राप्त करने के लिए इंटरव्यू के रिसाइज़िंग मास्क पर काम करें।

मत भूलो कि noteHeightOfRowsWithIndexesChanged:डिफ़ॉल्ट रूप से एनिमेट करता है। इसे चेतन बनाने के लिए नहीं:

[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0];
[tableView noteHeightOfRowsWithIndexesChanged:indexSet];
[NSAnimationContext endGrouping];

पुनश्च: मैं स्टैक ओवरफ्लो की तुलना में ऐप्पल देव फ़ोरम पर पोस्ट किए गए प्रश्नों का अधिक जवाब देता हूं।

PSS: मैंने दृश्य आधारित NSTableView लिखा है


जवाब के लिए धन्यवाद। मैंने इसे मूल रूप से नहीं देखा था ... मैंने इसे सही उत्तर के रूप में चिह्नित किया है। देव मंच महान हैं, मैं उनका भी उपयोग करता हूं।
जीवा देवो

"उस दृश्य के लिए आवश्यक ऊंचाई का पता लगाएं। उस मूल्य को वापस करें।" .. यह मेरी समस्या है :(। मैं दृश्य-आधारित तालिका दृश्य का उपयोग कर रहा हूं, और मुझे नहीं पता कि यह कैसे करना है!
Mazyod

@ कॉर्बिन जवाब के लिए धन्यवाद, यह वही है जो मैंने अपने ऐप पर दिया था। हालाँकि, मुझे Mavericks के बारे में इससे एक समस्या मिली। चूँकि आप स्पष्ट रूप से इस विषय पर पारंगत हैं, तो क्या आप मेरे प्रश्न की जाँच करेंगे? यहां: stackoverflow.com/questions/20924141/…
एलेक्स

1
@corbin इसके लिए एक विहित उत्तर है, लेकिन NSTableViews के साथ ऑटो-लेआउट और बाधाओं का उपयोग करना? ऑटो-लेआउट के साथ एक संभावित समाधान है; सोच है कि estimatedHeightForRowAtIndexPath एपीआई के बिना काफी अच्छा (कोको में है कि नहीं है) है
ZS

3
@ZS: मैं ऑटो लेआउट का उपयोग कर रहा हूं और कोर्बिन के उत्तर को कार्यान्वित कर रहा हूं। में tableView:heightOfRow:, मैंने अपने स्पेयर सेल दृश्य को पंक्ति के मानों के साथ सेट किया (मेरे पास केवल एक कॉलम है), और वापसी cellView.fittingSize.heightfittingSizeएक NSView तरीका है जो उस दृश्य के न्यूनतम आकार की गणना करता है जो उसके अवरोधों को संतुष्ट करता है।
पीटर होसी

43

इसके साथ macOS 10.13 में बहुत आसान हो गया .usesAutomaticRowHeights। विवरण यहाँ हैं: https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKit/#10_13 ("NSTableView Automatic Row Heights" शीर्षक वाले अनुभाग में)।

मूल रूप से आप सिर्फ अपने NSTableViewया NSOutlineViewस्टोरीबोर्ड संपादक में चयन करते हैं और आकार निरीक्षक में इस विकल्प का चयन करते हैं:

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

फिर आप NSTableCellViewअपने सेल में ऊपर और नीचे की बाधाओं को रखने के लिए सामान सेट करते हैं और आपका सेल स्वचालित रूप से फिट होने के लिए आकार बदल देगा। कोई कोड की आवश्यकता है!

आपका एप्लिकेशन heightOfRow( NSTableView) और heightOfRowByItem( NSOutlineView) में निर्दिष्ट किसी भी ऊंचाइयों को अनदेखा करेगा । आप देख सकते हैं कि इस विधि से आपकी ऑटो लेआउट पंक्तियों के लिए क्या ऊँचाई की गणना की जा रही है:

func outlineView(_ outlineView: NSOutlineView, didAdd rowView: NSTableRowView, forRow row: Int) {
  print(rowView.fittingSize.height)
}

@tofutim: यदि आप सही अड़चनों का उपयोग करते हुए लिपटी हुई पाठ कोशिकाओं के साथ सही ढंग से काम करते हैं और जब आप यह सुनिश्चित करते हैं कि गतिशील ऊंचाई के साथ प्रत्येक NSTextField की पसंदीदा चौड़ाई सेटिंग, स्वचालित पर सेट है। यह भी देखें stackoverflow.com/questions/46890144/...
Ely

मैं बात करता हूं @tofutim सही है, यह काम नहीं करेगा यदि आप NSTextView को TableView में डालते हैं, तो यह इसे संग्रहित करने की कोशिश करता है लेकिन यह काम नहीं करता है। यह अन्य घटक के लिए काम करता है, उदाहरण के लिए NSImage ..
अल्बर्ट

मैंने एक पंक्ति के लिए एक निश्चित ऊँचाई का उपयोग किया है लेकिन यह मेरे लिए काम नहीं करता है
केन ज़िरा

2
यह पता लगाने के कुछ दिनों के बाद कि यह मेरे लिए काम क्यों नहीं करता है मुझे पता चला: यह केवल तभी काम करता है जब TableCellViewसंपादन योग्य नहीं होता है। एट्रिब्यूट्स [व्यवहार: संपादन योग्य] या बाइंडिंग इंस्पेक्टर [सशर्त रूप से संपादन योग्य: हाँ]
asukasz

मैं सिर्फ इस बात पर जोर देना चाहता हूं कि आपके टेबल सेल में वास्तविक ऊंचाई की कमी का होना कितना महत्वपूर्ण है: मेरा नहीं था, इसलिए सेल की गणना की गई फिटिंग ०.० थी और हताशा का सामना करना पड़ा।
हरे_कंठ

9

कॉर्बिन के जवाब पर आधारित (btw धन्यवाद इस पर कुछ प्रकाश बहा):

स्विफ्ट 3, मैक-10.11 (और ऊपर) के लिए ऑटो-लेआउट के साथ व्यू-आधारित NSTableView

मेरा सेटअप: मेरे पास एक NSTableCellViewऑटो-लेआउट का उपयोग करके रखी गई है। इसमें (अन्य तत्वों के अलावा) एक बहु-पंक्ति है NSTextFieldजिसमें 2 पंक्तियाँ हो सकती हैं। इसलिए, पूरे सेल दृश्य की ऊंचाई इस पाठ क्षेत्र की ऊंचाई पर निर्भर करती है।

मैं दो मौकों पर ऊंचाई को अपडेट करने के लिए टेबल व्यू बताता हूं:

1) जब टेबल दृश्य आकार बदलता है:

func tableViewColumnDidResize(_ notification: Notification) {
        let allIndexes = IndexSet(integersIn: 0..<tableView.numberOfRows)
        tableView.noteHeightOfRows(withIndexesChanged: allIndexes)
}

2) जब डेटा मॉडल ऑब्जेक्ट बदलता है:

tableView.noteHeightOfRows(withIndexesChanged: changedIndexes)

यह तालिका दृश्य को नई पंक्ति ऊंचाई के लिए प्रतिनिधि के रूप में पूछने का कारण बनेगा।

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {

    // Get data object for this row
    let entity = dataChangesController.entities[row]

    // Receive the appropriate cell identifier for your model object
    let cellViewIdentifier = tableCellViewIdentifier(for: entity)

    // We use an implicitly unwrapped optional to crash if we can't create a new cell view
    var cellView: NSTableCellView!

    // Check if we already have a cell view for this identifier
    if let savedView = savedTableCellViews[cellViewIdentifier] {
        cellView = savedView
    }
    // If not, create and cache one
    else if let view = tableView.make(withIdentifier: cellViewIdentifier, owner: nil) as? NSTableCellView {
        savedTableCellViews[cellViewIdentifier] = view
        cellView = view
    }

    // Set data object
    if let entityHandler = cellView as? DataEntityHandler {
        entityHandler.update(with: entity)
    }

    // Layout
    cellView.bounds.size.width = tableView.bounds.size.width
    cellView.needsLayout = true
    cellView.layoutSubtreeIfNeeded()

    let height = cellView.fittingSize.height

    // Make sure we return at least the table view height
    return height > tableView.rowHeight ? height : tableView.rowHeight
}

सबसे पहले, हमें पंक्ति ( entity) और उचित सेल दृश्य पहचानकर्ता के लिए अपना मॉडल ऑब्जेक्ट प्राप्त करने की आवश्यकता है । हम तब जांचते हैं कि क्या हमने पहले से ही इस पहचानकर्ता के लिए एक दृश्य बना लिया है। ऐसा करने के लिए हमें प्रत्येक पहचानकर्ता के लिए सेल विचारों के साथ एक सूची बनाए रखनी होगी:

// We need to keep one cell view (per identifier) around
fileprivate var savedTableCellViews = [String : NSTableCellView]()

यदि कोई नहीं बचा है, तो हमें एक नया (और कैश) बनाना होगा। हम अपने मॉडल ऑब्जेक्ट के साथ सेल दृश्य को अपडेट करते हैं और इसे वर्तमान तालिका दृश्य चौड़ाई के आधार पर सब कुछ फिर से लेआउट करने के लिए कहते हैं। fittingSizeऊंचाई फिर नए ऊंचाई के रूप में इस्तेमाल किया जा सकता।


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

इसके अलावा, जैसा कि आप सेट करते हैं cellView.bounds.size.width = tableView.bounds.size.width, कम ऊंचाई को रीसेट करना एक अच्छा विचार है। यदि आप इस डमी दृश्य का पुन: उपयोग करने की योजना बनाते हैं, तो इसे कम संख्या पर सेट करने से फिटिंग का आकार "रीसेट" हो जाएगा।
वोज्टो

7

अधिक कोड चाहने वाले किसी भी व्यक्ति के लिए, यहां पूर्ण समाधान है जिसका मैंने उपयोग किया है। मुझे सही दिशा में इशारा करने के लिए धन्यवाद कॉर्बिन डन।

मुझे अपने संबंध में ऊँचाई निर्धारित करने की आवश्यकता थी कि NSTextViewमेरे अंदर कितनी ऊँचाई NSTableViewCellथी।

NSViewControllerअस्थायी रूप से मेरे उपवर्ग में कॉल करके एक नया सेल बनाते हैंoutlineView:viewForTableColumn:item:

- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
{
    NSTableColumn *tabCol = [[outlineView tableColumns] objectAtIndex:0];
    IBAnnotationTableViewCell *tableViewCell = (IBAnnotationTableViewCell*)[self outlineView:outlineView viewForTableColumn:tabCol item:item];
    float height = [tableViewCell getHeightOfCell];
    return height;
}

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    IBAnnotationTableViewCell *tableViewCell = [outlineView makeViewWithIdentifier:@"AnnotationTableViewCell" owner:self];
    PDFAnnotation *annotation = (PDFAnnotation *)item;
    [tableViewCell setupWithPDFAnnotation:annotation];
    return tableViewCell;
}

मेरे में IBAnnotationTableViewCellजो मेरे सेल के लिए नियंत्रक (के उपवर्ग है NSTableCellView) मैं एक सेटअप विधि है

-(void)setupWithPDFAnnotation:(PDFAnnotation*)annotation;

जो सभी आउटलेट सेट करता है और मेरे PDFAnnotations से पाठ सेट करता है। अब मैं "आसानी से" का उपयोग करके ऊंचाई को शांत कर सकता हूं:

-(float)getHeightOfCell
{
    return [self getHeightOfContentTextView] + 60;
}

-(float)getHeightOfContentTextView
{
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[self.contentTextView font],NSFontAttributeName,nil];
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[self.contentTextView string] attributes:attributes];
    CGFloat height = [self heightForWidth: [self.contentTextView frame].size.width forString:attributedString];
    return height;
}

- (NSSize)sizeForWidth:(float)width height:(float)height forString:(NSAttributedString*)string
{
    NSInteger gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ;
    NSSize answer = NSZeroSize ;
    if ([string length] > 0) {
        // Checking for empty string is necessary since Layout Manager will give the nominal
        // height of one line if length is 0.  Our API specifies 0.0 for an empty string.
        NSSize size = NSMakeSize(width, height) ;
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:size] ;
        NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:string] ;
        NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init] ;
        [layoutManager addTextContainer:textContainer] ;
        [textStorage addLayoutManager:layoutManager] ;
        [layoutManager setHyphenationFactor:0.0] ;
        if (gNSStringGeometricsTypesetterBehavior != NSTypesetterLatestBehavior) {
            [layoutManager setTypesetterBehavior:gNSStringGeometricsTypesetterBehavior] ;
        }
        // NSLayoutManager is lazy, so we need the following kludge to force layout:
        [layoutManager glyphRangeForTextContainer:textContainer] ;

        answer = [layoutManager usedRectForTextContainer:textContainer].size ;

        // Adjust if there is extra height for the cursor
        NSSize extraLineSize = [layoutManager extraLineFragmentRect].size ;
        if (extraLineSize.height > 0) {
            answer.height -= extraLineSize.height ;
        }

        // In case we changed it above, set typesetterBehavior back
        // to the default value.
        gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ;
    }

    return answer ;
}

- (float)heightForWidth:(float)width forString:(NSAttributedString*)string
{
    return [self sizeForWidth:width height:FLT_MAX forString:string].height ;
}

ऊँचाई कहाँ है
जेडएस

उसके लिए माफ़ करना। इसे उत्तर में जोड़ा गया। मूल SO पोस्ट को खोजने की कोशिश की, जो मुझे इस से मिली, लेकिन यह नहीं मिली।
सनकास

1
धन्यवाद! यह मेरे लिए लगभग काम कर रहा है, लेकिन यह मुझे गलत परिणाम देता है। मेरे मामले में, NSTextContainer में जो चौड़ाई मैं फीड कर रहा हूं वह गलत है। क्या आप अपने NSTableViewCell के साक्षात्कार को परिभाषित करने के लिए ऑटो लेआउट का उपयोग कर रहे हैं? "Self.contentTextView" की चौड़ाई कहाँ से आती है?
ZS

मैंने अपनी समस्या के बारे में एक प्रश्न यहाँ पोस्ट किया: stackoverflow.com/questions/22929441/…
ZS

3

मैं काफी समय से एक समाधान की तलाश में था और निम्नलिखित के साथ आया, जो मेरे मामले में बहुत अच्छा काम करता है:

- (double)tableView:(NSTableView *)tableView heightOfRow:(long)row
{
    if (tableView == self.tableViewTodo)
    {
        CKRecord *record = [self.arrayTodoItemsFiltered objectAtIndex:row];
        NSString *text = record[@"title"];

        double someWidth = self.tableViewTodo.frame.size.width;
        NSFont *font = [NSFont fontWithName:@"Palatino-Roman" size:13.0];
        NSDictionary *attrsDictionary =
        [NSDictionary dictionaryWithObject:font
                                    forKey:NSFontAttributeName];
        NSAttributedString *attrString =
        [[NSAttributedString alloc] initWithString:text
                                        attributes:attrsDictionary];

        NSRect frame = NSMakeRect(0, 0, someWidth, MAXFLOAT);
        NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
        [[tv textStorage] setAttributedString:attrString];
        [tv setHorizontallyResizable:NO];
        [tv sizeToFit];

        double height = tv.frame.size.height + 20;

        return height;
    }

    else
    {
        return 18;
    }
}

मेरे मामले में, मैं किसी दिए गए कॉलम को लंबवत रूप से विस्तारित करना चाहता था ताकि उस लेबल पर प्रदर्शित टेक्स्ट सभी में फिट हो जाए। इसलिए मुझे प्रश्न में कॉलम मिलता है और फ़ॉन्ट और उस से चौड़ाई को पकड़ो।
क्लेज्ड डेडा

3

चूंकि मैं कस्टम का उपयोग करता हूं NSTableCellViewऔर मेरे पास NSTextFieldमेरे समाधान तक पहुंच है, इसलिए मुझे एक विधि को जोड़ना पड़ा NSTextField

@implementation NSTextField (IDDAppKit)

- (CGFloat)heightForWidth:(CGFloat)width {
    CGSize size = NSMakeSize(width, 0);
    NSFont*  font = self.font;
    NSDictionary*  attributesDictionary = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
    NSRect bounds = [self.stringValue boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:attributesDictionary];

    return bounds.size.height;
}

@end

धन्यवाद! तुम मेरे तारणहार हो! यह सही ढंग से काम करने वाला एकमात्र है। मैंने यह पता लगाने के लिए एक पूरा दिन बिताया।
टॉमी

2

क्या आपने RowResizableViews पर एक नज़र डाली है ? यह काफी पुराना है और मैंने इसका परीक्षण नहीं किया है लेकिन फिर भी यह काम कर सकता है।


2

यहाँ मैंने इसे ठीक करने के लिए क्या किया है:

स्रोत: "पंक्ति ऊंचाई nstableview" के तहत XCode प्रलेखन में देखें। आपको "TableViewVariableRowHeights / TableViewVariableRowHeightsAppDelegate.m" नाम का एक नमूना स्रोत कोड मिलेगा।

(नोट: मैं तालिका 1 में कॉलम देख रहा हूं, आपको कहीं और देखना होगा)

डेलीगेट में

IBOutlet NSTableView            *ideaTableView;

डेलिगेट में

तालिका दृश्य प्रतिनिधियों को पंक्ति ऊँचाई का नियंत्रण देता है

    - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
    // Grab the fully prepared cell with our content filled in. Note that in IB the cell's Layout is set to Wraps.
    NSCell *cell = [ideaTableView preparedCellAtColumn:1 row:row];

    // See how tall it naturally would want to be if given a restricted with, but unbound height
    CGFloat theWidth = [[[ideaTableView tableColumns] objectAtIndex:1] width];
    NSRect constrainedBounds = NSMakeRect(0, 0, theWidth, CGFLOAT_MAX);
    NSSize naturalSize = [cell cellSizeForBounds:constrainedBounds];

    // compute and return row height
    CGFloat result;
    // Make sure we have a minimum height -- use the table's set height as the minimum.
    if (naturalSize.height > [ideaTableView rowHeight]) {
        result = naturalSize.height;
    } else {
        result = [ideaTableView rowHeight];
    }
    return result;
}

नई पंक्ति ऊंचाई (प्रत्यायोजित विधि) को प्रभावित करने के लिए भी आपको इसकी आवश्यकता है

- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
    [ideaTableView reloadData];
}

आशा है कि ये आपकी मदद करेगा।

अंतिम नोट: यह कॉलम की चौड़ाई को बदलने का समर्थन नहीं करता है।


आपने धमाल मचाया! :) धन्यवाद।
ध्वजवाहक

4
दुर्भाग्य से यह है कि Apple नमूना कोड (जिसे वर्तमान में संस्करण 1.1 के रूप में चिह्नित किया गया है) एक सेल-आधारित तालिका का उपयोग करता है, न कि एक दृश्य-आधारित तालिका (जिसका यह प्रश्न है)। कोड कहता है -[NSTableView preparedCellAtColumn:row], जो डॉक्स कहते हैं "केवल NSCell- आधारित तालिका विचारों के लिए उपलब्ध है"। दृश्य-आधारित तालिका पर इस विधि का उपयोग करने से यह लॉग आउटपुट रन टाइम पर उत्पन्न होता है: "आधारित NSTableView त्रुटि देखें: तैयार किया गयाCalAtColumn: row: कहा जाता था। कृपया इस लॉग से बैकट्रेस के साथ बग लॉग करें, या विधि का उपयोग करना बंद करें"
एशले

1

यहाँ JanApotheker के उत्तर के आधार पर एक समाधान है, जिसे संशोधित cellView.fittingSize.heightकरके मेरे लिए सही ऊँचाई नहीं दी जा रही है। मेरे मामले में, मैं मानक का उपयोग कर रहा हूं NSTableCellView, NSAttributedStringसेल के टेक्स्टफिल्ड टेक्स्ट के लिए, और आईबी में सेट सेल के टेक्स्टफिल्ड के लिए बाधाओं के साथ एक एकल स्तंभ तालिका।

मेरे विचार नियंत्रक में, मैं घोषणा करता हूं:

var tableViewCellForSizing: NSTableCellView?

ViewDidLoad () में:

tableViewCellForSizing = tableView.make(withIdentifier: "My Identifier", owner: self) as? NSTableCellView

अंत में, तालिका दृश्य प्रतिनिधि विधि के लिए:

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    guard let tableCellView = tableViewCellForSizing else { return minimumCellHeight }

    tableCellView.textField?.attributedStringValue = attributedString[row]
    if let height = tableCellView.textField?.fittingSize.height, height > 0 {
        return height
    }

    return minimumCellHeight
}

mimimumCellHeightबैकअप के लिए 30 के लिए एक निरंतर सेट है, लेकिन वास्तव में कभी भी उपयोग नहीं किया जाता है। attributedStringsके अपने मॉडल सरणी है NSAttributedString

यह मेरी जरूरतों के लिए पूरी तरह से काम करता है। पिछले सभी उत्तरों के लिए धन्यवाद, जिसने मुझे इस पेसकी समस्या के लिए सही दिशा में इंगित किया।


1
बहुत अच्छा। एक मुद्दा। तालिका संपादन योग्य नहीं हो सकती है या textfield.fittingSize.height काम नहीं करेगी और शून्य वापस आ जाएगी। तालिका सेट करें। दृश्यमान = दृश्यदर्शी में झूठा
jiminybob99

0

यह बहुत कुछ लगता है जैसे मुझे पहले करना था। काश मैं आपको बता सकता कि मैं एक सरल, सुरुचिपूर्ण समाधान के साथ आया लेकिन, अफसोस, मैंने नहीं किया। हालांकि कोशिश की कमी के लिए नहीं। जैसा कि आपने पहले ही UITableView की आवश्यकता पर ध्यान दिया है ताकि वास्तव में निर्मित होने वाली कोशिकाओं से पहले ऊँचाई जानने के लिए यह सब काफी परिपत्र हो।

मेरा सबसे अच्छा समाधान तर्क को सेल में धकेलना था, क्योंकि कम से कम मैं अलग कर सकता था कि किस वर्ग को यह समझने की जरूरत है कि कोशिकाओं को कैसे रखा गया था। जैसी विधि

+ (CGFloat) heightForStory:(Story*) story

यह निर्धारित करने में सक्षम होगा कि सेल कितना लंबा होना चाहिए था। बेशक, जिसमें टेक्स्ट को मापना शामिल है, आदि। कुछ मामलों में मैंने इस पद्धति के दौरान प्राप्त जानकारी को कैश करने के तरीके तैयार किए, जो तब उपयोग किए जा सकते थे जब सेल बनाया गया था। वह सबसे अच्छा था जो मैं लेकर आया था। यह एक समस्या है, हालांकि ऐसा लगता है कि एक बेहतर जवाब होना चाहिए।

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