如何在不同设备的段控制中管理文本大小?

How to manage text size in segment control for different devices?

我正在尝试使用 CollectionViewCell 创建自定义段控件。所以我可以管理不同设备中段控件的文本大小。但它并不是在所有设备上都能正常工作。 我在集合视图中使用了一个单元格,并使用 sizeForItemAt 委托方法来平等地设置单元格。只有 3 个单元格。如图所示。

这是 sizeForItemAt

的代码
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: (collectionView.frame.width / 3), height: 50.0)
}

这是我得到的输出

所以我试图找到解决方案,使用它我可以管理所有设备中的文本大小,并且所有单元格也可以采用相等的间距。

lbl_name.adjustsFontSizeToFitWidth = true

试试这个

UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).adjustsFontSizeToFitWidth = true 
UILabel.appearance(whenContainedInInstancesOf: [UISegmentedControl.self]).minimumScaleFactor = 6.0

以下是我能想到的一种方法,但绝不是唯一的方法。

首先,我首先设置了一个水平流布局的集合视图。

// Flow layout configuration, mainly to figure out width of the cells
private func createLayout() -> UICollectionViewFlowLayout {
    
    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.minimumLineSpacing = horizontalPadding
    flowLayout.minimumInteritemSpacing = 0
    flowLayout.scrollDirection = .horizontal
    
    // Calculate the available width to divide the segments evenly
    var availableWidth = UIScreen.main.bounds.width
    
    // There will always be segments - 1 gaps, for 3 segments, there will be
    // 2 gaps and for 4 segments there will be 3 gaps etc
    availableWidth -= horizontalPadding * CGFloat(segments.count - 1)
    
    let cellWidth = availableWidth / CGFloat(segments.count)
    
    flowLayout.itemSize = CGSize(width: cellWidth,
                                 height: collectionViewHeight)
    
    return flowLayout
}

执行此操作后,我 运行 遇到了同样的问题,根据屏幕的宽度,我的文本可能会被截断。

因此,一旦确定了每个段的宽度,我们就必须计算最大字体大小以显示最长段的完整文本,并且该字体大小应应用于所有

在这种情况下,长段的字符串长度为Vibration Intensity

// Flow layout configuration, mainly to figure out width of the cells
private func createLayout() -> UICollectionViewFlowLayout {
    
    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.minimumLineSpacing = horizontalPadding
    flowLayout.minimumInteritemSpacing = 0
    flowLayout.scrollDirection = .horizontal
    flowLayout.sectionInset = UIEdgeInsets(top: 0,
                                           left: horizontalPadding,
                                           bottom: 0,
                                           right: horizontalPadding)
    
    // Calculate the available width to divide the segments evenly
    var availableWidth = UIScreen.main.bounds.width
    
    // There will always be segments - 1 gaps, for 3 segments, there will be
    // 2 gaps and for 4 segments there will be 3 gaps etc
    availableWidth -= horizontalPadding * CGFloat(segments.count - 1)
    
    // Remove the insets
    availableWidth -= flowLayout.sectionInset.left + flowLayout.sectionInset.right
    
    let cellWidth = availableWidth / CGFloat(segments.count)
    
    // Add this function
    calculateApproxFontSize(forWidth: cellWidth)
    
    flowLayout.itemSize = CGSize(width: cellWidth,
                                 height: collectionViewHeight)
    
    return flowLayout
}

private func calculateApproxFontSize(forWidth width: CGFloat) {
    
    // Get the longest segment by length
    if let longestSegmentTitle = segments.max(by: { .count > [=11=].count }) {
        
        let tempLabel = UILabel()
        tempLabel.numberOfLines = 1
        tempLabel.text = longestSegmentTitle
        tempLabel.sizeToFit()
        
        guard var currentFont = tempLabel.font else { return }
        
        var intrinsicSize
            = (longestSegmentTitle as NSString).size(withAttributes: [.font : currentFont])
        
        // Keep looping and reduce the font size till the text
        // fits into the label
        // This could be optimized further using binary search
        // However this should be ok for small strings
        while intrinsicSize.width > width
        {
            currentFont = currentFont.withSize(currentFont.pointSize - 1)
            tempLabel.font = currentFont
            
            intrinsicSize
                = (longestSegmentTitle as NSString).size(withAttributes: [.font : currentFont])
        }

        // Set the font of the current label
        // segmentFontSize is a global var in the VC
        segmentFontSize = currentFont.pointSize
    }
}

然后在cellForItemAt indexPath中设置segmentFontSize

func collectionView(_ collectionView: UICollectionView,
                    cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    let cell = collectionView
        .dequeueReusableCell(withReuseIdentifier: SegmentCell.reuseIdentifier,
                             for: indexPath) as! SegmentCell
    
    cell.backgroundColor = .orange
    cell.title.text = segments[indexPath.item]
    
    // Adjust the font
    cell.title.font = cell.title.font.withSize(segmentFontSize)
    
    return cell
}

这会给你这样的东西:

如果您发现某些部分难以理解,这里是 link 完整代码:https://gist.github.com/shawn-frank/03bc06d13f90a54e23e9ea8c6f30a70e