UICollectionView的动态单元格宽度取决于标签宽度

pul*_*ulp 80 objective-c ios uicollectionview uicollectionviewcell swift

我有一个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;
}
Run Code Online (Sandbox Code Playgroud)

Bas*_*CAD 74

作为sizeForItemAtIndexPath回报文本的大小

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{

    return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL];
}
Run Code Online (Sandbox Code Playgroud)

  • 你无法想象我是多么感谢你!这确实有效.现在我只需要解决[cell.myLabel sizeToFit]问题,因为它只在滚动后才以完整大小显示.但我还没有接近你的解决方案. (4认同)
  • 代替sizeToFit,使用sizeWithAttributes获取文本的CGSize,然后使用新的大小设置标签的框架。 (2认同)

Raz*_*jam 27

结帐以下代码,您可能会给出非常短的CGSize.

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{

    NSString *testString = @"SOME TEXT";
    return [testString sizeWithAttributes:NULL];
}
Run Code Online (Sandbox Code Playgroud)


Hex*_*ire 25

Swift 4.2+

原则是:

  1. 实现UICollectionViewDelegateFlowLayout(它包含必要的方法签名)

  2. 通话collectionView...sizeForItemAt方式.

  3. 无需桥接String转换NSString为调用size(withAttributes:方法.斯威夫特String开箱即用.

  4. 属性与您设置的相同(NS)AttributedString,即字体系列,大小,重量等.可选参数.


样品溶液:

extension ViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return "String".size(withAttributes: nil)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是您很可能希望指定与您的单元格相对应的具体字符串属性,因此最终返回将如下所示:

// Replace "String" with proper string (typically array element). 
return "String".size(withAttributes: [
    NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)
])
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案。尽管我得到的尺寸比需要的尺寸小一点,但对于不同长度的字符串,我决定自己稍微修改一下尺寸。在宽度上添加额外的 5 个点就可以了: ```CGSize(width: title.size(withAttributes: [NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 16)]).width + 5, height: 50) ```` (2认同)

iOS*_*iOS 25

在 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)
}
Run Code Online (Sandbox Code Playgroud)

UICollectionViewDelegateFlowLayout添加到您的委托中

它非常适合我,具有相同的单元格空间和基于文本长度的动态单元格大小

下面的 PFA 图片...

在此输入图像描述

根据内容修复collectionView(不是cell)的高度(集合视图的动态高度)

如何将 UICollectionView 的高度调整为 UICollectionView 内容大小的高度?


小智 24

我发现了一个快速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)
    }
Run Code Online (Sandbox Code Playgroud)

对于动态高度和固定宽度:

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)
        }
Run Code Online (Sandbox Code Playgroud)

  • 使用时要小心。为每个单元格计算创建和绘制新的UILabel非常昂贵。 (5认同)
  • 为了解决关于创建虚拟标签成本高昂的评论,也许您可​​以只创建一个虚拟标签而不是多个。您真正想要的是来自标签属性的文本大小。不过,归根结底,它与通过“sizeWithAttributes”计算的文本大小基本相同,所以这可能是首选答案。 (3认同)

小智 18

在Swift 3中

let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil)
Run Code Online (Sandbox Code Playgroud)


Bar*_*ath 12

斯威夫特4

let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil)
Run Code Online (Sandbox Code Playgroud)