SwiftUI中如何为ImagePicker添加尾部按钮?
问题
需要在项目中添加一个Add按钮以实现图片编辑功能。添加NavigationView后UI显示未达预期,希望Add按钮能像参考图那样位于下方。相关代码片段如下:
var body: some View { NavigationView { VStack { HStack(alignment: .top) { Button { vm.imagePickerPresented.toggle() } label: { let image = vm.profileImage == nil ? Image(systemName: "photo.circle") : vm.profileImage ?? Image(systemName: "photo.circle") image .resizable() .foregroundColor(.gray) .scaledToFill() .frame(width: 48, height: 48) .clipShape(Rectangle()) } .sheet(isPresented: $vm.imagePickerPresented) { NavigationView { VStack { ImagePicker(image: $vm.selectedImage) .toolbar { ToolbarItem(placement: .navigationBarTrailing) { Button { vm.cropperShown.toggle() } label: { Text("Add") .foregroundColor(.primary) } .sheet(isPresented: $vm.cropperShown, onDismiss: vm.loadImage){ ImageCroppingView(shown: $vm.cropperShown, shownPicker: $vm.imagePickerPresented, image: vm.selectedImage!, croppedImage: $vm.croppedImage) } } } } } } } } } }
import SwiftUI struct ImagePicker: UIViewControllerRepresentable { @Binding var image: UIImage? @Environment(\.presentationMode) var mode func makeUIViewController(context: Context) -> some UIViewController { let picker = UIImagePickerController() picker.delegate = context.coordinator return picker } func makeCoordinator() -> Coordinator { return Coordinator(self) } func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { } class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { let parent: ImagePicker init(_ parent: ImagePicker) { self.parent = parent } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { guard let image = info[.originalImage] as? UIImage else { return } self.parent.image = image } } }
解答
不需要修改ImagePicker的核心实现,问题出在UI层级和工具栏的配置上,按以下方式调整即可:
关键修改点
- 移除
ImagePicker外层额外的NavigationView——UIImagePickerController本身自带导航栏,双层导航会导致UI混乱 - 将Add按钮所在的toolbar移到sheet的根容器上,并设置toolbar位置为
.bottomBar,让按钮固定在底部 - 给
ImagePicker的选择回调补充关闭picker的逻辑,避免选择图片后picker一直停留
修改后的完整代码
主视图部分
var body: some View { NavigationView { VStack { HStack(alignment: .top) { Button { vm.imagePickerPresented.toggle() } label: { let image = vm.profileImage == nil ? Image(systemName: "photo.circle") : vm.profileImage ?? Image(systemName: "photo.circle") image .resizable() .foregroundColor(.gray) .scaledToFill() .frame(width: 48, height: 48) .clipShape(Rectangle()) } .sheet(isPresented: $vm.imagePickerPresented) { VStack { ImagePicker(image: $vm.selectedImage) } .toolbar { ToolbarItem(placement: .bottomBar) { Button { vm.cropperShown.toggle() } label: { Text("Add") .foregroundColor(.primary) } .sheet(isPresented: $vm.cropperShown, onDismiss: vm.loadImage){ ImageCroppingView(shown: $vm.cropperShown, shownPicker: $vm.imagePickerPresented, image: vm.selectedImage!, croppedImage: $vm.croppedImage) } } } } } } } }
ImagePicker部分补充
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate { let parent: ImagePicker init(_ parent: ImagePicker) { self.parent = parent } func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) { guard let image = info[.originalImage] as? UIImage else { return } self.parent.image = image self.parent.mode.wrappedValue.dismiss() // 新增:选择图片后关闭picker } }
调整后,Add按钮会显示在底部工具栏,同时避免了双层导航的问题,符合需求。
内容的提问来源于stack exchange,提问作者AppleMango
相关产品推荐
相关产品推荐

