Tengo un UICollectionView, que carga celdas de una celda reutilizable, que contiene una etiqueta. Una matriz proporciona contenido para esa etiqueta. Puedo cambiar el tamaño del ancho de la etiqueta dependiendo del ancho del contenido fácilmente con sizeToFit. Pero no puedo hacer que la celda se ajuste a la etiqueta.
Aqui esta el codigo
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
arrayOfStats = @[@"time:",@"2",@"items:",@"10",@"difficulty:",@"hard",@"category:",@"main"];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection: (NSInteger)section{
return [arrayOfStats count];
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return CGSizeMake(??????????);
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
Cell *cell = (Cell *) [collectionView dequeueReusableCellWithReuseIdentifier:@"qw" forIndexPath:indexPath];
cell.myLabel.text = [NSString stringWithFormat:@"%@",[arrayOfStats objectAtIndex:indexPath.item]];
// make label width depend on text width
[cell.myLabel sizeToFit];
//get the width and height of the label (CGSize contains two parameters: width and height)
CGSize labelSize = cell.myLbale.frame.size;
NSLog(@"\n width = %f height = %f", labelSize.width,labelSize.height);
return cell;
}
Respuestas:
A
sizeForItemAtIndexPath
cambio del tamaño del texto- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL]; }
fuente
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{ Cell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"qw" forIndexPath:indexPath]; cell.myLbale.text = [NSString stringWithFormat:@"%@",[arrayOfStats objectAtIndex:indexPath.item]]; CGSize textSize; textSize = [[arrayOfStats objectAtIndex:indexPath.item] sizeWithAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0f]}]; [cell.myLbale sizeThatFits:textSize]; //[cell.myLbale sizeToFit]; return cell; }
Swift 4.2+
El principio es:
Asegúrese de que la delegación esté configurada (p
collectionView.delegate = self
. Ej. )Implementar
UICollectionViewDelegateFlowLayout
(contiene la firma del método necesaria).collectionView...sizeForItemAt
Método de llamada .No hay necesidad de puente de fundición
String
aNSString
al llamadosize(withAttributes:
método. Swift loString
tiene listo para usar.Los atributos son los mismos para los que configuró
(NS)AttributedString
, es decir, familia de fuentes, tamaño, peso, etc. Parámetro opcional.Solución de muestra:
extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return "String".size(withAttributes: nil) } }
Pero lo más probable es que desee especificar atributos de cadena concretos respectivos a su celda, por lo que el retorno final se vería así:
extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { // dataArary is the managing array for your UICollectionView. let item = dataArray[indexPath.row] let itemSize = item.size(withAttributes: [ NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14) ]) return itemSize } }
¿Por qué NO DEBE utilizar UILabel para calcular el tamaño? Aquí está la solución sugerida:
let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit()
Sí, obtienes el mismo resultado. Parece simplista y puede parecer una solución de referencia. Pero es incorrecto porque: 1) es caro, 2) elevado y 3) sucio.
Es caro porque UILabel es un objeto de interfaz de usuario complejo, que se crea en cada iteración cada vez que su celda está a punto de mostrarse, aunque no lo necesite aquí. Es una solución general porque solo necesita obtener el tamaño de un texto, pero llega a crear un objeto de interfaz de usuario completo. Y está sucio por esa razón.
fuente
collectionView.delegate == self // or whatever-object-which-do-it
CGSize(width: title.size(withAttributes: [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16)]).width + 5, height: 50)
Encontré un pequeño truco para Swift 4.2
Para ancho dinámico y alto fijo:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit() return CGSize(width: label.frame.width, height: 32) }
Para altura dinámica y ancho fijo:
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit() return CGSize(width: 120, height: label.frame.height) }
fuente
sizeWithAttributes
, por lo que tal vez esa sea la respuesta preferida.Verifique el código a continuación que podría estar dando CGSize muy corto.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ NSString *testString = @"SOME TEXT"; return [testString sizeWithAttributes:NULL]; }
fuente
En Swift 3
let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil)
fuente
Rápido 4
let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil)
fuente
// agregar en vista didload
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; layout.estimatedItemSize = CGSizeMake(self.breadScrumbCollectionView.frame.size.width, 30); self.breadScrumbCollectionView.collectionViewLayout = layout;
fuente