IOS:在滚动视图中添加图像视图以进行缩放
Posted
技术标签:
【中文标题】IOS:在滚动视图中添加图像视图以进行缩放【英文标题】:IOS: add imageview in a scrollview to have zoom 【发布时间】:2012-07-03 20:40:21 【问题描述】:我想设置一个带有UIImage
的UIImageView 并将这个imageview 放在UIScrollView
中以获得这个图像的缩放;
我希望这个UIImageView
和UIScrollView
适合视图中心的矩形...有可能吗?
【问题讨论】:
所以您希望图像通过捏合进行缩放,但滚动视图中的其他所有内容都保持不变? 是的,这绝对是可能的。你有没有尝试过任何东西?您所描述的大部分内容都可以在界面构建器/故事板中完成 【参考方案1】:-
将您的视图控制器设置为
<UIScrollViewDelegate>
将UIScrollView
绘制成视图中心矩形所需的大小。将检查器中的最大缩放设置为大于 1 的值。例如 4 或 10。
右键单击滚动视图并将代理连接到您的视图控制器。
在UIScrollView
中画出您的UIImageView
,并使用您想要的任何图像进行设置。使其大小与UIScrollView
相同。
Ctrl + 将 UIImageView
拖到 View 控制器的 .h
上,为 UIImageView
创建一个 IBOutlet
,称之为 imageView
之类的聪明的东西。
添加此代码:
-(UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView return self.imageView;
运行应用程序并捏合和平移,直到心满意足为止。
【讨论】:
你能以编程方式举一个例子吗? 迄今为止我找到的最简单、最清晰的解决方案 @Justin Paulson 我们可以将缩小限制为图像大小吗?我不希望用户缩小图像大小。你能帮帮我吗?【参考方案2】:下载this 和this 文件。你需要它们来处理触摸。
将 scrollView 委托 <UIScrollViewDelegate>
添加到您的视图并声明网点:
@property (nonatomic, retain) IBOutlet UIScrollView *imageScrollView;
@property (nonatomic, retain) UIImageView *imageView;
将下载的文件导入屏幕并执行:
#import "TapDetectingImageView.h"
#define ZOOM_STEP 2.0
@interface myView (UtilityMethods)
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center;
@end
@implementation myView
@synthesize imageScrollView, imageView;
- (void)viewDidLoad
[super viewDidLoad];
//Setting up the scrollView
imageScrollView.bouncesZoom = YES;
imageScrollView.delegate = self;
imageScrollView.clipsToBounds = YES;
//Setting up the imageView
imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"myImage.png"]];
imageView.userInteractionEnabled = YES;
imageView.autoresizingMask = ( UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin);
//Adding the imageView to the scrollView as subView
[imageScrollView addSubview:imageView];
imageScrollView.contentSize = CGSizeMake(imageView.bounds.size.width, imageView.bounds.size.height);
imageScrollView.decelerationRate = UIScrollViewDecelerationRateFast;
//UITapGestureRecognizer set up
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
UITapGestureRecognizer *doubleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleDoubleTap:)];
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTap:)];
[doubleTap setNumberOfTapsRequired:2];
[twoFingerTap setNumberOfTouchesRequired:2];
//Adding gesture recognizer
[imageView addGestureRecognizer:doubleTap];
[imageView addGestureRecognizer:twoFingerTap];
[singleTap release];
[doubleTap release];
[twoFingerTap release];
// calculate minimum scale to perfectly fit image width, and begin at that scale
float minimumScale = 1.0;//This is the minimum scale, set it to whatever you want. 1.0 = default
imageScrollView.maximumZoomScale = 4.0;
imageScrollView.minimumZoomScale = minimumScale;
imageScrollView.zoomScale = minimumScale;
[imageScrollView setContentMode:UIViewContentModeScaleAspectFit];
[imageView sizeToFit];
[imageScrollView setContentSize:CGSizeMake(imageView.frame.size.width, imageView.frame.size.height)];
- (void)scrollViewDidZoom:(UIScrollView *)aScrollView
CGFloat offsetX = (imageScrollView.bounds.size.width > imageScrollView.contentSize.width)?
(imageScrollView.bounds.size.width - imageScrollView.contentSize.width) * 0.5 : 0.0;
CGFloat offsetY = (imageScrollView.bounds.size.height > imageScrollView.contentSize.height)?
(imageScrollView.bounds.size.height - imageScrollView.contentSize.height) * 0.5 : 0.0;
imageView.center = CGPointMake(imageScrollView.contentSize.width * 0.5 + offsetX,
imageScrollView.contentSize.height * 0.5 + offsetY);
- (void)viewDidUnload
self.imageScrollView = nil;
self.imageView = nil;
#pragma mark UIScrollViewDelegate methods
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
return imageView;
#pragma mark TapDetectingImageViewDelegate methods
- (void)handleDoubleTap:(UIGestureRecognizer *)gestureRecognizer
// zoom in
float newScale = [imageScrollView zoomScale] * ZOOM_STEP;
if (newScale > self.imageScrollView.maximumZoomScale)
newScale = self.imageScrollView.minimumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
else
newScale = self.imageScrollView.maximumZoomScale;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
- (void)handleTwoFingerTap:(UIGestureRecognizer *)gestureRecognizer
// two-finger tap zooms out
float newScale = [imageScrollView zoomScale] / ZOOM_STEP;
CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gestureRecognizer locationInView:gestureRecognizer.view]];
[imageScrollView zoomToRect:zoomRect animated:YES];
#pragma mark Utility methods
- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center
CGRect zoomRect;
// the zoom rect is in the content view's coordinates.
// At a zoom scale of 1.0, it would be the size of the imageScrollView's bounds.
// As the zoom scale decreases, so more content is visible, the size of the rect grows.
zoomRect.size.height = [imageScrollView frame].size.height / scale;
zoomRect.size.width = [imageScrollView frame].size.width / scale;
// choose an origin so as to get the right center.
zoomRect.origin.x = center.x - (zoomRect.size.width / 2.0);
zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
return zoomRect;
完成!
基本上,这段代码的作用是将imageView
添加为imageScrollView
的子视图。
然后,它将TapDetecting
类方法添加到scrollView,以识别点击次数——用户捏合并添加缩放功能。
您可以设置图像的minimumScale
,如果您离开1.0
,图像应按原样显示(如果您将其设置得稍微低一点,则会被缩放),而maximumZoomScale
,我建议你留到4,没关系!
现在,您可以从那里以编程方式加载图像。
您要做的最后一件事是在您的 xib 文件中插入一个UIScrollView
并将其链接到imageScrollView
。您将拥有完美中心的图像,您可以在代码中设置时双击它进行缩放、捏合进行缩放。
【讨论】:
这就像一个烹饪食谱。步骤是正确的,但您没有解释他为什么要这样做。这最终会帮助他和其他人更多。 这基本上是我在我的应用程序中使用的代码。我来解释一下 不要误会我的意思——代码很好,但为什么也很重要。否则他将不知道如何解决类似的问题。 当然,你是对的!我只是认为代码中的 cmets 是不言自明的!不过,谢谢你注意到我。 双击时,缩放图像时,它会像滚动视图一样缩放并超出屏幕。如何解决?【参考方案3】:在 Swift 4 和 ios 11 中,您可以使用以下两种解决方案之一来解决您的问题。
#1。使用插图
ViewController.swift
import UIKit
final class ViewController: UIViewController
private let scrollView = ImageScrollView(image: UIImage(named: "image")!)
override func viewDidLoad()
view.backgroundColor = .black
view.addSubview(scrollView)
scrollView.frame = view.frame
scrollView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
ImageScrollView.swift
import UIKit
final class ImageScrollView: UIScrollView
private let imageView = UIImageView()
override var frame: CGRect
didSet
if frame.size != oldValue.size setZoomScale()
required init(image: UIImage)
super.init(frame: .zero)
imageView.image = image
imageView.sizeToFit()
addSubview(imageView)
contentSize = imageView.bounds.size
contentInsetAdjustmentBehavior = .never // Adjust content according to safe area if necessary
showsVerticalScrollIndicator = false
showsHorizontalScrollIndicator = false
alwaysBounceHorizontal = true
alwaysBounceVertical = true
delegate = self
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
// MARK: - Helper methods
func setZoomScale()
let widthScale = frame.size.width / imageView.bounds.width
let heightScale = frame.size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
minimumZoomScale = minScale
zoomScale = minScale
extension ImageScrollView: UIScrollViewDelegate
func viewForZooming(in scrollView: UIScrollView) -> UIView?
return imageView
func scrollViewDidZoom(_ scrollView: UIScrollView)
let imageViewSize = imageView.frame.size
let scrollViewSize = scrollView.bounds.size
let verticalInset = imageViewSize.height < scrollViewSize.height ? (scrollViewSize.height - imageViewSize.height) / 2 : 0
let horizontalInset = imageViewSize.width < scrollViewSize.width ? (scrollViewSize.width - imageViewSize.width) / 2 : 0
scrollView.contentInset = UIEdgeInsets(top: verticalInset, left: horizontalInset, bottom: verticalInset, right: horizontalInset)
#2。使用自动布局
ViewController.swift
import UIKit
final class ViewController: UIViewController
private let scrollView = ImageScrollView(image: UIImage(named: "image")!)
override func viewDidLoad()
view.backgroundColor = .black
view.addSubview(scrollView)
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
override func viewDidLayoutSubviews()
scrollView.setZoomScale()
ImageScrollView.swift
import UIKit
final class ImageScrollView: UIScrollView
private let imageView = UIImageView()
private var imageViewBottomConstraint = NSLayoutConstraint()
private var imageViewLeadingConstraint = NSLayoutConstraint()
private var imageViewTopConstraint = NSLayoutConstraint()
private var imageViewTrailingConstraint = NSLayoutConstraint()
required init(image: UIImage)
super.init(frame: .zero)
imageView.image = image
imageView.sizeToFit()
addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: leadingAnchor)
imageViewTrailingConstraint = imageView.trailingAnchor.constraint(equalTo: trailingAnchor)
imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: topAnchor)
imageViewBottomConstraint = imageView.bottomAnchor.constraint(equalTo: bottomAnchor)
NSLayoutConstraint.activate([imageViewLeadingConstraint, imageViewTrailingConstraint, imageViewTopConstraint, imageViewBottomConstraint])
contentInsetAdjustmentBehavior = .never // Adjust content according to safe area if necessary
showsVerticalScrollIndicator = false
showsHorizontalScrollIndicator = false
alwaysBounceHorizontal = true
alwaysBounceVertical = true
delegate = self
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
// MARK: - Helper methods
func setZoomScale()
let widthScale = frame.size.width / imageView.bounds.width
let heightScale = frame.size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
minimumZoomScale = minScale
zoomScale = minScale
extension ImageScrollView: UIScrollViewDelegate
func viewForZooming(in scrollView: UIScrollView) -> UIView?
return imageView
func scrollViewDidZoom(_ scrollView: UIScrollView)
let yOffset = max(0, (bounds.size.height - imageView.frame.height) / 2)
imageViewTopConstraint.constant = yOffset
imageViewBottomConstraint.constant = yOffset
let xOffset = max(0, (bounds.size.width - imageView.frame.width) / 2)
imageViewLeadingConstraint.constant = xOffset
imageViewTrailingConstraint.constant = xOffset
layoutIfNeeded()
来源:
Github / ImageScrollView raywenderlich.com / UIScrollView Tutorial: Getting Started【讨论】:
【参考方案4】:我编写了一个示例应用程序,它也支持 AutoLayout 和 Storyboards 来演示这种行为。我希望它可以节省每个人试图弄清楚这一点的时间:http://rexstjohn.com/facebook-like-ios-photo-modal-gallery-swipe-gestures/。
【讨论】:
以上是关于IOS:在滚动视图中添加图像视图以进行缩放的主要内容,如果未能解决你的问题,请参考以下文章