让用户向SwiftUI视图添加多个图像

让用户向SwiftUI视图添加多个图像,swiftui,Swiftui,我正在使用SwiftUI进行练习,制作一个meme maker,它的标签是从文本字段生成的,可以移动和调整大小。我也希望能够做到这一点,从用户的照片库的图像。我可以得到一张图片,但如果我尝试得到更多,它只会替换第一张图片。我尝试将图像添加到数组中,但是图像将不会显示在MemeImage视图中 var body: some View { VStack(spacing: 12) { memeImageView

我正在使用SwiftUI进行练习,制作一个meme maker,它的标签是从文本字段生成的,可以移动和调整大小。我也希望能够做到这一点,从用户的照片库的图像。我可以得到一张图片,但如果我尝试得到更多,它只会替换第一张图片。我尝试将图像添加到数组中,但是图像将不会显示在MemeImage视图中

var body: some View {
        VStack(spacing: 12) {
            
            memeImageView
            
            ForEach(0..<(meme.boxCount ?? 0)) { i in
                TextField("Statement \(i + 1)", text: $addedLabels[i])
                    .padding(.horizontal, 8)
                    .padding(.vertical, 4)
                    .background(Color.gray.opacity(0.25))
                    .cornerRadius(5)
                    .onTapGesture {
                        self.endEditing()
                    }

            }
            .padding(.horizontal)

        }.onTapGesture {
            self.endEditing()
        }
        
        
        // Gets a new Image
        Button {
            self.isShowPhotoLibrary = true
            addedImages.append(image)

        } label: {
            Text("Add Image")
                .foregroundColor(Color.yellow)
        }.sheet(isPresented: $isShowPhotoLibrary) {
            ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
        }
        
       
        Spacer()

        // Saves Image
        Button {
            // takes a screenshot and crops it
            if let image = memeImageView.takeScreenshot(origin: CGPoint(x: 0, y: UIApplication.shared.windows[0].safeAreaInsets.top + navBarHeight + 1), size: CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height / 2.5)) {
                UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil)
                presentationMode.wrappedValue.dismiss() // dismisses the view
            }
            
        }
        label: {
            Text("Save image")
                .foregroundColor(Color.yellow)
        }.frame( width: 150, height: 50)
        .overlay(
            RoundedRectangle(cornerRadius: 25)
                .stroke(Color.red, lineWidth: 3)
        )
        
        
        .navigationBarTitle(meme.name ?? "Meme", displayMode: .inline)
        .background(NavBarAccessor { navBar in
            self.navBarHeight = navBar.bounds.height
        })
    }
图像属性

   @State private var image = UIImage()
钮扣

Button {
            self.isShowPhotoLibrary = true

        } label: {
            Text("Add Image")
                .foregroundColor(Color.yellow)
        }.sheet(isPresented: $isShowPhotoLibrary) {
            ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
        }
Button {
    self.isShowPhotoLibrary = true
    addedImages.append(image)

} label: {
    Text("Add Image")
        .foregroundColor(Color.yellow)
}.sheet(isPresented: $isShowPhotoLibrary) {
    ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
}

var memeImageView: some View {
        ZStack {
            KFImage(URL(string: meme.url ?? ""))
                .placeholder {
                    ProgressView()
                }
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: UIScreen.main.bounds.height / 2.5)
            
            ForEach(addedLabels, id:\.self) { label in
                
                DraggableLabel(text: label)
                
            }
            
            ForEach(0..<addedImages.count) { index in
                DraggableImage(image: addedImages[index]!)
            }
            
        }
        .clipped()

    }
MemeUmageView

var memeImageView: some View {
    ZStack {
        KFImage(URL(string: meme.url ?? ""))
            .placeholder {
                ProgressView()
            }
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(height: UIScreen.main.bounds.height / 2.5)
        
        ForEach(addedLabels, id:\.self) { label in
            
            DraggableLabel(text: label)
            
        }
        
        DraggableImage(image: image)
        
    }
    .clipped()

}
尝试使用数组。我还尝试制作三个按钮,将三个图像相加,每个按钮都作为自己的属性,认为初始属性被覆盖

我的图像阵列

@State private var addedImages = [UIImage?]()
钮扣

Button {
            self.isShowPhotoLibrary = true

        } label: {
            Text("Add Image")
                .foregroundColor(Color.yellow)
        }.sheet(isPresented: $isShowPhotoLibrary) {
            ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
        }
Button {
    self.isShowPhotoLibrary = true
    addedImages.append(image)

} label: {
    Text("Add Image")
        .foregroundColor(Color.yellow)
}.sheet(isPresented: $isShowPhotoLibrary) {
    ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
}

var memeImageView: some View {
        ZStack {
            KFImage(URL(string: meme.url ?? ""))
                .placeholder {
                    ProgressView()
                }
                .resizable()
                .aspectRatio(contentMode: .fit)
                .frame(height: UIScreen.main.bounds.height / 2.5)
            
            ForEach(addedLabels, id:\.self) { label in
                
                DraggableLabel(text: label)
                
            }
            
            ForEach(0..<addedImages.count) { index in
                DraggableImage(image: addedImages[index]!)
            }
            
        }
        .clipped()

    }
DragImageView:

import SwiftUI


struct DragImageView: View {
    
    //===================
    // MARK: Properties
    //===================

    @State private var addedImages = [UIImage?]()
    @State private var isShowPhotoLibrary = false
    @State private var image = UIImage()

    
    
    var body: some View {
        VStack(spacing: 12) {
            
            imageView
            
        }
        
        
        // Gets a new Image
        Button {
            self.isShowPhotoLibrary = true
            addedImages.append(image)

        } label: {
            Text("Add Image")
                .foregroundColor(Color.yellow)
        }.sheet(isPresented: $isShowPhotoLibrary) {
            ImagePicker(sourceType: .photoLibrary, selectedImage: self.$image)
        }
        
       
        Spacer()

  
    }
    
    var imageView: some View {
        ZStack {
            DraggableImage(image: image)
        }
        //.clipped()
    }
    
    // This will dismiss the keyboard
    private func endEditing() {
        UIApplication.shared.endEditing()
    }
}

// Allows fot the keyboard to be dismissed
extension UIApplication {
    func endEditing() {
        sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
    }
}
可拖动图像:

import SwiftUI

struct DraggableImage: View {
    // Drag Gesture
    @State private var currentPosition: CGSize = .zero
    @State private var newPosition: CGSize = .zero
    
    // Roation Gesture
    @State private var rotation: Double = 0.0
    
    // Scale Gesture
    @State private var scale: CGFloat = 1.0
    
    
    // The different states the frame of the label could be
    private enum WidthState: Int {
        case full, half, third, fourth
    }
    
    @State private var widthState: WidthState = .full
    @State private var currentWidth: CGFloat = 100 //UIScreen.main.bounds.width
    
    var image: UIImage
    
    var body: some View {
        VStack {
            Image(uiImage: self.image)
                .resizable()
                .scaledToFill()
                .frame(width: self.currentWidth)
                .lineLimit(nil)
        }
        .scaleEffect(scale) // Scale based on our state
        .rotationEffect(Angle.degrees(rotation)) // Rotate based on the state
        .offset(x: self.currentPosition.width, // Offset from the drag difference from it's current position
                y: self.currentPosition.height)
        .gesture(
            
            // Two finger rotation
            RotationGesture()
                .onChanged { angle in
                    self.rotation = angle.degrees // keep track of the angle for state
                }
                // We want it to work with the scale effect, so they could either scale and rotate at the same time
                .simultaneously(with:
                                    MagnificationGesture()
                                    .onChanged { scale in
                                        self.scale = scale.magnitude // Keep track of the scale
                                    })
                // Update the drags new position to be wherever it was last dragged to. (we don't want to reset it back to it's current position)
                .simultaneously(with: DragGesture()
                                    .onChanged { value in
                                        self.currentPosition = CGSize(width: value.translation.width + self.newPosition.width,
                                                                      height: value.translation.height + self.newPosition.height)
                                    }
                                    .onEnded { value in
                                        self.newPosition = self.currentPosition
                                    })
        )
        
        /// Have to do double tap first or else it will never work with the single tap
        .onTapGesture(count: 2) {
            // Update our widthState to be the next on in the 'enum', or start back at .full
            self.widthState = WidthState(rawValue: self.widthState.rawValue + 1) ?? .full
            self.currentWidth = UIScreen.main.bounds.width / CGFloat(self.widthState.rawValue)
        }
    }
}
图像选择器:

import UIKit
import SwiftUI

struct ImagePicker: UIViewControllerRepresentable {
    
    var sourceType: UIImagePickerController.SourceType = .photoLibrary
    
    @Binding var selectedImage: UIImage
    @Environment(\.presentationMode) private var presentationMode

    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        
        let imagePicker = UIImagePickerController()
        imagePicker.allowsEditing = false
        imagePicker.sourceType = sourceType
        imagePicker.delegate = context.coordinator
        
        return imagePicker
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
        
    }
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
        
        var parent: ImagePicker
        
        init(_ parent: ImagePicker) {
            self.parent = parent
        }
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            
            if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
                parent.selectedImage = image
            }
            
            parent.presentationMode.wrappedValue.dismiss()
        }
    }
}
导入UIKit
导入快捷键
结构图像选择器:UIViewControllerRepresentable{
变量sourceType:UIImagePickerController.sourceType=.photoLibrary
@绑定变量SelecteImage:UIImage
@环境(\.presentationMode)私有变量presentationMode
func makeUIViewController(上下文:UIViewControllerRepresentableContext)->UIImagePickerController{
让imagePicker=UIImagePickerController()
imagePicker.allowsEditing=false
imagePicker.sourceType=源类型
imagePicker.delegate=context.coordinator
返回图像选择器
}
func updateUIViewController(uViewController:UIImagePickerController,上下文:UIViewControllerRepresentableContext){
}
func makeCoordinator()->Coordinator{
协调员(自我)
}
最终类协调器:NSObject、UIImagePickerControllerDelegate、UINavigationControllerDelegate{
var父对象:ImagePicker
init(uu父对象:ImagePicker){
self.parent=parent
}
func imagePickerController(picker:UIImagePickerController,didFinishPickingMediaWithInfo:[UIImagePickerController.InfoKey:Any]){
如果让image=info[UIImagePickerController.InfoKey.originalImage]作为?UIImage{
parent.selectedImage=image
}
parent.presentationMode.wrappedValue.disclease()
}
}
}

我应该加上这一点是为了制作模因,这样用户拾取的图像就会出现在我保存到相机卷的视图的顶部。

我不是100%清楚确切的期望输出应该是什么,但这应该让您开始(解释如下):


结构DragImageView:视图{
//===================
//马克:财产
//===================
@国家私有变量addedImages=[UIImage]()
@国家私有变量isShowPhotoLibrary=false
var bindingForImage:绑定{
在中绑定{()->UIImage
返回addedImages.last??UIImage()
}在中设置:{(新图像)
addedImages.append(新图像)
打印(“图像:\(addedImages.count)”)
}
}
var body:一些观点{
VStack(间距:12){
图像视图
}
//获取新图像
钮扣{
self.isShowPhotoLibrary=true
}标签:{
文本(“添加图像”)
.foregroundColor(颜色.黄色)
}.sheet(显示:$isShowPhotoLibrary){
ImagePicker(源类型:.photoLibrary,选择图像:bindingForImage)
}
垫片()
}
var-imageView:一些视图{
VStack{
ForEach(addedImages,id:\.self){image in
DragTableImage(图像:图像)
}
}
}
//这将关闭键盘
私有函数endEditing(){
UIApplication.shared.endEditing()
}
}
addedImages
现在是一个非可选的
UIImages

图像选择器有一个自定义绑定。当它接收到一个新图像时,它会将其附加到数组的末尾


var-imageView
中,有一个
VStack
而不是
ZStack
,这样可以显示多个图像(而不是堆叠在一起),并有一个
ForEach
循环来遍历图像。

你能显示你用数组尝试的代码吗?你肯定需要一个数组和一个
ForEach
,就像你在
addedLabels中使用的那样是的,我将使用相同的按钮向你展示最新的方法。你在编辑中没有显示所有的代码。您在哪里定义了
addedImages
?很抱歉,我现在已经添加了它。调用
memeImageView
的位置在哪里?你能举一个最小的、可重复的例子吗?非常感谢。我欠你的!这正是我想做的!