为每个 Action Sheet 按钮添加不同的修饰符
Add a different modifier to each Action Sheet button
这可能是个很简单的问题,但我找不到答案。
我正在尝试构建一个带有两个按钮(以及一个取消按钮)的 ActionSheet:
- 按钮“来自图库的Select”打开
imagePicker
,其中 sourceType
设置为 .photoLibrary
。
- “拍一张新照片”按钮会打开
imagePicker
,其中 sourceType
设置为 .camera
。
我已经成功制作了 ActionSheet 和 imagePicker,但无法确定在何处添加修饰符以告知每个按钮应使用哪个 sourceType。我设法将它添加到 ActionSheet 之外的 sheet()
修饰符中,像这样的普通按钮中并且一切正常:
Button(action: {
self.show.toggle()
})
{Text("Take a new picture")}
.sheet(isPresented: self.$show, content: {
ImagePicker(sourceType: .camera, show: self.$show, image: self.$imageTemp)
})
但是我看不到将此信息包含在 ActionSheet 中的什么位置。非常感谢任何能提供帮助的人,我希望这很清楚:-)
这是我的代码:
struct ContentView: View {
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View {
NavigationView {
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture {
self.showingActionSheet = true
}
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(title: Text("Image selector"), message: Text("Select an image"), buttons: [
.default(Text("Select from Gallery"))
{
self.show.toggle()
},
.default(Text("Take new picture")) {
self.show.toggle()
},
.cancel()
]
)
}
}
}
}
并且,以防万一,这是我的 imagePicker 的代码,尽管我认为它可能没有必要。
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var show: Bool
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator {
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var child : ImagePicker
init(child1: ImagePicker) {
child = child1
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.child.show.toggle()
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
let image = info[.originalImage]as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.show.toggle()
}
}
}
您的问题几乎可以归结为“我如何呈现多个 sheet?”,因此 可能会有所帮助。
- 定义一个新的
enum
以包含可能的 sheet 类型(gallery/take 照片)
- 声明一个
@State
属性 来保存当前的 sheet 类型。它是可选的,因为当它为 nil 时,将不会显示 sheet。
- 将 属性 设置为您想要的类型
- 使用
sheet(item:onDismiss:content:)
instead of sheet(isPresented:onDismiss:content:)
。 isPresented
最适合静态 sheets。 item
适用于当您有多个 sheet 类型时,这就是您想要的。
enum PhotoSheetType: Identifiable { /// 1.
var id: UUID {
UUID()
}
case gallery
case picture
}
struct ContentView: View {
/// 2.
@State private var showingType: PhotoSheetType?
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View {
NavigationView {
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture {
self.showingActionSheet = true
}
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(
title: Text("Image selector"),
message: Text("Select an image"),
buttons: [
.default(Text("Select from Gallery")) {
showingType = .gallery /// 3.
},
.default(Text("Take new picture")) {
showingType = .picture /// 3.
},
.cancel()
]
)
} /// 4.
.sheet(item: $showingType) { type in
if type == .gallery {
ImagePicker(sourceType: .photoLibrary, showingType: $showingType, image: self.$imageTemp)
} else {
ImagePicker(sourceType: .camera, showingType: $showingType, image: self.$imageTemp)
}
}
}
}
}
您还需要修改 ImagePicker
,以便 Binding
接受 PhotoSheetType?
而不是 Bool
。要关闭 sheet,只需将 showingType
设置为 nil。
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var showingType: PhotoSheetType?
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator {
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var child : ImagePicker
init(child1: ImagePicker) {
child = child1
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.child.showingType = nil /// set to nil here
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
let image = info[.originalImage] as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.showingType = nil /// set to nil here
}
}
}
这可能是个很简单的问题,但我找不到答案。
我正在尝试构建一个带有两个按钮(以及一个取消按钮)的 ActionSheet:
- 按钮“来自图库的Select”打开
imagePicker
,其中sourceType
设置为.photoLibrary
。 - “拍一张新照片”按钮会打开
imagePicker
,其中sourceType
设置为.camera
。
我已经成功制作了 ActionSheet 和 imagePicker,但无法确定在何处添加修饰符以告知每个按钮应使用哪个 sourceType。我设法将它添加到 ActionSheet 之外的 sheet()
修饰符中,像这样的普通按钮中并且一切正常:
Button(action: {
self.show.toggle()
})
{Text("Take a new picture")}
.sheet(isPresented: self.$show, content: {
ImagePicker(sourceType: .camera, show: self.$show, image: self.$imageTemp)
})
但是我看不到将此信息包含在 ActionSheet 中的什么位置。非常感谢任何能提供帮助的人,我希望这很清楚:-)
这是我的代码:
struct ContentView: View {
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View {
NavigationView {
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture {
self.showingActionSheet = true
}
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(title: Text("Image selector"), message: Text("Select an image"), buttons: [
.default(Text("Select from Gallery"))
{
self.show.toggle()
},
.default(Text("Take new picture")) {
self.show.toggle()
},
.cancel()
]
)
}
}
}
}
并且,以防万一,这是我的 imagePicker 的代码,尽管我认为它可能没有必要。
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var show: Bool
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator {
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var child : ImagePicker
init(child1: ImagePicker) {
child = child1
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.child.show.toggle()
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
let image = info[.originalImage]as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.show.toggle()
}
}
}
您的问题几乎可以归结为“我如何呈现多个 sheet?”,因此
- 定义一个新的
enum
以包含可能的 sheet 类型(gallery/take 照片) - 声明一个
@State
属性 来保存当前的 sheet 类型。它是可选的,因为当它为 nil 时,将不会显示 sheet。 - 将 属性 设置为您想要的类型
- 使用
sheet(item:onDismiss:content:)
instead ofsheet(isPresented:onDismiss:content:)
。isPresented
最适合静态 sheets。item
适用于当您有多个 sheet 类型时,这就是您想要的。
enum PhotoSheetType: Identifiable { /// 1.
var id: UUID {
UUID()
}
case gallery
case picture
}
struct ContentView: View {
/// 2.
@State private var showingType: PhotoSheetType?
@State private var showingActionSheet = false
@State var imageTemp : Data = (UIImage(systemName: "photo.on.rectangle.angled")?.jpegData(compressionQuality: 1))!
var body: some View {
NavigationView {
Image(uiImage: UIImage(data: imageTemp)!)
.onTapGesture {
self.showingActionSheet = true
}
.actionSheet(isPresented: $showingActionSheet) {
ActionSheet(
title: Text("Image selector"),
message: Text("Select an image"),
buttons: [
.default(Text("Select from Gallery")) {
showingType = .gallery /// 3.
},
.default(Text("Take new picture")) {
showingType = .picture /// 3.
},
.cancel()
]
)
} /// 4.
.sheet(item: $showingType) { type in
if type == .gallery {
ImagePicker(sourceType: .photoLibrary, showingType: $showingType, image: self.$imageTemp)
} else {
ImagePicker(sourceType: .camera, showingType: $showingType, image: self.$imageTemp)
}
}
}
}
}
您还需要修改 ImagePicker
,以便 Binding
接受 PhotoSheetType?
而不是 Bool
。要关闭 sheet,只需将 showingType
设置为 nil。
struct ImagePicker: UIViewControllerRepresentable {
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var showingType: PhotoSheetType?
@Binding var image: Data
func makeCoordinator() -> ImagePicker.Coordinator {
let imagePicker = UIImagePickerController()
return ImagePicker.Coordinator(child1: self)
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
picker.sourceType = sourceType
return picker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var child : ImagePicker
init(child1: ImagePicker) {
child = child1
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
self.child.showingType = nil /// set to nil here
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
let image = info[.originalImage] as! UIImage
let data = image.jpegData(compressionQuality: 0.45)
self.child.image = data!
self.child.showingType = nil /// set to nil here
}
}
}