Динамическая ширина ячейки UICollectionView в зависимости от ширины метки
У меня есть UICollectionView, который загружает ячейки из повторно используемой ячейки, которая содержит метку. Массив предоставляет контент для этой метки. Я могу легко изменить размер метки в зависимости от ширины содержимого с помощью sizeToFit. Но я не могу сделать клетку, чтобы соответствовать этикетке.
Вот код
- (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;
}
11 ответов
В sizeForItemAtIndexPath
вернуть размер текста
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL];
}
Swift 4.2+
Принцип таков:
Воплощать в жизнь
UICollectionViewDelegateFlowLayout
(содержит необходимую подпись метода)Вызов
collectionView...sizeForItemAt
метод.Не нужно накидывать мост
String
вNSString
звонитьsize(withAttributes:
метод. стрижString
есть это из коробки.Атрибуты те же, что вы установили для
(NS)AttributedString
т. е. семейство шрифтов, размер, вес и т. д. Необязательный параметр.
Пример решения:
extension ViewController: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return "String".size(withAttributes: nil)
}
}
Но вы, скорее всего, захотите указать конкретные строковые атрибуты, соответствующие вашей ячейке, поэтому итоговый возврат будет выглядеть так:
// Replace "String" with proper string (typically array element).
return "String".size(withAttributes: [
NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)
])
Я нашел маленький трюк для быстрой 4.2
Для динамической ширины и фиксированной высоты:
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)
}
Для динамической высоты и фиксированной ширины:
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)
}
Оформить заказ ниже код, который вы могли бы дать очень короткий CGSize.
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *testString = @"SOME TEXT";
return [testString sizeWithAttributes:NULL];
}
В Swift 5.X этой единственной строчки кода достаточно.
В ответе ниже я добавил динамическую ширину и статическую высоту. В зависимости от ваших требований измените значение высоты.
//MARK: - UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: itemsArray[indexPath.item].size(withAttributes: [NSAttributedString.Key.font : UIFont.systemFont(ofSize: 17)]).width + 25, height: 30)
}
Добавьте UICollectionViewDelegateFlowLayout к своему делегату
В Свифт 3
let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil)
Swift 4
let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil)
осуществлять
UICollectionViewDelegateFlowLayout
и добавьте код
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let label = UILabel(frame: CGRect.zero)
label.text = arr[indexPath.row]
label.sizeToFit()
return CGSize(width: (label.frame.width+20), height: label.frame.size.height+20)
}
//Создаем UICollectionView
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
collectionView.translatesAutoresizingMaskIntoConstraints = false
//CollectionCellView width autoSize
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.register(CustomCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
[enter image description here][1]
return collectionView
}()
// добавить в вид didload
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
[layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
layout.estimatedItemSize = CGSizeMake(self.breadScrumbCollectionView.frame.size.width, 30);
self.breadScrumbCollectionView.collectionViewLayout = layout;
Эта одна строка для моего
UICollectionViewFlowLayout()
сделал трюк для меня:
collectionViewLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize