I am building an application where I want to display a floor plan where the image is 1260x1000, 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.
Below is the code in my view controller. When I run the simulator, the image is panning but the zooming in and out isn't working. Any suggestions on how to fix my code would be helpful.
class ViewController: UIViewController, UIScrollViewDelegate {
var scrollView: UIScrollView!
var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
imageView = UIImageView(image: UIImage(named: "myMap.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 viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView? {
return imageView
}
}
Your function signature is wrong:
func viewForZooming(in scrollView: UIScrollView) -> UIView? {
return imageView
}
Note: If you want to be able to scale your pdf image while keeping the vector-based rendering (so it doesn't get blurry when zoomed), you should probably use PDFKit and a PDFView.
Add your myMap.pdf file to your bundle... not to your Asset Catalog.
import UIKit
import PDFKit
class ZoomingPDFViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
guard let fileURL = Bundle.main.url(forResource: "myMap", withExtension: "pdf") else {
fatalError("Could not load myMap.pdf!")
}
// Add PDFView to view controller.
let pdfView = PDFView(frame: self.view.bounds)
pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(pdfView)
// Load myMap.pdf file from app bundle.
pdfView.document = PDFDocument(url: fileURL)
pdfView.autoScales = true
pdfView.maxScaleFactor = 5.0
pdfView.minScaleFactor = pdfView.scaleFactorForSizeToFit
}
}
Related
I just recently migrated my iOS UIWebview objective-c to WKWebkit swift, the problem am facing now is how to hide the scroll bar from the website I loaded. I have tried anything but not of it work, please can anyone help me out.
I have followed this step here How to hide scrollbar in WebView?, both the question and accepted answer but it didn't work for me.
Please I know this might be a duplicate question but have I have tried many post to solve this none work.
var lastOffsetY :CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
webViewSetup()
}
In webViewSetup
func webViewSetup(){
webView.scrollView.delegate = self
}
In viewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
let scrollView = webView.subviews[0] as? UIScrollView
webView.scrollView.contentSize = CGSize(width: webView.frame.size.width, height: webView.scrollView.contentSize.height)
scrollView?.bounces = false
scrollView?.decelerationRate = .fast
scrollView?.showsHorizontalScrollIndicator = false
webView.scrollView.showsHorizontalScrollIndicator = false
webView.scrollView.showsVerticalScrollIndicator = false
webView.scrollView.alwaysBounceHorizontal = false
webView.scrollView.bounces = false
}
In scrollViewDidScroll
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) {
scrollView.setContentOffset(CGPoint(x:scrollView.contentOffset.x, y:scrollView.contentSize.height - scrollView.frame.size.height), animated: false)
}
}
//FIXING SCROLL VIEW
//Delegate Methods
func scrollViewWillBeginDragging(_ scrollView: UIScrollView){
lastOffsetY = scrollView.contentOffset.y
}
//FIXING SCROLL VIEW
func scrollViewWillBeginDecelerating(_ scrollView: UIScrollView){
let hide = scrollView.contentOffset.y > self.lastOffsetY
self.navigationController?.setNavigationBarHidden(hide, animated: true)
}
To turn off the web view's scrolling:
webView.scrollView.isScrollEnabled = false
If the code you provided is only for turning off the scrollview, that code can largely be culled down to something like this:
import UIKit
import WebKit
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
//configure webView
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
webView.scrollView.isScrollEnabled = false
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
if let url = URL(string: "https://www.stackoverflow.com") {
webView.load(URLRequest(url: url))
}
}
}
I'm trying to display a pdf on ios via apples PDFKit library, and rather than use PDFDisplayMode.singlePageContinuous mode, I want to stop at page breaks so I'm trying to use PDFDisplayMode.singlePage.
https://developer.apple.com/documentation/pdfkit/pdfdisplaymode
However, this mode seems to only display one page of the pdf which is quite useless. I've tried adding swipe handlers to the page but they aren't working either.
I've found sample applications and altered their code to test the pdfdisplaymode but get the same problem e.g.
https://github.com/vipulshah2010/PDFKitDemo
How can I implement a one page at a time pdfviewer with pdfkit, that allows swiping between pages?!
A another simple way to do this is setting
pdfView.usePageViewController(true)
This adds the swiping between pages for you and no need to set up your own gestures. See example below:
override func viewDidLoad() {
super.viewDidLoad()
// Add PDFView to view controller.
let pdfView = PDFView(frame: self.view.bounds)
self.view.addSubview(pdfView)
// Configure PDFView to be one page at a time swiping horizontally
pdfView.autoScales = true
pdfView.displayMode = .singlePage
pdfView.displayDirection = .horizontal
pdfView.usePageViewController(true)
// load PDF
let webUrl: URL! = URL(string: url)
pdfView.document = PDFDocument(url: webUrl!)
}
Use the swipe gesture recognizer (UISwipeGestureRecognizer) to let the user swipe the PDF view screen (PDFView) to the left and right.
import UIKit
import PDFKit
class ViewController: UIViewController, PDFViewDelegate {
// MARK: - Variables
// MARK: - IBOutlet
#IBOutlet weak var pdfView: PDFView!
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
let filePath = "/Users/george/Library/Developer/CoreSimulator/Devices/B5C5791C-3916-4BCB-8EB6-5D3D61C08DC0/data/Containers/Data/Application/4B644584-0025-45A7-9D71-C8F8478E4620/Documents/my PDF.pdf"
pdfView.document = getDocument(path: filePath)
pdfView.backgroundColor = .lightGray
pdfView.autoScales = true
pdfView.displayMode = .singlePageContinuous
pdfView.usePageViewController(true, withViewOptions: nil)
createMenu()
thumbnail()
/* swipe gesture */
let leftSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondLeftSwipeGesture(_:)))
leftSwipeGesture.direction = [UISwipeGestureRecognizer.Direction.left]
self.view.addGestureRecognizer(leftSwipeGesture)
let rightSwipeGesture = UISwipeGestureRecognizer(target: self, action: #selector(respondRightSwipeGesture(_:)))
rightSwipeGesture.direction = [UISwipeGestureRecognizer.Direction.right]
pdfView.addGestureRecognizer(rightSwipeGesture)
}
#objc func respondLeftSwipeGesture(_ sender: UISwipeGestureRecognizer) {
if pdfView.document == nil { return }
pdfView.goToPreviousPage(self)
}
#objc func respondRightSwipeGesture(_ sender: UISwipeGestureRecognizer) {
if pdfView.document == nil { return }
pdfView.goToNextPage(self)
}
func getDocument(path: String) -> PDFDocument? {
let pdfURL = URL(fileURLWithPath: path)
let document = PDFDocument(url: pdfURL)
return document
}
}
You might simply set the displayMode to continuous and it might work:
pdfView.displayMode = .singlePageContinuous
I have a tap gesture recognizer hooked up to my image view. When the image is tapped it becomes full screen and when tapped again it is dismissed. The user has the ability to pinch to zoom the image, however when the image is held down and moved around by the user it shows the background view. I want to hide the background so the view can not be seen until the image is dismissed. I think the images I have provided will explain better than I can through words.
var newImageView: UIImageView!
#IBAction func imageTapped(_ sender: UITapGestureRecognizer) {
self.navigationController?.setNavigationBarHidden(true, animated: true)
let imageView = sender.view as! UIImageView
let scrollView = UIScrollView(frame: self.view.frame)
newImageView = UIImageView(image: imageView.image)
newImageView.frame = self.view.frame
newImageView.backgroundColor = .black
newImageView.contentMode = .scaleAspectFit
newImageView.isUserInteractionEnabled = true
let tap = UITapGestureRecognizer(target: self, action: #selector(dismissFullscreenImage))
scrollView.addGestureRecognizer(tap)
scrollView.delegate = self
scrollView.minimumZoomScale = 1.0
scrollView.maximumZoomScale = 3.0
scrollView.addSubview(newImageView)
self.view.addSubview(scrollView)
}
func viewForZooming(in scrollView: UIScrollView) -> UIView?
{
return newImageView;
}
func dismissFullscreenImage(_ sender: UITapGestureRecognizer) {
self.navigationController?.setNavigationBarHidden(false, animated: true)
sender.view?.removeFromSuperview()
}
You can simply hide an element with the backgroundElement.isHidden = true property. You can reset the background using backgroundElement.isHidden = false once the view has been dismissed.
Use following method of UIScrollView to check at what Scale it is zoomed.
func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat) {
print(scale)
if scale == 1.0 {
self.lblDesc.isHidden = false
self.btnDelete.isHidden = false
} else {
}
}
When scale is 1.0 it is normal minimumZoomScale.
Following is method called when you zoom. Use it to hide your elements.
func scrollViewDidZoom(_ scrollView: UIScrollView) {
self.lblDesc.isHidden = true
self.btnDelete.isHidden = true
}
Hope it helps you.
I created a UIViewController having a view with two UIWebViews. My structure looks like this (I also use auto layout with SnapKit):
class MyIntViewController: UIViewController, UIWebViewDelegate {
private var scrollView: UIScrollView!
private var contentView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.whiteColor()
setupView()
}
private func setupView() {
scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(self.view)
}
contentView = UIView()
contentView.backgroundColor = UIColor.greenColor()
scrollView.addSubview(contentView)
contentView.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(self.scrollView)
make.width.equalTo(self.view.bounds.width)
}
// first webView
let contentWebView1 = UIWebView()
contentWebView1.scalesPageToFit = false
contentWebView1.delegate = self
contentWebView1.scrollView.bounces = false
contentWebView1.scrollView.scrollEnabled = false
contentView.addSubview(contentWebView1)
contentWebView1.snp_makeConstraints { (make) -> Void in
make.top.equalTo(contentView.snp_top)
make.left.equalTo(self.view.snp_left)
make.right.equalTo(self.view.snp_right)
make.height.equalTo(1)
}
// second webView
let contentWebView2 = UIWebView()
contentWebView2.scalesPageToFit = false
contentWebView2.delegate = self
contentWebView2.scrollView.bounces = false
contentWebView2.scrollView.scrollEnabled = false
contentView.addSubview(contentWebView2)
contentWebView2.snp_makeConstraints { (make) -> Void in
make.top.equalTo(contentWebView1.snp_bottom)
make.left.equalTo(self.view.snp_left)
make.right.equalTo(self.view.snp_right)
make.height.equalTo(1)
make.bottom.equalTo(self.contentView.snp_bottom)
}
// load content for contentWebView1 and contentWebView2
let path: String = NSBundle.mainBundle().bundlePath
let baseURL: NSURL = NSURL.fileURLWithPath(path)!
let myFileHtml: String = "HTWML for contentWebView1""
let myFileHtmlPlusCss = MMCssHelper.appendCustomCSS(myFileHtml)
contentWebView1.loadHTMLString(myFileHtmlPlusCss, baseURL: baseURL)
let path: String = NSBundle.mainBundle().bundlePath
let baseURL: NSURL = NSURL.fileURLWithPath(path)!
let myFileHtml: String = "HTWML for contentWebView2""
let myFileHtmlPlusCss = MMCssHelper.appendCustomCSS(myFileHtml)
contentWebView2.loadHTMLString(myFileHtmlPlusCss, baseURL: baseURL)
}
// MARK: UIWebViewDelegate
func webViewDidFinishLoad(webView: UIWebView) {
let webViewContentHeight: CGFloat = webView.scrollView.contentSize.height
println("webViewDidFinishLoad webViewContentHeight: \(webViewContentHeight)")
webView.snp_updateConstraints { (make) -> Void in
make.height.equalTo(webViewContentHeight)
}
}
}
When I have only one UIWebView on the page everything works fine the content of the UIWebView is calculated correctly in webViewDidFinishLoad. The problem occurs with two UIViewViews as shown above. The console output is this:
webViewDidFinishLoad webViewContentHeight: 1.0
webViewDidFinishLoad webViewContentHeight: 17.0
You can see that one webViewContentHeight is calculated correct while the other seems to be not calculated at all.
How do I get the height of a UIWebView calculated correctly when there are more than one UIWebViews on the page?
I want to create the slide to unlock animation like it is there on the iPhone lock screen. I want the user to swipe right so that another view comes to the front. How should I make this? I have tried this, and here is my code:-
import UIKit
class PageViewController: UIViewController, UIScrollViewDelegate {
#IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
setUpScrollView()
}
func setUpScrollView () {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let aViewController = storyboard.instantiateViewControllerWithIdentifier("Hello") as! HelloViewController;
let bViewController = storyboard.instantiateViewControllerWithIdentifier("Home") as! HomeViewController;
let viewControllers = [bViewController, aViewController]
scrollView.pagingEnabled = true
scrollView.contentSize.height = 600
var contentSizeWidth = CGFloat(2) * self.view.frame.width
scrollView.contentSize.width = contentSizeWidth
scrollView.showsHorizontalScrollIndicator = false
scrollView.showsVerticalScrollIndicator = false
scrollView.scrollsToTop = false
scrollView.delegate = self
// add all views to scrollView
for (index, vc) in enumerate(viewControllers) {
var frame = self.view.frame
frame.origin.x = frame.width * CGFloat(index)
frame.origin.y = 0
vc.view.frame = frame
self.addChildViewController(vc)
self.scrollView.addSubview(vc.view)
vc.didMoveToParentViewController(self)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
The problem that I face is, that the view on the left is cropped somehow. To make you visualise this, the view with the slide to unlock label appears when the iOS simulator boots up. But when I swipe right, the scrollView works perfectly, just the second view is cropped (it is on the extreme left, occupying less than half of the screen that it should ideally fully occupy. Please help me out here. Thanks in advance.