10.5 C
London
Monday, November 20, 2023

ios – Two scrollviews aspect by aspect, one doesn’t present the content material


I’ve two scrollviews aspect by aspect. Each are set identical however the left one does’nt present the content material in it. Once I use simply one after the other it really works tremendous. However once I use each on the identical time, it doesn’t work. You may run it, simply give ComplexVC to a view controller. There are two scrollviews in a view controller and two completely different UIView courses which can be every linked to 1 scrollview.

enter image description here

import UIKit

class DrawZoomBaseVC: UIViewController {
    //let container : UIView = UIView()
    let scrollView: UIScrollView = UIScrollView()
    let scrollViewleft: UIScrollView = UIScrollView()
    
    // this might be a plain, clear UIView that we are going to use
    //  because the viewForZooming
    let zoomView = UIView()
    let zoomViewleft = UIView()
    // this might be positioned *behind* the scrollView
    //  in our subclasses, we'll set it to both
    //      Easy or Advanced
    //  and we'll set its zoomScale and contentOffset
    //  to match the scrollView
    var drawView: UIView!
    var drawViewleft: UIView!
    // a label to place on the high to indicate the present zoomScale
    let infoLabel: UILabel = {
        let v = UILabel()
        v.backgroundColor = UIColor(white: 0.95, alpha: 1.0)
        v.textAlignment = .heart
        v.numberOfLines = 0
        v.textual content = "nnn"
        return v
    }()
    
    override func viewDidLoad() {
        tremendous.viewDidLoad()
        
        view.backgroundColor = UIColor.yellow
        
        [infoLabel,drawViewleft, drawView, scrollView,scrollViewleft].forEach { v in
            v!.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(v!)
        }
     
        zoomView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.addSubview(zoomView)
        zoomViewleft.translatesAutoresizingMaskIntoConstraints = false
        scrollViewleft.addSubview(zoomViewleft)
        drawView.backgroundColor = .black
        scrollView.backgroundColor = .clear
        zoomView.backgroundColor = .clear
        scrollViewleft.backgroundColor = .orange

        
        let g = view.safeAreaLayoutGuide
        let cg = scrollView.contentLayoutGuide
        let cgl = scrollViewleft.contentLayoutGuide
        
        NSLayoutConstraint.activate([
            
            // info label at the top
            infoLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
            infoLabel.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            infoLabel.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
            
        
            scrollView.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 20.0),
            scrollView.leadingAnchor.constraint(equalTo: scrollViewleft.trailingAnchor, constant: 0.0),
            scrollView.trailingAnchor.constraint(equalTo:g.trailingAnchor, constant: -20.0),
            scrollView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
            
            scrollViewleft.topAnchor.constraint(equalTo: infoLabel.bottomAnchor, constant: 20.0),
            scrollViewleft.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
            scrollViewleft.trailingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0.0),
            scrollViewleft.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -20.0),
            scrollViewleft.widthAnchor.constraint(equalToConstant: 120.0),
            
            zoomView.topAnchor.constraint(equalTo: cg.topAnchor, constant: 0.0),
            zoomView.leadingAnchor.constraint(equalTo: cg.leadingAnchor, constant: 0.0),
            zoomView.trailingAnchor.constraint(equalTo: cg.trailingAnchor, constant: 0.0),
            zoomView.bottomAnchor.constraint(equalTo: cg.bottomAnchor, constant: 0.0),
            
            drawView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0.0),
            drawView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0.0),
            drawView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: 0.0),
            drawView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0.0),
            
            zoomViewleft.topAnchor.constraint(equalTo: cgl.topAnchor, constant: 0.0),
            zoomViewleft.leadingAnchor.constraint(equalTo: cgl.leadingAnchor, constant: 0.0),
            zoomViewleft.trailingAnchor.constraint(equalTo: cgl.trailingAnchor, constant: 0.0),
            zoomViewleft.bottomAnchor.constraint(equalTo: cgl.bottomAnchor, constant: 0.0),
            
            drawViewleft.topAnchor.constraint(equalTo: scrollViewleft.topAnchor, constant: 0.0),
            drawViewleft.leadingAnchor.constraint(equalTo: scrollViewleft.leadingAnchor, constant: 0.0),
            drawViewleft.trailingAnchor.constraint(equalTo: scrollViewleft.trailingAnchor, constant: 0.0),
            drawViewleft.bottomAnchor.constraint(equalTo: scrollViewleft.bottomAnchor, constant: 0.0),
            
            
            ])
        
        scrollView.maximumZoomScale = 60.0
        scrollView.minimumZoomScale = 0.1
        scrollView.zoomScale = 1.0
        
        scrollViewleft.maximumZoomScale = 60.0
        scrollViewleft.minimumZoomScale = 0.1
        scrollViewleft.zoomScale = 1.0
        
        scrollView.indicatorStyle = .white
        scrollViewleft.indicatorStyle = .white
        
        scrollView.delegate = self
        scrollViewleft.delegate = self
        
        infoLabel.isHidden = false
    }
    
    override func viewDidAppear(_ animated: Bool) {
        tremendous.viewDidAppear(animated)
        
        // if we're utilizing the ComplexDrawScaledView
        //  we *get* its dimension that was decided by
        //  it laying out its parts in its commonInit()
        
        
            if let dv = drawView as? ComplexDrawScaledView {
                zoomView.widthAnchor.constraint(equalToConstant: dv.virtualSize.width).isActive = true
                zoomView.heightAnchor.constraint(equalToConstant: dv.virtualSize.top).isActive = true
        }
        
        
        if let dvl = drawView as? ComplexDrawScaledViewleft {
            zoomViewleft.widthAnchor.constraint(equalToConstant: dvl.virtualSize.width).isActive = true
            zoomViewleft.heightAnchor.constraint(equalToConstant: dvl.virtualSize.top).isActive = true
        }
        
        // let auto-layout dimension the view earlier than we replace the data label
        DispatchQueue.predominant.async {
            self.updateInfoLabel()
        }
    }
    
    func updateInfoLabel() {
        infoLabel.textual content = String(format: "nzoomView dimension: (%0.0f, %0.0f)nzoomScale: %0.3fn", zoomView.body.width, zoomView.body.top, scrollView.zoomScale)
    }
    
}





extension DrawZoomBaseVC: UIScrollViewDelegate {
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if let dvl = drawViewleft as? ComplexDrawScaledViewleft {
            dvl.contentOffset = scrollViewleft.contentOffset
        }
     
            if let dv = drawView as? ComplexDrawScaledView {
                dv.contentOffset = scrollView.contentOffset
        }
    }
    func scrollViewDidZoom(_ scrollView: UIScrollView) {
        updateInfoLabel()
      
        if let dvl = drawViewleft as? ComplexDrawScaledViewleft {
            dvl.zoomScale = scrollViewleft.zoomScale
        }

            if let dv = drawView as? ComplexDrawScaledView {
                dv.zoomScale = scrollView.zoomScale
        }
    }
    func viewForZooming(in scrollView: UIScrollView) -> UIView? {
        if scrollView == self.scrollView {
            return zoomView
        } else if scrollView == self.scrollViewleft {
      
            return zoomViewleft
        }
        return nil
    }

}





class ComplexVC: DrawZoomBaseVC {
    
    override func viewDidLoad() {
        drawView = ComplexDrawScaledView()
        drawViewleft = ComplexDrawScaledViewleft()
        tremendous.viewDidLoad()
    }
    
}





class ComplexDrawScaledView: UIView {
    
    // this might be set by the "rects" structure in commonInit()
    public var virtualSize: CGSize = .zero
    
    public var zoomScale: CGFloat = 1.0 { didSet { setNeedsDisplay() } }
    public var contentOffset: CGPoint = .zero { didSet { setNeedsDisplay() } }
    
    personal let nCols: Int = 10
    personal let nRows: Int = 20
    personal let colWidth: CGFloat = 120.0
    personal let rowHeight: CGFloat = 80.0
    personal let colSpacing: CGFloat = -2.0
    personal let rowSpacing: CGFloat = -2.0
    
    personal let rectInset: CGSize = .init(width: 1.0, top: 1.0)
   
    
    personal var theRectPaths: [UIBezierPath] = []
 
    
    override init(body: CGRect) {
        tremendous.init(body: body)
        commonInit()
    }
    required init?(coder: NSCoder) {
        tremendous.init(coder: coder)
        commonInit()
    }
    personal func commonInit() {
        
        // let's create a "grid" of rects
        // each rect might be used to create a
        //  rect path - alternating between rect and roundedRect
        //  a centered oval path
        //  and a centered textual content level
        
        var r: CGRect = .init(x: 0.0, y: 0.0, width: colWidth, top: rowHeight)
        for _ in 0..<nRows {
            for _ in 0..<nCols {
                let rPath =  UIBezierPath(rect: r.insetBy(dx: rectInset.width, dy: rectInset.top))
                theRectPaths.append(rPath)
                r.origin.x += colWidth + colSpacing
            }
            r.origin.x = 0.0
            r.origin.y += rowHeight + rowSpacing
        }
        
        // our "digital dimension"
        let w: CGFloat = theRectPaths.compactMap( { $0.bounds.maxX }).max()!
        let h: CGFloat = theRectPaths.compactMap( { $0.bounds.maxY }).max()!
        
        let sz: CGSize = .init(width: w, top: h)
        

        
        let v: CGFloat = 100.0
        r = .init(x: 0.0, y: 0.0, width: v, top: v)
        
      
        virtualSize = sz
        
    }
    
    override func draw(_ rect: CGRect) {
        
        let tr = CGAffineTransform(translationX: -contentOffset.x, y: -contentOffset.y)
            .scaledBy(x: zoomScale, y: zoomScale)
        
        drawRects(insideRect: rect, withTransform: tr)
      
        
    }
    
    personal func drawRects(insideRect: CGRect, withTransform tr: CGAffineTransform) {
        UIColor.inexperienced.setStroke()
        theRectPaths.forEach { pth in
            if let path = pth.copy() as? UIBezierPath {
                //  rework a replica of the trail
                path.apply(tr)
                // solely draw if seen
                if path.bounds.intersects(insideRect) {
                    path.lineWidth = 1.0 * zoomScale
                    path.stroke()
                }
            }
        }
    }

    
}





class ComplexDrawScaledViewleft: UIView {
    
    // this might be set by the "rects" structure in commonInit()
    public var virtualSize: CGSize = .zero
    
    public var zoomScale: CGFloat = 1.0 { didSet { setNeedsDisplay() } }
    public var contentOffset: CGPoint = .zero { didSet { setNeedsDisplay() } }
    
    personal let nCols: Int = 10
    personal let nRows: Int = 20
    personal let colWidth: CGFloat = 120.0
    personal let rowHeight: CGFloat = 80.0
    personal let colSpacing: CGFloat = -2.0
    personal let rowSpacing: CGFloat = -2.0
    
    personal let rectInset: CGSize = .init(width: 1.0, top: 1.0)
    
    
    personal var theRectPaths: [UIBezierPath] = []
    
    
    override init(body: CGRect) {
        tremendous.init(body: body)
        commonInit()
    }
    required init?(coder: NSCoder) {
        tremendous.init(coder: coder)
        commonInit()
    }
    personal func commonInit() {
        
        // let's create a "grid" of rects
        // each rect might be used to create a
        //  rect path - alternating between rect and roundedRect
        //  a centered oval path
        //  and a centered textual content level
        
        var r: CGRect = .init(x: 0.0, y: 0.0, width: colWidth, top: rowHeight)
        for _ in 0..<nRows {
            for _ in 0..<nCols {
                let rPath =  UIBezierPath(rect: r.insetBy(dx: rectInset.width, dy: rectInset.top))
                theRectPaths.append(rPath)
                r.origin.x += colWidth + colSpacing
            }
            r.origin.x = 0.0
            r.origin.y += rowHeight + rowSpacing
        }
        
        // our "digital dimension"
        let w: CGFloat = theRectPaths.compactMap( { $0.bounds.maxX }).max()!
        let h: CGFloat = theRectPaths.compactMap( { $0.bounds.maxY }).max()!
        
        let sz: CGSize = .init(width: w, top: h)
        
        
        
        let v: CGFloat = 100.0
        r = .init(x: 0.0, y: 0.0, width: v, top: v)
        
        
        virtualSize = sz
        
    }
    
    override func draw(_ rect: CGRect) {
        
        let tr = CGAffineTransform(translationX: -contentOffset.x, y: -contentOffset.y)
            .scaledBy(x: zoomScale, y: zoomScale)
        
        drawRects(insideRect: rect, withTransform: tr)
        
        
    }
    
    personal func drawRects(insideRect: CGRect, withTransform tr: CGAffineTransform) {
        UIColor.white.setStroke()
        theRectPaths.forEach { pth in
            if let path = pth.copy() as? UIBezierPath {
                //  rework a replica of the trail
                path.apply(tr)
                // solely draw if seen
                if path.bounds.intersects(insideRect) {
                    path.lineWidth = 1.0 * zoomScale
                    path.stroke()
                }
            }
        }
    }
}

Latest news
Related news

LEAVE A REPLY

Please enter your comment!
Please enter your name here