Search code examples
swiftswiftuidatepicker

Increase tappable area Datepicker SwiftUI


I'm trying to build a custom datepicker which is working perfectly so far. The last thing I try to increase is the tappable area, which I prefer to be the entire shape. Currently, a user has to tap the Calendar picture for date selection.

I've experimented with Contentshape, increasing the frame and adding padding, but nothing works as expected. How can I increase the tappable area while keeping it looking like this? Ideally, a user could tap the area within the border and the picker pops up. enter image description here

My code:

struct DatePickerView: View {
    @State private var selectedDate = Date()

    var body: some View {
        VStack(alignment: .leading) {
            Text("Datum")
                .foregroundColor(.black)
            HStack {
                Text("\(selectedDate.formatted())")
                Spacer()
                ZStack {
                    DatePicker("", selection: $selectedDate, in: ...Date(), displayedComponents: .date)
                        .datePickerStyle(.compact)
                        .labelsHidden()
                        .accentColor(.black)
                    SwiftUIWrapper {
                        Image(systemName: "calendar")
                            .resizable()
                            .frame(width: 18, height: 20)
                    }
                    .allowsHitTesting(false)
                }
                .frame(width: 18, height: 20)
            }
            .padding(16)
            .overlay {
                RoundedRectangle(cornerRadius: 8)
                    .strokeBorder(
                        style: StrokeStyle(
                            lineWidth: 0.5
                        )
                    )
                    .foregroundColor(.black)
            }
        }
    }
}

struct DatePicker_Previews: PreviewProvider {
    static var previews: some View {
        DatePickerView()
    }
}

struct SwiftUIWrapper<T: View>: UIViewControllerRepresentable {
    let content: () -> T
    func makeUIViewController(context: Context) -> UIHostingController<T> {
        UIHostingController(rootView: content())
    }
    func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {}
}


Solution

  • Managed to make it work with some minor tweaks. Especially scaleEffect!

    .compositingGroup()
    .scaleEffect(x: 10, y: 1.5)
    .clipped()
    

    Endresult:

    struct DatePickerView: View {
        @State private var selectedDate = Date()
    
        var body: some View {
            VStack(alignment: .leading) {
                Text("Datum")
                    .foregroundColor(.gray)
                    ZStack {
                        DatePicker("", selection: $selectedDate, in: ...Date(), displayedComponents: .date)
                            .datePickerStyle(.compact)
                            .labelsHidden()
                            .accentColor(.black)
                            .compositingGroup()
                            .scaleEffect(x: 10, y: 1.5)
                            .clipped()
                        SwiftUIWrapper {
                            HStack {
                                Text(selectedDate.formatted())
                                Spacer()
                                Image(systemName: "calendar")
                                    .resizable()
                                    .frame(width: 18, height: 20)
                            }
                            .padding(16)
                            .background(Color.white)
                        }
                        .padding(.vertical, 32)
                        .fixedSize(horizontal: false, vertical: true)
                        .allowsHitTesting(false)
                }
                .overlay (
                    RoundedRectangle(cornerRadius: 8)
                        .strokeBorder(
                            style: StrokeStyle(lineWidth: 0.5)
                        )
                        .foregroundColor(.black)
                )
            }
        }
    }
    
    struct SwiftUIWrapper<T: View>: UIViewControllerRepresentable {
        let content: () -> T
        func makeUIViewController(context: Context) -> UIHostingController<T> {
            UIHostingController(rootView: content())
        }
        func updateUIViewController(_ uiViewController: UIHostingController<T>, context: Context) {}
    }
    
    struct DatePicker_Previews: PreviewProvider {
        static var previews: some View {
            DatePickerView()
        }
    }