我在 UIScrollView
中有一个 UIImageView
。最终目标是在 UIScrollView
范围内旋转、平移和缩放图像。平移和缩放效果很好。旋转最初起作用,但是在旋转完成后,紧接着捏缩放,图像旋转被重置为 0 并且图像被移到 UIScrollView
之外。
任何关于我可能遗漏的建议
@IBOutlet weak var innerScrollView: UIScrollView!
private weak var innerImageView: UIImageView?
var beforeImage: UIImage?
// MARK: -
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
innerScrollView.delegate = self
configureScrollView(innerScrollView, image: beforeImage)
let recognizer = UIRotationGestureRecognizer(target: self, action: "rotateRecognizer:")
if let imageView = innerImageView {
imageView.addGestureRecognizer(recognizer)
}
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
resetScrollView(innerScrollView)
}
// MARK: -
// MARK: Private Helpers
private func resetScrollView(scrollView: UIScrollView) {
let scaleWidth = scrollView.frame.size.width / scrollView.contentSize.width
let scaleHeight = scrollView.frame.size.height / scrollView.contentSize.height
let minScale = min(scaleHeight, scaleWidth)
scrollView.minimumZoomScale = minScale
scrollView.maximumZoomScale = 1.0
scrollView.zoomScale = minScale
centerScrollViewContents()
}
private func configureScrollView(scrollView: UIScrollView, image: UIImage?) {
guard let img = image else {
return
}
let imageView = UIImageView(image: image)
imageView.userInteractionEnabled = true
imageView.frame = CGRect(origin: CGPoint(x: 0, y: 0), size: img.size)
scrollView.addSubview(imageView)
scrollView.contentSize = img.size
innerImageView = imageView
}
private func centerScrollViewContents() {
let boundsSize = innerScrollView.bounds.size
var contentsFrame = innerImageView!.frame
if contentsFrame.size.width < boundsSize.width {
contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2.0
} else {
contentsFrame.origin.x = 0.0
}
if contentsFrame.size.height < boundsSize.height {
contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2.0
} else {
contentsFrame.origin.y = 0.0
}
innerImageView!.frame = contentsFrame
}
func rotateRecognizer(recognizer: UIRotationGestureRecognizer) {
print("The content Offset is \(innerScrollView.contentOffset)")
guard let recView = recognizer.view else {
return
}
recView.transform = CGAffineTransformRotate(recView.transform, recognizer.rotation);
recognizer.rotation = 0;
}
// MARK: -
// MARK: UIGestureRecognizer Delegate Protocol
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
if let imageView = scrollView.subviews.first as? UIImageView {
return imageView
}
return nil
}
最佳答案
我成功了。还有另一个建议的解决方案here ,但我的不一样。
使用 scrollview 缩放和平移很容易,但是当添加旋转时,它会立即重置,就像你说的那样(我也发生过)。我所做的是完全放弃 scrollView 的手势,而不依赖于它的代表。我为平移、缩放和旋转添加了自己的手势识别器。然后,您可以随意组合它们:让它们中的两个同时感知变化,甚至三个都可以。在我的解决方案中,我希望单独感知平移,同时感知缩放和旋转。您在方法中执行此操作:
func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool
请参阅下面我的其余代码。当然,在我的示例中,我有一个 UIView,而不是 ImageView ,但从转换的角度来看,这并不重要。
private struct Constants {
private init() {}
static let minZoom = CGFloat(0.3)
static let maxZoom = CGFloat(6)
}
private var activeView: UIView
private var savedTransform: CGAffineTransform
// Represents rotation performed since the last transform save
private var editedRotation = TransformConstants.defaultRotation
// Represents scaling performed since the last transform save
private var editedScale = TransformConstants.defaultScale
override func didPan(recognizer: UIPanGestureRecognizer) {
let translation = recognizer.translation(in: activeView)
activeView.transform = savedTransform.translatedBy(x: translation.x, y: translation.y)
if shouldSaveGestures(recognizer: recognizer) {
saveChanges(operation: .pan)
return
}
}
override func didPinch(recognizer: UIPinchGestureRecognizer) {
if shouldSaveGestures(recognizer: recognizer) {
saveChanges(operation: .zoom)
return
}
var scale = recognizer.scale
if Constants.minZoom > scale * savedTransform.getScale().x {
scale = Constants.minZoom / savedTransform.getScale().x
} else if scale * savedTransform.getScale().x > Constants.maxZoom {
scale = Constants.maxZoom / savedTransform.getScale().x
}
activeView.transform = savedTransform.scaledBy(x: scale, y: scale).rotated(by: editedRotation)
editedScale = CGPoint(x: scale, y: scale)
}
override func didRotate(recognizer: UIRotationGestureRecognizer) {
if shouldSaveGestures(recognizer: recognizer) {
saveChanges(operation: .rotate)
return
}
activeView.transform = savedTransform.scaledBy(x: editedScale.x, y: editedScale.y).rotated(by: recognizer.rotation)
editedRotation = recognizer.rotation
}
private func shouldSaveGestures(recognizer: UIGestureRecognizer) -> Bool {
return recognizer.state == .ended || recognizer.state == .failed
}
private func saveChanges(operation: OperationType) {
savedTransform = activeView.transform
editedScale = TransformConstants.defaultScale
editedRotation = TransformConstants.defaultRotation
}
关于ios - 在 UIScrollView 中旋转 UIImageView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34258257/