切换中的图片与应有的图像不一致
下面的示例代码展示了我的问题:
import SwiftUI
struct TestView: View
{
enum Option: Int, CaseIterable, Hashable, Identifiable {
var id: Self { self }
case one = 1
case two = 2
case three = 3
var title: String {
switch self {
case .one: return "One"
case .two: return "Two"
case .three: return "Three"
}
}
var image: some View {
Image("TestImage")
.frame(width: 24.0, height: 24.0)
.clipShape(.circle)
.overlay {
Circle()
.strokeBorder(.black)
}
}
}
@State var selectedOptions: Set<Option> = []
var body: some View {
VStack {
VStack {
ForEach(Option.allCases) { option in
Label {
Text(option.title)
} icon: {
option.image
}
}
}
}
.toolbar {
ToolbarItem(placement: .bottomBar) {
Menu {
ForEach(Option.allCases) { option in
let binding = Binding<Bool> {
selectedOptions.contains(option)
} set: { value in
if value {
selectedOptions.insert(option)
} else {
selectedOptions.remove(option)
}
}
Toggle(isOn: binding) {
Label {
Text(option.title)
} icon: {
option.image
}
}
}
} label: {
Image(systemName: "checklist")
}
.menuOrder(.fixed)
}
}
}
}
#Preview {
TestView()
}
菜单中显示的图像与我预期的以及在VStack中显示的不同。
有人知道为什么会这样,以及我该如何让菜单中的图标像在VStack中那样显示?
解决方案
当把图像用作菜单项时,剪裁形状(圆形)以及你应用到图像上的黑色边框都会被忽略。所以你的源图像很可能只是一个红色正方形。
一个简单的变通办法是使用一张已经看起来符合你期望的图像,换句话说,具有圆形并带黑色边框的图像。
否则,如果你想对现有图像应用样式,可以考虑从样式化的图像创建一个新图像。一个 ImageRenderer 可以用于此。
下面演示如何以这种方式更新示例。主要变化如下:
- 通用函数
content2Image使用一个ImageRenderer将任意内容转换为图像。这基于我另一条回答中同名的函数,但在这里为iOS(而非macOS)进行了改造。 - 使用此函数将样式化的枚举图像转换为新图像。
- 将新图像用作菜单项的图标。
struct TestView: View {
enum Option: Int, CaseIterable, Hashable, Identifiable {
// ...
}
@Environment(\.displayScale) private var displayScale // 👈 added
@State var selectedOptions: Set<Option> = []
private func content2Image<C: View>(content: () -> C) -> Image { // 👈 added
let result: Image
let renderer = ImageRenderer(content: content())
renderer.scale = displayScale
if let uiImage = renderer.uiImage {
result = Image(uiImage: uiImage)
} else {
result = Image(systemName: "exclamationmark.triangle")
}
return result
}
var body: some View {
VStack {
// ...
}
.toolbar {
ToolbarItem(placement: .bottomBar) {
Menu {
ForEach(Option.allCases) { option in
let binding = Binding<Bool> {
// ...
}
Toggle(isOn: binding) {
Label {
Text(option.title)
} icon: {
content2Image { option.image } // 👈 changed
}
}
}
} label: {
Image(systemName: "checklist")
}
.menuOrder(.fixed)
}
}
}
}

站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。
