I am currently trying to create a page with three adjacent Picker
views inside of an HStack
as seen below:
I made a CustomPicker
view where I limit the frame to 90 x 240, and then use .compositingGroup()
and .clipped()
to make the selectable area of each picker not overlap.
CustomPicker.swift
import SwiftUI
struct CustomPicker: View {
@Binding var selection: Int
let pickerColor: Color
var numbers: some View {
ForEach(0...100, id: .self) { num in
Text("(num)")
.bold()
}
}
var stroke: some View {
RoundedRectangle(cornerRadius: 16)
.stroke(lineWidth: 2)
}
var backgroundColor: some View {
pickerColor
.opacity(0.25)
}
var body: some View {
Picker("Numbers", selection: $selection) {
numbers
}
.frame(width: 90, height: 240)
.compositingGroup()
.clipped()
.pickerStyle(.wheel)
.overlay(stroke)
.background(backgroundColor)
.cornerRadius(16)
}
}
ChoicePage.swift
struct ChoicePage: View {
@State var choiceA: Int = 0
@State var choiceB: Int = 0
@State var choiceC: Int = 0
var body: some View {
HStack(spacing: 18) {
CustomPicker(selection: $choiceA, pickerColor: .red)
CustomPicker(selection: $choiceB, pickerColor: .green)
CustomPicker(selection: $choiceC, pickerColor: .blue)
}
}
}
When testing both CustomPicker
and ChoicePage
in the preview canvas and simulator, it had worked perfectly fine, but when I tried to use it on my physical devices (iPhone 8 and iPhone 13, both on iOS 15.1) the clickable areas overlap. I have tried solutions from this post and this post, as well as many others, but nothing seems to be working for me.
3
Answers
I solved this issue by modifying the solution from Steve M, so all the credit for this goes to him.
He uses a
UIViewRepresentable
, but in his implementation, it's for three different selections inside of one. I slightly adjusted his implementation, to be used for just one value to select from in a given picker.I start with
BasePicker
, which acts as theUIViewRepresentable
:BasePicker.swift
I then use the
BasePicker
Representable inside ofCustomPicker
, which is a SwiftUIView
. I did this to make it a bit easier to keep my previous styling/structure in the original code.CustomPicker.swift
I then just need to slightly change
ChoicePage
and it's fixed. Also, take note that I moved thenumbers
array into myCustomPicker
view, but you adust it so that you can pass it in fromChoicePage
if you wanted.ChoicePage.swift
adding this extension is working for me in 15.4
found at https://developer.apple.com/forums/thread/687986?answerId=706782022#706782022
I have a workaround for iOS 15+.
Use .scaleEffect(x: 0.5) to half the touchable area, of the Inline picker.
This will however also squish the text inside it, to fix this, apply .scaleEffect(x: 2), ONLY to the text inside the ForEach.