SwiftUI: DragGesture в ScrollView не регистрирует прокрутку, когда смахивание начинается в представлении DragGesture. - PullRequest
1 голос
/ 27 марта 2020

Итак, у меня есть действительно хорошая анимация, которую я хочу, когда пользователь нажимает на вид, где он как бы «подпрыгивает» под пальцем, как будто он реагирует на прикосновение.

Исходная цель

Мне нужно зарегистрироваться, когда пользователь нажимает на представление ( черный прямоугольник в этом примере), чтобы я мог начать его уменьшать, затем мне нужно зарегистрироваться, когда они отпустят представление, чтобы я мог позволить ему вернуться к первоначальному размеру. Пользователь по-прежнему должен иметь возможность нормально прокручивать в ScrollView

Начальное «Решение»

Мне удалось добиться нужной анимации с помощью жеста DragGesture() с помощью minimumDistance: 0.

См. Пример GIF здесь

Это достигается с помощью следующего кода:

@State private var pressed: Bool = false

var body: some View {
        let drag = DragGesture(minimumDistance: 0)
            .onChanged({_ in
                self.pressed = true
            })
            .onEnded({_ in
                self.pressed = false
            })

        return ScrollView {
            Rectangle()
                .frame(minHeight: 100)
                .scaleEffect(self.pressed ? 0.5 : 1)
                .animation(.easeInOut)
//                .onTapGesture(perform: {
//                    self.pressed.toggle()
//                })
                .gesture(drag)
        }
    }

Проблема

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

См. Пример GIF здесь

Альтернатива

Если я использую модификатор .onTapGesture(), тогда я могу нажмите, и он зарегистрирован, а также начнет прокрутку, и при необходимости он зарегистрируется как прокрутка

См. пример GIF здесь

Это достигается с помощью следующего кода:

@State private var pressed: Bool = false

    var body: some View {
        let drag = DragGesture(minimumDistance: 0)
            .onChanged({_ in
                self.pressed = true
            })
            .onEnded({_ in
                self.pressed = false
            })

        return ScrollView {
            Rectangle()
                .frame(minHeight: 100)
                .scaleEffect(self.pressed ? 0.5 : 1)
                .animation(.easeInOut)
                .onTapGesture(perform: {
                    self.pressed.toggle()
                })
//                .gesture(drag)
        }
    }

Вопрос

Так как же мне по-прежнему получать желаемую анимацию при одновременной прокрутке? Я изучил GestureMasks, simultaneousGesture, LongPressGesture и другие, и они не достигают быстрой анимации, которую я ищу ...

Спасибо!

1 Ответ

1 голос
/ 27 марта 2020

Успел "по большей части" исправить это сам, разместив ответ, чтобы помочь другим.

Это не идеально, но намного лучше. Если кто-нибудь может понять, как сделать так, чтобы он не уменьшался при прокрутке, это было бы здорово. Но в противном случае вы можете нажать на него и прокручивать его просто отлично.

struct ContentView: View {
    @State private var pressed: Bool = false

    var body: some View {
        print(self.pressed)
        return ScrollView {
            Button(action: { self.pressed.toggle() }) {
                Rectangle()
                    .frame(minHeight: 100)
                    .animation(.easeInOut)
            }.buttonStyle(tapBounceButtonStyle())
        }
    }
}

struct tapBounceButtonStyle: ButtonStyle {
  func makeBody(configuration: Self.Configuration) -> some View {
    configuration.label
        .scaleEffect(configuration.isPressed ? 0.9 : 1)
  }
}
...