I’ve created a Sentence creator
like in right here(Pure SwiftUI). Button dragging and positioning is working superb. The issue is,
- Whereas dragging the button, it is not going to displaying on Sentence space & sensible versa.
(There are 2 areas, Sentence & Button space) - After dropping the button it is positioned with none challenge.
- Different behaviors are working as anticipated
Can anybody assist me easy methods to repair this challenge?
struct SwiftUIDraggableButtonView: View {
@State non-public var buttons: [DraggableButtonModel] = [
DraggableButtonModel(id: 1, text: "me"),
DraggableButtonModel(id: 2, text: "foreign friends."),
DraggableButtonModel(id: 3, text: "to me,"),
DraggableButtonModel(id: 4, text: "to make"),
DraggableButtonModel(id: 5, text: "means"),
DraggableButtonModel(id: 6, text: "because"),
DraggableButtonModel(id: 7, text: "it"),
DraggableButtonModel(id: 8, text: "allows"),
DraggableButtonModel(id: 9, text: "study"),
DraggableButtonModel(id: 10, text: "My foreign language"),
DraggableButtonModel(id: 11, text: "a lot")
]
@State non-public var sentenceButtons: [DraggableButtonModel] = []
var physique: some View {
VStack(spacing: 20) {
// Unified FlowLayout for sentence and default areas
FlowLayout(spacing: 5, objects: sentenceButtons) { button in
DraggableButtonNew(
mannequin: button,
isInSentence: true
) { motion in
handleButtonAction(motion, button: button)
}
.transition(.transfer(edge: .backside))
}
.padding()
.body(peak: 200) // Set peak for sentence space
.background(Coloration.grey)
.cornerRadius(8)
.zIndex(0)
// Default button space
FlowLayout(spacing: 10, objects: buttons) { button in
DraggableButtonNew(
mannequin: button,
isInSentence: false
) { motion in
handleButtonAction(motion, button: button)
}
.allowsHitTesting(!button.isDisabled) // Disable interplay for disabled buttons
.transition(.transfer(edge: .high))
}
.body(peak: 200) // Set peak for default button space
.cornerRadius(8)
.zIndex(1)
Spacer()
}
.padding()
}
non-public func handleButtonAction(_ motion: DraggableButtonAction, button: DraggableButtonModel) {
withAnimation {
swap motion {
case .faucet, .drag:
// Deal with button faucet: transfer button between sentence and default areas
if let index = sentenceButtons.firstIndex(the place: { $0.id == button.id }) {
// Button is within the sentence space, transfer it again to default
sentenceButtons.take away(at: index)
if let defaultIndex = buttons.firstIndex(the place: { $0.id == button.id }) {
buttons[defaultIndex].isDisabled = false // Re-enable in default space
}
} else if let defaultIndex = buttons.firstIndex(the place: { $0.id == button.id }),
!buttons[defaultIndex].isDisabled {
// Button is in default space, transfer it to condemn
buttons[defaultIndex].isDisabled = true
sentenceButtons.append(button)
}
}
}
}
}
// FlowLayout for wrapping buttons in a number of strains
struct FlowLayout<Knowledge: RandomAccessCollection, Content material: View>: View
the place Knowledge.Aspect: Identifiable {
let spacing: CGFloat
let objects: Knowledge
let content material: (Knowledge.Aspect) -> Content material
var physique: some View {
var width: CGFloat = 0
var peak: CGFloat = 0
return GeometryReader { geometry in
ZStack(alignment: .topLeading) {
ForEach(objects) { merchandise in
content material(merchandise)
.alignmentGuide(.main) { d in
if abs(width - d.width) > geometry.measurement.width {
width = 0
peak -= d.peak + spacing
}
let end result = width
if merchandise.id == objects.final?.id {
width = 0
} else {
width -= d.width + spacing
}
return end result
}
.alignmentGuide(.high) { _ in
let end result = peak
if merchandise.id == objects.final?.id {
peak = 0
}
return end result
}
}
}
}
.body(maxHeight: .infinity, alignment: .topLeading)
}
}
// Draggable Button
struct DraggableButtonNew: View {
let mannequin: DraggableButtonModel
let isInSentence: Bool
let actionHandler: (DraggableButtonAction) -> Void
@State non-public var offset: CGSize = .zero
var physique: some View {
Textual content(mannequin.textual content)
.padding(8)
.background(isInSentence ? Coloration.orange : mannequin.isDisabled ? Coloration.grey : Coloration.orange)
.foregroundColor(Coloration.white)
.cornerRadius(6)
.offset(offset)
.zIndex(offset == .zero ? 0 : 1)
.gesture(
DragGesture()
.onChanged { worth in
offset = worth.translation
}
.onEnded { _ in
actionHandler(.drag)
offset = .zero
}
)
.onTapGesture {
actionHandler(.faucet)
}
}
}
// Button Mannequin
struct DraggableButtonModel: Identifiable, Equatable {
let id: Int
let textual content: String
var isDisabled: Bool = false
}
enum DraggableButtonAction {
case faucet
case drag
}