UIScrollView zooming with Auto Layout

后端 未结 3 2134
渐次进展
渐次进展 2020-12-08 14:12

I\'m trying to implement a UIScrollView the New Way, using Auto Layout. I\'ve set up constraints from the inner view to the scroll view so that it can compute i

3条回答
  •  甜味超标
    2020-12-08 14:30

    Complete Swift Playground Example

    The simplest example I can think of is adding a UIImageView to a UIScrollView. This is 100% in code, you'll just need to add a PNG to the Playground. I called mine Image.png. In a Playground you'll see the whole thing rendered in the 'Live View'. Pinch-zoom works using a Ctrl-click to place one finger on the screen and then dragging around. Until the content is zoomed in bigger than the screen panning will not work. Double-tap the image to toggle between 1x and 3x scale.

    Based upon the Apple's Technical Note TN2154: UIScrollView and Autolayout

    Gotcha

    You'll find the whole thing very frustrating if your content is not bigger than the screen size. If your content completely fits on screen nothing will happen. That's why you must get zooming to work too. If you want to prove to yourself it works, test with a really big image (bigger than the window).

    import UIKit
    import PlaygroundSupport
    
    enum TapToggle {
        case Regular, Large
    }
    
    class ScrollingViewController : UIViewController
    {
        var tapToggle: TapToggle = .Large
        var scrollView: UIScrollView?
        var imageView: UIImageView?
    
        override func viewDidLoad()
        {
            let image = UIImage(named: "Image")
            let imageView = UIImageView(image: image)
            imageView.translatesAutoresizingMaskIntoConstraints = false
            imageView.backgroundColor = .white
            imageView.isUserInteractionEnabled = true
    
            let scrollView = UIScrollView()
            scrollView.minimumZoomScale = 0.5
            scrollView.maximumZoomScale = 10.0
            scrollView.delegate = self
            scrollView.translatesAutoresizingMaskIntoConstraints = false
            scrollView.addSubview(imageView)
            let imageViewKey = "imageView"
            let imageViews = [imageViewKey: imageView]
            scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
            scrollView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(imageViewKey)]|", options: [], metrics: nil, views: imageViews))
            self.imageView = imageView
    
            scrollView.backgroundColor = .white
            self.view.addSubview(scrollView)
    
            let scrollViewKey = "scrollView"
            let scrollViews = [scrollViewKey: scrollView]
            self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
            self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[\(scrollViewKey)]|", options: [], metrics: nil, views: scrollViews))
    
            self.scrollView = scrollView
    
            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(didDoubleTap(sender:)))
            tapGesture.numberOfTapsRequired = 2
            self.imageView?.addGestureRecognizer(tapGesture)
        }
    
        @objc
        public func didDoubleTap(sender: AnyObject)
        {
            switch self.tapToggle {
            case .Regular:
                self.scrollView?.zoomScale = 1.0
                self.tapToggle = .Large
            case .Large:
                self.scrollView?.zoomScale = 3.0
                self.tapToggle = .Regular
            }
        }
    }
    
    extension ScrollingViewController: UIScrollViewDelegate
    {
        func viewForZooming(in scrollView: UIScrollView) -> UIView? {
            return self.imageView
        }
    
        func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat)
        {
            print("\(scale)")
        }
    }
    
    PlaygroundPage.current.needsIndefiniteExecution = true
    PlaygroundPage.current.liveView = ScrollingViewController()
    

提交回复
热议问题