带有 ImageView 的 UIScrollView 不垂直滚动

Posted

技术标签:

【中文标题】带有 ImageView 的 UIScrollView 不垂直滚动【英文标题】:UIScrollView with an ImageView not scrolling vertically 【发布时间】:2015-04-24 11:42:06 【问题描述】:

我有一个UIImageView,它的图像大于屏幕尺寸。我有这个UIImageView 作为UIScrollView 的子视图。现在,我无法向下滚动。查看整个图像。但是缩放功能运行良好。

@IBOutlet weak var scrollView: UIScrollView!

var imageView = UIImageView();

override func viewDidLoad() 
    super.viewDidLoad()


func centerScrollViewContents()
    let boundsSize = scrollView.bounds.size
    var contentsFrame = imageView.frame

    if contentsFrame.size.width < boundsSize.width 
       contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width) / 2
    
    else  
       contentsFrame.origin.x = 0
    

    if contentsFrame.size.height < boundsSize.height             
        contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height) / 2
    
    else 
        contentsFrame.origin.y = 0
    

    imageView.frame = contentsFrame
   // scrollView.frame = contentsFrame        


func scrollViewDidZoom(scrollView: UIScrollView) 
    centerScrollViewContents()


func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? 
    return imageView


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()

    // Dispose of any resources that can be recreated.


override func viewDidAppear(animated: Bool) 

    scrollView.delegate = self
    imageView.frame = CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height)

   // imageView.contentMode = UIViewContentMode.ScaleAspectFill
   // imageView.clipsToBounds = true
    imageView.image = UIImage(named: imgstr)

    var imagee = UIImage(named: imgstr)
    let size = imagee?.size
   // imageView.frame = CGRectMake(0, 0, size.width!, size.height!)
    imageView.contentMode = .Top
    scrollView.addSubview(imageView)

    scrollView.contentSize = size!
    let scrollViewFrame = scrollView.frame
    let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
    let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
    let minScale = min(scaleHeight, scaleWidth)

    scrollView.minimumZoomScale = 1
    scrollView.maximumZoomScale = 5
    scrollView.zoomScale = minScale

    centerScrollViewContents()   

【问题讨论】:

所有答案都是错误的,您使用的是AutoLayout,因此您可以使用frame 属性进行更改,您应该为您的ImageView top constraint 创建一个IBOutlet 并更改它,加上看到这个@987654321 @ 您可以使用 ImageScrollView 开源,一个可缩放和可滚动的图像视图。 github.com/huynguyencong/ImageScrollView 【参考方案1】:

您必须解决 UIScrollView 工作的两个主要问题

    一个问题在于您初始化UIScrollView 的所有数据,我的意思是函数viewDidAppear。 您必须为您设置约束UIScrollView,如TopBottomLeftRight 为0,尊重您的SuperView

如果您将代码放入您的 viewDidAppear 内的函数 viewDidLoad 并删除您的函数 viewDidAppear,它可以正常工作。像下面这样:

override func viewDidLoad() 
    super.viewDidLoad()


    scrollView.delegate = self
    imageView.frame = CGRectMake(0, 0, scrollView.frame.size.width, scrollView.frame.size.height)

    // imageView.contentMode = UIViewContentMode.ScaleAspectFill
    // imageView.clipsToBounds = true
    imageView.image = UIImage(named: "imgstr.jpg")

    var imagee = UIImage(named: "imgstr.jpg")
    let size = imagee?.size
    // imageView.frame = CGRectMake(0, 0, size.width!, size.height!)
    imageView.contentMode = .Top
    scrollView.addSubview(imageView)

    scrollView.contentSize = size!
    let scrollViewFrame = scrollView.frame
    let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
    let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
    let minScale = min(scaleHeight, scaleWidth)

    scrollView.minimumZoomScale = 1
    scrollView.maximumZoomScale = 5
    scrollView.zoomScale = minScale

    centerScrollViewContents()

您还必须在 Storyboard 中为 UIScrollView 设置约束

我认为问题在于以下区别:

viewDidAppear 在视图实际可见时调用,并且可以在视图控制器的生命周期内多次调用(例如,当模态视图控制器被关闭并且视图再次可见时)。这是您想要在 UI 中执行任何布局操作或进行任何绘图的地方 - 例如,呈现模态视图控制器。但是,您在这里所做的任何事情都应该是可重复的。最好不要在这里保留东西,否则你会得到记忆 如果视图消失时不释放它们,就会泄漏。 viewDidLoad 只被调用一次,当视图控制器第一次加载到内存中时。这是您要实例化任何实例变量并构建在此视图控制器的整个生命周期中存在的任何视图的地方。但是,此时视图通常还不可见。

如果您有任何问题,如果您想查看,我已经准备好提交到 Github 的项目。

更新: 再次测试您的代码后,我将您的错误恢复为更少的代码。你的代码工作正常,如果你把你的行 imageView.frame = CGRectMake(0, 0, size!.width, size!.height) 你的代码工作正常,没有约束。

类似这样的:

override func viewDidAppear(animated: Bool) 


    scrollView.delegate = self        

    // imageView.contentMode = UIViewContentMode.ScaleAspectFill
    // imageView.clipsToBounds = true
    imageView.image = UIImage(named: "imgstr.jpg")

    var imagee = UIImage(named: "imgstr.jpg")
    let size = imagee?.size

    // This line should be here!!!
    imageView.frame = CGRectMake(0, 0, size!.width, size!.height)
    imageView.contentMode = .Top
    scrollView.addSubview(imageView)

    scrollView.contentSize = size!
    let scrollViewFrame = scrollView.frame
    let scaleWidth = scrollViewFrame.size.width / scrollView.contentSize.width
    let scaleHeight = scrollViewFrame.size.height / scrollView.contentSize.height
    let minScale = min(scaleHeight, scaleWidth)

    scrollView.minimumZoomScale = 1
    scrollView.maximumZoomScale = 5
    scrollView.zoomScale = minScale

    centerScrollViewContents()       


关键是在您之前的代码中,您将图像的frame 设置为scrollViewframe,而不是大于scrollView 的图像大小。

希望对你有所帮助。

【讨论】:

在这种情况下将其固定到超级视图是什么意思?屏幕不是超级视图吗?我已经更新了我的问题以显示我是如何固定它的? @AdamYoung 正是我的意思,只是取消标记“限制到边距”并将其余的左侧、右侧、底部和顶部设置为 0。 如果您想在 Github 中查看我的测试项目,请告诉我 @AdamYoung 查看更新的答案,我现在要上传项目 @AdamYoung 这是 Github 中项目测试的链接github.com/Vkt0r/ScrollViewTest【参考方案2】:

确保您已启用滚动视图的用户交互:scrollview.userInteractionEnabled=YES

【讨论】:

我正在尝试,但缩放效果很好。所以这意味着它已经启用了。 @AdamYoung 您仍然可以通过添加该行来确保。我希望它肯定会起作用 还要确保你的 UIScrollView 的大小小于 contentsize (ImageSize),然后只有它会滚动。 您对使用自动布局方法感兴趣吗?您不必为 autolayout 编写代码。您只能使用 Interface builder 处理它 代码 sn-p 会有很大帮助【参考方案3】:UIScrollView 放入滚动视图中,然后将图像视图放入容器视图中。

现在像这样将自动布局约束应用于 uiscrollview

现在将自动布局约束应用到 containerView

现在将自动布局约束应用于 imageView

在此之后,您的自动布局结构必须是这样的

之后在 ViewController.m 中编写以下代码

- (void)viewWillAppear:(BOOL)animated

   [super viewWillAppear:animated];
   [self.doubleTapGesture setNumberOfTapsRequired:2];


- (IBAction)handleDoubleTapGesture:(UITapGestureRecognizer *)sender 
    
   float newScale = self.scrollView.zoomScale *3;
 if (self.scrollView.zoomScale > self.scrollView.minimumZoomScale) 
  
    [self.scrollView 
        setZoomScale:self.scrollView.minimumZoomScale animated:YES];
   
   else             
    CGRect zoomRect = 
     [self zoomRectForScale:newScale
                   withCenter:
    [self.doubleTapGesture 
   locationInView:self.doubleTapGesture.view]];
       [self.scrollView zoomToRect:zoomRect animated:YES];
    
  

 - (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center 
     
    CGRect zoomRect;

    zoomRect.size.height = 
       self.contentViewHeightConstraint.constant / scale;
    zoomRect.size.width  = 
        self.contentViewWidthConstraint.constant  / scale;

    center = [self.contentView 
        convertPoint:center fromView:self.view];

    zoomRect.origin.x = center.x - ((zoomRect.size.width / 2.0));
    zoomRect.origin.y = center.y - ((zoomRect.size.height / 2.0));

     return zoomRect;
 

#pragma mark - UIScrollViewDelegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView

    return self.contentView;


- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView 
            withView:(UIView *)view

    self.ContentViewVerticalSpaceConstraint.constant = 0;
    [self.contentView layoutIfNeeded];

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView 
                    withView:(UIView *)view atScale:(CGFloat)scale

    if (scale <= 1)                    self.ContentViewVerticalSpaceConstraint.constant = 174;
        [self.contentView layoutIfNeeded];
    

现在检查它是否可以通过双击和捏合手势正常工作。

【讨论】:

非常感谢!我唯一需要删除的是 ContentViewVerticalSpaceConstraint 其他一切正常。【参考方案4】:

试试这个:

imageView.frame = CGRectMake(0, 0, imageSize.height, imageSize.height)

或者

scrollView.contentSize = CGSizeMake(imageSize.width * 2, imageSize.height * 2)

一般情况下,我会在ViewDidLoad中添加子视图。

【讨论】:

【参考方案5】:

确保您的 UIScrollView 的高度不超过视图本身的高度。

示例代码

@IBOutlet weak var scroller: UIScrollView!

override func viewDidLoad() 
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    scroller.contentSize = CGSizeMake(400, 2300)
    scroller.showsHorizontalScrollIndicator = true
    scroller.scrollEnabled = true

参考:http://blog.revivalx.com/2015/02/23/how-to-use-scroll-view-in-xcode-6-ios-8xcode6/

【讨论】:

【参考方案6】:

启用 UIImageView 用户交互。

imageView.userInteractionEnabled=true;

【讨论】:

【参考方案7】:

为了垂直滚动您必须在scrollView的内容大小中将x轴设置为0。 并在您的 viewDidLoad 方法中设置它。

【讨论】:

【参考方案8】:

您需要取消注释此行:

//imageView.frame = CGRectMake(0, 0, size.width!, size.height!)

当然,它会给你一个编译器错误。由于可选值是size,所以正确的做法是:

imageView.frame = CGRectMake(0, 0, size!.width, size!.height)

【讨论】:

【参考方案9】:

由于自动布局,它不会使用拖动手势滚动。 在viewDidLoad 中,自动布局将在您定义后重置内容大小。您有两个选择:您可以禁用自动布局,或者您可以在 viewDidLayoutSubviews 中设置 contentSize。

override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    scrollView.contentSize = CGSize(width:10, height:10)

【讨论】:

以上是关于带有 ImageView 的 UIScrollView 不垂直滚动的主要内容,如果未能解决你的问题,请参考以下文章

android 自定义控件(带有删除按钮的imageview) 怎么在ImageView背景上添加button按钮 动态添加imageview 自带删除图标的imageview list删除某

带有约束的标签添加到具有纵横比的 ImageView

IOS:在带有动画的 ImageView 下禁用滚动视图

包含带有很多按钮的 ImageView 的 ScrollView

带有自动布局的滚动视图内的iOS 8 imageView不起作用

来自 URL 和 TextView 的带有 ImageView 的 ListView 不起作用