【问题标题】:Change UISegmentControl height with respect to label height相对于标签高度更改分段控制高度
【发布时间】:2017-04-07 03:39:13
【问题描述】:

我的应用中有一个UISegmentControl。我已经添加了所有必需的约束并将其高度约束设置为>= 40。控制有 3 段。问题是我从服务器获取段标题数据,它可以是任意长度。当段标题超过一行时,文本将被截断。

我通过添加以下代码解决了这个问题:-

[[UILabel appearanceWhenContainedIn:[UISegmentedControl class], nil] setNumberOfLines:0];

当标题长度为 2 行时,它可以正常工作。当标题长度超过 2 行并且文本再次被截断时,真正的问题开始了,理想情况下,UISegmentControl 应该像 UILabel 通过检查其内容压缩属性来增加其高度以适应更长的图块。我尝试通过更改优先级的值来使用 contentCompression 阻力属性,但徒劳无功。 UISegmentControl 不会自动调整大小以适应更大的文本。知道如何使用自动布局实现所需的行为。

【问题讨论】:

  • 我认为我们应该使用setTitleTextAttributes(_ attributes: [AnyHashable : Any]?, for state: UIControlState) 代替UISegmentControl 而不是当前使用的方法
  • 我通过将NSParagraphStyleAttributeName 设置为NSMutableParagraphStyle 来使用文本属性,但它仍然不起作用。

标签: ios iphone autolayout xib uisegmentedcontrol


【解决方案1】:

我只会说 Swift,所以我希望这会有所帮助。

您需要做很多事情来动态调整分段控件的高度。

1. 像这样对 UILable 进行扩展:

import Foundation
import UIKit

    extension UILabel{
        var defaultNumberOfLines: Int{
            get{return self.numberOfLines}
            set{self.numberOfLines = newValue}
        }

        var defaultFont: UIFont{
            get {return self.font}
            set{self.font = newValue}
        }
    }

2.计算将包含您的字符串的边界矩形。此矩形的高度将决定分段控件的高度。您可以使用 NSString 或 NSAttributedString 的实例而不是 String 来计算字符串的边界矩形。我在“getHeightForSegControl(withString:withWidth:)”方法中计算了边界矩形。

3.在计算字符串的边界矩形时,您还必须记住使用与 UILabel 相同的字体,否则由于明显的差异,您的文本将被截断...

4. 在方法 viewWillLayoutSubviews() 中设置您的框架。这很重要,因为每当您为段设置新文本时,您都需要调用超级视图的 setNeedsLayout() 来计算生成的边界文本和分段控件的相应大小。

在下面的代码中,如果将实例成员“text”的值更改为任意长度的字符串,分段控件将相应地更新其高度:

import UIKit

class ViewController: UIViewController {
    var segmentedControl: UISegmentedControl!
    var text = "This is a text that is supposed to dynamically change the height of an instance of UISegmentedControl"
    override func viewDidLoad() {
        super.viewDidLoad()
        setUpSegmentedControl()
        UILabel.appearance().defaultNumberOfLines = 0
        UILabel.appearance().defaultFont = UIFont.boldSystemFont(ofSize: 15)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    override func viewWillLayoutSubviews() {

        segmentedControl.frame = CGRect(x: view.bounds.size.width / 2 - 100, y: view.bounds.size.height / 2 - (getHeightForSegControl(withString: text, withLabelWidth: 100) / 2), width: 200, height: getHeightForSegControl(withString: text, withLabelWidth: 100))
    }

    func setUpSegmentedControl(){
        segmentedControl = UISegmentedControl(items: [text, "Oranges"])
        view.addSubview(segmentedControl)
    }

    func getHeightForSegControl(withString string: String, withLabelWidth width: CGFloat) -> CGFloat {
        let nsString: NSString = string as NSString
        let size: CGSize = CGSize(width: width, height: CGFloat.greatestFiniteMagnitude)
        let boundingRectSize = nsString.boundingRect(with: size, options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSFontAttributeName: UILabel.appearance().defaultFont], context: nil).size

        print(ceil(boundingRectSize.height))
        return ceil(boundingRectSize.height)
    }

}

结果:

附:这是假设你想要一个固定的宽度。如果您还想要动态宽度……那就另当别论了。

【讨论】:

  • 是的,你可能是对的我也通过循环UISegemenControl 的子视图和检查UILabel 的高度来调整 UISegmentControl 的高度来实现相同的效果。正如我在评论中提到的,我想通过AutoLayout 来完成,所以上面的代码对我来说不是一个选项。我仍然认为使用内在尺寸我们可以达到预期的效果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多