Разве нет простого способа увеличить изображение в Swiftui? - PullRequest
2 голосов
/ 11 октября 2019

Я хочу иметь возможность изменять размер и перемещать изображение в SwiftUI (как если бы это была карта) с помощью щепотки для масштабирования и перетаскивания.

С помощью UIKit я встроил изображение в UIScrollViewи он позаботился об этом, но я не знаю, как это сделать в SwiftUI. Я пытался использовать MagnificationGesture, но не могу заставить его работать гладко.

Я давно об этом искал, кто-нибудь знает, есть ли более простой способ?

Ответы [ 2 ]

3 голосов
/ 20 октября 2019

SwiftUI API здесь довольно бесполезен: onChanged дает число относительно начала текущего жеста масштабирования и не имеет очевидного пути в обратном вызове для получения начального значения. И есть обратный обратный вызов, но его легко пропустить / забыть.

Чтобы обойти, добавьте:

@State var lastScaleValue: CGFloat = 1.0

Затем в обратном вызове:

.gesture(MagnificationGesture().onChanged { val in
            let delta = val / self.lastScaleValue
            self.lastScaleValue = val
            let newScale = self.scale * delta

//... anything else e.g. clamping the newScale
}.onEnded { val in
  // without this the next gesture will be broken
  self.lastScaleValue = 1.0
}

, где newScaleэто ваше собственное отслеживание масштаба (возможно, состояние или привязка). Если вы установите свою шкалу напрямую, она будет испорчена, так как на каждом тике сумма будет относительно предыдущей суммы.

3 голосов
/ 11 октября 2019

Похоже, что в SciftView SwiftUI нет встроенной поддержки, однако все еще есть довольно простой способ сделать это.

Создайте MagnificationGesture, как вы и хотели, но обязательно умножьте ваш текущий масштаб на значение, которое вы получите в закрытии .onChanged жеста. Это закрытие дает вам изменение масштаба вместо текущего значения масштаба.

Когда вы уменьшите масштаб и начнете увеличивать масштаб, оно не увеличится с текущего масштаба (0,5до 0,6 в качестве произвольного примера), он увеличится с 1 до 1,1. Вот почему вы видели странное поведение.

Этот ответ будет работать, если MagnificationGesture находится в том же виде, что и .scaleEffect. В противном случае ответ Джеймса будет работать лучше.

struct ContentView: View {
    @State var scale: CGFloat
    var body: some View {
        let gesture = MagnificationGesture(minimumScaleDelta: 0.1)
            .onChanged { scaleDelta in
                self.scale *= scaleDelta
        }
        return ScrollView {
            // Your ScrollView content here :)
        }
            .gesture(gesture)
            .scaleEffect(scale)
    }
}

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

...