You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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层级和工具栏的配置上,按以下方式调整即可:

关键修改点

  1. 移除ImagePicker外层额外的NavigationView——UIImagePickerController本身自带导航栏,双层导航会导致UI混乱
  2. 将Add按钮所在的toolbar移到sheet的根容器上,并设置toolbar位置为.bottomBar,让按钮固定在底部
  3. 给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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 00:42:03