I want to control the zoom level of pdf file. By default when it launches it doesn't fits the screen. Even manually (pinch zoom) zoom-in and zoom-out doesn't make it fit the page. I have set the autoScales for true.
Also tried playing with below variable but it didn't help
open var scaleFactorForSizeToFit: CGFloat { get }
Below is my code for the same
pdfView = PDFView(frame: view.bounds)
pdfdocument = PDFDocument(url: filePathUrl!)
pdfView.document = pdfdocument
pdfView.displayMode = PDFDisplayMode.singlePageContinuous
pdfView.autoScales = true
view.addSubview(pdfView)
Some control were user can control zoom level.
Can it be achieved using gesture recognizer?
Any Hint in right direction would be highly appreciated
You can use scaleFactor to adjust zooming using UISlider.
pdfView.scaleFactor = 0.5
Related
I'm using PDFView in order to let users fill PDF Forms. Whenever the user touch a field in the document, the cursor appears in the field and he can enter text. That's ok. But the problem is that the PDFView scrolls the document chaotically and the fields gets out of the view. Sometimes, even if the user scrolls the doc to the correct position, it scrolls out again whenever he uses the keyboard. It's really weird.
Here is my very simple code where I create the PDFView and set the doc:
let pdfView = PDFView(frame: self.view.bounds)
pdfView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
self.view.addSubview(pdfView)
// Fit content in PDFView.
pdfView.autoScales = true
pdfView.document = PDFDocument(url: fileURL)
self.pdfView = pdfView
Why does it happen. Can it be a fault in the pdf form format?
I am working in pdf editing project, in that I have to add signature in pdfview and after that need to resize and delete that signature. Now for this I am adding one scrollview with UIView on top of pdfview with transparent alpha and add image view to that UIView but I had an issue with zooming. How can I get how much zoom pdfview zooming when user pinch zoom. I want to find pdfview's zoom contentInset, so I can set my own scrollview's contentInset.
try to get pdfview scale factor when pdfview zoom with :
#objc func pdfViewScaleChange(notification:NSNotification){
print(self.pdfView.scaleFactor)
}
But Still I can't find How can I zoom and set my UIScrollview as pdfview zoom.
Your PDFView has a property called scaleFactorForSizeToFit, which is the scale factor that PDFKits autoScales would use for scaling the current document and layout.
What this means is that if you use the autoScales property when you set your pdf you will be able to calculate an amount to scale your UIScrollview by.
Here is an example of what I mean for some more context:
//wherever you set your pdf (doesn't have to be viewDidAppear)
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
pdfView.document = PDFDocument(data: data)
pdfView.autoScales = true
//Add the observer here to detect when your pdf is zoomed in or out
NotificationCenter.default.addObserver(self,
selector: #selector(pdfPageWasZoomed),
name: Notification.Name.PDFViewPageChanged,
object: nil)
}
//wherever you want to zoom use this
func getScrollViewScaleFactor() -> CGFloat {
return (pdfView.scaleFactor / pdfView.scaleFactorForSizeToFit)
}
//Objc function which is called everytime the zoom changes
#objc private func pdfPageWasZoomed() {
//Here use the function getScrollViewScaleFactor() to get a factor to scale in or out by
}
Something like this should solve your problem.
I am attempting to display a pdf document on a pdfView and would like it to scale such that I can see the full content view within the bounds of the device. However, I am unable to scale it small enough to do so. I have attempted some solutions on SO but still doesn't work.
My implementation so far:
let pdfView: PDFView = {
let v = PDFView()
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
override func viewDidLoad() {
super.viewDidLoad()
//addSubview and autolayout constraints to superview
if let url = Bundle.main.url(forResource: "documentName", withExtension: "pdf"), let document = PDFDocument(url: url) {
pdfView.document = document
guard let page = document.page(at: 0) else {return}
let pageSize = page.bounds(for: .cropBox)
let screenSize = UIScreen.main.bounds
let scale = screenSize.width / pageSize.width
pdfView.scaleFactor = scale
}
}
Note that these are things I have tried but doesn't work:
pdfView.autoScales = true
pdfView.displayMode = .singlePage
pdfView.minScaleFactor = // to a very small value
I also attempted to iterate the scaleFactor manually by setting 0.01 but realised that the view will not scale lower than 0.25. Is there a way for me to scale even lower? The order of scaling in my appliction is in the order of 0.1-0.2. Thanks.
If I remember correctly, PDFKit seems a bit buggy concerning autoScales. PDFView must be set up in the correct order. You can try:
Add PDFView in subview in viewDidLoad
Set up other PDFView properties, like displayMode, displayDirection, and set up constraint for PDFView in viewWillAppear
Finally, set pdfView.document = document then pdfView.autoScales = true
This setup order work for me.
I don't have answer for your next question. But it could also be related to the setup order. Let me know if it works for you.
Hope this helps.
I have a custom UITableViewCell that displays either an image or a video. If there's a video, it initially downloads and displays the thumbnail from that video while the video is loading and preparing to play.
It all works, the problem is that I get the ratio of the thumbnail, store it in the database and when I download the thumbnail, it makes the height based on that ratio. It works great for images. But the issue is that the AVPlayerLayer frame doesn't cover the entire thumbnail and it looks like this:
Here's how I do it:
func updateView() {
if let videoUrlString = post?.videoUrl, let videoUrl = URL(string: videoUrlString) {
volumeView.isHidden = false
player = AVPlayer(url: videoUrl)
playerLayer = AVPlayerLayer(player: player)
playerLayer!.frame = postImageView.frame // thumbnail image
playerLayer!.videoGravity = AVLayerVideoGravity.resizeAspectFill
contentView.layer.addSublayer(playerLayer!)
self.volumeView.layer.zPosition = 1
layoutIfNeeded()
player?.play()
player?.isMuted = videoIsMuted
}
if let ratio = post?.ratio {
photoHeightConstraint.constant = UIScreen.main.bounds.width / ratio
layoutIfNeeded()
}
}
I'm not doing something right apparently or I'm missing something based on my final result. Any clue?
UPDATE:
I notice that if you scroll the cells slowly, the video is being displayed according to the size of the thumbnail. But if you scroll fast, it mismatches the frame. I assume it has something to do with reusability or it simply cannot catch up with the frame? Here's my code for prepareForReuse() method:
override func prepareForReuse() {
super.prepareForReuse()
profileImageView.image = UIImage(named: "placeholder")
postImageView.image = UIImage(named: "profile_placeholder")
volumeView.isHidden = true
if let p = player, let pLayer = playerLayer {
p.pause()
pLayer.removeFromSuperlayer()
}
}
The solution turned out to be rather simple. Basically each post contains either post or a video, but either way, it always contains an image. I also set the ratio of that image (the width devided by the height). So, all I had to do is set the player's width to the screen width devided by the ratio and it gives your the proper frame.
playerLayer.frame.size.height = UIScreen.main.bounds.width / postRatio
Quick question, does anybody know how i can get rid of the black bars at the top and bottom of my video? I just started using AVPlayer and i'm just removing codes here and there in attempt to remove the black layers. Appreciate those who can help me, Thanks!
UIViewController
import UIKit
import AVKit
import AVFoundation
private var looper: AVPlayerLooper?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let path = Bundle.main.path(forResource: "Innie-Kiss", ofType:"mp4")
let player = AVQueuePlayer(url: URL(fileURLWithPath: path!))
looper = AVPlayerLooper(player: player, templateItem: AVPlayerItem(asset: AVAsset(url: URL(fileURLWithPath: path!))))
let controller = AVPlayerViewController()
controller.player = player
let screenSize = UIScreen.main.bounds.size
let videoFrame = CGRect(x: 0, y: 200, width: screenSize.width, height: (screenSize.height - 130) / 2)
controller.view.frame = videoFrame
self.view.addSubview(controller.view)
player.play()
}
}
You need to set the videoGravity of the AVLayer. The default value is .resizeAspect which will preserve the aspect ratio with black bars on top/bottom or left/right. What you want is .resize
The AVLayer you need to set the videoGravity on is the layer property of your AVPlayer.
see this for more info: https://developer.apple.com/documentation/avfoundation/avplayerlayer/1388915-videogravity
#import AVKit
var playerController = AVPlayerViewController()
playerController.videoGravity = .resizeAspect
/*playerController.videoGravity = .resizeAspectFill*/
playerController.view.backgroundColor = UIColor.white //set color as per super or custom view.
Note: If you set the videoGravity of the AVPlayerViewController. The default value is .resizeAspect then it is possible to visibility of black color(default) in background if you wants this color would similar to your super view's color then you must set superview's or custom view's color to your playercontroller's view background color.
*Example:Suppose super view's or custom view's background color is white then playerController view's background color must be set as playerController.view.backgroundColor = UIColor.white *
Note :playerController's backgroundColor should not be set as UIColor.white ,always. It must me set as super view' background color.
If you set playerController.videoGravity = .resizeAspectFill then it will fill the player content to super view or custom view, here also no black color would be shown. So choose either .resizeAspect or resizeAspectFill as per your requirements.