Home > Blockchain >  How to set size limit using DragGesture() when resizing a shape in SwiftUI?
How to set size limit using DragGesture() when resizing a shape in SwiftUI?

Time:12-13

I am trying to create a resizable shape by using DragGesture() and I can't find a way to limit the size of the shape when dragging.

Here is the current output. I don't want to cross the green line. https://imgur.com/a/MgyLdpj

This is the current code:

struct ContentView: View {
    
    var body: some View {
        VStack {
            CustomDraggableComponent()
                .frame(width: 350, height: 350, alignment: .center)
                .border(Color.green, width: 5)
        }
    }
    
    
    
    struct CustomDraggableComponent: View {
        @State var height: CGFloat = 200
        @State var width: CGFloat = 200
        
        
        
        var body: some View {
            VStack {
                Rectangle()
                    .fill(Color.red)
                    .frame(minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)
                
                HStack {
                    Spacer()
                    Rectangle()
                        .fill(Color.gray)
                        .frame(width: 80, height: 30)
                        .cornerRadius(10)
                        .overlay(Text("Drag"))
                        .gesture(
                            DragGesture()
                                .onChanged { value in
                                    height = max(200, height   value.translation.height)
                                    width = max(200, height   value.translation.width)
                                }
                        )
                    Spacer()
                }
            }
        }
    }
}

CodePudding user response:

You can use GeometryReader to get subview size and restrict size with min condition.

struct CustomDraggableComponent: View {
        @State var height: CGFloat = 200
        @State var width: CGFloat = 200
        
        @State private var maxWidth = 0
        @State private var maxHeight = 0
        
        var body: some View {
            GeometryReader { geo in
                VStack(alignment: .center) {
                    Rectangle()
                        .fill(Color.red)
                        .frame(minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)
                    
                    HStack {
                        Spacer()
                        Rectangle()
                            .fill(Color.gray)
                            .frame(width: 80, height: 30)
                            .cornerRadius(10)
                            .overlay(Text("Drag"))
                            .gesture(
                                DragGesture()
                                    .onChanged { value in
                                        // This code allows resizing view min 200 and max to parent view size
                                        height = min(max(200, height   value.translation.height), geo.size.height - 45) // 45 for Drag button height   padding
                                        width = min(max(200, height   value.translation.width), geo.size.width)
                                    }
                            )
                        Spacer()
                    }
                } .frame(width: geo.size.width, height: geo.size.height)
            }
        }
    }

CodePudding user response:

You need just place second shape into overlay of first one and then it will be limited to needed area automatically, like

var body: some View {
    Rectangle()
        .fill(Color.red)
        .frame(minWidth: width, maxWidth: width, minHeight: height, maxHeight: height)
        .overlay(
            Rectangle()
                .fill(Color.gray)
                .frame(width: 80, height: 30)
                .cornerRadius(10)
                .overlay(Text("Drag"))
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            height = max(200, height   value.translation.height)
                            width = max(200, height   value.translation.width)
                        }
                )
        )
}
  • Related