解决UIButton开启showsActivityIndicator时高度不一致问题
问题描述
在默认大动态字体尺寸下,以下代码创建的UIButton初始高度为28.33;点击按钮开启showsActivityIndicator后,高度意外增至34.33。字体越小、动态字体尺寸越大,高度差异越明显。
let button = UIButton(configuration: { var config = UIButton.Configuration.filled() config.title = "Button" config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { var container = $0 container.uiKit.font = .preferredFont(forTextStyle: .caption1) return container } return config }()) button.addAction(UIAction() { _ in button.configuration?.showsActivityIndicator = true }, for: .touchUpInside)
问题核心:按钮高度由内容内边距决定,内边距是基于当前最大内容计算的。初始仅显示标题时高度较小,添加更高的活动指示器后,按钮为满足内边距要求自动增高。需求是不设置固定高度约束,让按钮在加载和非加载状态下高度保持一致。
解决方案
方法1:预计算活动指示器高度,调整非加载状态内边距
先获取系统活动指示器的默认高度,再计算它和标题文本的高度差,把这个差值平均分配到上下内边距里,让非加载状态的按钮高度和加载状态对齐。
示例代码:
let button = UIButton(configuration: { var config = UIButton.Configuration.filled() config.title = "Button" config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { var container = $0 container.uiKit.font = .preferredFont(forTextStyle: .caption1) return container } // 获取系统默认活动指示器的高度 let indicator = UIActivityIndicatorView(style: .medium) indicator.sizeToFit() let indicatorHeight = indicator.frame.height // 计算当前标题文本的高度 let titleFont = UIFont.preferredFont(forTextStyle: .caption1) let titleHeight = "Button".size(withAttributes: [.font: titleFont]).height // 计算需要补充的内边距,让按钮高度匹配指示器 let paddingDelta = max(0, indicatorHeight - titleHeight) config.contentInsets = NSDirectionalEdgeInsets( top: config.contentInsets.top + paddingDelta/2, leading: config.contentInsets.leading, bottom: config.contentInsets.bottom + paddingDelta/2, trailing: config.contentInsets.trailing ) return config }()) button.addAction(UIAction() { _ in button.configuration?.showsActivityIndicator = true }, for: .touchUpInside)
方法2:复用加载状态的内边距配置
先创建一个临时的加载状态配置,提取它的内容内边距,把这个内边距直接应用到默认状态的按钮上,确保两种状态下的内边距基准一致。
示例代码:
let button = UIButton(configuration: { var config = UIButton.Configuration.filled() config.title = "Button" config.titleTextAttributesTransformer = UIConfigurationTextAttributesTransformer { var container = $0 container.uiKit.font = .preferredFont(forTextStyle: .caption1) return container } // 生成加载状态的临时配置,提取其内容内边距 let tempLoadingConfig = UIButton.Configuration.filled() tempLoadingConfig.showsActivityIndicator = true tempLoadingConfig.title = "" if let resolvedInsets = tempLoadingConfig.resolvedConfiguration(for: .normal)?.contentInsets { config.contentInsets = resolvedInsets } return config }()) button.addAction(UIAction() { _ in button.configuration?.showsActivityIndicator = true }, for: .touchUpInside)
内容的提问来源于stack exchange,提问作者Jordan H
相关产品推荐
相关产品推荐

