如何在 Swift 的分段控件中调整 textLabel 的大小?

Posted

技术标签:

【中文标题】如何在 Swift 的分段控件中调整 textLabel 的大小?【英文标题】:How to resize textLabel in segmented control in Swift? 【发布时间】:2018-05-29 07:55:14 【问题描述】:

UIViewController 中,视图顶部有一个分段控制器。约束:左:0,右:0,上:0,高度:90。

每次发布​​UIApplicationDidBecomeActive 通知时,分段控件应通过调用func updateUI() 将其视图更新为最新日期

首次加载时,当调用 viewDidLoad 时,每个段中的文本都会按预期显示。 但是,如果应用程序进入后台,当它返回前台时,分段控件的标签不包含文本并显示 3 个点......之后。请参阅下面的附件和 gif。

范围:每次发布.UIApplicationDidBecomeActive 通知时更新每个段的分段控件标题。 公共 Github 项目https://github.com/bibscy/testProject

 class ViewController: UIViewController 

   var stringDates = [String]()

   var dateNow: Date 
     return Date()
   
      @IBOutlet weak var segmentedControl: UISegmentedControl!

       func updateUI() 
    //create string dates and set the title of for each segment in segmented control
          self.getNextDays()  
     

   override func viewDidLoad() 
      super.viewDidLoad()

      NotificationCenter.default.addObserver(self, selector: #selector(updateUI), name: .UIApplicationDidBecomeActive, object: nil)

     UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0

      self.getNextDays()
   



  extension ViewController 

//for each segment, construct a string date with the currentDate() being first, followed by 5 consecutive days
func getNextDays()  

    stringDates.removeAll() //clear any previous data

    for i in 0...5 
        let dateFormatter = DateFormatter()
        let today = dateNow
        let calendar = Calendar.current

        if i == 0 
            let dayComponent = Calendar.current.component(.weekday,from: today)
            let day = Calendar.current.component(.day, from: today) //Int
            let dayString = dateFormatter.shortWeekdaySymbols[dayComponent-1] //Symbol


            let month = Calendar.current.component(.month, from: today)
            let monthSymbol = dateFormatter.shortMonthSymbols[month-1]
            let dayMonthString =  dayString + " " + String(day) + " " + monthSymbol
            stringDates.append(dayMonthString)


         else 
            var components = DateComponents()
            components.weekday = i

            let nextDay = calendar.date(byAdding: components, to: today)
            let nextDayComponent = Calendar.current.component(.weekday,from: nextDay!)
            let day = Calendar.current.component(.day, from: nextDay!)
            let dayString = dateFormatter.shortWeekdaySymbols[nextDayComponent-1] // Symbol


            let month = Calendar.current.component(.month, from: nextDay!)
            let monthSymbol = dateFormatter.shortMonthSymbols[month-1]
            let dayMonthString = dayString + " " + String(day) + " " + monthSymbol
            stringDates.append(dayMonthString)
        
    


      //set the title for each segment from stringDates array
       for value in 0...5 
         self.segmentedControl.setTitle(self.stringDates[value], forSegmentAt: value)
      
    //end of getNextDays()  

【问题讨论】:

隐藏这个extension Claim func updateUI() self.getNextDays() // UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0 并检查 @Anbu.karthik 如果我在扩展名self.getNextDays()UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).numberOfLines = 0 中注释掉,文本将按预期呈现在每个段中。基本上,如果我调用 self.getNextDays() ,标签不会调整大小。这反过来意味着当在 self.getNextDays() 内部调用 self.segmentedControl.setTitle(self.stringDates[value], forSegmentAt: 时,标签没有正确调整大小,这是我的理解。 【参考方案1】:

该问题仅在 ios 10.3 版本中重现。 解决方案:

存储分段标签的初始属性:

fileprivate var height: CGFloat! 
fileprivate var width: CGFloat!

getNextDays 之前添加到 ViewDidLoad:

let label = segmentedControl.subviews[0].subviews[0] as! UILabel 
height = label.frame.height 
width = label.frame.width

设置文字:

for value in 0...5 
   segmentedControl.setTitle(stringDates[value], forSegmentAt: value)

然后修复帧:

let labels = segmentedControl.subviews.map $0.subviews[1]  as! [UILabel]
    labels.forEach  (label) in
        label.numberOfLines = 0
        let frame = label.frame
        label.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: width, height: height)
    

Sample code with some crash protection

【讨论】:

我在 Xcode 版本 8.3.3 (8E3004b) 上运行。在界面生成器中设置分段控件的高度是不可能的。所有约束框都是灰色的,不可选择。见截图imgur.com/a/W8nGJ4i 我无法设置约束的原因是分段控件放置在导航栏上。谢谢 如我所见,您将它放在导航项中。尝试将其放在主视图中。 当应用程序第一次启动时,我得到的结果如上图所示。但是,当应用程序在后台运行,然后在前台运行时,标签上的文本看起来很糟糕。基本上,当应用程序进入前台时,我调用updateUI(),它调用getNextDays(),它又调用segmentedControl.setTitle(self.stringDates[value], forSegmentAt: value),这又是它出错的地方。你在模拟器中运行过一个简单的项目吗? 是的,我做到了。我认为问题在于自动布局与 tableView 或 safeArea 冲突。尝试使用没有 tableView 的分段控制器实现 clear ViewController。

以上是关于如何在 Swift 的分段控件中调整 textLabel 的大小?的主要内容,如果未能解决你的问题,请参考以下文章

Swift - 如何让分段控制锁定在屏幕顶部

在 Swift 的标头中使用分段控件更改 UICollectionView 的内容

swift Swift中的通用分段控件

Swift 自定义分段控件 SegmentedControl

如何从另一个 UIViewController 更改分段控件标题(设置)

Swift 分段控制和 UITableView