I have a view and within an image that works as a button. I would like to know if there is a way to lock the size of the button so that when I zoom in, the view remains small and does not enlarge with the view..
I thought it was hard to manager in the beginning. But finally, if you put the imageView in a UIScrollView, It's not hard to achieve.
The idea is move the buttonView outside of imageView during zooming and when zoom is over, put it back to imageView to pretend nothing happened. I know it's too verbose in programming but actually it works perfectly for your case.
var originalCenter : CGPoint! // The center of ButtonView in imageView.
//All functions are from the UIScrollViewDelegate.
func viewForZooming(in scrollView: UIScrollView) -> UIView?{
originalCenter = buttonView.center // remember the original position.
return imageView
}
func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
buttonView.frame = imageView.convert(buttonView.frame, to: scrollView)
scrollView.addSubview(buttonView)//add to superView of imageImage.
}
func scrollViewDidZoom(_ scrollView: UIScrollView){
buttonView.center = imageView.convert(originalCenter, to: scrollView) //During Zooming, update the buttonView in ScrollView.
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat){
buttonView.frame = imageView.convert(buttonView.frame, from: scrollView)
imageView.addSubview(buttonView) //put it back.
}
I know it's better to use a parameter to control such operation. But I have-not found one according to public APIs. Maybe there is a better way, hope this one is your answer too.
Because you called transform for superView. It will make all subViews inside transform together.
You need to remake you views:
SuperView:
- Content view (the image view)
- Border view
- Button close
When you want to zoom the image, you only need to reset the superview frame.
You found a git SPUserResizableView.
Related
I am building an application where I want to display a floor plan where the image is 2952x3600, larger than the size of my view controller. I want the user to be able to pan the image and zoom in and out, similar to how a map behaves in Mapview.
I was able to obtain the desired result programmatically with the below code. However, I want to be able to add buttons to the image and it will be easier to do in the storyboard. How can I accomplish the same result in the Storyboard?
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(image: UIImage(named: "TorontoPATHNetworkMap_v.2018.08.pdf"))
scrollView = UIScrollView(frame: view.bounds)
scrollView.contentSize = imageView.bounds.size
scrollView.addSubview(imageView)
scrollView.delegate = self
scrollView.minimumZoomScale = 0.3
scrollView.maximumZoomScale = 5
view.addSubview(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}
If you want to add other UI elements (buttons, labels, subviews, etc) and have them scale and move when the scroll view content is zoomed, you have a couple options:
1) Add your buttons in code as subviews of the image view. They will move / size along with the image view.
2) If you'd find it easier to layout your buttons visually, you can do your layout in Storyboard / Interface Builder. In IB, though, you cannot add subviews to a UIImageView, so you will need to embed the image view and buttons in a "container" UIView. Then in your controller class return that container view from viewForZooming
Edit
Here's an example of setting up the views in Storyboard / IB: https://github.com/DonMag/PDFImagePanZoom
I have a scroll view and inside the scrollview I am having a content view with few subview inside this content view. My requirement is to zoom the content view but not the subview of content view.
Can anyone faced this before, or did the same. Any help would be appreciated.
Thanks in advance.
Scroll view just apply transform to contentView. This transform applied to all children in contentView. So you can apply inverted transform to children to negate parent transform.
func scrollViewDidZoom(_ scrollView: UIScrollView) {
guard let content = viewForZooming(in: scrollView) else {
return
}
let t = content.transform.inverted()
for v in content.subviews {
v.transform = t
}
}
I have an UIView in ScrollView superview. I want this UIView to stick to the top and stays there when users scrolls down.
Note that it should start in the middle of a screen and go up respectively when scrolling down.
I've seen many questions and answers but none of them solved my problem
iOS: Add subview with a fix position on screen
Simple way to change the position of UIView?
My code in scrollViewDidScroll method
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if scrollView.contentOffset.y > anchor.frame.origin.y {
var fixedFrame:CGRect = self.anchor.frame
fixedFrame.origin.y = (self.navigationController?.navigationBar.frame.height)!
self.anchor.frame = fixedFrame
}
}
you can do this by saving a initial offset value of Y for your anchor view, then compare it in the scrollview delegate event.
self.initialOffSet = self.anchor.frame.origin.y
func scrollViewDidScroll(_ scrollView: UIScrollView) {
var newFrame = self.anchor.frame
newFrame.origin.y = max(self.initialOffSet!, scrollView.contentOffset.y)
self.anchor.frame = newFrame
}
Why dont you put that view out of your scrollview?It will stay at the top only even when you will be scrolling your scrollview?
I do have a UIScrollView with a single customContentView as subview. This is returned as the viewForZoomingInScrollView: . But this way, every subview of my customContentView is zoomed: I would like to have some zoomed, others not (e.g. labels), but of course the relative position should remain. Is there a way to achieve this?
You need apply inverse scale transform to the label as below,
func scrollViewDidZoom(_ scrollView: UIScrollView) {
sampleLabel.transform = CGAffineTransform(scaleX: 1/scrollView.zoomScale, y: 1/scrollView.zoomScale)
}
Before Zoom,
After Zoom,
I have a scroll view with several elements (textview, label, image view...), I need to display an uiview when my label appears on the screen when I'm scrolling.
How can I do ?
Make sure your view controller is the scroll view delegate. Implement the scrollViewDidScroll method, and check whether the scroll view's frame, offset by the contentOffset, overlaps the label's frame.
func scrollViewDidScroll(scrollView: UIScrollView) {
let offset = self.scrollView.contentOffset
let onScreen = CGRectOffset(self.scrollView.frame, offset.x, offset.y)
if CGRectIntersectsRect(onScreen, self.label.frame) {
NSLog("Overlap")
}
}
If you want to detect when the label is fully on the screen, use CGRectContainsRect instead of CGRectIntersectsRect.