2010-01-21 4 views
8

Ich habe eine NSCollectionView, die eine Sammlung von CustomViews enthält. Anfangs wurden die Unteransichten wie ein Gitter in Spalten und Zeilen gekachelt. Ich habe dann die Eigenschaft Columns in IB auf 1 gesetzt, so dass sie nun nacheinander in Reihen angezeigt werden. Obwohl meine CustomView 400 Pixel breit ist, ist sie auf Autoresize eingestellt, die ist 400 Pixel breit, und sie ist auf 1 Spalte eingestellt, die Unteransichten sind etwa 80 Pixel breit.Kann NSCollectionView die Breite seiner Unteransichten autorisieren, um eine Spalte anzuzeigen

Ich weiß, ich kann dieses Problem umgehen, durch den Aufruf:

CGFloat width = collectionView.bounds.size.width; 
NSSize size = NSMakeSize(width, 85); 
[collectionView setMinItemSize:size]; 
[collectionView setMaxItemSize:size]; 

Aber setze diesen Code in der awakeFromNib Methode meines WindowController setzt nur die richtige Breite, wenn das Programm startet. Wenn ich die Größe des Fensters ändere (und die Autoresize wie ich angegeben habe), bleiben die CustomViews auf der ursprünglich eingestellten Breite.

Ich kümmere mich gerne um die Größenanpassung der Unteransichten, wenn es sein muss, aber ich bin ziemlich neu in Cocoa und kann anscheinend keine Artikel finden, die erklären, wie man so etwas macht. Kann mir jemand in die richtige Richtung zeigen?

Anthony

+0

dass entdeckt haben jetzt brauchen Ich kann meinen WindowController als den Delegaten des Windows festlegen und Größenänderung Benachrichtigungen über WindowDidResize erhalten. Also verwende ich jetzt den Code über jedes Mal, wenn das Fenster die Größe ändert, um die Max- und Min-Artikelgrößen einzustellen. Dies funktioniert gut, wenn das Fenster wächst, aber aus irgendeinem Grund die Erhöhung der Min/Max Item Größen bewirkt, dass die Grenzen der CollectionView nie schrumpfen, auch wenn das Fenster dies tut. Also, obwohl die CollectionView visuell schrumpft, wenn ich die Größe des Fensters ändern, ist es Grenzen, und dort für meine Subviews auch nicht! – littlecharva

+0

Haben Sie jemals einen Weg gefunden, dies automatisch zu tun? – tofutim

Antwort

-2

Matt Gallagher wunderbare Blog Cocoa with Love ist über an diese Adresse. In dieser Woche teilte er die Bindungen Details eines Ein-Spalten-Ansicht wie die in Frage:

http://cocoawithlove.com/2010/03/designing-view-with-bindings.html

Nächster Eintrag, verspricht er den Rest der Umsetzung zu teilen, was sollten Sie geben, was du bist Auf der Suche nach.

(sollte ich beachten Sie, dass er NSView ist Subklassen direkt und Neuimplementierung viele NSCollectionView-Funktionen Dies scheint allerdings üblich zu sein, nicht viele Leute sind gern von Subklassen NSCollectionView..)

Edit: scheint er hat sein Versprechen gebrochen ... wir haben diesen Posten nie erhalten. Siehe unten Tofutims Antwort.

3

Ich weiß, das ist eine sehr späte Antwort, aber ich habe das gleiche Problem und hoffe, meine Lösung wird jemandem helfen. Die Lösung besteht darin, auf die Grenzen der umschließenden Bildlaufansicht und nicht auf die Sammlungsansicht selbst zuzugreifen. Also, es zu lösen müssen Sie mit dem ersten Linie ersetzen:

CGFloat width = collectionView.enclosingScrollView.bounds.size.width; 
+0

Wo ist die Breite eingestellt? – tofutim

+0

Ich habe versucht, es mit watchFromNib einstellen - etwa 60% der Zeit, das funktioniert - aber seltsam in den anderen 40% der Zeit hat die umschließende ScrollView 0 Breite. Ich habe das Gefühl, dass XCode irgendwie etwas zwischenspeichert und es endet damit, die Feder wieder herzustellen, ohne sie richtig aufzubauen. – tofutim

9

Die wahre Antwort ist die MaxItemSize auf 0,0 (NSZeroSize) einzustellen. Andernfalls wird es berechnet.

[self.collectionView setMaxItemSize:NSZeroSize]; 

Dies kann in awakeFromNib eingestellt werden.

+0

Das ist so einfach und es tut genau das, was ich brauchte. Die Elemente in meiner Sammlungsansicht werden jetzt mit der Sammlungsansicht genau so geändert, wie ich es beabsichtigt habe. – Chris

1

ein anderes spätes - ich habe gerade auf die Verwendung einer NSTableView und Bereitstellung einer NSView von der delegate Methode umgeschaltet.

Autoresizing ist kostenlos, eine Spalte ist einfach, und es rendert massiv schneller.

0

Lets sagen, Sie wollen Ihre CollectionViewItem mit einer Größe von 200x180px, dann sollten Sie Folgendes einstellen:

[myCollectionView setMinItemSize:NSMakeSize(200, 180)]; 
[myCollectionView setMaxItemSize:NSMakeSize(280, 250)]; 

Ihre Max-Größe groß genug sein sollte, um gut auszusehen und genügend Platz zum Strecken des collectionView- passen Breite.

Wenn Sie eine feste Anzahl von Spalten haben, können Sie wahrscheinlich (0,0) verwenden, aber wenn Sie eine dynamische Anzahl von Zeilen und Spalten wie ich wollen .. sollten Sie eine feste Mindestgröße und eine größere festlegen maximale Größe.

0

Während Sie vielleicht eine Sammlung Ansichten zu verhalten, wie Sie wollen, ich glaube, Sie ein Design-Problem haben

Sie sollten eine NSTableView verwenden und Spalten 1 und deren Dimensionierung auf alles eingestellt, aber „None“. NSTableView ist für tabellarische Daten gedacht, und es kann Zellen recyceln, was einen großen Leistungsschub für eine große Menge von Gegenständen ergibt. ist mehr wie ein lineares Layout, das Elemente in einem Raster mit vertikalem Scrollen anordnet. Dies ist nützlich, wenn sich die Spaltennummer dynamisch ändern kann, damit mehr Elemente auf dem Bildschirm angezeigt werden können. Dies hängt normalerweise von der Geräteausrichtung und der Bildschirmgröße ab.

2

konnte ich nicht bekommen dies mit einem Standard-Layout zu arbeiten - aber es ist ziemlich einfach, ein eigenes Layout zu implementieren:

/// Simple single column layout, assuming only one section 
class SingleColumnLayout: NSCollectionViewLayout { 

    /// Height of each view in the collection 
    var height:CGFloat = 100 

    /// Padding is wrapped round each item, with double an extra bottom padding above the top item, and an extra top padding beneath the bottom 
    var padding = EdgeInsets.init(top: 5, left: 10, bottom: 5, right: 10) 

    var itemCount:Int { 
     guard let collectionView = collectionView else { 
      return 0 
     } 

     return collectionView.numberOfItems(inSection:0) 
    } 

    override func shouldInvalidateLayout(forBoundsChange newBounds: NSRect) -> Bool { 
     return true 
    } 

    override open func layoutAttributesForItem(at indexPath: IndexPath) -> NSCollectionViewLayoutAttributes? { 
     let attributes = NSCollectionViewLayoutAttributes(forItemWith: indexPath) 
     guard let collectionView = collectionView else { 
      return attributes 
     } 

     let bounds = collectionView.bounds 
     let itemHeightWithPadding = height + padding.top + padding.bottom 
     let row = indexPath.item 

     attributes.frame = NSRect(x: padding.left, y: itemHeightWithPadding * CGFloat(row) + padding.top + padding.bottom , width: bounds.width - padding.left - padding.right , height: height) 
     attributes.zIndex = row 

     return attributes 
    } 

    //If you have lots of items, then you should probably do a 'proper' implementation here 
    override open func layoutAttributesForElements(in rect: NSRect) -> [NSCollectionViewLayoutAttributes] { 
     var attributes = [NSCollectionViewLayoutAttributes]() 

     if (itemCount>0){ 
      for index in 0...(itemCount-1) { 
       if let attribute = layoutAttributesForItem(at: NSIndexPath(forItem: index, inSection: 0) as IndexPath) { 
        attributes.append(attribute) 
       } 
      } 
     } 

     return attributes 
    } 

    override open var collectionViewContentSize: NSSize { 

     guard let collectionView = collectionView else { 
      return NSSize.zero 
     } 

     let itemHeightWithPadding = height + padding.top + padding.bottom 

     return NSSize.init(width: collectionView.bounds.width, height: CGFloat(itemCount) * itemHeightWithPadding + padding.top + padding.bottom) 
    } 
} 

dann alles, was Sie

var layout=SingleColumnLayout() 
collectionView.collectionViewLayout = layout