【问题标题】:UICollectionView: Apply dynamic width for each cell according to UIButton's text widthUICollectionView:根据UIButton的文字宽度为每个单元格应用动态宽度
【发布时间】:2021-11-04 11:01:23
【问题描述】:

我知道关于这个问题有很多类似的主题。虽然,我已经先尝试了它们,但没有解决我的问题。

如下图所示,我尝试使用 UICollectionView 应用水平滚动视图。每个单元格都包含一个具有动态文本长度的 UIButton。

问题是某些单元格的宽度错误/短。我尝试先获取每个 NSString 文本大小的解决方案,然后将其设置为 sizeForItemAt 委托方法。但是效果不好,即使我手动添加了填充值CGSize sizeWithPadding = CGSizeMake(size.width + 30, 40),文本仍在缩小。

经过几个小时的搜索和测试,仍然不知道如何解决这个问题。欢迎任何建议。

数据源 = NSString 数组

[NSMutableArray arrayWithObjects:@"All", @"Computer programming", @"Taylor Swift", @"Movies", @"Airplane", @"Basketball", @"Iron man", @"Football", @"ABC", @"Gong Fu", @"Dong Hua", nil]

一个 UIView 作为 collectionView 的容器。

- (void)setViews {
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    layout.minimumLineSpacing = CGFLOAT_MAX;
    self.collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:layout];
    self.collectionView.translatesAutoresizingMaskIntoConstraints = false;
    self.collectionView.backgroundColor = UIColor.systemBackgroundColor;
    _collectionView.dataSource = self;
    _collectionView.delegate = self;
    [_collectionView registerClass:MenuBarCell.class forCellWithReuseIdentifier:menuBarCellID];

    [self addSubview:self.collectionView];
    
    [self.collectionView.topAnchor constraintEqualToAnchor:self.topAnchor].active = true;
    [self.collectionView.leadingAnchor constraintEqualToAnchor:self.leadingAnchor].active = true;
    [self.collectionView.trailingAnchor constraintEqualToAnchor:self.trailingAnchor].active = true;
    [self.collectionView.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = true;
}

# pragma mark - collectionView dataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return _menuBarArray.count;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MenuBarCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:menuBarCellID forIndexPath:indexPath];
    NSString *model = _menuBarArray[indexPath.item];
    [cell configure:model];
    
    return cell;
}

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

    CGSize size = [self.menuBarArray[indexPath.item] sizeWithAttributes:NULL];
    NSLog(@"size: width = %f", size.width);
    CGSize sizeWithPadding = CGSizeMake(size.width + 30, 40);
    
    return sizeWithPadding;
}

我的 UICollectionView 自定义单元格

- (void)setViews {
    [super setViews];
    
    self.contentView.backgroundColor = UIColor.systemYellowColor;
    
    // create buttons
    _button = [UIButton buttonWithType:UIButtonTypeCustom];
    _button.translatesAutoresizingMaskIntoConstraints = false;
    _button.layer.cornerRadius = 15;
    _button.layer.masksToBounds = true;
    [_button setBackgroundColor:[UIColor colorWithWhite:0.92 alpha:1]];
    [_button setTitleColor:UIColor.labelColor forState:UIControlStateNormal];
    [_button setTitleColor:UIColor.buttonTitleHighlighted forState:UIControlStateHighlighted];
    
    [self.contentView addSubview:_button];
    
    // set constraints
    [_button.centerXAnchor constraintEqualToAnchor:self.contentView.centerXAnchor].active = true;
    [_button.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor].active = true;
    [_button.widthAnchor constraintEqualToAnchor:self.contentView.widthAnchor].active = true;
    [_button.heightAnchor constraintLessThanOrEqualToAnchor:self.contentView.heightAnchor].active = true;
}

- (void)configure: (NSString *)model {
    [_button setTitle:model forState:UIControlStateNormal];
}

【问题讨论】:

  • 您的代码是您计算大小并通过委托方法设置它。那么 'sizeWithAttributes:NULL' 为什么要使用 NULL,我们应该使用正确的字体属性吗?
  • 实际上我尝试给它一个字体大小或NULL,虽然它没有包含在上面的代码中,但也不能给我一个正确的标题文本的 UIButton 宽度。请参阅 Don Mag 的回答,它非常有效。

标签: ios objective-c uicollectionview


【解决方案1】:

有些地方不对劲……

摆脱sizeForItemAtIndexPath 方法——您想使用自动调整单元格大小。

接下来,您不会显示用于约束“容器”视图的代码,但我假设它是这样的:

- (void)viewDidLoad {
    [super viewDidLoad];

    menuBarView = [MenuBarView new];

    menuBarView.translatesAutoresizingMaskIntoConstraints = NO;
    
    [self.view addSubview:menuBarView];
    
    UILayoutGuide *g = [self.view safeAreaLayoutGuide];
    [NSLayoutConstraint activateConstraints:@[
        [menuBarView.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],
        [menuBarView.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:0.0],
        [menuBarView.topAnchor constraintEqualToAnchor:g.topAnchor constant:4.0],
        [menuBarView.heightAnchor constraintEqualToConstant:42.0],
    ]];

}

您的UICollectionViewFlowLayout 应遵循以下原则:

UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;

// spacing between cells
layout.minimumLineSpacing = 8.0;

// prevents last cell from being cut-off
layout.minimumInteritemSpacing = layout.minimumLineSpacing;

// must have an estimated size
//  inconsequential, but needs to be less than expectd
layout.estimatedItemSize = CGSizeMake(10, 10);

然后像这样配置你的单元类:

// I don't know what your super-class is...
//[super setViews];

self.contentView.backgroundColor = UIColor.systemYellowColor;

// create buttons
_button = [UIButton buttonWithType:UIButtonTypeCustom];
_button.translatesAutoresizingMaskIntoConstraints = false;
_button.layer.cornerRadius = 15;
_button.layer.masksToBounds = true;

// give the button a little top / leading / bottom / trailing "padding"
_button.contentEdgeInsets = UIEdgeInsetsMake(8, 20, 8, 20);

[_button setBackgroundColor:[UIColor colorWithWhite:0.92 alpha:1]];
[_button setTitleColor:UIColor.labelColor forState:UIControlStateNormal];
[_button setTitleColor:UIColor.whiteColor forState:UIControlStateHighlighted];

[self.contentView addSubview:_button];

// set constraints
UIView *g = self.contentView;
[NSLayoutConstraint activateConstraints:@[
    [_button.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:0.0],
    [_button.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:0.0],
    [_button.topAnchor constraintEqualToAnchor:g.topAnchor constant:2.0],
    [_button.bottomAnchor constraintEqualToAnchor:g.bottomAnchor constant:-2.0],
]];

结果应该是这样的(我给“容器”视图设置了蓝色背景,以便我们可以看到它):

【讨论】:

  • 谢谢,现在可以使用了:) 首先你的猜测是对的!经过一番测试,我发现如果未指示layout.estimatedItemSize,则 UIButtons 不会自动更改其大小。而且我们不应该使用sizeForItemAtIndexPath 方法来自动调整单元格大小,尽管许多线程建议使用这种方法......另一个好处是首先知道“NEW”关键字,为什么我没有在任何代码中看到这个/doc,他们都使用alloc,init。
猜你喜欢
  • 2018-07-20
  • 2016-01-01
  • 2021-09-15
  • 1970-01-01
  • 2020-03-08
  • 2010-09-22
  • 2017-12-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多