SwiftUI: Настройка границ просмотра прокрутки

#swift #swiftui #uikit #swiftui-scrollview

Вопрос:

Я пытаюсь масштабировать представление по горизонтали, используя scaleEffect и MagnificationGesture . Он почти работает так, как я хочу, за исключением того, что ScrollView он не изменяет размер при изменении размера дочернего представления.

Есть ли решение для этого? Любое решение будет высоко оценено.

Чтобы воспроизвести:

  1. запустите приведенный ниже код
  2. увеличьте изображение по горизонтали с помощью жеста щепотки
  3. обратите внимание, что ScrollView прокрутки выглядят так, как будто изображение все еще имеет тот же размер.
 struct ContentView: View {

    @State private var currentAmount: CGFloat = 0
    @State private var finalAmount: CGFloat = 1

    var body: some View {
        ScrollView(.horizontal) {
            Image(systemName: "star")
                .resizable()
                .scaledToFit()
                .scaleEffect(x: finalAmount   currentAmount, y: 1)
                .gesture(
                    MagnificationGesture()
                        .onChanged { amount in
                            self.currentAmount = amount - 1
                        }
                        .onEnded { amount in
                            self.finalAmount  = self.currentAmount
                            self.currentAmount = 0
                        }
                )
        }
        .frame(maxHeight: 300)
    }
}
 

Комментарии:

1. Эффект масштабирования — это только визуальный эффект, реальный кадр остается прежним, поэтому, если вы хотите изменить реальный размер изображения, измените его кадр.

2. Вот и все! Работайте над чем угодно, кроме масштаба!

Ответ №1:

Этот взгляд делает это.

 struct HorizontalScaleView<Content: View>: View {

    @ViewBuilder var content: Content

    @State private var currentAmount: CGFloat = 0
    @State private var finalAmount: CGFloat = 1

    var body: some View {
        GeometryReader { geo in
            ScrollView(.horizontal) {
                content
                    .scaledToFit()
                    .scaleEffect(x: finalAmount   currentAmount, y: 1)
                    .frame(width: (finalAmount   currentAmount) * geo.size.width, height: geo.size.width)
                    .gesture(
                        MagnificationGesture()
                            .onChanged { amount in
                                self.currentAmount = amount - 1
                            }
                            .onEnded { _ in
                                if self.finalAmount   self.currentAmount >= 1 {
                                    self.finalAmount  = self.currentAmount
                                } else {
                                    self.finalAmount = 1
                                }
                                self.currentAmount = 0
                            }
                    )
            }
        }
    }
}