赞
踩
一个自定义日期选择器,代码如下。在iOS16.12上一切正常,但在iOS15.8就出现问题。
-
- HStack {
- let pickerLabelOffset: CGFloat = 25
- ZStack {
- Picker(selection: $selectedMonth, label: Text("Month")) {
- ForEach(1...12, id: \.self) { month in
- Text(String(format: "%02d", month))
- .tag(month)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .background(Color.red)
- .clipped()
- Text("M")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
-
- ZStack {
- Picker(selection: $selectedDay, label: Text("Day")) {
- ForEach(1...31, id: \.self) { day in
- Text(String(format: "%02d", day))
- .tag(day)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .background(Color.green)
- .clipped()
- Text("D")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
-
- ZStack {
- Picker(selection: $selectedYear,label: Text("Year")) {
- ForEach(2024..<2034, id: \.self) { year in
- let y = "\(year - 2000)"
- Text(y)
- .tag(year)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .background(Color.yellow)
- .clipped()
- Text("Y")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
- }
- .frame(height: 286)
- .background(Color.white)
- .cornerRadius(8)
- .padding(.horizontal, 35)

正常效果:
异常效果:
代码如下,给Picker限制宽度后,虽然修复了上面区域平分问题,但又产生了一个新问题(下面的问题二)。
-
- HStack {
- let pickerLabelOffset: CGFloat = 25
- Spacer()
-
- ZStack {
- Picker(selection: $selectedMonth, label: Text("Month")) {
- ForEach(1...12, id: \.self) { month in
- Text(String(format: "%02d", month))
- .tag(month)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .frame(width: 88)
- .background(Color.red)
- .clipped()
- Text("M")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
-
- Spacer()
-
- ZStack {
- Picker(selection: $selectedDay, label: Text("Day")) {
- ForEach(1...31, id: \.self) { day in
- Text(String(format: "%02d", day))
- .tag(day)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .frame(width: 88)
- .background(Color.green)
- .clipped()
- Text("D")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
-
- Spacer()
-
- ZStack {
- Picker(selection: $selectedYear,label: Text("Year")) {
- ForEach(2024..<2034, id: \.self) { year in
- let y = "\(year - 2000)"
- Text(y)
- .tag(year)
- .font(.regular(23))
- }
- }
- .pickerStyle(InlinePickerStyle())
- .frame(width: 88)
- .background(Color.yellow)
- .clipped()
- Text("Y")
- .font(.regular(20))
- .offset(x: pickerLabelOffset)
- }
-
- Spacer()
- }
- .frame(height: 286)
- .background(Color.white)
- .cornerRadius(8)
- .padding(.horizontal, 35)

示意图:
如上图,想要滚动左边第一个Picker实际却滚动了中间第二个Picker,想要滚动第二个picker实际却滚动了第三个picker。问题就是,Picker在父视图ZStack的边框之外还能响应滚动事件。
这个问题,网上推荐给Picker添加.clipped()和.compositingGroup()修饰,以及给ZStack添加.contentShape(Rectangle()),但这些方式都没让我的问题得到解决。
在stackoverflow找到了另一种解决方案,能完美解决我这里的问题。这种方式能同时修复问题一和问题二,问题一的源码不用修改,直接添加下方的扩展就解决问题了。
- import Foundation
-
- // 解决Picker在父视图之外还能滚动问题
- extension UIPickerView {
-
- open override var intrinsicContentSize: CGSize {
- return CGSize(width: UIView.noIntrinsicMetric, height: super.intrinsicContentSize.height)
- }
-
- }
示意图:
Form
之内将Picker放到ScrollView或者Form
之内,这样它们将在隔离的滚动视图中,可能减少触摸事件的冲突。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。