UIScrollView带有ImageView无法垂直滚动

8

我有一个包含比屏幕尺寸更大的图像的 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()   
}

enter image description here


所有的答案都是错误的,因为你正在使用AutoLayout,所以你可以使用frame属性进行更改,你应该为你的ImageView top constraint创建一个IBOutlet并更改它,另外请参考https://www.google.co.in/search?q=autolayout+and+scrollview&oq=autolayout+and+scrollview&aqs=chrome..69i57j0l5.4077j0j1&sourceid=chrome&es_sm=119&ie=UTF-8 - iphonic
你可以使用开源的ImageScrollView,它是一个可缩放和可滚动的图像视图。github.com/huynguyencong/ImageScrollView - huync
9个回答

4
您需要解决两个主要问题才能使您的UIScrollView正常工作:
  1. 一个问题位于您初始化UIScrollView的所有数据的位置,我指的是viewDidAppear函数。
  2. 您必须为您的UIScrollView设置约束,如TopBottomLeftRight,以便相对于您的SuperView为0。
如果您将代码放在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,而不是图片大小超过scrollViewframe
希望这能帮到你。

@AdamYoung 就是这样,只需取消“限制到边缘”并将其余部分左、右、下和上设置为0,这就是我的意思。 - Victor Sigler
如果您想在Github上查看我的测试项目,请告诉我。 - Victor Sigler
@AdamYoung,请看更新后的答案,我现在会上传这个项目。 - Victor Sigler
嘿,我觉得即使在你的情况下,垂直滚动也不正常。请尝试使用此图像进行测试。https://www.dropbox.com/s/62hjqitimlk4m4p/001.jpg?dl=0 - Adam Young
让我们在聊天中继续这个讨论 - Victor Sigler
显示剩余4条评论

3

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


@AdamYoung 仍需确保添加该行代码。我希望它一定会起作用。 - Sohil R. Memon
你有兴趣使用自动布局吗?你不必为自动布局编写代码。你只需要在Interface Builder中处理它即可。 - Raj
@AdamYoung 你在使用“Storyboard”来设计布局吗? - Sohil R. Memon
是的,我已经将 UIScrollView 固定在顶部、底部、左侧和右侧。覆盖整个屏幕。 - Adam Young
我已经通过编程方式添加了ImageView。 - Adam Young
显示剩余7条评论

2
  • UIScrollView放入一个UIView中(我们称之为container view),然后将imageView放入containerView中。

  • 现在对UIScrollView应用自动布局约束,如下所示:

left, right, top, bottom margins, width and height constraints in scrollview

  • 现在对containerView应用自动布局约束

left, right, top, bottom margins, width and height constraints in containerView

  • 现在对imageView应用自动布局约束

left, right, top, bottom constraints to the imageView

  • 完成上述步骤后,您的自动布局结构应该如下图所示

autolayout structure

  • after this write the following code in the 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];
        }
    }
    
  • now check it it will be working fine with the double tap and pinch gesture.


非常感谢!我需要移除的唯一一件事就是ContentViewVerticalSpaceConstraint,其他的都可以正常工作。 - 3akat

1

试试这个:

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

或者

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

一般来说,我会在 ViewDidLoad 中添加子视图。

1

请确保您的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/

1

启用UIImageView的用户交互。

imageView.userInteractionEnabled=true;

1
您需要取消注释这行代码:
//imageView.frame = CGRectMake(0, 0, size.width!, size.height!)

当然,这会导致编译错误。由于可选值是大小,正确的方法是:
imageView.frame = CGRectMake(0, 0, size!.width, size!.height)

1
为了实现垂直滚动,您需要将scrollView的内容大小中的x轴设置为0,并在viewDidLoad方法中进行设置。

0

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

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接