简体   繁体   English

更改UIButton状态时不更新内部大小

[英]Intrinsic size not updating when changing UIButton state

I have a UIView that contains a UIButton. 我有一个包含UIButton的UIView。 The UIButton has 2 titles set for the UIControlStateNormal ("Follow") and UIControlStateSelected ("Following") states. UIButton为UIControlStateNormal(“Follow”)和UIControlStateSelected(“Following”)状态设置了2个标题。 I am using auto layout on the UIButton and it has a constraint to be a certain distance from the top of the superview and another to be a certain distance from the left side of the superview. 我在UIButton上使用自动布局,它有一个约束,距离超视图顶部一定距离,另一个距离超视图左侧有一定距离。 I've also used "Size to fit Content" on it. 我也使用了“尺寸适合内容”。

When I set the button to be in the selected state from code, the title changes correctly but the intrinsic width of the UIButton doesn't change so that when changing from "Follow" to "Following" the text gets ellipsized. 当我从代码中将按钮设置为处于选定状态时,标题会正确更改,但UIButton的固有宽度不会更改,因此当从“Follow”更改为“Follow”时,文本会被椭圆化。

self.selected = self.following;

在此输入图像描述在此输入图像描述

When I approach the problem differently and simply change the text for UIControlStateNormal when someone hits the button, the button changes size correctly. 当我以不同的方式处理问题时,只需在有人点击按钮时更改UIControlStateNormal的文本,该按钮就会正确地改变大小。

NSString *title = (self.following) ? @"Following" : @"Follow"
[self setTitle:title forState:UIControlStateNormal];

在此输入图像描述在此输入图像描述

Is this a bug in UIKit? 这是UIKit中的一个错误吗? I would expect the button to change its intrinsic size to correctly reflect the new size of the text when its state changes especially because there are other things I would like to change besides just the text for the 2 button states. 我希望按钮可以更改其内在大小,以便在状态发生变化时正确反映文本的新大小,特别是因为除了2按钮状态的文本之外还有其他我想要更改的内容。

Like David Caunt pointed out in a comment, calling invalidateIntrinsicContentSize will cause autolayout to resize the button to fit it's new content. 就像David Caunt在评论中指出的那样,调用invalidateIntrinsicContentSize会导致autolayout调整按钮的大小以适应它的新内容。

self.selected = self.following;
[self invalidateIntrinsicContentSize];

PS. PS。 David, if you want to post your commant as an answer I will remove mine. 大卫,如果你想发布你的commant作为答案我会删除我的。

In your storyboard select your UIButton and on top select editor->size to fit content size. 在您的故事板中选择您的UIButton并在顶部选择editor-> size以适合内容大小。

EDIT: Try this: 编辑:试试这个:

[self.myButton setTitle:@"Following" forState:UIControlStateSelected];
[self.myButton sizeToFit];

For me setting the contentEdgeInsets gave me the only reliable solution. 对我来说,设置contentEdgeInsets给了我唯一可靠的解决方案。

I'm using custom buttons, with background images. 我正在使用带有背景图像的自定义按钮。 So, slices come into the picture. 因此,切片出现在图片中。 It turns out that how you slice images can also affect intrinsic content size! 事实证明,切片图像的方式也会影响内在的内容大小! Test it! 测试一下! So, I had to make sure I was slicing identically between images for different states. 所以,我必须确保我在不同状态的图像之间切换相同。 I'm also using attributed strings. 我也在使用属性字符串。 The solutions posted here didn't work for my case. 这里发布的解决方案对我的案例不起作用。

What I found after a day(!) of experimenting is that setting sufficient contentEdgeInsets values on the button makes it behave correctly when titles are changed using autolayout. 我在一天(!)的实验后发现,在按钮上设置足够的contentEdgeInsets值使得在使用autolayout更改标题时它的行为正确。 There's no need to invalidate intrinsic content size or call any layout code if you do this. 如果您这样做,则无需使内在内容大小无效或调用任何布局代码。

You can either set the contentEdgeInsets in code or in IB. 您可以在代码或IB中设置contentEdgeInsets。

self.button.contentEdgeInsets = UIEdgeInsetsMake(10.0, 16.0, 10.0, 16.0);

I think the Swift code is identical except for the var attribute. 我认为Swift代码除了var属性外是相同的。

Apple says this in the docs: "The button uses this property to determine intrinsicContentSize and sizeThatFits:.". Apple在文档中说明了这一点:“按钮使用此属性来确定intrinsicContentSize和sizeThatFits:。”。

在此输入图像描述

Whether this is a bug, or just the way it is, I don't know, but it looks like you'll have to work around it -- I don't think you're doing anything wrong. 无论这是一个错误,还是它的方式,我不知道,但看起来你将不得不解决它 - 我不认为你做错了什么。 If you want to toggle between selected and not after each touch, you could do something like this: 如果您想在每次触摸后在所选内容之间切换,则可以执行以下操作:

- (IBAction)buttonClick:(UIButton *)sender {
    sender.selected = !sender.selected;
    if (sender.selected) {
        [self.button setTitle:@"Following" forState:UIControlStateNormal];
        //Do whatever else you want to do here for the selected state
    }else{
        [self.button setTitle:@"Follow" forState:UIControlStateNormal];
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM