如何在不同设备的段控制中管理文本大小?
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
我正在尝试使用 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