user979331 user979331 - 4 months ago 70
iOS Question

Swift - Add UIImageView as subview of UIWebView scrollView and scaling

I have a

UIWebView
and I have successfully added a
UIImage
view to the
UIWebView
’s
scrollView
like so:

let localUrl = String(format:"%@/%@", PDFFilePath, fileNameGroup)
let url = NSURL.fileURLWithPath(localUrl)

panRecognizer = UITapGestureRecognizer(target: self, action: #selector(panDetected))
pinchRecognizer = UIPinchGestureRecognizer(target: self, action: #selector(pinchDetected))

panRecognizer.delegate = self
pinchRecognizer.delegate = self

webview = UIWebView()
webview.frame = self.view.bounds
webview.scrollView.frame = webview.frame

webview.userInteractionEnabled = true
webview.scalesPageToFit = true
webview.becomeFirstResponder()
webview.delegate = self
webview.scrollView.delegate = self
self.view.addSubview(webview)
webview.loadRequest(NSURLRequest(URL:url))
webview.gestureRecognizers = [pinchRecognizer, panRecognizer]

let stampView:StampAnnotation = StampAnnotation(imageIcon: UIImage(named: "approved.png"), location: CGPointMake(currentPoint.x, currentPoint.y))
self.webview.scrollView.addSubview(stampView)


My
UIWebView
scrollView
is scalable. Now I am looking for away to have my
UIImageView
(
StampAnnotation
is a class and
UIImageView
is its subclass) scale when the
scrollView
scales. So if the user zooms in on the
scrollView
, the
UIImageView
will get bigger and stay in a fixed position and if the user zooms out, the
UIImageView
will get smaller while the
scrollView
gets smaller while staying in a fixed position.

I really hope that makes sense. I have tried the following:

func pinchDetected(recognizer:UIPinchGestureRecognizer)
{

for views in webview.scrollView.subviews
{
if(views.isKindOfClass(UIImageView))
{
views.transform = CGAffineTransformScale(views.transform, recognizer.scale, recognizer.scale)
recognizer.scale = 1
}
}

if(appDelegate.annotationSelected == 0)
{
webview.scalesPageToFit = true
}
else
{
webview.scalesPageToFit = false
}

}


but this does nothing, if I remove this line:

recognizer.scale = 1


it scales way too big too fast. My question is, how do I get my
UIImageView
to scale when the
UIWebview
’s
scrollView
scrolls?

Any help would be appreciated.

This solved my problem.

func scrollViewDidZoom(scrollView: UIScrollView) {

for views in webview.scrollView.subviews
{
if(views.isKindOfClass(UIImageView))
{
views.transform = CGAffineTransformMakeScale(scrollView.zoomScale, scrollView.zoomScale)
}
}

}


No it does not stay in a fixed position on the page, but I think that is a constraints issue?

Answer

You were close...

1) Add a property to hold onto an external reference for your stampViewFrame:

var stampViewFrame = CGRect(x: 100, y: 100, width: 100, height: 100)

2) Replace your scrollViewDidZoom() with this:

 func scrollViewDidZoom(scrollView: UIScrollView) {
    for views in webView.scrollView.subviews
    {
        if(views.isKindOfClass(UIImageView))
        {
            views.frame = CGRect(x: stampViewFrame.origin.x * scrollView.zoomScale, y: stampViewFrame.origin.y * scrollView.zoomScale, width: stampViewFrame.width * scrollView.zoomScale, height: stampViewFrame.height * scrollView.zoomScale)
        }
    }
}

3) Finally, because the zoom scale resets to 1 at the begining of each new zooming action, you need to adjust the value of your stampViewFrame property:

func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView?, atScale scale: CGFloat) {
    stampViewFrame = CGRect(x: stampViewFrame.origin.x * scale, y: stampViewFrame.origin.y * scale, width: stampViewFrame.width * scale, height: stampViewFrame.height * scale)
}

I also tried to answer your other question about layout during orientation change, but I now have a much better understanding of what you are trying to do. If you want your stampView to always be on in the same place relative to the web content, you have to get into HTML/JS because the webpage lays itself out dynamically. A much much more simple (and hopefully close enough) solution would be to add the following:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    webView.frame = view.bounds
    stampView.frame = stampViewFrame
}