user1269290
user1269290

Reputation: 481

iOS Fix the location of a UIButton over a zoomable image so it zoomed and scaled with the image

New guy here to programming. Also, my first post. I did try to do some research over this, and I did find some threads, but most were a few years old or not for iOS.

In an iOS app I am trying to place clickable buttons over a high definition image of a mechanical panel of some equipment. The idea is the user could zoom into the image, tap over i.e. switch, and get a pop up that explains what the switch is for.

After watching some videos I was able to create a UIScrollView and place a UIImageView of the HD image into it. I can zoom in/out and move the panel fine.

I figured using UIButton to define "clickable" areas of the panel would be one way to go (not sure if this is the best approach). However, the buttons are giving me some problems:

After zooming in, the buttons won't stay over the same pixels relative to the HD image, and the button's size does not "grow" with zooming. So when zoomed in, the area the button covers is smaller and it is not over the correct place.

I have tried to apply constrains relative to the HD image, and also relative the scroll view. I have tried to put the image and the button into a stack. Obviously, I am missing some basics here. It seems this is a bit too advanced for where I am at.

Any ides on how to fix this? Also, would it be better to try going for tap gestures instead of UIButtons?

Thank you for your time! PS: Any tutorial videos or articles about this topic would be appreciated.

Upvotes: 1

Views: 713

Answers (2)

user1269290
user1269290

Reputation: 481

I finally have found the answer. It is very simple. The button needs to be added as a subview of the imageView where the image resides. I was not able to do this through the interface, only programmatically like this:

imageView.addSubview(button)

It seems, Swift takes care of the rest. The button is moving and scaling perfectly with the image.

Upvotes: 1

danh
danh

Reputation: 62676

One idea is to make the button a child of the scroll view's parent (a sibling to the scroll view), ordered after the scroll view so it sits on top.

     parent view  (probably the view controllers view)
          |
    |-----------|
scrollView    button

Let's say, before the scroll has been scrolled or zoomed, you'd like the button to appear at CGRect imageButtonFrame = CGRectMake(10,20,80,40). We might say these coordinates are in "image space". The function that maps these to the scroll view's sibling looks like this:

UIView *parentView = self.view;  // this assumes both button and scrollView are children of the view controller's view
self.button.frame = [scrollView convertRect:imageButtonFrame toView:parentView];

What's nice about this is that the UIScrollView, aware of it's own contentOffset and zoomScale, does the computation with respect to those values. As long as you use that code snippet to set the button's frame, that frame will remain fixed in image space as imageButtonFrame.

Keep the frame up-to-date by becoming the delegate of the scrollView...

self.scrollView.delegate = self;

And find out when the offset or zoom level changes with:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    self.button.frame = // ... as above
}

Same for scrollViewDidZoom:(UIScrollView *)scrollView

Upvotes: 0

Related Questions