Swiftui 构建显示类似照片的照片应用程序的页面(缩放和平移)
如何构建一个与iOS的照片应用程序完全相同的页面,可以使用放大手势()放大照片,并使用纯SwiftUI在放大后平移 我曾试图在论坛上寻找解决方案,然而,没有一个问题有解决方案。有什么建议吗 这是我的密码:Swiftui 构建显示类似照片的照片应用程序的页面(缩放和平移),swiftui,Swiftui,如何构建一个与iOS的照片应用程序完全相同的页面,可以使用放大手势()放大照片,并使用纯SwiftUI在放大后平移 我曾试图在论坛上寻找解决方案,然而,没有一个问题有解决方案。有什么建议吗 这是我的密码: let magnificationGesture = MagnificationGesture() .onChanged { amount in self.currentAmount = amount - 1
let magnificationGesture = MagnificationGesture()
.onChanged { amount in
self.currentAmount = amount - 1
}
.onEnded { amount in
self.finalAmount += self.currentAmount
self.currentAmount = 0
}
let tapGesture = TapGesture()
.onEnded {
self.currentAmount = 0
self.finalAmount = 1
}
Image("Cat")
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width:UIScreen.main.bounds.width,height: UIScreen.main.bounds.height)
.scaleEffect(finalAmount + currentAmount)
.simultaneousGesture(magnificationGesture)
.simultaneousGesture(tapGesture)
最初,我试图再添加1个同步手势,即dragGesture(),用于调整偏移量,但失败了
当前代码可以很好地缩放图像,但放大后,我希望允许它平移。我尝试添加UIScrollView,但它也失败了
以下是我的想法:
let dragGesture = DragGesture()
.onChanged { value in self.offset = value.translation }
并将.offset()添加到图像中。
但是,它无法工作,模拟器内存不足
有什么建议吗?将DragGesture()
与位置一起使用。
使用iOS 14.2测试了Xcode 12.1(无内存问题。)
我终于用UIViewRepresentable解决了这个问题
struct ImageScrollView: UIViewRepresentable {
private var contentSizeWidth: CGFloat = 0
private var contentSizeHeight: CGFloat = 0
private var imageView = UIImageView()
private var scrollView = UIScrollView()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: UIViewRepresentableContext<ImageScrollView>) -> UIScrollView {
let image = UIImage(named: "Dummy")
let width = image?.size.width
let height = image?.size.height
imageView.image = image
imageView.frame = CGRect(x: 0, y: 0, width: width ?? 0, height: height ?? 0)
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.isUserInteractionEnabled = true
scrollView.delegate = context.coordinator
scrollView.isScrollEnabled = true
scrollView.clipsToBounds = true
scrollView.bouncesZoom = true
scrollView.isUserInteractionEnabled = true
scrollView.minimumZoomScale = 0.5 //scrollView.frame.size.width / (width ?? 1)
scrollView.maximumZoomScale = 2
scrollView.zoomScale = 1
scrollView.contentSize = imageView.frame.size
scrollView.addSubview(imageView)
let doubleTapGestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(sender:)))
doubleTapGestureRecognizer.numberOfTapsRequired = 2;
doubleTapGestureRecognizer.numberOfTouchesRequired=1;
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
imageView.addGestureRecognizer(doubleTapGestureRecognizer)
return scrollView
}
func updateUIView(_ uiView: UIScrollView,
context: UIViewRepresentableContext<ImageScrollView>) {
}
class Coordinator: NSObject, UIScrollViewDelegate {
var control: ImageScrollView
init(_ control: ImageScrollView) {
self.control = control
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("scrollViewDidScroll")
centerImage()
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView,
with view: UIView?,
atScale scale: CGFloat) {
print("scrollViewDidEndZooming")
print(scale, scrollView.minimumZoomScale, scrollView.maximumZoomScale)
scrollView.setZoomScale(scale, animated: true)
centerImage()
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.control.imageView
}
func centerImage() {
let boundSize = self.control.scrollView.frame.size
var frameToCenter = self.control.imageView.frame
frameToCenter.origin.x = 0
frameToCenter.origin.y = 0
if (frameToCenter.size.width<boundSize.width) {
frameToCenter.origin.x = (boundSize.width-frameToCenter.size.width)/2;
}
if (frameToCenter.size.height<boundSize.height) {
frameToCenter.origin.y = (boundSize.height-frameToCenter.size.height)/2;
}
self.control.imageView.frame = frameToCenter
}
@objc func handleTap(sender: UITapGestureRecognizer) {
if (self.control.scrollView.zoomScale==self.control.scrollView.minimumZoomScale) {
self.control.scrollView.zoomScale = self.control.scrollView.maximumZoomScale/2;
} else {
self.control.scrollView.zoomScale = self.control.scrollView.minimumZoomScale;
}
print("tap")
}
}
struct ImageScrollView:UIViewRepresentable{
私有变量contentSizeWidth:CGFloat=0
私有var contentSizeHeight:CGFloat=0
私有变量imageView=UIImageView()
私有变量scrollView=UIScrollView()
func makeCoordinator()->Coordinator{
协调员(自我)
}
func makeUIView(上下文:UIViewRepresentableContext)->UIScrollView{
让image=UIImage(命名为:“Dummy”)
让宽度=图像?.size.width
让高度=图像?.size.height
imageView.image=image
imageView.frame=CGRect(x:0,y:0,宽度:宽度??0,高度:高度??0)
imageView.contentMode=UIView.contentMode.ScaleSpectFit
imageView.isUserInteractionEnabled=true
scrollView.delegate=context.coordinator
scrollView.IsCrollenabled=true
scrollView.clipsToBounds=true
scrollView.bouncesZoom=true
scrollView.isUserInteractionEnabled=true
scrollView.minimumZoomScale=0.5//scrollView.frame.size.width/(宽度??1)
scrollView.maximumZoomScale=2
scrollView.zoomScale=1
scrollView.contentSize=imageView.frame.size
scrollView.addSubview(imageView)
让doubleTapGestureRecognizer=UITapGestureRecognizer(目标:context.coordinator,操作:#选择器(coordinator.handleTap(发送方:))
DoubleTapGestureRecognitor.numberOfTapsRequired=2;
DoubleTapGestureRecognitor.numberOfTouchesRequired=1;
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
imageView.AddGestureRecognitizer(DoubleTapGestureRecognitizer)
返回滚动视图
}
func updateUIView(uiView:UIScrollView,
上下文:UIViewRepresentableContext){
}
类协调器:NSObject、UIScrollViewDelegate{
变量控制:ImageScrollView
init(u控制:ImageScrollView){
自我控制
}
func scrollViewDidScroll(scrollView:UIScrollView){
打印(“scrollViewDidScroll”)
centerImage()
}
func ScrollViewDiEndZooming(uScrollView:UIScrollView,
带视图:UIView?,
atScale比例:CGFloat){
打印(“ScrollViewDiEndZooming”)
打印(缩放、scrollView.minimumZoomScale、scrollView.maximumZoomScale)
scrollView.setZoomScale(比例,动画:真)
centerImage()
}
func VIEWFOR缩放(在scrollView:UIScrollView中)->UIView{
返回self.control.imageView
}
func centerImage(){
让boundSize=self.control.scrollView.frame.size
var frameToCenter=self.control.imageView.frame
frameToCenter.origin.x=0
frameToCenter.origin.y=0
if(frameToCenter.size.width)尝试使用LazyVGrid并调整与放大手势()相关的列数我不是在寻找网格视图,而是快速缩放和平移手势。是否可以不允许用户使用您的方法将图像移出UI屏幕?是,可能需要修改代码。当图像移出屏幕或用户缩放太小时,代码不起作用。图像的中心位置可能会发生变化,并且图像会被删除sappearedI刚刚根据您的问题添加了解决方案。为什么手势不起作用。为了进一步了解并根据您的需求,您必须修改此代码。您必须使用滚动视图并管理所有内容请添加最小规模约束并管理所有场景。我们不在这里完成全部功能
struct ImageScrollView: UIViewRepresentable {
private var contentSizeWidth: CGFloat = 0
private var contentSizeHeight: CGFloat = 0
private var imageView = UIImageView()
private var scrollView = UIScrollView()
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: UIViewRepresentableContext<ImageScrollView>) -> UIScrollView {
let image = UIImage(named: "Dummy")
let width = image?.size.width
let height = image?.size.height
imageView.image = image
imageView.frame = CGRect(x: 0, y: 0, width: width ?? 0, height: height ?? 0)
imageView.contentMode = UIView.ContentMode.scaleAspectFit
imageView.isUserInteractionEnabled = true
scrollView.delegate = context.coordinator
scrollView.isScrollEnabled = true
scrollView.clipsToBounds = true
scrollView.bouncesZoom = true
scrollView.isUserInteractionEnabled = true
scrollView.minimumZoomScale = 0.5 //scrollView.frame.size.width / (width ?? 1)
scrollView.maximumZoomScale = 2
scrollView.zoomScale = 1
scrollView.contentSize = imageView.frame.size
scrollView.addSubview(imageView)
let doubleTapGestureRecognizer = UITapGestureRecognizer(target: context.coordinator, action: #selector(Coordinator.handleTap(sender:)))
doubleTapGestureRecognizer.numberOfTapsRequired = 2;
doubleTapGestureRecognizer.numberOfTouchesRequired=1;
scrollView.addGestureRecognizer(doubleTapGestureRecognizer)
imageView.addGestureRecognizer(doubleTapGestureRecognizer)
return scrollView
}
func updateUIView(_ uiView: UIScrollView,
context: UIViewRepresentableContext<ImageScrollView>) {
}
class Coordinator: NSObject, UIScrollViewDelegate {
var control: ImageScrollView
init(_ control: ImageScrollView) {
self.control = control
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("scrollViewDidScroll")
centerImage()
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView,
with view: UIView?,
atScale scale: CGFloat) {
print("scrollViewDidEndZooming")
print(scale, scrollView.minimumZoomScale, scrollView.maximumZoomScale)
scrollView.setZoomScale(scale, animated: true)
centerImage()
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.control.imageView
}
func centerImage() {
let boundSize = self.control.scrollView.frame.size
var frameToCenter = self.control.imageView.frame
frameToCenter.origin.x = 0
frameToCenter.origin.y = 0
if (frameToCenter.size.width<boundSize.width) {
frameToCenter.origin.x = (boundSize.width-frameToCenter.size.width)/2;
}
if (frameToCenter.size.height<boundSize.height) {
frameToCenter.origin.y = (boundSize.height-frameToCenter.size.height)/2;
}
self.control.imageView.frame = frameToCenter
}
@objc func handleTap(sender: UITapGestureRecognizer) {
if (self.control.scrollView.zoomScale==self.control.scrollView.minimumZoomScale) {
self.control.scrollView.zoomScale = self.control.scrollView.maximumZoomScale/2;
} else {
self.control.scrollView.zoomScale = self.control.scrollView.minimumZoomScale;
}
print("tap")
}
}