Swift 4 Pinch-to-Zoom with view on scrollview - ios

If I pinch the simulator, it does not work! I want to zoom in and out )=
Here is my Code:
import UIKit
class ViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
let onView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
scrollView.contentSize.width = 10000
scrollView.contentSize.height = 10000
onView.frame = CGRect(x: 0, y: 0, width: scrollView.frame.width, height: scrollView.frame.height)
scrollView.addSubview(onView)
for _ in 1...1000{
let x = arc4random_uniform(10000)
let y = arc4random_uniform(10000)
let btn = UIButton(frame: CGRect(x: Int(x), y: Int(y), width: Int(150), height: Int(100)))
btn.backgroundColor = .red
self.board.addSubview(btn)
}
scrollView.minimumZoomScale = 0.5
scrollView.maximumZoomScale = 10.0
scrollView.zoomScale = 1.0
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return scrollView
}
}

Related

UiImageView blurs after zooming

I have a UIImageView inside a scrollView. Its initial width and height are equal to 100. I want this UIImageView to appear in same size even after zooming. For that I modify its size inside scrollViewDidEndZooming method. This is working fine without a problem. However UiImage of the UiImageView looks blurry when zoom scale is increased. I tried to set contentScale property of the UiImageView, but it is not working.
How I can fix this?
import UIKit
class ViewController: UIViewController {
static var zoomScale: CGFloat = 1.0
let scrollView = UIScrollView()
let contentView = UIView()
let imageView: UIImageView = UIImageView()
let imageViewSize: CGFloat = 100
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .yellow
self.setupScrollView()
self.setuContentView()
self.addImageView()
}
func setupScrollView() {
let vWidth = self.view.frame.width
let vHeight = self.view.frame.height
scrollView.delegate = self
scrollView.frame = CGRect(x: 0, y: 0, width: vWidth, height: vHeight)
scrollView.backgroundColor = .lightGray
scrollView.alwaysBounceVertical = false
scrollView.alwaysBounceHorizontal = false
scrollView.showsVerticalScrollIndicator = true
scrollView.flashScrollIndicators()
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 10.0
self.view.addSubview(scrollView)
}
func setuContentView() {
contentView.frame = scrollView.frame.insetBy(dx: 20, dy: 20)
contentView.backgroundColor = .white
scrollView.addSubview(contentView)
}
func addImageView(){
let image = UIImage(systemName: "arrow.triangle.2.circlepath")
imageView.frame = CGRect(x: 200, y: 200, width: imageViewSize, height: imageViewSize)
imageView.image = image
imageView.contentMode = .scaleAspectFit
imageView.backgroundColor = .systemBlue
imageView.tintColor = .white
imageView.clipsToBounds = true
imageView.layer.cornerRadius = 0.5 * imageView.bounds.size.width // I want rounded imageView
self.contentView.addSubview(imageView)
}
}
extension ViewController: UIScrollViewDelegate {
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.contentView
}
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
ViewController.zoomScale = scale
imageView.frame = CGRect(x: imageView.frame.origin.x, y: imageView.frame.origin.y, width: imageViewSize/scale, height: imageViewSize/scale)
imageView.layer.cornerRadius = 0.5 * imageView.bounds.size.width
imageView.layer.contentsScale = scale
}
}

UIScrollView with wider UIView not scrolling

I'm learning to use UIScrollView to make several pictures could scroll horizontally. These images are programmatically added as a subview to a UIView within UIScrollView. The 'Scrolling enabled' is also set true. However, when I run the app, the UIScrollView cannot scroll.
Here is my code.
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var scrollContentView: UIView!
var imageViews = [UIImageView]()
override func viewDidLoad() {
super.viewDidLoad()
let imageWidth: CGFloat = 200.0 / 768.0 * 1024.0
for i in 1...3 {
let image = UIImage(named: "image\(i)")
let imageView = UIImageView(image: image)
imageViews.append(imageView)
let x: CGFloat = CGFloat(i - 1) * (imageWidth + 10)
scrollContentView.addSubview(imageView)
print(imageView.frame)
imageView.frame = CGRect(x: x, y: 0, width: imageWidth, height: 200.0)
}
scrollContentView.frame = CGRect(x: 0.0, y: 0.0, width: imageWidth * 3 + 20.0, height: 200.0)
scrollView.contentSize = scrollContentView.frame.size
}
}
Instead of creating the scrollContentView in Interface Builder, create it programmatically.
Xcode won't complain anymore about missing contraints, and you will be able to play with the frame manually.
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
var scrollContentView: UIView!
var imageViews = [UIImageView]()
override func viewDidLoad() {
super.viewDidLoad()
scrollContentView = UIView()
scrollView.addSubview(scrollContentView)
let imageWidth: CGFloat = 200.0 / 768.0 * 1024.0
for i in 1...3 {
let image = UIImage(named: "image\(i)")
let imageView = UIImageView(image: image)
imageViews.append(imageView)
let x: CGFloat = CGFloat(i - 1) * (imageWidth + 10)
scrollContentView.addSubview(imageView)
print(imageView.frame)
imageView.frame = CGRect(x: x, y: 0, width: imageWidth, height: 200.0)
}
scrollContentView.frame = CGRect(x: 0.0, y: 0.0, width: imageWidth * 3 + 20.0, height: 200.0)
scrollView.contentSize = scrollContentView.frame.size
}
}

Zooming an UIImageView that contains subviews

I have an UIImageView object in UIScrollView(to zoom). In addition, UIImageView also contains subviews. I am using following function to zoom in UIImageView.
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return self.imageView
}
It works perfectly fine for UIImageView.
The problem is when zooming these subviews, it also zooms these subviews the same way. Is there a way to disable zooming for these subviews?
There are many ways to achieve this. I would say the easiest one is to simply back-scale your views. This is what I used as a demo:
class ViewController: UIViewController {
#IBOutlet private var scrollView: UIScrollView?
private var imageView: UIImageView?
private var annotations: [UIView] = [UIView]()
override func viewDidLoad() {
super.viewDidLoad()
let imageView = UIImageView(image: UIImage(named: "background"))
scrollView?.addSubview(imageView)
scrollView?.contentSize = imageView.bounds.size
scrollView?.maximumZoomScale = 5.0
self.imageView = imageView
scrollView?.delegate = self
applyAnnotationView({
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
view.backgroundColor = UIColor.red
view.layer.cornerRadius = view.bounds.width*0.5
return view
}(), at: CGPoint(x: 100.0, y: 100.0))
applyAnnotationView({
let view = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 10.0, height: 10.0))
view.backgroundColor = UIColor.green
view.layer.cornerRadius = view.bounds.width*0.5
return view
}(), at: CGPoint(x: 200.0, y: 200.0))
}
func applyAnnotationView(_ view: UIView, at position: CGPoint) {
view.center = position
annotations.append(view)
imageView?.addSubview(view)
}
}
// MARK: - UIScrollViewDelegate
extension ViewController: UIScrollViewDelegate {
func scrollViewDidZoom(_ scrollView: UIScrollView) {
annotations.forEach { item in
item.transform = CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale)
}
}
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
}
Simply applying CGAffineTransform(scaleX: 1.0/scrollView.zoomScale, y: 1.0/scrollView.zoomScale) does all the work. It should be OK even when using constraints.
The UIView, which is inside the UIImageView, will always be the same size, but will be anchored to a specific point in the image (10% at the top and 10% at the left):
var item: UIView?
override func viewDidLoad() {
...
item = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 200))
setPosition()
item?.backgroundColor = UIColor.red
imageView.addSubview(item!)
...
}
func setPosition() {
let x = imageView.frame.size.width/10
let y = imageView.frame.size.height/10
item?.frame = CGRect(x: x, y: y, width: 200, height: 200)
}
func scrollViewDidZoom(_ scrollView: UIScrollView) {
...
setPosition()
...
}
Instead of 10%, you can use the exact figure, using the formula:
x = startPosition/startWidthImage*currentWidthImage

Vertical Align Images in ScrollView swift 3

I am trying to align my images vertical in my scrollView. Unfortunately I can't figure out what the problem is. I think it's something mathematical and this is not my strongest thing. :(
I hope someone can help me out with this problem. I will also provide my code and image of the problem below:
//
// muscleListVC.swift
// ActiveRest
//
// Created by Fhict on 04/10/16.
// Copyright © 2016 Kevin Vugts. All rights reserved.
//
import UIKit
class muscleListVC: UIViewController {
var images = [UIImageView]()
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
print("Count: \(images.count)")
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
var contentHeight: CGFloat = 0.0
let scrollHeight = scrollView.frame.size.height
for x in 0...4 {
let image = UIImage(named: "muscle\(x).png")
let imageView = UIImageView(image: image)
images.append(imageView)
var newX: CGFloat = 0.0
newX = scrollHeight / 4 + scrollHeight * CGFloat(x) / 4
print("the size is \(newX)")
contentHeight += newX
scrollView.addSubview(imageView)
imageView.frame = CGRect(x: 0, y: newX, width: view.frame.size.width, height: 166)
print("the content height: \(contentHeight)")
scrollView.contentSize = CGSize(width: scrollView.frame.size.width, height: contentHeight)
}
scrollView.clipsToBounds = false
}
}
Thank you very much! <3
I am not quite sure what you intend to do but I tried to modify your code a bit to make it work.
override func viewDidLoad() {
super.viewDidLoad()
let numberOfImages = 5
let imageViewHeight:CGFloat = 166.0
scrollView.contentSize = CGSize(width: view.frame.size.width, height: imageViewHeight*(CGFloat)(numberOfImages))
var newY:CGFloat = 0
for x in 0...(numberOfImages-1) {
let image = UIImage(named: "muscle\(x).png")
let imageView = UIImageView(image: image)
images.append(imageView)
imageView.frame = CGRect(x: 0, y: newY, width: view.frame.size.width, height: imageViewHeight)
newY = newY + CGFloat(imageViewHeight)
scrollView.addSubview(imageView)
}
}

swift change uiviewcontroller's view

I create a new UIViewController, I don't use storyboard, this is my code. I want to change my view frame, this not work for me, I had try to add on viewWillAppear, it's still not work, I know I can add a new UIView to do it. Can I change my viewcontroller's view? Thanks your help.
import UIKit
class NewDetailViewController: UIViewController {
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
let statusBarHeight: CGFloat = UIApplication.sharedApplication().statusBarFrame.height
let navBarHeight = self.navigationController?.navigationBar.frame.size.height
println("statusBarHeight: \(statusBarHeight) navBarHeight: \(navBarHeight)")
// view
var x:CGFloat = self.view.bounds.origin.x
var y:CGFloat = self.view.bounds.origin.y + statusBarHeight + CGFloat(navBarHeight!)
var width:CGFloat = self.view.bounds.width
var height:CGFloat = self.view.bounds.height - statusBarHeight - CGFloat(navBarHeight!)
var frame:CGRect = CGRect(x: x, y: y, width: width, height: 100)
println("x: \(x) y: \(y) width: \(width) height: \(height)")
self.view.frame = frame
self.view.backgroundColor = UIColor.redColor()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
I found I add on viewDidLayoutSubviews, it work for me.
override func viewDidLayoutSubviews() {
let statusBarHeight: CGFloat = UIApplication.sharedApplication().statusBarFrame.height
let navBarHeight = self.navigationController?.navigationBar.frame.size.height
println("statusBarHeight: \(statusBarHeight) navBarHeight: \(navBarHeight)")
// view
var x:CGFloat = self.view.bounds.origin.x
var y:CGFloat = self.view.bounds.origin.y + statusBarHeight + CGFloat(navBarHeight!)
var width:CGFloat = self.view.bounds.width
var height:CGFloat = self.view.bounds.height - statusBarHeight - CGFloat(navBarHeight!)
var frame:CGRect = CGRect(x: x, y: y, width: width, height: height)
println("x: \(x) y: \(y) width: \(width) height: \(height)")
self.view.frame = frame
self.view.backgroundColor = UIColor.redColor()
}

Resources