使用资产目录和大小类错误地渲染 UIButton 的图像属性

Posted

技术标签:

【中文标题】使用资产目录和大小类错误地渲染 UIButton 的图像属性【英文标题】:Incorrectly rendered UIButton’s image property using asset catalog and size classes 【发布时间】:2014-11-12 22:53:11 【问题描述】:

我遇到了 UIButton 的 image 属性的问题。我的资产目录包含任何/任何尺寸类的默认图像和特定于常规/常规类的图像。当我在 Interface Builder 中将 UIButton 的图像属性设置为“img_facebook”时,图像在 iPad 上的渲染不正确(选择了 Any / Any 大小的图像,而不是 Regular / Regular 的图像)。但是当我在“traitCollectionDidChange:”方法中刷新它时,图像就会正确呈现(参见附加代码 sn-p)。

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection

    [super traitCollectionDidChange:previousTraitCollection];
    [_facebookButton setImage:[UIImage imageNamed:@"img_facebook"] forState:UIControlStateNormal];

看起来 IB 创建了一个 UIImage 实例并将其分配给属性仅一次。这是有道理的,但如果我用 UIImage 而不是 UIButton 做同样的事情,一切都很好。

有没有人遇到过类似的问题?是否可以在 IB 中解决这个问题,还是我必须在代码中手动重置图像?

【问题讨论】:

当您想在 iPad 上使用除 Regular x Regular 以外的尺寸等级时,这在 ios 9 中更是一个问题。你有没有想出更好的方法来解决这个问题? 对此提出了雷达。希望他们能解决。 openradar.appspot.com/22593495 Jacob 顺便说一句,该问题在没有状态更改的情况下发生。如果我为紧凑型设置了不同的按钮图像,然后使用 iPhone6+ 纵向启动,它会显示非紧凑型图像。旋转到横向并返回,它会选择紧凑版本。 【参考方案1】:

我刚刚遇到了类似的问题。它似乎是 UIButton 的一个错误。我检查了按钮的 traitCollection 属性(通过 Interface Builder 添加到常规视图控制器视图中):

<UITraitCollection: 0x7ff6f27a8930; _UITraitNameUserInterfaceIdiom = Phone, _UITraitNameDisplayScale = 2.000000>

它缺少预期的尺寸等级。例如,父视图 traitCollection 如下所示:

<UITraitCollection: 0x7ff6f48a1640; _UITraitNameUserInterfaceIdiom = Phone, _UITraitNameDisplayScale = 2.000000, _UITraitNameHorizontalSizeClass = Compact, _UITraitNameVerticalSizeClass = Regular, _UITraitNameTouchLevel = 0, _UITraitNameInteractionModel = 1>

最简单的解决方法是修改您的 UIImageAsset 以使用 Device Specific 选项而不是大小类:

并添加 iPhone 和 iPad 特定图像。这为我解决了(Xcode Beta 6.3)

【讨论】:

但它是否适用于分配给设备特定资产的尺寸等级? 如果您选择我提供的解决方法,那么您将获得一个特定于设备(iPad 或 iPhone)的图像,并针对该设备的屏幕比例进行了优化。所以是的,它会做你所追求的。还有其他方法可以使用大小类来实现这一点 - 例如您可以通过您自己的视图控制器将尺寸类强制到代码中的按钮上。我的解决方法就是完全避免编写任何代码。【参考方案2】:

我有同样的问题,我发现的唯一方法是使用另一个 api 为按钮设置正确的图像。

UIImage *image;
if ( NSClassFromString(@"UITraitCollection") )  //need to support iOS7
    image = [UIImage imageNamed:@"xxx" inBundle:nil compatibleWithTraitCollection:self.traitCollection];
 else 
    image = [UIImage imageNamed:@"xxx"];

[button setImage:image forState:UIControlStateNormal];

根据我的测试,似乎只有在按钮上调用 traitCollectionDidChange 时,按钮的图像才会自动更改为相应的特征。这意味着如果您想手动控制按钮的图像,则必须在将图像设置为按钮时获取正确的特征图像,否则您需要等待按钮发生下一个 traitCollectionDidChange 才能自动获取图像更改。

【讨论】:

以上是关于使用资产目录和大小类错误地渲染 UIButton 的图像属性的主要内容,如果未能解决你的问题,请参考以下文章

iOS:如何干净地删除 UIButton 插座? [复制]

资产目录编译器错误

Swift:使用 CGRect 设置 UIButton 图像

子类化 UIButton 标题字体大小意外更改

UIButton的使用

自动布局 - UIButton 的固有大小不包括标题插图