Currently i am trying to create some kind of an imageviewer, where you can click on an image which is then displayed in full size. Now i want to add gestures to it to zoom. I want to understand and see how to add the pinch gesture to zoom in and out, to be able to pan around the image and to zoom in quickly with the double tap gesture. I did not found much good tutorials.
I know that you zoom into the view, not into the image. That is why you use a ScrollView containing an ImageView. Now what is missing to enable zooming, pinching and moving the image around?
Thank you in advance for any helpful post.
In the following is "my" current code base for this feature. What needs to be added?
class DetailViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationController?.isNavigationBarHidden = false
scrollView=UIScrollView()
scrollView.frame = CGRect(x: 0, y: 0, width: self.view.frame.width, height: (self.view.frame.height - (self.navigationController?.navigationBar.frame.size.height)! + 44))
scrollView.minimumZoomScale=1
scrollView.maximumZoomScale=3
scrollView.bounces=false
scrollView.delegate=self
self.view.addSubview(scrollView)
imageView=UIImageView()
imageView.image = UIImage(named: "inlinelogo.jpg")
imageView.frame = CGRect(x: 0, y: 0, width: scrollView.frame.width, height: scrollView.frame.height - (44 + UIApplication.shared.statusBarFrame.size.height))
imageView.backgroundColor = .black
imageView.contentMode = .scaleAspectFit
scrollView.addSubview(imageView)
}
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
{
return imageView
}
}
you missed the userInteractionEnabled property of UIImageView add
imageView.isuserInteractionEnabled = true
Related
I am playing around with scroll views, and I've run into an issue I'be stuck with. I have a view controller create in Storyboard. The view controller contains a scroll view which fills the entire superview.
I then added the images programmatically to the scroll view. The images do show within the scroll view and paging works just fine. Only problem is the scroll view is set ti fill superview but the image view that hold the images seems like it stops above where the navigation bar would be. How can I have the image view fill the whole view within the scroll view?
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pagingView: UIPageControl!
var images = [UIImage]()
var frame = CGRect(x: 0, y: 0,width: 0,height: 0)
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
scrollView.isPagingEnabled = true
images = [UIImage(named: "Slide1")!, UIImage(named: "Slide2")!, UIImage(named: "Slide3")!, UIImage(named: "Slide4")!]
pagingView.numberOfPages = images.count
// This is where I think I'm having the height problem.
for i in 0..<images.count {
let imageView = UIImageView()
let x = self.view.frame.size.width * CGFloat(i)
imageView.frame = CGRect(x: x, y: 0, width: self.view.frame.width, height: self.view.frame.height)
imageView.contentMode = .scaleAspectFill
imageView.image = images[i]
scrollView.contentSize.width = scrollView.frame.size.width * CGFloat(i + 1)
scrollView.addSubview(imageView)
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
let pageNumber = scrollView.contentOffset.x / scrollView.frame.size.width
pagingView.currentPage = Int(pageNumber)
}
After setting nav bar to hidden, here is the output
Scroll view background color is red
In this case you need to enable the parent view clipsToBounds. Set UIScrollview clipsToBounds property to True.
Programmatically scrollView.clipsToBounds = true
In UIStoryBoard - Click the view->Attributes Inspector
If you would like to see the whole screen, make sure to add the topConstraint of scrollView assigned superView and hide the navigationBar in viewWillAppear,
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
navigationController?.setNavigationBarHidden(true, animated: animated)
}
Make sure to remove the status bar by
override var prefersStatusBarHidden: Bool {
return true
}
Update the Y position of Image.
imageView.frame = CGRect(x: x, y: **self.scrollView.frame.minY**, width: self.view.frame.width, height: self.view.frame.height)
Update the scrollView topConstraint by -20.
Is it possible to pan an object that is behind another object?
Currently I have a imageview and a view with clear color and only a border around, that I can see the imageview. I want to achieve that the view with the border is always on top. Trough the view I want to pan the image view with pan gesture.
You can add Pan gesture to the view and apply the transformation to the imageView.
var translation = panGesture.translationInView(imageView)
panGesture.setTranslation(CGPointZero, inView: imageView)
Just set isUserInteractionEnabled false for upper view.
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let bottomView = UIView.init(frame: .init(x: 100, y: 100, width: 300, height: 300))
bottomView.backgroundColor = .yellow
let upperView = UIView.init(frame: .init(x: 100, y: 100, width: 300, height: 300))
upperView.backgroundColor = .clear
upperView.layer.borderWidth = 1
upperView.layer.borderColor = UIColor.red.cgColor
upperView.isUserInteractionEnabled = false //<------------
view.addSubview(bottomView)
view.addSubview(upperView)
bottomView.addGestureRecognizer(UIPanGestureRecognizer.init(target: self, action: #selector(handle)))
}
#objc func handle() {
print("handletapgesture")
}
}
i am trying to create something like Photos gallery.
But now i have problem, with zooming in UIScrollView.
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.isUserInteractionEnabled = true
imageView.image = imageArray[i]
imageView.contentMode = .scaleAspectFit
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: 0, y: 0, width: self.scrollView.frame.width, height: self.scrollView.frame.height)
scrollView.addSubview(imageView)
scrollView.contentSize.width = scrollView.frame.width * CGFloat(i+1)
}
scrollView.isScrollEnabled = true
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 6.0
scrollView.isUserInteractionEnabled = true
scrollView.delegate = self
Paging works fine, but i dont know now how to enable zooming each imageView.
You will need to implement the following method from the UIScrollViewDelegate protocol:
func viewForZooming(in: UIScrollView) -> UIView?
In that you return the view that you want to be zooming.
Now in this case you have multiple image views (depending on imageArray.count) but I assume you want to scroll into them all (i.e. not an individual image) so the best thing would be to add a 'content view' (UIView) to the scroll view and then add the individual image views to that instead of the scroll view directly and size it appropriately.
Then you can return that 'content view' in the viewForZooming method.
So assuming you have created this 'content view' then the method would look like this:
func viewForZooming(in: UIScrollView) -> UIView? {
return self.contentView
}
I try to add button overlay on UITableViewController with static cells. But i get this result, button is working, but i not see result of search:
I'm trying to get this result:
I want to button was always at the bottom regardless of scrolling up or down.
In my code i use framework InstantSearch:
import UIKit
import InstantSearch
import WARangeSlider
class SearchTableViewController: UITableViewController {
#IBOutlet weak var resultButton: StatsButtonWidget!
override func viewDidLoad() {
super.viewDidLoad()
resultButton.frame = CGRect(x: 0, y: 0, width: 150, height: 60)
navigationController?.view.addSubview(resultButton)
InstantSearch.shared.registerAllWidgets(in: self.view)
LayoutHelpers.setupResultButton(button: resultButton)
resultButton.addTarget(self, action: #selector(resultButtonClicked), for: .touchUpInside)
}
}
How can i add button overlay on bottom in UITableViewController? Me need use only UITableViewController, not UIViewController with TableView.
You could directly add the button to the UITableView without AutoLayout, and make sure TableView's delegate is the controller, like:
override func viewDidLoad() {
super.viewDidLoad()
self.button.frame = CGRect(x: 0, y: self.tableView.frame.size.height - 50, width: self.tableView.frame.width, height: 50)
self.tableView.addSubview(self.button)
self.tableView.delegate = self
}
Then you are able to fix the button's position by UIScrollView delegate (UITableViewDelegate inherited from this) while TableView is scrolling:
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (scrollView == self.tableView) {
let originY = scrollView.frame.size.height - self.button.frame.size.height + scrollView.contentOffset.y
self.button.frame = CGRect(x: 0, y: originY, width: scrollView.frame.width, height: self.button.frame.size.height)
}
}
Alternatively, if you want to position the button by AutoLayout, just define a NSLayoutConstraint property, and bind it to button's bottom space constraint to its super view. Then adjust the constraint's constant value by same mechanism in scrollViewDidScroll function.
You can just add an view at the bottom of your tableview.
override func viewDidLoad() {
super.viewDidLoad()
addResultButtonView()
}
private func addResultButtonView() {
let resultButton = UIButton()
resultButton.backgroundColor = .red
resultButton.setTitle("Hello", for: .normal)
tableView.addSubview(resultButton)
// set position
resultButton.translatesAutoresizingMaskIntoConstraints = false
resultButton.leftAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.leftAnchor).isActive = true
resultButton.rightAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.rightAnchor).isActive = true
resultButton.bottomAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.bottomAnchor).isActive = true
resultButton.widthAnchor.constraint(equalTo: tableView.safeAreaLayoutGuide.widthAnchor).isActive = true
resultButton.heightAnchor.constraint(equalToConstant: 50).isActive = true // specify the height of the view
}
I am making an app that the user can upload 1 to 3 photos.
I want the user to be able to see them it as a slider in with Page Control,
I started to code it but for some reason the images do not added to the scrollView (I see nothing when running the app).
This is my code so far:
class dogProfileViewController: UIViewController {
var imagesArray = [UIImageView()]
#IBOutlet var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
let image1: UIImageView = UIImageView(image: UIImage(named: "image1.png"))
let image2: UIImageView = UIImageView(image: UIImage(named: "image2.png"))
imagesArray.append(image1)
imagesArray.append(image2)
var countIndex = CGFloat(0)
for image in imagesArray {
image.frame = CGRectMake(countIndex*view.frame.width, 0, view.frame.width, 100)
scrollView.addSubview(image)
countIndex = countIndex + 1
}
// Do any additional setup after loading the view.
}
}
Add the following line after the for loop ends
scrollView.contentSize = CGSizeMake(countIndex*view.frame.width,0)
I think this will work.
#IBOutlet var mainScrollView: UIScrollView!
var imageArray = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
mainScrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 175)
imageArray = [#imageLiteral(resourceName: "cake"),#imageLiteral(resourceName: "food")]
for i in 0..<imageArray.count{
let imageView = UIImageView()
imageView.image = imageArray[i]
imageView.contentMode = .scaleToFill
let xPosition = self.view.frame.width * CGFloat(i)
imageView.frame = CGRect(x: xPosition, y: 0, width: self.mainScrollView.frame.width, height: self.mainScrollView.frame.height)
mainScrollView.contentSize.width = mainScrollView.frame.width * CGFloat(i + 1)
mainScrollView.addSubview(imageView)
}
}
Well, according to what you provided, you haven't added the scrollView to the view. So, first step, make sure the scrollView is added to the view. self.view.addSubiew(scrollView). Change the scrollView background to make sure it is there.
Also, I don't see that you have initialized the scrollView frame. The scrollView has no frame, so it won't show anywhere. Make sure that you initialize the scrollView.