Objective c 带大小调整的UIImage WithCapinsets在暗模式下不响应

Objective c 带大小调整的UIImage WithCapinsets在暗模式下不响应,objective-c,ios13,ios-darkmode,Objective C,Ios13,Ios Darkmode,是否有人知道一种方法,可以使使用大小可调的图像WithCapinset拉伸的UIImage响应明暗模式的更改?我当前的实现仅在第一次绘制时考虑暗/光模式 [thumbnailContainer addSubview:[self addTileBackgroundOfSize:thumbnailContainer.bounds]]; - (UIImageView *) addTileBackgroundOfSize:(CGRect)bounds { UIImageView *backgr

是否有人知道一种方法,可以使使用大小可调的图像WithCapinset拉伸的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委托方法重新绘制它们,但我希望有更好的方法让它们做出响应。

似乎
ResizebleimageWithCossinsets
会导致图像失去其动态自适应属性。您可以尝试为这两种外观创建图像,并将它们重新组合成动态图像。看看这是怎么做到的。

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

我首先将图像视图存储在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;
    }
}

首先,这里没有什么令人惊讶的。当您说
调整大小图像
时,您将生成一个新图像。它不再是您从资产目录获得的图像,因此它失去了自动链接/动态性,当特征集合更改时,该链接/动态性会使图像自动更改为另一个图像

其次,这无关紧要,因为您可以使用任意两个图像(不在资源目录中)创建链接。您可以通过UIImageAsset类来实现这一点

这里有一个有效的例子。假设Faces是资产目录中一对的名称,一个表示任意,一个表示黑暗。我将提取该对中的每个成员,对每个成员应用
resizeable
,然后将新对作为彼此的变体连接在一起:

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];
都做完了。请注意,在代码中不需要保留任何对象(
链接
笑脸
皱眉
)。 现在,如果在图像视图中插入该对中的一个成员,当用户亮/暗模式更改时,它将自动更改为另一个成员:

let tc = self.traitCollection
let im = link.image(with: tc)
self.imageView.image = im
我将在明暗模式之间来回切换,以证明这是可行的:


不清楚您希望对明暗模式做出何种“反应”。UIImage不会因为模式改变而神奇地改变。你必须把它们配对。您没有可与之配对的此图像的暗模式版本。我认为存在暗模式版本,因为Gergely说该图像对于当前模式是正确的,但不会自动切换。显然,我在引用的图像资源中有一个亮版本和一个暗版本;否则,期待任何类型的更改都会有一点问题……”显然,我在引用的图像资源中有一个亮版和一个暗版“是的,但是当您将
resizebleimage
应用于该图像时,它会返回一个新的不同UIImage,并且显然该图像不在资源目录中。这就是我要说的。另一个想法是:你需要在代码中设置插入还是它们总是一样的?如果没有,您可以尝试在资产目录中指定它们(在属性检查器中,在“切片”部分的底部),然后检查自动暗模式更改是否有效。我认为可以。当您按名称加载UIImage时,它基本上是一个占位符,根据trait环境解析为具体的图像。然而,似乎
ResizeableImageWithCapInsets
会导致它解析为具体的图像(针对当前的trait环境),并丢失其占位符状态。今晚我将尝试一下。非常感谢。要点不是一个好的模式。它试图重新发明一个不需要重新发明的轮子。这有一个内置的机制,UIImageAsset。是的,这就是他们在要点中使用的。不,这是错误的。有一种方法可以将任意两个图像(而不是资产目录中的图像)配对为彼此的自动变体。谢谢您的回答。能否请您也提供Objective-C变体?那我就试试看。不幸的是,我对斯威夫特几乎一无所知。