UIScrollView zooming and panning - ios

I've got a UIViewController with a UIView.
I put inside an UIScrollView with another UIView inside, all in my storyboard with AutoLayout.
After ViewDidLoad method I create an array of UIButton to represent them as a matrix NxM.
The matrix can go out of bounds but the scrollview is here for a reason.
When I pan some UIButtons don't capture any touch event and if I zoom the UIScrollView doesn't zoom very well, is not centered and it brokes the panning.
Anybody knows why?

I solved this issue implementing the UIScrollViewDelegate like this:
func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView!, atScale scale: CGFloat) {
let w = max(scrollView.frame.size.width, totalWidth)
let h = max(scrollView.frame.size.height, totalHeight)
view.frame.size = CGSize(width: w * scale, height: h * scale)
scrollView.contentSize = CGSize(width: w * scale, height: h * scale)
}
So it recalculate size correctly and zooming and panning worked nice

Related

Swift - Mapping invisible button on UIImage which zoom In/Out

Can some one suggest the best way to do this..
In the Below Image
Add invisible buttons over the image for each section of the map.
The image should be in a scrollview to zoom in and out the image.
Zooming in/out should not change the button mapping area
Should support for all iPhone models.
What I did..
Added a UIImageView inside a UIScrollView(for zoom in/out) and on viewDidAppear() manually added invisible button for the UIImage like this.
self.image.frame = CGRect(x: xValue , y:yValue, width: 60, height: 60)
Is there any better solution for finding the UIImage coordinates?
Very late to the party, but this should work:
in ViewDidLoad add this:
scrollView.minimumZoomScale = 0.5
scrollView.maximumZoomScale = 6.0
scrollView.contentSize = self.imageView.frame.size
scrollView.delegate = self
After ViewDidLoad add this:
// MARK: - Update the minimum zoom scale each time the controller updates its subviews
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
updateMinZoomScaleForSize(view.bounds.size)
}
Then create a file private function to calculate the zoom scale for scrollView
fileprivate func updateMinZoomScaleForSize(_ size: CGSize) {
let widthScale = size.width / imageView.bounds.width
let heightScale = size.height / imageView.bounds.height
let minScale = min(widthScale, heightScale)
imageScrollView.minimumZoomScale = minScale
imageScrollView.zoomScale = minScale
}
Are you using nine imageViews? No. it's not correct it seems.
Try like this :
Take a collection view and give necessary constraints like top, bottom, left and right.
Add image view to collection view cell. Add corner radius properties(it seems ur image views need this).
For zoom in and zoom out actions, add pinch gesture to collection view.
Add tap gesture for image view, instead of buttons.

Swift 3 - Scale round ImageView

I have a round Imageview in my ReusableCollectionView.
When I scroll down my collectionView I scale my Imageview and as soon as it scrolls back to place I scale it to its original size.
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// Exit early if swiping up (scrolling down)
if scrollView.contentOffset.y > 0 { return }
// this is just a demo method on how to compute the scale factor based on the current contentOffset
var scale = 1.0 + fabs(scrollView.contentOffset.y) / scrollView.frame.size.height
//Cap the scaling between zero and 1
scale = max(0.0, scale)
// Set the scale to the imageView
headerView.imageview.transform = CGAffineTransform(scaleX: scale, y: scale)
headerView.categoryButton.transform = CGAffineTransform(scaleX: scale, y: scale)
}
The imageview is not round anymore while doing so.
Here is an image visualising the problem:
This is how I solved the problem:
imageView.autoresizesSubviews = false

A bug of UIScrollView contentOffset?

I set the property isPagingEnabled of a scrollView to true, like this:
let scrollView = UIScrollView(frame: view.bounds)
scrollView.contentSize = CGSize(width: view.bounds.width * 2, height: 0)
scrollView.delegate = self
scrollView.isPagingEnabled = true
view.addSubview(scrollView)
and delegate method:
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print(scrollView.contentOffset.x)
}
When scrolling the view to the boundary, the console print, as shown in:
and
The values in the red box should not be printed out, right?
But, if setting isPagingEnabled to false, the console print is normal. Is this a bug of UIScrollView?
Your Content offset is showing wrong because your are using content size in viewdidload use content size in this method than print your content off set
override func viewDidLayoutSubviews()
{
scrollView.contentSize = CGSize(width: view.bounds.width * 2, height: 0)
}
As far as i Know, Its working correctly, when you are setting contentSize to your scrollview, that will respond to their delegate at first time itself.
func scrollViewDidScroll(_ scrollView: UIScrollView)
Whenever user try to scroll or drag, the above delegate will call recursively, Here your contentSize of width is double of Your view bounds width(so there is two page, the contentOffset.x will start with 0 and current position of scroll, if it is in second page, that will give your view width * n ), and you set isPagingEnabled to true.
Check this https://developer.apple.com/reference/uikit/uiscrollview/1619404-contentoffset
The default value is CGPoint​Zero.
Actually contentOffset will tell you that current scroll position.
Whenever UIScrollView make scrolling, this method scrollViewDidScroll(_ scrollView: UIScrollView) invokes. Any of the direction if you scroll you will get these types of output.
However if you want like a pagination approach then instead of this method you can use:
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
print("pageNumber = \(pageNumber)")
}
By this method you will get the exact page no of UIScrollView.
Please use frame instead of bounds .
The bounds of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to its own coordinate system (0,0).The frame of an UIView is the rectangle, expressed as a location (x,y) and size (width,height) relative to the superview it is contained within.
let scrollView = UIScrollView(frame: view.frame.size)
scrollView.contentSize = CGSize(width: view.frame.size.width * 2,
height: 0)
scrollView.delegate = self
scrollView.isPagingEnabled = true
view.addSubview(scrollView)

UIScrollView has large contentSize but doesn't scroll - no autoLayout

In my Swift 2 iOS 9.0 project I've set up a UIScrollView with a UIImageView and some buttons and labels. For some other reasons the scrollView's frame is 652 points wide and 652 points high. Its content is decided by the image in the imageView (it's 1000x1000):
func loadImageOntoView(FloorImage:UIImage) -> Void {
mapImageView.image = FloorImage
// containerView is my root view, same size as the screen
let cw = containerView.frame.width
let ch = containerView.frame.height
let cd = sqrt(cw*cw + ch*ch)
/* Here I set scrollView's frame to be a square with sides as
long as containerView's diagonal. This makes sure that if the scrollView
is rotated it's always bigger than the screen*/
scrollView.frame = CGRect(
x: -(cd-cw)/2, y: -(cd-ch)/2,
width: cd, height: cd
)
scrollView.contentSize = FloorImage.size
//Here it centers the imageView in the scrollView
mapImageView.center = CGPoint(
x: scrollView.frame.size.width/2, y: scrollView.frame.size.height/2)
scrollView.minimumZoomScale = 0.9
scrollView.maximumZoomScale = 15.1
}
I'm not completely sure on these scrollViews, but I thought it was supposed to be able to scroll with these settings? When I zoom in I can scroll, but when the zoomScale = 1 it doesn't work. What have I done wrong, or how should I go about using scrollViews?

Why is UIView moved to right on offsetBy

I have a scrollview with an UIImageView on it. When the user scrolls, I would like to keep the UIImageView at its original place. I am using offsetBy for this:
func scrollViewDidScroll(scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
self.headerView!.currentLoadLabel.frame = currentLoadLabelFrame.offsetBy(dx: 0, dy: offset)
}
The UIImageView stays at his y position but moves to the farmost x position at the right of the screen. Why?
try following code:
self.headerView!.currentLoadLabel.frame = currentLoadLabelFrame.offsetBy(dx: scrollView.contentOffset.x, dy: scrollView.contentOffset.y)

Resources