在不更改位置的情况下更改自定义 UIButton 中的 UILabel 标题

Changing UILabel title in custom UIButton without positional change

我有一个 UIButton,左侧是标签,右侧是 UIImageView。该按钮用于打开 UIPicker。当在选取器中选取一个值时,相同的值将显示在按钮标题中。当标题改变时(或者,更准确地说,当 uilabel 的宽度使 UI 变大时)标题和图标被移动并且 UI 看起来不太好。

当使用文本太长的标题时,单词会被剪掉,当标题太短时,对齐就会混乱。

我试过更改标签框架,使其可以保持不变,无论文本是什么,并左对齐文本以停止跳转。我添加了 adjustsFontSizeToFitWidth = true 哪种方法有效,但标题较长时文本会变得太小。我也试过 recreating/rerendering 标题更改时的按钮,但所有尝试都失败了。

lazy var sortButton = { () -> UIButton in
        let btn = UIButton()
        btn.addTarget(self, action: #selector(sortButtonPressed), for: .touchUpInside)
        btn.setTitle(NSLocalizedString("Sortera", comment: ""), for: .normal)
        btn.titleLabel?.text = btn.titleLabel?.text?.uppercased()
        btn.setImage(UIImage(named: "ios-down"), for: .normal)

        btn.translatesAutoresizingMaskIntoConstraints = false
        btn.setTitleColor(Colors.FILTER_BUTTON_TEXT_COLOR, for: .normal)
        btn.titleLabel?.adjustsFontSizeToFitWidth = true
        btn.titleLabel?.font = UIFont(name: Fonts.AkzidenzGroteskProMd, size: 16)
        btn.backgroundColor = Colors.BUTTON_BACKGROUND_GRAY
        btn.imageView?.contentMode = .scaleAspectFit
        btn.imageEdgeInsets = UIEdgeInsets(top: 16, left: (btn.titleLabel?.frame.size.width)! - buttonInsideOffset/2, bottom: 16, right: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset/2)
        btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset, bottom: 0, right: (btn.titleLabel?.frame.size.width)! - buttonInsideOffset)
        return btn
    }()

我希望所有按钮都像这样,无论标题文本是什么:

但是,当文本太小时,它看起来像这样:

或太长时:

您可以通过多种方式完成,但最简单的方式是:

在此视图中设置一个 UIView 和其他两个元素(标签和 imageView),使其看起来像按钮,然后根据需要设置约束。然后将 addTarget 添加到标签并对该目标选择器方法执行所有功能。

如果您不希望按钮图像向右或向左移动,则必须独立于按钮的标题标签进行约束

     btn.imageView?.frame = CGRect(x: 0, y: 0, width: 20, height: 20) // Or any size you want

    // NB: I ommited left insets intentionally
    btn.imageEdgeInsets.top = 16
    btn.imageEdgeInsets.bottom = 16
    btn.imageEdgeInsets.right = 16

然后根据 imageView 位置约束您的标签,这样只有标签大小会发生变化,而不会影响图像的位置。

btn.titleEdgeInsets = UIEdgeInsets(top: 0, left: -(btn.titleLabel?.frame.size.width)! + buttonInsideOffset, bottom: 0, right:   btn.imageView?.frame.width + 10)

最后,由于框架是固定大小的,我认为您需要将字体缩放因子限制为您想要的最小大小,并在达到该大小时截断尾部。如果您不想截断尾巴,则必须启用多行 titleLabel(我认为您不希望这样做)。

    btn.titleLabel?.minimumScaleFactor = 0.5 // Or whatever minimum scale you wish
    btn.titleLabel?.lineBreakMode = NSLineBreakMode.byTruncatingTail // Since button size is fixed and you want to limit font size then the best option is to truncate tail