6

I have in a View a Picker that I wish to limit to a defined height and width. While the code below accomplishes that visually, the picker responds to tap actions outside of its area -- in some cases, responding to tap on a nearby button as if I were tapping to scroll the picker to the beginning or end of its values. (The button doesn't respond to the tap; the picker does. But this also occurs when tapping close to - but outside of - the Picker, where there is NO control.)

The picker seems to respond to touches both above, below, and to the side. When the view is big enough (full screen, or 2/3 screen), the effect become less noticeable, but when the whole app is getting only 1/3 of the screen, and the picker's width -- as a function of the View's geometry -- becomes small, the other controls are also closer together, and it becomes very difficult to work with.

How can the Picker be made to ignore all touches outside of its visible area?

Picker(selection: self.$monthSelector, label: Text("Month")) {
   ForEach(0 ..< 12, id: \.self) {
      Text(self.monthNames()[$0])
         .foregroundColor(  Color.black )
      }
   }
      .labelsHidden()
       // THE FOLLOWING 2 STATEMENTS *IN CONJUNCTION* SEEM TO GIVE DESIRED Height/Width
      .fixedSize()
      .frame(maxWidth: geometry.size.width * 0.35, maxHeight: 100)
      .clipped()     // seems to accomplish nothing, visually or regarding touches
      .background(Color.white)
      .cornerRadius(10)

Things I've considered:

  • Putting .clipped on the frame (suggested here). No effect.
  • This Question Not SwiftUI, and no real lead from it I could determine.
  • This Question Discusses expanding the tappable area of a button. Don't see a way to apply the key insight ("apply modifiers to the content of the button rather than to the button itself") to a Picker -- especially with regard to its height.
  • This Question Has no answer, and what I'm seeing with the picker seems well beyond the ~ 15 pts "margin of error" that the comment to that question seems to attribute. Also, what I'm seeing with the Picker happens in both the simulator and also an actual device.
ConfusionTowers
  • 911
  • 11
  • 34
  • I attempted to post the answer here but it was deleted because it’s a duplicate answer. I was able to post the answer in the first link you posted(regarding .clipped) – Prasanth Mar 27 '22 at 13:40

4 Answers4

7

Here is a solution. Tested with Xcode 11.4 / iOS 13.4.

.compositingGroup() // << add this modifier above clipping !!!
.clipped()
Asperi
  • 228,894
  • 20
  • 464
  • 690
3

iOS 16 - I found that I had a few Pickers that were operating outside of their expected 'tap-zone' when I was using their default appearance which was 'menu' Once I specified what type of Picker it should be, such as the 'menu', then this solved my problem. The picker only activated when you tap on the expected reaction area.

.pickerStyle(.menu)
David_2877
  • 257
  • 4
  • 7
  • I was having the same issue and this solution worked for me on Xcode 14.3.1 and the iOS 16.4 simulator. I'll remember to always specify the picker type now. Thanks! – Evan K. Stone Aug 21 '23 at 21:09
1

This link goes through some of the old workarounds, but there doesn't appear to be a good one for iOS 15.1.

There is an example of how to get it working though. He makes a ViewRepresentable struct.

iOS15 - SwiftUI WheelPicker scrollable outside frame and clipped area destructing other interfaces

PDoran89
  • 11
  • 1
-2

If you apply .contentShape(Rectangle()) prior to clipped it will limit touches to the visible area.

Michael Latta
  • 47
  • 1
  • 4