Как ущипнуть и прокрутить изображение в SwiftUI? - PullRequest
0 голосов
/ 11 марта 2020

Я хочу добавить в свое приложение средство просмотра изображений, но у меня возникли проблемы с его реализацией. Я хочу отобразить изображение и позволить пользователю сжимать и прокручивать изображение, чтобы детально изучить его. Исходя из того, что я собрал из нескольких постов Inte rnet, у меня что-то вроде работает, но не совсем. Вот мой код:

import SwiftUI

struct ContentView: View {

    @State var currentScale: CGFloat = 1.0
    @State var previousScale: CGFloat = 1.0

    @State var currentOffset = CGSize.zero
    @State var previousOffset = CGSize.zero

    var body: some View {

        ZStack {

            Image("bulldog2")
                .resizable()
                .edgesIgnoringSafeArea(.all)
                .aspectRatio(contentMode: .fit)
                .offset(x: self.currentOffset.width, y: self.currentOffset.height)
                .scaleEffect(self.currentScale)
                .gesture(DragGesture()
                    .onChanged { value in
                        let deltaX = value.translation.width - self.previousOffset.width
                        let deltaY = value.translation.height - self.previousOffset.height
                        self.previousOffset.width = value.translation.width
                        self.previousOffset.height = value.translation.height
                        self.currentOffset.width = self.currentOffset.width + deltaX / self.currentScale
                        self.currentOffset.height = self.currentOffset.height + deltaY / self.currentScale }
                    .onEnded { value in self.previousOffset = CGSize.zero })
                .gesture(MagnificationGesture()
                    .onChanged { value in
                        let delta = value / self.previousScale
                        self.previousScale = value
                        self.currentScale = self.currentScale * delta
                }
                .onEnded { value in self.previousScale = 1.0 })

            VStack {

                Spacer()

                HStack {
                    Text("Menu 1").padding().background(Color.white).cornerRadius(30).padding()
                    Spacer()
                    Text("Menu 2").padding().background(Color.white).cornerRadius(30).padding()
                }
            }
        }
    }
}

Первоначальный вид выглядит следующим образом:

enter image description here

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

enter image description here

Вторая проблема, которая не является большой Во-первых, я могу уменьшить изображение, но оно становится слишком маленьким по сравнению с изображением. Я хочу ограничить его так, чтобы «подгонка» была его наименьшим размером. Есть ли лучший способ, чем ограничение self.currentScale и self.previousScale?

enter image description here

Третья проблема заключается в том, что если я изменю изображение, чтобы заполнить пространство нижнее меню становится больше, чем экран телефона.

enter image description here

Я не iOS разработчик, и, вероятно, есть гораздо лучший способ реализовать эту функцию. Спасибо за помощь.

1 Ответ

0 голосов

Я могу ответить на 2 из 3 вопросов. Я не могу повторить третий.

  1. вы можете использовать GeometryReader и использовать его frame и size, чтобы наложить некоторые ограничения (я покажу это в примере ниже);
  2. возможно, самый простой и лучший способ - просто использовать функцию max, например .scaleEffect(max(self.currentScale, 1.0)).

Вот пример изменения:

struct BulldogImageViewerView: View {
    @State var currentScale: CGFloat = 1.0
    @State var previousScale: CGFloat = 1.0

    @State var currentOffset = CGSize.zero
    @State var previousOffset = CGSize.zero

    var body: some View {

        ZStack {

            GeometryReader { geometry in // here you'll have size and frame

                Image("bulldog")
                    .resizable()
                    .edgesIgnoringSafeArea(.all)
                    .aspectRatio(contentMode: .fit)
                    .offset(x: self.currentOffset.width, y: self.currentOffset.height)
                    .scaleEffect(max(self.currentScale, 1.0)) // the second question
                    .gesture(DragGesture()
                        .onChanged { value in

                            let deltaX = value.translation.width - self.previousOffset.width
                            let deltaY = value.translation.height - self.previousOffset.height
                            self.previousOffset.width = value.translation.width
                            self.previousOffset.height = value.translation.height

                            let newOffsetWidth = self.currentOffset.width + deltaX / self.currentScale
                            // question 1: how to add horizontal constraint (but you need to think about scale)
                            if newOffsetWidth <= geometry.size.width - 150.0 && newOffsetWidth > -150.0 {
                                self.currentOffset.width = self.currentOffset.width + deltaX / self.currentScale
                            }

                            self.currentOffset.height = self.currentOffset.height + deltaY / self.currentScale }

                        .onEnded { value in self.previousOffset = CGSize.zero })

                    .gesture(MagnificationGesture()
                        .onChanged { value in
                            let delta = value / self.previousScale
                            self.previousScale = value
                            self.currentScale = self.currentScale * delta
                    }
                    .onEnded { value in self.previousScale = 1.0 })

            }

            VStack {

                Spacer()

                HStack {
                    Text("Menu 1").padding().cornerRadius(30).background(Color.blue).padding()
                    Spacer()
                    Text("Menu 2").padding().cornerRadius(30).background(Color.blue).padding()
                }
            }
        }
    }
}

с этот код, которого я достиг:

  • пользователь не может отодвинуть изображение от экрана в горизонтальном направлении;

  • пользователь не может уменьшить изображение ;

...