首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Swiftui中,难道没有一种简单的缩小图像的方法吗?

在Swiftui中,难道没有一种简单的缩小图像的方法吗?
EN

Stack Overflow用户
提问于 2019-10-11 13:00:32
回答 13查看 31.6K关注 0票数 47

我想要能够调整大小和移动一个图像在SwiftUI (如果它是一个地图)与捏,以缩放和拖动它周围。

使用UIKit,我将图像嵌入到UIScrollView中,并由它来处理,但我不知道如何在SwiftUI中实现它。我试着使用MagnificationGesture,但是我不能让它顺利地工作。

我已经搜索了一段时间了,有人知道有没有更简单的方法吗?

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2019-10-19 21:39:44

在这里,SwiftUI API是非常没有帮助的: onChanged给出的数字相对于当前缩放手势的开始,并且在回调中没有明显的方法来获得初始值。还有一个onEnded回调,但很容易错过/忘记。

在周围工作,加上:

代码语言:javascript
运行
复制
@State var lastScaleValue: CGFloat = 1.0

然后在回调中:

代码语言:javascript
运行
复制
.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是您自己的规模跟踪(可能是状态或绑定)。如果你直接设置你的刻度,它会被弄乱,因为在每一个滴答,金额将相对于以前的金额。

票数 35
EN

Stack Overflow用户

发布于 2020-09-28 22:05:15

这里的其他答案与自定义缩放逻辑过于复杂。如果您想要标准,经过战斗测试的UIScrollView缩放行为,您只需使用UIScrollView即可!

SwiftUI允许您使用UIViewRepresentableUIViewControllerRepresentable将任何UIView放入否则的SwiftUI视图层次结构中。然后,要在该视图中放入更多的SwiftUI内容,可以使用UIHostingController。在与UIKit接口API文档中阅读更多关于SwiftUI互操作的信息。

您可以找到一个更完整的示例,在实际的应用程序at:https://github.com/jtbandes/SpacePOD/blob/main/SpacePOD/ZoomableScrollView.swift中使用该示例(该示例还包含了更多对图像进行对齐的技巧)。

代码语言:javascript
运行
复制
var body: some View {
  ZoomableScrollView {
    Image("Your image here")
  }
}
代码语言:javascript
运行
复制
struct ZoomableScrollView<Content: View>: UIViewRepresentable {
  private var content: Content

  init(@ViewBuilder content: () -> Content) {
    self.content = content()
  }

  func makeUIView(context: Context) -> UIScrollView {
    // set up the UIScrollView
    let scrollView = UIScrollView()
    scrollView.delegate = context.coordinator  // for viewForZooming(in:)
    scrollView.maximumZoomScale = 20
    scrollView.minimumZoomScale = 1
    scrollView.bouncesZoom = true

    // create a UIHostingController to hold our SwiftUI content
    let hostedView = context.coordinator.hostingController.view!
    hostedView.translatesAutoresizingMaskIntoConstraints = true
    hostedView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    hostedView.frame = scrollView.bounds
    scrollView.addSubview(hostedView)

    return scrollView
  }

  func makeCoordinator() -> Coordinator {
    return Coordinator(hostingController: UIHostingController(rootView: self.content))
  }

  func updateUIView(_ uiView: UIScrollView, context: Context) {
    // update the hosting controller's SwiftUI content
    context.coordinator.hostingController.rootView = self.content
    assert(context.coordinator.hostingController.view.superview == uiView)
  }

  // MARK: - Coordinator

  class Coordinator: NSObject, UIScrollViewDelegate {
    var hostingController: UIHostingController<Content>

    init(hostingController: UIHostingController<Content>) {
      self.hostingController = hostingController
    }

    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
      return hostingController.view
    }
  }
}
票数 63
EN

Stack Overflow用户

发布于 2020-01-23 12:44:34

这里有一种向SwiftUI视图添加夹点缩放的方法。它将UIViewUIPinchGestureRecognizer覆盖在UIViewRepresentable中,并通过绑定将相关的值转发回SwiftUI。

您可以添加这样的行为:

代码语言:javascript
运行
复制
Image("Zoom")
    .pinchToZoom()

这增加了类似于在Instagram上放大图片的行为。下面是完整的代码:

代码语言:javascript
运行
复制
import UIKit
import SwiftUI

class PinchZoomView: UIView {

    weak var delegate: PinchZoomViewDelgate?

    private(set) var scale: CGFloat = 0 {
        didSet {
            delegate?.pinchZoomView(self, didChangeScale: scale)
        }
    }

    private(set) var anchor: UnitPoint = .center {
        didSet {
            delegate?.pinchZoomView(self, didChangeAnchor: anchor)
        }
    }

    private(set) var offset: CGSize = .zero {
        didSet {
            delegate?.pinchZoomView(self, didChangeOffset: offset)
        }
    }

    private(set) var isPinching: Bool = false {
        didSet {
            delegate?.pinchZoomView(self, didChangePinching: isPinching)
        }
    }

    private var startLocation: CGPoint = .zero
    private var location: CGPoint = .zero
    private var numberOfTouches: Int = 0

    init() {
        super.init(frame: .zero)

        let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(pinch(gesture:)))
        pinchGesture.cancelsTouchesInView = false
        addGestureRecognizer(pinchGesture)
    }

    required init?(coder: NSCoder) {
        fatalError()
    }

    @objc private func pinch(gesture: UIPinchGestureRecognizer) {

        switch gesture.state {
        case .began:
            isPinching = true
            startLocation = gesture.location(in: self)
            anchor = UnitPoint(x: startLocation.x / bounds.width, y: startLocation.y / bounds.height)
            numberOfTouches = gesture.numberOfTouches

        case .changed:
            if gesture.numberOfTouches != numberOfTouches {
                // If the number of fingers being used changes, the start location needs to be adjusted to avoid jumping.
                let newLocation = gesture.location(in: self)
                let jumpDifference = CGSize(width: newLocation.x - location.x, height: newLocation.y - location.y)
                startLocation = CGPoint(x: startLocation.x + jumpDifference.width, y: startLocation.y + jumpDifference.height)

                numberOfTouches = gesture.numberOfTouches
            }

            scale = gesture.scale

            location = gesture.location(in: self)
            offset = CGSize(width: location.x - startLocation.x, height: location.y - startLocation.y)

        case .ended, .cancelled, .failed:
            isPinching = false
            scale = 1.0
            anchor = .center
            offset = .zero
        default:
            break
        }
    }

}

protocol PinchZoomViewDelgate: AnyObject {
    func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangePinching isPinching: Bool)
    func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeScale scale: CGFloat)
    func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeAnchor anchor: UnitPoint)
    func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeOffset offset: CGSize)
}

struct PinchZoom: UIViewRepresentable {

    @Binding var scale: CGFloat
    @Binding var anchor: UnitPoint
    @Binding var offset: CGSize
    @Binding var isPinching: Bool

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func makeUIView(context: Context) -> PinchZoomView {
        let pinchZoomView = PinchZoomView()
        pinchZoomView.delegate = context.coordinator
        return pinchZoomView
    }

    func updateUIView(_ pageControl: PinchZoomView, context: Context) { }

    class Coordinator: NSObject, PinchZoomViewDelgate {
        var pinchZoom: PinchZoom

        init(_ pinchZoom: PinchZoom) {
            self.pinchZoom = pinchZoom
        }

        func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangePinching isPinching: Bool) {
            pinchZoom.isPinching = isPinching
        }

        func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeScale scale: CGFloat) {
            pinchZoom.scale = scale
        }

        func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeAnchor anchor: UnitPoint) {
            pinchZoom.anchor = anchor
        }

        func pinchZoomView(_ pinchZoomView: PinchZoomView, didChangeOffset offset: CGSize) {
            pinchZoom.offset = offset
        }
    }
}

struct PinchToZoom: ViewModifier {
    @State var scale: CGFloat = 1.0
    @State var anchor: UnitPoint = .center
    @State var offset: CGSize = .zero
    @State var isPinching: Bool = false

    func body(content: Content) -> some View {
        content
            .scaleEffect(scale, anchor: anchor)
            .offset(offset)
            .animation(isPinching ? .none : .spring())
            .overlay(PinchZoom(scale: $scale, anchor: $anchor, offset: $offset, isPinching: $isPinching))
    }
}

extension View {
    func pinchToZoom() -> some View {
        self.modifier(PinchToZoom())
    }
}
票数 34
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58341820

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档