【问题标题】:UIImage with resizableImageWithCapInsets Does Not Respond in Dark Mode具有 resizableImageWithCapInsets 的 UIImage 在暗模式下不响应
【发布时间】:2020-03-31 04:37:00
【问题描述】:

有谁知道一种方法可以使使用 resizableImageWithCapInsets 拉伸的 UIImage 响应明暗模式的变化?我当前的实现只在第一次绘制时考虑了暗/亮模式。

[thumbnailContainer addSubview:[self addTileBackgroundOfSize:thumbnailContainer.bounds]];

- (UIImageView *) addTileBackgroundOfSize:(CGRect)bounds {
    UIImageView *backgroundView = [[UIImageView alloc] initWithFrame:bounds];
    UIEdgeInsets insets         = UIEdgeInsetsMake(10.0f, 49.0f, 49.0f, 10.0f);
    UIImage *backgroundImage    = [[UIImage imageNamed:@"UnivGalleryTile"] resizableImageWithCapInsets:insets];
    backgroundView.image        = backgroundImage;

    return backgroundView;
}

我想我可以在 traitCollection 委托方法中重绘它们,但我希望有更好的方法让它们做出响应。

【问题讨论】:

  • 不清楚您期望对亮/暗模式有什么样的“响应”。 UIImages 不会因为模式改变而神奇地改变。您必须将它们相互配对。您没有此图像的深色模式版本可与之配对。
  • 我认为有暗模式版本,因为 Gergely 说图像对于当前模式是正确的,但不会自动切换。
  • 显然,我在引用的图像资产中有浅色和深色版本;否则,期待任何形式的改变都会有点问题......
  • “很明显,我在引用的图像资产中有一个浅色和一个深色版本”是的,但是当你应用 resizableImage 时,它会返回一个新的不同 UIImage 并且显然那个不在资产目录。这就是我要说的。
  • 另一个想法:您需要在代码中设置插图还是它们总是相同的?如果没有,您可以尝试在资产目录中指定它们(在属性检查器中,在“切片”部分的底部)并检查自动暗模式更改是否会起作用。

标签: objective-c ios13 ios-darkmode


【解决方案1】:

首先,这里没有惊喜。当您说resizableImage 时,您将创建一个新图像。它不再是您从资产目录中获得的图像,因此它失去了在特征集合更改时使图像自动更改为另一个图像的自动链接/动态。

其次,这没关系,因为您可以创建与任意两个图像(不在资产目录中)的链接。你可以通过 UIImageAsset 类来做到这一点。

所以这是一个工作示例。想象一下,Faces 是资产目录中一对的名称,一个代表 Any,一个代表 Dark。我将提取对中的每个成员,将resizable 应用于每个成员,然后将 new 对作为彼此的变体连接在一起:

let tclight = UITraitCollection(userInterfaceStyle: .light)
let tcdark = UITraitCollection(userInterfaceStyle: .dark)
var smiley = UIImage(named: "Faces", in: nil, compatibleWith: tclight)!
var frowney = UIImage(named: "Faces", in: nil, compatibleWith: tcdark)!
let link = UIImageAsset()
let insets = UIEdgeInsets(top: 30, left: 30, bottom: 30, right: 30)
smiley = smiley.resizableImage(withCapInsets: insets)
frowney = frowney.resizableImage(withCapInsets: insets)
link.register(smiley, with: tclight)
link.register(frowney, with: tcdark)

或者在 Objective-C 中:

UITraitCollection* tclight = [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleLight];
UITraitCollection* tcdark = [UITraitCollection traitCollectionWithUserInterfaceStyle:UIUserInterfaceStyleDark];
UIImage* smiley = [UIImage imageNamed:@"Faces" inBundle:nil compatibleWithTraitCollection:tclight];
UIImage* frowney = [UIImage imageNamed:@"Faces" inBundle:nil compatibleWithTraitCollection:tcdark];
UIImageAsset* link = [UIImageAsset new];
UIEdgeInsets insets = UIEdgeInsetsMake(30, 30, 30, 30);
smiley = [smiley resizableImageWithCapInsets:insets];
frowney = [frowney resizableImageWithCapInsets:insets];
[link registerImage:smiley withTraitCollection:tclight];
[link registerImage:frowney withTraitCollection:tcdark];

全部完成。请注意,在代码中不需要保留任何对象(linksmileyfrowney)。 现在,如果您将其中的一个成员插入到图像视图中,当用户明暗模式更改时,它将自动更改为另一个:

let tc = self.traitCollection
let im = link.image(with: tc)
self.imageView.image = im

我将在明暗模式之间来回切换以证明这是有效的:

【讨论】:

  • 感谢您的回答。您能否也提供一个 Objective-C 变体?那我试试看。
  • 不幸的是,我对 Swift 几乎一无所知。
【解决方案2】:

似乎resizableImageWithCapsInsets 导致图像失去其动态、自动适应的属性。您也许可以尝试为两种外观创建图像并将它们再次组合成动态图像。查看this gist 了解如何做到这一点。

【讨论】:

  • 我认为确实如此。当您按名称加载 UIImage 时,它​​基本上是一个占位符,根据 trait 环境解析为具体图像。然而,resizableImageWithCapInsets 似乎导致它解析为一个具体的图像(对于当前的 trait 环境)并失去其占位符状态。
  • 今晚我会试一试。谢谢!
  • 要点不是一个很好的模型。它试图重新发明一个不需要重新发明的轮子。有一个内置的机制,UIImageAsset。
  • 是的,这就是他们在 gist 中使用的内容。
【解决方案3】:

我已经解决了,但是男孩就是这么丑。所以,如果有人有更好的解决方案,我愿意接受:

我首先将图像视图存储在 NSMutableArray 中:

- (UIImageView *) addTileBackgroundOfSize:(CGRect)bounds {
    UIImageView *backgroundView     = [[UIImageView alloc] initWithFrame:bounds];
        UIEdgeInsets insets         = UIEdgeInsetsMake(10.0f, 49.0f, 49.0f, 10.0f);
        UIImage *backgroundImage    = [[UIImage imageNamed:@"UnivGalleryTile"] resizableImageWithCapInsets:insets];
    backgroundView.image            = backgroundImage;

    // Store image for re-drawing upon dark/light mode change
    [thumbnailArray addObject:backgroundView];

    return backgroundView;
}

然后当用户更改屏幕模式时,我手动重置背景图像:

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection {
    for (int i = 0; thumbnailArray.count > i; i++) {
        UIEdgeInsets insets         = UIEdgeInsetsMake(10.0f, 49.0f, 49.0f, 10.0f);
        UIImage *backgroundImage    = [[UIImage imageNamed:@"UnivGalleryTile"] resizableImageWithCapInsets:insets];

        ((UIImageView *)[thumbnailArray objectAtIndex:i]).image = backgroundImage;
    }
}

【讨论】:

  • 不,这是错误的。有一种方法可以将不在资产目录中的任意两个图像配对为彼此的自动变体。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多