London Escorts sunderland escorts 1v1.lol unblocked yohoho 76 https://www.symbaloo.com/mix/yohoho?lang=EN yohoho https://www.symbaloo.com/mix/agariounblockedpvp https://yohoho-io.app/ https://www.symbaloo.com/mix/agariounblockedschool1?lang=EN
6 C
New York
Friday, January 31, 2025

ios – SwiftUI Sticky Notes: Incorrect Place and Body Alignment in a Canvas-like View


I’m engaged on a SwiftUI challenge the place I’m making an attempt to implement interactive Sticky Notes that may be moved, resized, and rotated on a Canvas-like view. The Sticky Notes must also have editable textual content fields. Nevertheless, I’ve encountered an issue the place:

  1. The place of the Sticky Notes doesn’t align with the seen notice on the display.

  2. When the Sticky Word is moved or resized, the interactive body (used for context menus or gestures) doesn’t observe the notice.

  3. The rotation and scaling transformations don’t apply constantly to the textual content or body.

I’ve tried debugging the problem by inspecting the frames and positions in each native and international coordinate areas, and it looks like the worldwide offset of the Canvas is perhaps interfering with the Sticky Notes’ alignment.

I’ve my Code under:


struct StickyNoteView: View {
    @Binding var stickyNote: StickyNote
    @State personal var isEditing: Bool = false
    var onDelete: () -> Void
    var onDuplicate: () -> Void

    var physique: some View {
        InteractiveElementView(aspect: $stickyNote) {
            ZStack {
                Rectangle()
                    .fill(stickyNote.shade.toColor())
                SelectableTextEditor(textual content: $stickyNote.textual content, isEditing: $isEditing)
                    .padding()
                    .background(Colour.clear)
            }
            .highPriorityGesture(
                TapGesture(rely: 2).onEnded {
                    isEditing = true
                }
            )
        }
        .contextMenu {
            Button("Löschen") {
                onDelete()
            }
            Button("Duplizieren") {
                onDuplicate()
            }
        }
    }
}
import PencilKit

struct NotesDetailView: View {
    @Surroundings(.presentationMode) var presentationMode
    @Surroundings(NotesViewModel.self) personal var viewModel
    let noteIndex: Int

    @State personal var canvasView = PKCanvasView()
    @State personal var toolPicker = PKToolPicker()
    @State personal var isShowingImagePicker = false
    @State personal var isInteractingWithElement = false

    var physique: some View {
        @Bindable var viewModel = viewModel

        VStack {
            GeometryReader { geometry in
                ZStack {
                    CanvasRepresentable(
                        canvasView: $canvasView,
                        toolPicker: $toolPicker,
                        notice: $viewModel.notes[noteIndex],
                        isInteractingWithElement: $isInteractingWithElement
                    )
                    .disabled(isInteractingWithElement) // Disable Canvas when interacting with StickyNotes
                    .body(width: geometry.dimension.width, peak: geometry.dimension.peak)
                    .onAppear {
                        toolPicker.addObserver(canvasView)
                        toolPicker.setVisible(true, forFirstResponder: canvasView)
                        canvasView.becomeFirstResponder()
                    }
                    .onDisappear {
                        saveDrawing()
                    }

                    // Overlay StickyNotes
                    ForEach($viewModel.notes[noteIndex].stickyNotes) { $stickyNote in
                        StickyNoteView(
                            stickyNote: $stickyNote,
                            onDelete: {
                                if let index = viewModel.notes[noteIndex].stickyNotes.firstIndex(the place: { $0.id == stickyNote.id }) {
                                    viewModel.notes[noteIndex].stickyNotes.take away(at: index)
                                }
                            },
                            onDuplicate: {
                                let newStickyNote = stickyNote.duplicate()
                                viewModel.notes[noteIndex].stickyNotes.append(newStickyNote)
                            }
                        )
                    }

                    // Overlay NoteImages
                    ForEach($viewModel.notes[noteIndex].photographs) { $noteImage in
                        NoteImageView(
                            noteImage: $noteImage,
                            onDelete: {
                                if let index = viewModel.notes[noteIndex].photographs.firstIndex(the place: { $0.id == noteImage.id }) {
                                    viewModel.notes[noteIndex].photographs.take away(at: index)
                                }
                            },
                            onDuplicate: {
                                let newImage = noteImage.duplicate()
                                viewModel.notes[noteIndex].photographs.append(newImage)
                            }
                        )
                    }
                }
            }
        }
        .navigationBarBackButtonHidden(true)
        .toolbar {
            // Linker Button: Zurück zur Notizen-Übersicht + Titel
            ToolbarItem(placement: .navigationBarLeading) {
                HStack {
                    Button(motion: {
                        presentationMode.wrappedValue.dismiss()
                    }) {
                        Picture(systemName: "chevron.left")
                            .font(.title2)
                    }
                    Textual content(viewModel.notes[noteIndex].title)
                        .font(.headline)
                        .lineLimit(1)
                        .truncationMode(.tail)
                }
            }

            // Mittiges Menü
            ToolbarItem(placement: .principal) {
                NotesMenu(
                    isShowingImagePicker: $isShowingImagePicker,
                    notice: $viewModel.notes[noteIndex]
                )
            }

            // Rechter Button: Fertig
            ToolbarItem(placement: .navigationBarTrailing) {
                Button("Fertig") {
                    presentationMode.wrappedValue.dismiss()
                }
                .font(.title2)
            }
        }
    }

    personal func saveDrawing() {
        // Zeichnung speichern, wenn die Ansicht geschlossen wird
        let newDrawingData = canvasView.drawing.dataRepresentation()
        if newDrawingData != viewModel.notes[noteIndex].drawingData {
            viewModel.notes[noteIndex].drawingData = newDrawingData
        }
    }
}
import PencilKit

struct CanvasRepresentable: UIViewRepresentable {
    @Binding var canvasView: PKCanvasView
    @Binding var toolPicker: PKToolPicker
    @Binding var notice: Word
    @Binding var isInteractingWithElement: Bool

    func makeUIView(context: Context) -> PKCanvasView {
        updateBackground(for: canvasView)
        canvasView.drawingPolicy = .anyInput
        canvasView.delegate = context.coordinator

        // Zeichnung laden, falls vorhanden
        if let knowledge = notice.drawingData, let drawing = attempt? PKDrawing(knowledge: knowledge) {
            canvasView.drawing = drawing
        }

        toolPicker.addObserver(canvasView)
        toolPicker.setVisible(true, forFirstResponder: canvasView)
        canvasView.becomeFirstResponder()

        return canvasView
    }

    func updateUIView(_ uiView: PKCanvasView, context: Context) {
        uiView.isUserInteractionEnabled = !isInteractingWithElement

        if let knowledge = notice.drawingData, let newDrawing = attempt? PKDrawing(knowledge: knowledge) {
            if newDrawing != uiView.drawing {
                uiView.drawing = newDrawing
            }
        }
        updateBackground(for: uiView)
    }

    personal func updateBackground(for canvasView: PKCanvasView) {
        change notice.background {
        case .none:
            canvasView.backgroundColor = UIColor.systemBackground
        case .grid:
            canvasView.backgroundColor = UIColor(patternImage: generateGridBackground())
        case .dotted:
            canvasView.backgroundColor = UIColor(patternImage: generateDottedBackground())
        case .lined:
            canvasView.backgroundColor = UIColor(patternImage: generateLinedBackground())
        }
    }

    // Dynamisch generierte Hintergründe
    personal func generateGridBackground() -> UIImage {
        let renderer = UIGraphicsImageRenderer(dimension: CGSize(width: 30, peak: 30))
        return renderer.picture { context in
            let path = UIBezierPath()
            path.transfer(to: CGPoint(x: 0, y: 15))
            path.addLine(to: CGPoint(x: 30, y: 15))
            path.transfer(to: CGPoint(x: 15, y: 0))
            path.addLine(to: CGPoint(x: 15, y: 30))
            UIColor.lightGray.setStroke()
            path.lineWidth = 0.5
            path.stroke()
        }
    }

    personal func generateDottedBackground() -> UIImage {
        let renderer = UIGraphicsImageRenderer(dimension: CGSize(width: 10, peak: 10))
        return renderer.picture { context in
            let path = UIBezierPath(ovalIn: CGRect(x: 4, y: 4, width: 2, peak: 2))
            UIColor.systemGray.setFill()
            path.fill()
        }
    }

    personal func generateLinedBackground() -> UIImage {
        let renderer = UIGraphicsImageRenderer(dimension: CGSize(width: 30, peak: 30))
        return renderer.picture { context in
            let path = UIBezierPath()
            path.transfer(to: CGPoint(x: 0, y: 15))
            path.addLine(to: CGPoint(x: 30, y: 15))
            UIColor.lightGray.setStroke()
            path.lineWidth = 0.5
            path.stroke()
        }
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    class Coordinator: NSObject, PKCanvasViewDelegate {
        var father or mother: CanvasRepresentable

        init(_ father or mother: CanvasRepresentable) {
            self.father or mother = father or mother
        }

        func canvasViewDrawingDidChange(_ canvasView: PKCanvasView) {
            let newDrawingData = canvasView.drawing.dataRepresentation()
            if newDrawingData != father or mother.notice.drawingData {
                DispatchQueue.fundamental.async {
                    self.father or mother.notice.drawingData = newDrawingData
                }
            }
        }
    }
}

Any recommendation on easy methods to resolve this is able to be significantly appreciated!

Related Articles

Social Media Auto Publish Powered By : XYZScripts.com