Mam UICollectionView, który ładuje komórki z komórki wielokrotnego użytku, która zawiera etykietę. Tablica zawiera treść dla tej etykiety. Mogę łatwo zmienić szerokość etykiety w zależności od szerokości treści za pomocą sizeToFit. Ale nie mogę dopasować komórki do etykiety.
Oto kod
- (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;
}
Odpowiedzi:
W
sizeForItemAtIndexPath
zamian rozmiar tekstu- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL]; }
źródło
- (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+
Zasada jest taka:
Upewnij się, że delegowanie zostało skonfigurowane (np.
collectionView.delegate = self
)Implement
UICollectionViewDelegateFlowLayout
(zawiera niezbędną sygnaturę metody).collectionView...sizeForItemAt
Metoda wywołania .Nie ma potrzeby, aby most-cast
String
, abyNSString
do połączeniasize(withAttributes:
metody. SwiftString
ma to po wyjęciu z pudełka.Atrybuty są takie same, jak ustawiłeś
(NS)AttributedString
, np. Rodzina czcionki, rozmiar, grubość itp. Parametr opcjonalny.Przykładowe rozwiązanie:
extension ViewController: UICollectionViewDelegateFlowLayout { func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { return "String".size(withAttributes: nil) } }
Ale najprawdopodobniej chciałbyś określić konkretne atrybuty ciągu odpowiadające twojej komórce, stąd ostateczny wynik będzie wyglądał następująco:
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 } }
Dlaczego NIE NALEŻY używać UILabel do obliczania rozmiaru? Oto sugerowane rozwiązanie:
let label = UILabel(frame: CGRect.zero) label.text = textArray[indexPath.item] label.sizeToFit()
Tak, uzyskasz ten sam wynik. Wygląda na uproszczone i może wydawać się rozwiązaniem, które należy wykonać. Ale to niewłaściwe, ponieważ: 1) jest drogie, 2) napowietrzne i 3) brudne.
Jest to kosztowne, ponieważ UILabel jest złożonym obiektem UI, który jest tworzony przy każdej iteracji, ilekroć twoja komórka ma się pokazać, nawet jeśli nie potrzebujesz tego tutaj. Jest to ogólne rozwiązanie, ponieważ wystarczy uzyskać rozmiar tekstu, ale posuwasz się nawet do utworzenia całego obiektu interfejsu użytkownika. I z tego powodu jest brudny.
źródło
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)
Znalazłem małą sztuczkę do szybkiego 4.2
Dla dynamicznej szerokości i stałej wysokości:
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) }
Dla dynamicznej wysokości i stałej szerokości:
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) }
źródło
sizeWithAttributes
, więc może jest to preferowana odpowiedź.Sprawdź poniższy kod, który możesz podać bardzo krótki rozmiar CG.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{ NSString *testString = @"SOME TEXT"; return [testString sizeWithAttributes:NULL]; }
źródło
W Swift 3
let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil)
źródło
Szybki 4
let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil)
źródło
// dodaj w widoku didload
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init]; [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal]; layout.estimatedItemSize = CGSizeMake(self.breadScrumbCollectionView.frame.size.width, 30); self.breadScrumbCollectionView.collectionViewLayout = layout;
źródło