J'essaie de créer une vue de collection avec des cellules affichant une chaîne de longueur variable.
J'utilise cette fonction pour définir la disposition des cellules:
func collectionView(collectionView : UICollectionView,layout collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath) -> CGSize
{
var cellSize:CGSize = CGSizeMake(self.whyCollectionView.frame.width, 86)
return cellSize
}
ce que j'aimerais faire, c'est manipuler cellSize.height
basé sur mon cell.labelString.utf16Count
longueur. la logique de base serait de sa que
if((cell.labelString.text) > 70){
cellSize.height = x
}
else{
cellSize.height = y
}
Cependant, je ne parviens pas à récupérer la longueur de chaîne de mon étiquette de cellule qui renvoie toujours la valeur nil. (Je pense que ce n'est pas encore chargé ...
pour une meilleure compréhension, voici le code complet:
// 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
}
Vous pouvez définir de manière dynamique le cadre de la cellule dans la fonction cellForItemAtIndexPath
afin de personnaliser la hauteur en fonction d'une étiquette si vous ignorez la fonction sizeForItemAtIndexPath
. Avec la personnalisation de la taille, vous devrez probablement vous pencher sur le flux de présentation de la vue Collection, mais espérons que cela vous oriente dans la bonne direction. Cela peut ressembler à quelque chose comme ça:
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)
}
}
qui donne des hauteurs dynamiques comme si
Bien que la réponse ci-dessus puisse résoudre votre problème, elle établit une manière assez rudimentaire d’affecter la hauteur de chaque cellule. Vous êtes obligé de coder en dur chaque hauteur de cellule en vous basant sur une estimation. Une meilleure façon de traiter ce problème consiste à définir la hauteur de chaque cellule dans la méthode sizeForItemAtIndexPath
delegate de la collectionview.
Je vais vous expliquer les étapes à suivre ci-dessous.
Étape 1: Améliorez votre classe UICollectionViewDelegateFlowLayout
Étape 2: Créez une fonction pour estimer la taille de votre texte: Cette méthode renverra une valeur de hauteur qui conviendra à votre chaîne!
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)
}
Étape 3: Utilisez ou substituez la méthode déléguée ci-dessous:
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)
}
Dans Swift 3, utilisez la méthode ci-dessous:
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()
}
}