collection automatic layout swift height uicollectionview

layout - automatic - uicollectionview dynamic cell size



CollectionView Dynamic cell height swift (3)

Estoy intentando crear una vista de colección con celdas que muestran una cadena con longitud variable.

Estoy usando esta función para establecer el diseño de la celda:

func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize { var cellSize:CGSize = CGSizeMake(self.whyCollectionView.frame.width, 86) return cellSize }

Lo que me gustaría hacer es manipular cellSize.height función de mi longitud de cell.labelString.utf16Count . La lógica básica sería sa que

if((cell.labelString.text) > 70){ cellSize.height = x } else{ cellSize.height = y }

Sin embargo, no puedo recuperar la longitud de la cadena de la etiqueta de mi celda que siempre devuelve nula. (Creo que aún no está cargado ...

Para una mejor comprensión, aquí está el código completo:

// WhyCell section var whyData:NSMutableArray! = NSMutableArray() var textLength:Int! @IBOutlet weak var whyCollectionView: UICollectionView! //Loading data @IBAction func loadData() { whyData.removeAllObjects() var findWhyData:PFQuery = PFQuery(className: "PlacesWhy") findWhyData.whereKey("placeName", equalTo: placeName) findWhyData.findObjectsInBackgroundWithBlock({ (objects:[AnyObject]!,error:NSError!)->Void in if (error == nil) { for object in objects { self.whyData.addObject(object) } let array:NSArray = self.whyData.reverseObjectEnumerator().allObjects self.whyData = array.mutableCopy() as NSMutableArray self.whyCollectionView.reloadData() println("loadData completed. datacount is /(self.whyData.count)") } }) } override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. self.loadData() } func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 1 } func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return whyData.count } func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell:whyCollectionViewCell = whyCollectionView.dequeueReusableCellWithReuseIdentifier("whyCell", forIndexPath: indexPath) as whyCollectionViewCell // Loading content from NSMutableArray to cell let therew:PFObject = self.whyData.objectAtIndex(indexPath.row) as PFObject cell.userWhy.text = therew.objectForKey("why") as String! textLength = (therew.objectForKey("why") as String!).utf16Count self.whyCollectionView.layoutSubviews() // Displaying user information var whatUser:PFQuery = PFUser.query() whatUser.whereKey("objectId", equalTo: therew.objectForKey("reasonGivenBy").objectId) whatUser.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]!, error: NSError!)->Void in if !(error != nil) { if let user:PFUser = (objects as NSArray).lastObject as? PFUser { cell.userName.text = user.username // TODO Display avatar } } }) return cell } func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize { var cellSize:CGSize = CGSizeMake(self.whyCollectionView.frame.width, 86) return cellSize }


En Swift 3, use el siguiente método:

private func updateCollectionViewLayout(with size: CGSize) { var margin : CGFloat = 0; if isIPad { margin = 10 } else{ margin = 6 /* if UIDevice.current.type == .iPhone6plus || UIDevice.current.type == .iPhone6Splus || UIDevice.current.type == .simulator{ margin = 10 } */ } if let layout = menuCollectionView.collectionViewLayout as? UICollectionViewFlowLayout { layout.itemSize = CGSize(width:(self.view.frame.width/2)-margin, height:((self.view.frame.height-64)/4)-3) layout.invalidateLayout() } }


Puede establecer dinámicamente el marco de la celda en la función cellForItemAtIndexPath , por lo que puede personalizar la altura en función de una etiqueta si ignora la función sizeForItemAtIndexPath . Con la personalización del tamaño, es probable que tenga que ver el flujo de diseño de la vista de colección, pero espero que esto le indique la dirección correcta. Puede parecer algo como esto:

class CollectionViewController: UICollectionViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout { var array = ["a","as","asd","asdf","asdfg","asdfgh","asdfghjk","asdfghjklas","asdfghjkl","asdghjklkjhgfdsa"] var heights = [10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,110.0] as [CGFloat] override func viewDidLoad() { super.viewDidLoad() } override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int { return 1 } override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return array.count } override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellID", forIndexPath: indexPath) as Cell cell.textLabel.text = array[indexPath.row] cell.textLabel.sizeToFit() // Customize cell height cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, heights[indexPath.row]) return cell } func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { return CGSizeMake(64, 64) } }

Lo que da alturas dinámicas como tal.


Si bien la respuesta anterior puede resolver su problema, establece una forma bastante burda de asignar la altura de cada celda. Se le obliga a codificar de forma rígida cada altura de celda en función de alguna estimación. Una mejor manera de manejar este problema es estableciendo la altura de cada celda en el método delegado sizeForItemAtIndexPath la sizeForItemAtIndexPath de colección.

Te guiaré a través de los pasos sobre cómo hacer esto a continuación.

Paso 1: Haz que tu clase extienda UICollectionViewDelegateFlowLayout

Paso 2: crea una función para estimar el tamaño de tu texto: ¡Este método devolverá un valor de altura que se ajustará a tu cadena!

private func estimateFrameForText(text: String) -> CGRect { //we make the height arbitrarily large so we don''t undershoot height in calculation let height: CGFloat = <arbitrarilyLargeValue> let size = CGSize(width: yourDesiredWidth, height: height) let options = NSStringDrawingOptions.UsesFontLeading.union(.UsesLineFragmentOrigin) let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18, weight: UIFontWeightLight)] return NSString(string: text).boundingRectWithSize(size, options: options, attributes: attributes, context: nil) }

Paso 3: Utilice o anule el método de delegado a continuación:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { var height: CGFloat = <someArbitraryValue> //we are just measuring height so we add a padding constant to give the label some room to breathe! var padding: CGFloat = <someArbitraryPaddingValue> //estimate each cell''s height if let text = array?[indexPath.item].text { height = estimateFrameForText(text).height + padding } return CGSize(width: yourDesiredWidth, height: height) }