我在iOS中使用分段 Select 器,它包含了很少的项目.当用户点击未选中项目时,该项目变为选中.有些项目可以包含子项目.因此,当用户点击已经 Select 的类型,我需要显示模态窗口与子项目 Select 其中之一. 但点击已 Select 的项目分段拾取器是不处理.我试着使用"长按",但它不工作,以及.

我想使用原生iOS设计,这就是为什么我不想使用"按钮"而不是分段拾取器.

因此,问题是我如何处理点击已经 Select 的项目分段拾取器显示子项目 Select 其中一个?它可以是"长按"或其他选项,这将是直观的用户.

import SwiftUI

struct CustomSegmentedPicker: View {
    
    @State private var showModalSelectD: Bool = false
    
    enum periods {
        case A, B, C, D, All
    }
    
    @State var predefinedPeriod: periods = periods.All
    @State var predefinedPeriodD: String = "D1"
    
    var body: some View {
        ZStack {
            Color.clear
                .sheet(isPresented: $showModalSelectD, content: {
                    List {
                        Picker("D", selection: $predefinedPeriodD) {
                            Text("D1").tag("D1")
                            Text("D2").tag("D2")
                            Text("D3").tag("D3")
                        }
                        .pickerStyle(.inline)
                    }
                })
            VStack {
                HStack {
                    Picker("Please choose a currency", selection: $predefinedPeriod) {
                        Text("A").tag(periods.A)
                        Text("B").tag(periods.B)
                        Text("C").tag(periods.C)
                        Text("D (\(predefinedPeriodD))").tag(periods.D)
                            .contentShape(Rectangle())
                            .simultaneousGesture(LongPressGesture().onEnded { _ in
                                print("Got Long Press")
                                showModalSelectD.toggle()
                            })
                            .simultaneousGesture(TapGesture().onEnded{
                                print("Got Tap")
                                showModalSelectD.toggle()
                            })
                        Text("All").tag(periods.All)
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }
            }
        }
    }
}

推荐答案

您可以利用这样一个事实,即分段 Select 器的按钮都具有相等的宽度.覆盖层可用于仅覆盖当前活动的拾取器项目.然后,覆盖层可以截取同一项目上的进一步点击手势.如果 Select 了不同的项目,则覆盖层将改为移动到该项目,等等.

  • 如果覆盖层的不透明度为0.001,那么它实际上是不可见的,但它仍然能够接收手势.

  • 由于拾取器的项目都具有相同的宽度,因此单个项目的宽度可以很容易地从总宽度中计算出来,总宽度可以使用GeometryReader来测量.然后可以通过施加x偏移将覆盖物移动到适当位置.偏移量需要是项目宽度的倍数,具体取决于当前 Select 的索引.

  • 执行定位的另一种方法是使用.matchedGeometryEffect.我发现使用项目标签作为职位的源并不起作用,这可能是因为项目标签被本地 Select 器实现"分解"了.然而,在 Select 器后面使用一行(隐藏的)占位符确实有效.

下面的代码使用了.matchedGeometryEffect的技巧.这需要一个名称空间:

@Namespace private var ns

为了使实现更简单,我还创建了enum CaseIterable:

enum periods: CaseIterable {
    case A, B, C, D, All
}

然后,覆盖的应用如下:

Picker("Please choose a currency", selection: $predefinedPeriod) {
    Text("A").tag(periods.A)
    Text("B").tag(periods.B)
    Text("C").tag(periods.C)
    Text("D (\(predefinedPeriodD))").tag(periods.D)
    Text("All").tag(periods.All)
}
.pickerStyle(SegmentedPickerStyle())
.background {

    // A row of placeholders
    HStack(spacing: 0) {
        ForEach(periods.allCases, id: \.self) { period in
            Color.clear
                .frame(maxWidth: .infinity)
                .matchedGeometryEffect(id: period, in: ns, isSource: true)
        }
    }
}
.overlay {
    Rectangle()
        .fill(.background)
        .opacity(0.001)
        .matchedGeometryEffect(id: predefinedPeriod, in: ns, isSource: false)
        .simultaneousGesture(LongPressGesture().onEnded { _ in
            print("Got Long Press on \(predefinedPeriod)")
            if predefinedPeriod == .D {
                showModalSelectD.toggle()
            }
        })
        .simultaneousGesture(TapGesture().onEnded{
            print("Got Tap on \(predefinedPeriod)")
            if predefinedPeriod == .D {
                showModalSelectD.toggle()
            }
        })
}

Ios相关问答推荐

ITMS—91053:Flutter Project中缺少API声明

SWIFT中具有可选返回类型和泛型的网络请求

如何使视图完全适合屏幕,而不会在旋转时溢出手机屏幕的边界?

如何在iPhone 15上消除.NET Maui中状态栏和页面之间的差距

如何在react 本机模块中使用Bundle.main.Path()在SWIFT中导入assets资源

Xcode -Google Mobile Ads SDK在没有AppMeasurement的情况下初始化

无法添加以供审阅-Xcode 15.0.1

Flutter 应用程序中带有Firebase的GoogleService-Info.plist中缺少CLIENT_ID、REVERSED_CLIENT_ID和ANDROID_CLIENT-ID

分配给指针会通过 class_addMethod 导致 EXC_BAD_ACCESS

Swift Vision库识别文本后如何将其赋值给 struct 体实例属性以供显示?

在 iOS 上启用明文本地流量在 .NET MAUI 中不起作用

iOS 16 堆栈视图中按钮的奇怪动画

iOS 是否支持使用独立 .xib 文件创建的嵌套自定义子视图?

在 UICollectionView 上动态设置布局导致莫名其妙的 contentOffset 变化

滑动列表项以获取更多选项(Flutter)

在滚动视图中使用动态大小的控制器调整容器视图的大小

什么是强属性属性

如何防止 iOS 设备上的显示屏变暗和关闭?

如何在 iphone 屏幕中间显示活动指示器?

使用 swift 3 在 UIView 上添加阴影