gpt4 book ai didi

ios - 激活 iOS 13 上下文菜单时,如何防止 UIScrollView 放大一吨?

转载 作者:行者123 更新时间:2023-12-01 16:05:37 25 4
gpt4 key购买 nike

如果您有 UIScrollView您可以放大,然后将 iOS 13 上下文菜单交互添加到 ScrollView 内的 View (例如: UIImageView ),当您执行交互时,它会奇怪地瞬间放大图像,然后将其缩小以显示上下文菜单,然后在退出此上下文菜单时,它会将图像放大得很远。它似乎超出了 UIImageView 的界限。

StackOverflow 似乎不支持嵌入视频/GIF,所以这是 Imgur 上的视频,展示了我的意思:https://imgur.com/mAzWlJA

有没有办法防止这种行为?在 WKWebView (一个 UIScrollView 子类)例如,长按图像不会表现出这种行为。

如果您想在一个简单的新 Xcode 项目中测试它,下面是显示它的示例的简单代码:

import UIKit

class RootViewController: UIViewController, UIScrollViewDelegate, UIContextMenuInteractionDelegate {
let scrollView = UIScrollView()
let imageView = UIImageView(image: UIImage(named: "cat.jpg")!)

override func viewDidLoad() {
super.viewDidLoad()

[view, scrollView].forEach { $0.backgroundColor = .black }

scrollView.delegate = self
scrollView.frame = view.bounds
scrollView.addSubview(imageView)
scrollView.contentSize = imageView.frame.size
view.addSubview(scrollView)

// Set zoom scale
let scaleToFit = min(scrollView.bounds.width / imageView.bounds.width, scrollView.bounds.height / imageView.bounds.height)
scrollView.maximumZoomScale = max(1.0, scaleToFit)
scrollView.minimumZoomScale = scaleToFit < 1.0 ? scaleToFit : 1.0
scrollView.zoomScale = scaleToFit

// Add context menu support
imageView.isUserInteractionEnabled = true
imageView.addInteraction(UIContextMenuInteraction(delegate: self))
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()

scrollView.frame = view.bounds
}

// MARK: - UIScrollView

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}

// MARK: - Context Menus

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
return UIContextMenuConfiguration(identifier: nil, previewProvider: { () -> UIViewController? in
return nil
}) { (suggestedElements) -> UIMenu? in
var children: [UIAction] = []

children.append(UIAction(title: "Upvote", image: UIImage(systemName: "arrow.up")) { (action) in
})

children.append(UIAction(title: "Downvote", image: UIImage(systemName: "arrow.down")) { (action) in
})

return UIMenu(title: "", image: nil, identifier: nil, options: [], children: children)
}
}
}

这是 cat.jpg如果你也喜欢它: https://imgur.com/hTTZaw4

最佳答案

以为我解决了。解决方案的要点是不要像直觉上认为的那样将交互添加到 ImageView 本身,而是将其添加到外部 View ,然后使用 UITargetPreview 将上下文菜单预览聚焦到 ImageView 的矩形上。蜜蜂。通过这种方式,你们一起避免接触出错的 ImageView ,而是转到它的父 View ,只是“裁剪”到 subview ,这使 subview 保持愉快。 :)

这是我最终得到的代码:

import UIKit

class RootViewController: UIViewController, UIScrollViewDelegate, UIContextMenuInteractionDelegate {
let wrapperView = UIView()
let scrollView = UIScrollView()
let imageView = UIImageView(image: UIImage(named: "cat.jpg")!)

override func viewDidLoad() {
super.viewDidLoad()

wrapperView.frame = view.bounds
view.addSubview(wrapperView)

[view, wrapperView, scrollView].forEach { $0.backgroundColor = .black }

scrollView.delegate = self
scrollView.frame = view.bounds
scrollView.addSubview(imageView)
scrollView.contentSize = imageView.frame.size
wrapperView.addSubview(scrollView)

// Set zoom scale
let scaleToFit = min(scrollView.bounds.width / imageView.bounds.width, scrollView.bounds.height / imageView.bounds.height)
scrollView.maximumZoomScale = max(1.0, scaleToFit)
scrollView.minimumZoomScale = scaleToFit < 1.0 ? scaleToFit : 1.0
scrollView.zoomScale = scaleToFit

// Add context menu support
wrapperView.addInteraction(UIContextMenuInteraction(delegate: self))
}

// MARK: - UIScrollView

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}

// MARK: - Context Menus

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
scrollView.zoomScale = scrollView.minimumZoomScale

return UIContextMenuConfiguration(identifier: nil, previewProvider: { () -> UIViewController? in
return nil
}) { (suggestedElements) -> UIMenu? in
var children: [UIAction] = []

children.append(UIAction(title: "Upvote", image: UIImage(systemName: "arrow.up")) { (action) in
})

children.append(UIAction(title: "Downvote", image: UIImage(systemName: "arrow.down")) { (action) in
})

return UIMenu(title: "", image: nil, identifier: nil, options: [], children: children)
}
}

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForHighlightingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()

let rect = imageView.convert(imageView.bounds, to: wrapperView)
parameters.visiblePath = UIBezierPath(roundedRect: rect, cornerRadius: 13.0)

return UITargetedPreview(view: wrapperView, parameters: parameters)
}

func contextMenuInteraction(_ interaction: UIContextMenuInteraction, previewForDismissingMenuWithConfiguration configuration: UIContextMenuConfiguration) -> UITargetedPreview? {
let parameters = UIPreviewParameters()

let rect = imageView.convert(imageView.bounds, to: wrapperView)
parameters.visiblePath = UIBezierPath(roundedRect: rect, cornerRadius: 0.0)

return UITargetedPreview(view: wrapperView, parameters: parameters)
}
}

一些注意事项:
  • 不幸的是,当 View 放大时,这不能很好地工作(我没有做任何更改)。无论出于何种原因,iOS 仍然试图弄乱 ScrollView ,这次将其缩小,但不会渲染它周围的区域,导致在不完整的 ImageView 周围有大的白色区域。叹。在这一点上我已经完成了这个,你可能会尝试用一些 UIScrollView 在内部对抗它。试图谴责 iOS 级别更改的子类,但是是的,我在这方面花费了我想要的时间,所以我只是将 scrollView 的 zoomScale 重置为在它要求上下文菜单时完全缩小(请注意,您必须在此处执行此操作,在 willPresent 上下文菜单 API 中为时已晚)。它并没有那么糟糕并且完全解决了它,只是有点烦人地重置了用户的缩放级别。但是,如果我收到一封支持电子邮件,我会将它们链接到这篇文章。
  • 角半径 13.0 与 iOS 默认值匹配。唯一要注意的是,这不会像 iOS 那样将圆角半径从 0 动画化到圆角半径,它有点跳跃,但几乎不明显。我确信有一种方法可以解决这个问题,上下文菜单 API 的标题在某种程度上提到了动画,但文档确实缺乏,我不想花大量时间试图弄清楚如何。
  • 在这个例子中,我使用 wrapperView在 View Controller View 中。这可能特定于我的用例,在您的用例中可能不需要。基本上你可以把它附加到 scrollView本身,但我的有一些自定义插入,以使其始终在安全区域插入方面保持在有缺口的 iPhone 内居中,如果我使用 ScrollView 进行交互/目标预览,它会稍微跳动一下,这看起来不太好。您也不想直接使用 View Controller 的 View 作为交互,因为它在执行动画时将其屏蔽,因此媒体查看器/ ScrollView 的黑色背景完全消失,这看起来不太好。因此,顶层的包装 View 可以很好地防止这两种情况。
  • 关于ios - 激活 iOS 13 上下文菜单时,如何防止 UIScrollView 放大一吨?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61597274/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com