Невосприимчивое представление (проблема) в ScrollView, который содержит GeometryReader для определения размера каждого вложенного представления

Представьте себе список задач, в котором вам нужны настраиваемые анимированные флажки для каждой задачи. Поскольку списки, похоже, плохо работают со специальными кнопками, я решил использовать вертикальный ScrollView, который состоит из VStack из массива элементов с помощью ForEach. Для каждой ячейки задачи я установил GeometryReader, чтобы использовать его геометрию для изменения размера фигур, которые я собираюсь использовать для флажков. Проблема в том, что последний элемент в ForEach перестает отвечать на жесты. Если я добавляю еще одну задачу, добавленная задача перестает отвечать. Как я могу это исправить? Я не могу получить GeometryReader из ScrollView, потому что он не дает мне размер ячейки задачи. Есть идеи? Кроме того, если я делаю это неправильно, дайте мне знать, я новичок в Swift. В последний раз я программировал много лет назад.

Это представление, которое использует TaskCell:

struct TaskListView: View {
    
    @ObservedObject var catalog: GoalsCatalog
        
    var body: some View {
        NavigationView {
            VStack {
                ScrollView(.vertical, showsIndicators: true) {
                    VStack(spacing: 40) {
                        ForEach(catalog.tasks) { task in
                            TaskCell(task: task)
                                .environmentObject(self.catalog)
                        }
                    }
                    .padding([.top, .leading], 20.0)
                    .frame(maxWidth: .infinity)
                    .fixedSize(horizontal: false, vertical: true)
                }
                // Solves ScrollView init resizing issue:
                if self.catalog.tasks.count == 0 {
                    Spacer()
                }
                Button(action: {
                    self.catalog.addTaskByName(name: "New Task")
                }) {
                    Text("New Task")
                }
                .padding(.bottom, 8.0)
                .navigationBarTitle("Title")
            }
        }
    }
}

Это TaskCell (в процессе):

struct TaskCell: View {
    
    var task: GoalsSystem.Task
    @EnvironmentObject var catalog: GoalsCatalog

    let generator = UIImpactFeedbackGenerator()
    
    var body: some View {
        GeometryReader { geometry in
            self.body(for: geometry.size)
        }
    }

    func body(for size: CGSize) -> some View {
        ZStack(alignment: .leading) {
            RoundedRectangle(cornerRadius: 1)
                .fill(self.completedLongPress ? Color.blue : Color.white)
            HStack(spacing: 20) {
                Button(action: {
                    print("Click")
                    self.generator.impactOccurred(intensity: 0.5)
                    self.catalog.toggleTaskCompletition(of: self.task)
                    // TODO: - LAST task added can't be toggled as completed. Why?
                }) {
                    ZStack {
                        RoundedRectangle(cornerRadius: checkBoxCornerRadius)
                            .fill(Color.gray)
                            .aspectRatio(1, contentMode: .fit)
                        RoundedRectangle(cornerRadius: checkBoxCornerRadius)
                            .stroke(lineWidth: checkBoxLineWidth)
                            .aspectRatio(1, contentMode: .fit)
                    }.frame(width: size.width/20, height: size.width/10, alignment: .center)
                }
                VStack(alignment: .leading) {
                    Text(task.taskName).strikethrough(task.isComplete)
                    Text("Details")
                        .font(.subheadline)
                        .foregroundColor(Color.gray)
                }
                .gesture(self.pressToSelect())
                .onTapGesture {
                    self.catalog.toggleTaskCompletition(of: self.task)
                }
            }
            .fixedSize(horizontal: true, vertical: false)
            .opacity(task.isComplete ? taskOpacityInactive : taskOpacityActive)
            .scaleEffect(self.isDetectingLongPress ? 1.05 : (self.completedLongPress ? 1.1 : 1))
        }

    }
    
    @GestureState private var isDetectingLongPress = false
    @State private var completedLongPress = false
    
    private func pressToSelect() -> some Gesture {
        LongPressGesture(minimumDuration: 0.3, maximumDistance: 10)
            .updating($isDetectingLongPress) { currentState, gestureState, transaction in
                gestureState = currentState
                transaction.animation = Animation.easeIn(duration: 0.5)
            }
            .onEnded { finished in
                self.generator.impactOccurred(intensity: 0.5)
                    self.completedLongPress = true
            }
    }
    
    // MARK: - Drawing constants

    let checkBoxCornerRadius: CGFloat = 7
    let checkBoxLineWidth: CGFloat = 2
    let taskOpacityActive: Double = 1
    let taskOpacityInactive: Double = 0.5
    let longPressDuration: Double = 3
    let longPressMaximumDistance: CGFloat = 10
    
}

0 ответов

Другие вопросы по тегам