You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

StackView内UILabel骨架不显示问题求助

UIStackView子Label骨架屏异常问题解决

问题描述

尝试给UIStackView内的两个UILabel添加骨架屏效果:

  • 单独设置label.isSkeletonable = true完全无效
  • 设置stackView.isSkeletonable = true后,出现异常效果:
    骨架屏异常效果

使用的库:SkeletonView

原代码实现

class ArticleCellView: UITableViewCell {
// MARK: - *** Properties ***
static let cellIdentifier = "ArticleTableViewCell"

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    self.isSkeletonable = true
    contentView.isSkeletonable = true
    configure()
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

// MARK: - *** UI Elements ***
lazy var titleLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 0
    label.textAlignment = .natural
    label.textColor = UIColor(named: "AccentColor")
    label.font = UIFont.systemFont(ofSize: 13.0, weight: .medium)
    label.isSkeletonable = true
    
    return label
}()

lazy var abstractLabel: UILabel = {
    let label = UILabel()
    label.numberOfLines = 2
    label.textAlignment = .natural
    label.textColor = UIColor(named: "AccentColor")
    label.font = UIFont.systemFont(ofSize: 12.0)
    label.isSkeletonable = true

    return label
}()

lazy var thumbnailImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.contentMode = .scaleAspectFill
    imageView.frame.size.width = 100
    imageView.layer.cornerRadius = imageView.frame.size.width / 2
    imageView.clipsToBounds = true
    imageView.isSkeletonable = true

    return imageView
}()

lazy var stackView: UIStackView = {
    let stack = UIStackView()
    stack.contentMode = .scaleToFill
    stack.distribution = .fillEqually
    stack.spacing = 20
    stack.isSkeletonable = true

    return stack
}()

func configure() {
    // Adding subviews
    contentView.addSubview(thumbnailImageView)
    contentView.addSubview(stackView)
    stackView.addSubview(titleLabel)
    stackView.addSubview(abstractLabel)
    
    // Setting up the constraints
    thumbnailImageView.snp.makeConstraints {
        $0.leading.equalToSuperview().inset(10)
        $0.width.height.equalTo(100)
        $0.centerY.equalToSuperview()
    }
    
    stackView.snp.makeConstraints {
        $0.leading.equalTo(thumbnailImageView.snp.trailing).offset(10)
        $0.trailing.equalToSuperview().inset(10)
        $0.top.bottom.equalTo(thumbnailImageView)
    }
    
    titleLabel.snp.makeConstraints {
        $0.leading.equalToSuperview().inset(10)
        $0.trailing.equalToSuperview().inset(2)
        $0.top.equalToSuperview().inset(10)
    }
    
    abstractLabel.snp.makeConstraints {
        $0.leading.equalToSuperview().inset(10)
        $0.trailing.equalToSuperview().inset(2)
        $0.top.equalTo(titleLabel.snp.bottom).offset(10)
        $0.bottom.equalToSuperview().offset(2)
    }
    
}

问题原因及修复方案

核心问题

  1. 错误添加子视图到StackView:直接用addSubview添加Label到StackView,而非StackView专用的addArrangedSubview,导致StackView无法正确管理子视图布局,SkeletonView也无法识别这些子视图为StackView的排列元素。
  2. StackView未设置排列方向:默认StackView为水平排列,而需求是垂直排列两个Label,未设置axis = .vertical导致布局混乱。
  3. 手动约束与StackView冲突:给Label设置了上下约束,StackView本身会管理子视图位置,手动约束会干扰布局,进而影响骨架屏渲染。

修复后的代码修改点

1. 调整StackView配置,设置垂直排列

lazy var stackView: UIStackView = {
    let stack = UIStackView()
    stack.axis = .vertical // 新增:设置垂直排列
    stack.contentMode = .scaleToFill
    stack.distribution = .fill // 替换fillEqually,避免强制两个Label等高
    stack.spacing = 10 // 调整为更合理的间距
    stack.isSkeletonable = true

    return stack
}()

2. 替换子视图添加方式

在configure()方法中,将:

stackView.addSubview(titleLabel)
stackView.addSubview(abstractLabel)

改为:

stackView.addArrangedSubview(titleLabel)
stackView.addArrangedSubview(abstractLabel)

3. 移除Label的上下约束,保留左右约束

删除Label的top/bottom相关约束,仅保留左右边距:

titleLabel.snp.makeConstraints {
    $0.leading.equalToSuperview().inset(10)
    $0.trailing.equalToSuperview().inset(2)
}

abstractLabel.snp.makeConstraints {
    $0.leading.equalToSuperview().inset(10)
    $0.trailing.equalToSuperview().inset(2)
}

最终效果

修复后,StackView会正确垂直排列两个Label,SkeletonView可识别每个Label的骨架屏,既不会失效,也不会出现异常拉伸效果。

内容的提问来源于stack exchange,提问作者Ahmed AlFailakawi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 00:15:36