Распознаватель жестов касания SwiftUI вызывается только один раз, когда он вызывает изменение состояния - PullRequest
1 голос
/ 04 февраля 2020

Я создаю пользовательский вид (многоколесный сборщик) для использования в форме. Для того чтобы форма была компактной, я хочу отображать средство выбора только после касания соответствующей строки. Это должно быть просто, но у меня неожиданное поведение.

Если замыкание, связанное с распознавателем жестов крана, не влияет на состояние просмотра (например, путем выполнения простого оператора печати), все отводы регистрируются. как и следовало ожидать. Когда я пытаюсь обновить состояние представления, переключая логическое значение в замыкании, жест касания выполняется только один раз (отображается средство выбора). Дальнейшие нажатия не влияют на дальнейшие изменения состояния. Добавление границ ко всем представлениям в иерархии не показало какого-либо сдвига в положении или размерах распознавателя жестов.

Это должно быть очень простым делом, но я потратил немало времени на попытки отладить мой код. Я, несомненно, пну себя, когда узнаю, что я сделал неправильно, но тем временем помощь будет с благодарностью получена. Код немного запутанный, так как на данный момент это доказательство концепции.

//
//  MultiWheelPickerView.swift
//  AthenaVS
//
//  Created by Adrian Ward on 02/02/2020.
//  Copyright © 2020 AwardVetSciences. All rights reserved.
//

import SwiftUI

struct MultiWheelPickerView: View {
    @State private var isWheelVisible = false
    @State var selection = ["", ""]
    private var prompt: String {
        let currentValue = selection.reduce("", +)
        return currentValue.count == 0 ? "Not set" : currentValue
    }
    private var title: String = "title".uppercased()

    var body: some View {
        VStack(alignment: .center) {
            VStack(alignment: .leading) {
                HStack {
                    Text("\(self.title)")
                        .font(.caption)
                        .bold()
                    Spacer()
                    Text("\(prompt)")
                        .foregroundColor(Color.gray)
                }
                    .contentShape(Rectangle()) // ensures entire HStack is tapable
                    .onTapGesture {
                        self.isWheelVisible = !self.isWheelVisible
                        print("Tapped")
                }

                if isWheelVisible {
                    GeometryReader { geometry in
                        HStack {
                            ZStack {
                                Text("One")
                                Picker(selection: self.$selection[0], label: Text("one")) {
                                    ForEach(0..<10) { row in
                                        Text("\(row)")
                                            .tag(String(row))
                                    }
                                }
                                    .labelsHidden()  // label is misplaced otherwise
                                    .pickerStyle(WheelPickerStyle())
                                    .fixedSize(horizontal: true, vertical: true)
                                    .frame(width: geometry.size.width / 2,
                                           alignment: .trailing)
                                    .clipped() // to enusre touch zone matches the text position
                            }

                            ZStack {
                                Text("Two")
                                Picker(selection: self.$selection[1], label: Text("two")) {
                                    ForEach(10..<100) { row in
                                        Text("\(row)")
                                            .tag(String(row))
                                    }
                                }
                                    .labelsHidden() // label is misplaced otherwise
                                    .pickerStyle(WheelPickerStyle())
                                    .fixedSize(horizontal: true, vertical: true)
                                    .frame(width: geometry.size.width / 2, alignment: .trailing)
                                    .clipped() // to enusre touch zone matches the text position
                            }

                        }
                    }
                    .frame(height:100)
                        .clipped() // ensures that wheel isn't superimposed on next row
                }
            }

        }
    }
}

struct MultiPickerView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            Form {
                MultiWheelPickerView().previewDisplayName("As Form child")
            }
            MultiWheelPickerView().previewDisplayName("As View child")
        }
    }
}

1 Ответ

1 голос
/ 04 февраля 2020

Ваш GeometryReader перехватывает отводы, когда средства выбора видны.

Вы не можете проверить его, добавив к нему .onTapGesture { print("Wheel tapped!") }.

Попробуйте добавить модификатор .contentShape(Rectangle()) перед установкой высоты кадра GeometryReader в 100. Это решает проблему для меня.

...