Swift中如何调整分段控件文本标签大小?解决后台返回显示不全问题
解决Segmented Control后台返回后标题显示省略号的问题
我来帮你搞定这个困扰你的问题!首先咱们先明确下问题:首次加载页面时,Segmented Control的日期标题显示正常,但应用切后台再回到前台后,标题就被截断成省略号了,对吧?
问题原因分析
主要有两个关键点导致这个问题:
- 更新分段标题后,Segmented Control没有自动触发重新布局,导致内部的标签尺寸没有适配新的文本(哪怕文本内容和首次加载一致,控件也不会主动重新计算布局);
- 你之前的日期计算逻辑有个隐藏bug——用
components.weekday = i来获取后续日期,这其实是跳转到对应星期几的日期,而不是连续的后几天,不过这个不是导致省略号的直接原因,但会影响日期显示的正确性。
修复方案及代码修改
下面是修改后的完整代码,我会标注关键的修改点:
class ViewController: UIViewController { var stringDates = [String]() var dateNow: Date { return Date() } @IBOutlet weak var segmentedControl: UISegmentedControl! // 把DateFormatter提为类属性,避免重复创建浪费性能 private let dateFormatter = DateFormatter() func updateUI() { getNextDays() // ✅ 更新标题后强制触发重新布局,确保控件适配文本尺寸 segmentedControl.setNeedsLayout() segmentedControl.layoutIfNeeded() } override func viewDidLoad() { super.viewDidLoad() NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: UIApplication.didBecomeActiveNotification, object: nil) // 设置分段内的标签支持多行显示 UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0 // ✅ 开启内容自适应宽度,让每个分段根据文本长度自动分配空间 segmentedControl.apportionsSegmentWidthsByContent = true getNextDays() } deinit { // ✅ 移除通知观察者,防止内存泄漏 NotificationCenter.default.removeObserver(self) } } extension ViewController { func getNextDays() { stringDates.removeAll() let today = dateNow let calendar = Calendar.current for i in 0...5 { let targetDate: Date if i == 0 { targetDate = today } else { var components = DateComponents() // ✅ 修复日期计算bug:用day而不是weekday,确保获取连续的后几天 components.day = i targetDate = calendar.date(byAdding: components, to: today)! } // 统一日期格式化逻辑,减少重复代码 let dayComponent = calendar.component(.weekday, from: targetDate) let dayString = dateFormatter.shortWeekdaySymbols[dayComponent - 1] let day = calendar.component(.day, from: targetDate) let monthComponent = calendar.component(.month, from: targetDate) let monthSymbol = dateFormatter.shortMonthSymbols[monthComponent - 1] let dayMonthString = "\(dayString) \(day) \(monthSymbol)" stringDates.append(dayMonthString) } // 设置每个分段的标题 for index in 0...5 { segmentedControl.setTitle(stringDates[index], forSegmentAt: index) } } }
关键修改说明
- 强制布局更新:在
updateUI()最后添加setNeedsLayout()和layoutIfNeeded(),让Segmented Control在更新标题后立即重新计算内部布局,确保文本能完整显示; - 开启内容自适应宽度:设置
apportionsSegmentWidthsByContent = true,让分段控件根据每个标题的长度自动分配空间,避免短标题占太多空间、长标题被截断; - 修复日期计算bug:把
components.weekday = i改成components.day = i,这样才能获取连续的后5天(之前的逻辑会跳转到对应星期的日期,比如i=1会跳到下一个周一,而不是明天); - 优化DateFormatter:把DateFormatter作为类属性,避免每次调用
getNextDays()都创建新实例,提升性能; - 内存泄漏防护:在
deinit中移除通知观察者,防止内存泄漏。
验证效果
修改后,你再把应用切后台然后回到前台,Segmented Control的日期标题应该就能完整显示,不会出现省略号啦~
内容的提问来源于stack exchange,提问作者bibscy
相关产品推荐
相关产品推荐

