IOS:使用Autolayout调整UIButton高度取决于标题文本?

时间:2016-01-04 10:02:16

标签: ios objective-c iphone uibutton autolayout

我有一个UIButton,它可以在运行时更改标题。因此,我希望使用UIButton增加AutoLayout高度,具体取决于标题文字以显示全文。

我可以通过将UILabel设置为"大于或等于"来增加height constraint高度但它不适用于UIButton 我使用了[myButton sizeToFit],但它只增加UIButon宽度(不增加高度)。

我现在的UIButton属性现在是
  - 约束高度:30   - 领先:15   - 尾随:15  - 前5   - fontsize:12

更新
我创建了一个约束高度为UIButton的IBOutlet,用于更改@NSNood所说的高度 然后我需要在标题文本中使用\n来分割线 但我不知道我应该把\n放在哪里?

以下是我想要的Button

enter image description here

以下是我想要的Button横向 enter image description here

如何确定放置\n的位置?

请指导我如何使用AutoLayout来实现它。任何帮助,将不胜感激。

4 个答案:

答案 0 :(得分:8)

很抱歉,我最近没有关注这个帖子,因此我想出了一个真正的后期解决方案。如果有人可能在将来发现它有用,我仍然可以将答案作为参考。

首先让我们展示按钮的故事板配置。这些描述如下:

Constraint configuration

图片显示我只为按钮添加了左,上,右约束,没有别的。这允许按钮的高度为intrinsicContentSize,但它的宽度仍由其左右约束决定。

下一阶段是编写一些包含按钮的ViewController类。在我的VC中,我已经按名称button

为按钮创建了一个插座
@property(nonatomic,weak) IBOutlet UIButton* button;

并将其附加到故事板按钮。现在我已经覆盖了两个方法,即viewDidLoadviewWillLayoutSubviews,如下所示:

-(void)viewDidLoad {
    [super viewDidLoad];

    self.button.titleLabel.numberOfLines = 0;
    self.button.titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
}
-(void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.button setTitle:@"Chapter One\n "
     "A Stop on the Salt Route\n "
     "1000 B.C.\n "
     "As they rounded a bend in the path that ran beside the river, Lara recognized the silhouette of a fig tree atop a nearby hill. The weather was hot and the days were long. The fig tree was in full leaf, but not yet bearing fruit." forState:UIControlStateNormal];
}
  1. viewDidLoad方法可确保titleLabel(标签) 保持按钮文本)是多行的,如果有一些大文本来到它, 它通过包装文字来包装文本。
  2. viewWillLayoutSubviews方法确保按钮布局过程 每当主视图的边界改变时发生,例如,因为 改变界面方向。
  3. 最后也是最有效的部分是手动处理按钮的布局过程。为此,我们需要继承UIButton。我编写了一个名为MyButton的子类,它继承自UIButton,您可以使用您喜欢的任何名称。将其设置为Identity Inspector中按钮的自定义类。

    子类重写了两个方法,即intrinsicContentSizelayoutSubviews。类主体看起来如下所示:

    #import "MyButton.h"
    
    @implementation MyButton
    
    -(CGSize)intrinsicContentSize {
        return [self.titleLabel sizeThatFits:CGSizeMake(self.titleLabel.preferredMaxLayoutWidth, CGFLOAT_MAX)];;
    }
    -(void)layoutSubviews {
        self.titleLabel.preferredMaxLayoutWidth = self.frame.size.width;
        [super layoutSubviews];
    }
    @end
    

    UIButon子类通过覆盖layoutSubviews方法获取布局过程的所有权。这里的基本思想是确定按钮宽度,一旦布局。然后将宽度设置为preferredMaxLayoutWidth(布局引擎的最大宽度,多线标签应占用的最大宽度)的子titleLabel(包含按钮文本的标签)。最后,根据按钮intrinsicContentSize的大小返回titleLabel按钮,以便按钮完全包裹它titleLabel

    1. 当按钮已经被调用时,将调用被覆盖的layoutSubviews 布局并确定它的框架尺寸。在它的第一步, 按钮的渲染宽度设置为preferredMaxLayoutWidth 按钮' titleLabel
    2. 第二步通过调用[super layoutSubviews]重新调用布局引擎,以便按钮intrinsicContentSize为 根据它titleLabel重新确定 preferredMaxLayoutWidth,设置为按钮渲染宽度, 到现在为止。
    3. 在重写的intrinsicContentSize方法中,我们返回 完全包裹它的按钮的最小装配尺寸 设置titleLabel的{​​{1}}。我们用 preferredMaxLayoutWidth符合按钮sizeThatFits的方法 只是作为titleLabel没有遵循任何基于约束的工作 布局。
    4. 结果应该类似于您可能需要的结果。

      Portrait Landscape

      请随时告诉我任何其他澄清/关注事项。

      感谢。

答案 1 :(得分:1)

关键是,如果您设置了sizeToFit属性,那么文本将始终在一行中,并且按钮的宽度将会增加,除非您将下一行符号\n明确说出你希望它是几行。

你将'\ n'放在第一行的末尾,如"line \n line"代表

line
line

如果您希望人像风景有两个不同的字符串值(\n位置不同),您可以使用{{1}检查方向条件(UIDeviceOrientationdescribed here并根据设备的方向设置字符串值

答案 2 :(得分:1)

斯威夫特的Ayan Sengupta解决方案:

  1. 对您的UIButton进行子类化以获取布局过程的所有权:

    /// https://stackoverflow.com/a/50575588/1033581
    class AutoLayoutButton: UIButton {
        override var intrinsicContentSize: CGSize {
            return titleLabel!.sizeThatFits(CGSize(width: titleLabel!.preferredMaxLayoutWidth, height: .greatestFiniteMagnitude))
        }
        override func layoutSubviews() {
            titleLabel?.preferredMaxLayoutWidth = frame.size.width
            super.layoutSubviews()
        }
    }
    
  2. 在故事板中使用此类,并为“前导”,“尾随”,“上”,“下”设置约束。但是不要设置任何高度限制。

  3. 没有子类化的替代方法是按照Bartłomiej Semańczyk answerTimur Bernikowich comment的建议添加包装器视图。

答案 3 :(得分:0)

我一直使用一种方法:

  1. 添加另一个引用UILabel,其lineNumber = 0且宽度与目标按钮相同。
  2. 请勿为ref-UILable设置高度限制,而应为按钮设置高度限制以调整其高度
  3. 使用button.titleLable,sizeTofit并将其设置为参考UILabel的相同文本,并获取其frame.size.height
  4. 使用高度值作为目标按钮的高度约束。 (当然,button.titleLabel行号应设置为0或更多行)

完成。 :)

PS1。这种方法可用于滚动视图中的按钮和参考标签。

PS2。在某些情况下,我们无法获得正确的ref标签高度,因为它无法在滚动视图中获得正确的frame.width,特别是当我们使用尾随约束时。我们可以考虑在sizeTofit之前为ref标签定义一个固定宽度,并为目标按钮使用获取正确的高度。