I'm trying to use PDFKit with Swift in iOS 11. I have a PDFView and a PDFSelection that I would like to scroll to, zoom in to, and center within the overall view. I'm able to scroll to the PDFView's currentSelection with the function scrollSelectionToVisible(_ sender: Any?), but the selection always appear in the upper left of the screen.
How can I reposition the page to make the selection be at the center?
I know a PDFSelection has a bounds(for: PDFPage) function that returns a CGRect, in page space. But I don't know what to do with it beyond that.
What I currently see with after pdfView.scrollSelectionToVisible() (currentSelection in green upper left):
What I'd like to see (currentSelection in center of view):
This:
pdfView.currentSelection = selection
pdfView.scrollSelectionToVisible(nil)
And this:
pdfView.currentSelection = selection
let pdfPage = pdfView.document!.page(at: 0)!
let cgRect = pdfView.currentSelection!.bounds(for: pdfPage)
pdfView.go(to: cgRect, on: pdfPage)
are producing the same effect (the effect in the first image).
After you create the PDFviewer center the view like this
let pdfView = PDFView(frame: viewFA.view.bounds)
pdfView.center.y = viewFA.view.center.y - 100
Related
I took one custom view (SignatoryView) on pdf, When I click on Add button from Navigation bar, it will add that SignatoryView on PDF view and according to my choice I can move/drag that signatory view to any location.
Problem: When I am moving that signatory view on pdf, it is going outside edges of pdfView. (Left, right, bottom and top also)
It should not go beyond its boundaries, it should be movable only inside edges on PDF view.
How I can achieve this ? Here is the complete project code
You just need to get half of the width and half of the height of your signature and when setting the new center position of it add or subtract it from the origin x and/or y:
let minX = frame!.width/2
let minY = frame!.height/2
let maxX = pdfView.frame.width-minX
let maxY = pdfView.frame.height-minY
customView1?.center = CGPoint(
x: min(maxX, max(minX, touchLocation!.x)),
y: min(maxY ,max(minY, touchLocation!.y)))
Put simply, I want to get the bounds of this blue rectangle using Swift code:
The coordinates of this rectangle are visible in the Size inspector:
In an empty App project in Xcode, I've tried using view.safeAreaLayoutGuide.layoutFrame to get the CGRect, but this property seems to contain the bounds of the entire view, not the safe area. Specifically, it returns 0.0, 0.0, 896.0 and 414.0 for minX, minY, width and height respectively.
I've also tried to get the top, bottom, left and right properties of view.safeAreaInsets, but this returns 0 for each of them.
I've also tried to get the view.superview in case there was another view on top, but it returned nil.
All these values come from the iPhone 11. I'm using Xcode 12.
First, get the safe area insets. (Wait until they are known before you get them.) Okay, what are they inset from? The view controller's view. So simply apply those insets to the view controller's view's bounds and you have the rect of your rectangle (in view coordinates).
So, I believe this is the rectangle you were looking for?
How I did that:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
for v in self.view.subviews {
v.removeFromSuperview()
}
let v = UIView()
v.backgroundColor = .blue
self.view.addSubview(v)
// okay, ready? here we go ...
let r = self.view.bounds.inset(by:self.view.safeAreaInsets) // *
v.frame = r
}
Remember, that rect, r, is in view coordinates. If you need the rect in some other coordinate system, there are coordinate conversion methods you can call.
i have this structure. Scrollview -> UICollectionview + Label
This viewcontroller has array of items (BlockItem). On scrollViewDidScroll i change current test label (description)
func scrollViewDidScroll(_ scrollView:UIScrollView)
{
let midX:CGFloat = scrollView.bounds.midX
let midY:CGFloat = scrollView.bounds.midY
let point:CGPoint = CGPoint(x:midX, y:midY)
guard
let indexPath:IndexPath = collectionView.indexPathForItem(at:point)
else
{
return
}
let currentPage:Int = indexPath.item
if let found = items.first(where: {$0.id == String(block[currentPage])}) {
description.text = found.description
}
}
The main issue that i want my description label will be moving together when i move my collectionview cell and appear from the next cell. In other words, if I scroll to the left my description should move along with the cell, i.e. go to the left and appear on the right of the screen.
How can i do this? I know i could make a big collectionview but i need that only image part should be scrollable, not the entire block.
Here is what i want to achieve
Here is video example: scroll works only if i swipe on the image area, and doesn't work when i scroll down the page
https://drive.google.com/file/d/1kl1GYgXvK4bL3toTfOvpxF2WqS56pQO9/view?usp=sharing
You exactly said this:
"The main issue that I want my description label will be moving together when I move my collection view cell and appear from the next cell."
If you want your description label moving together, just include them into your collection cell. It's very clear from your point there
I don't understand why u need to separate it, but you want it to slide from new cell.
If you insisted that you want to archive the label, not in a scroll view, then use 2 label
One label for this cell and one label will come from scroll direction, u can archive this by creating manually. This is a simple code for a swipe left to scroll
UIView.animate(withDuration: 0.5) {
//insert your label animation
//current label moved with the scroll to left
//create a new label from the outer right of the current view, scroll it to the middle of your view
}
But it will be hard work for good animation or scroll support.
I want to get the distance of a button to the bottom of the screen in Swift 3.
I can see the correct value in the Storyboard when I look at the distance (alt key) but unfortunately I am not able to calculate it manually.
The value I am looking for is the same as the constant in the "Vertical Spacing to Bottom Layout" constraint for the button.
view.frame.maxY - randomButton.frame.maxY
gave me a value way too high.
view.frame.size.height - (button.frame.size.height + button.frame.origin.y)
I think its ok! Hope it helps
If your button is not a direct successor of the view controller's view (aka, the hierarchy is something like ViewController's View -> SomeOtherView->Button), you won't get the right math by simply using frames. You will have to translate the button's Y-position to the coordinate space of the window object or your view controller's main view.
Take a look at this question: Convert a UIView origin point to its Window coordinate system
let realOrigin = someView.convert(button.frame.origin, to: self.view)
Then apply the math suggested by Lucas Palaian.
let bottomSpace = view.frame.maxY - (button.frame.height + realOrigin.y)
Another work around, in case something really wild and wierd is going on there, is to drag and drop an outlet of the button's bottom constraint. (Select the constraint from the view hierarchy in Interface Builder, hold the control key and drag the constraint to your view controller.) Then in your code you can access the constant.
let bottomSpace = myButtonBottomConstraint.constant
Use this to have it from the bottom of the button to the bottom of the view (Tested):
view.frame.size.height - randomButton.frame.size.height/2 - randomButton.frame.origin.y
I needed to find the distance from the bottom edge of the UICollectionView
to the bottom edge of the screen.
This code works for me:
#IBOutlet weak var collectionView: UICollectionView!
private var bottomSpace = CGFloat()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
bottomSpace = UIScreen.main.bounds.height - collectionView.frame.maxY
}
This method is called several times it gives the correct result.
I've tried a lot of things but couldn't come up with a solution. Any words of thought can help me evaluate on this. I made a full view DrawBoard class which is inherited from a UITextView class.When the switch on the view controller is on the user can type and scroll, when it is off the user can draw on the Drawboard.
#IBAction func changeSwitch(sender: UISwitch) {
if sender.on{
drawBoard.setNeedsDisplay()
drawBoard.scrollEnabled = true
drawBoard.editable = true
drawBoard.selectable = true
drawBoard.switchBool = false
}else if !sender.on {
drawBoard.switchBool=true
let a:CGPoint = drawBoard.contentOffset
drawBoard.scrollEnabled = false
drawBoard.setContentOffset(a, animated: false)
drawBoard.editable = false
drawBoard.selectable=false
}
}
It updates the scrolling but scrollEnabled= false just saves the text that is in the first page range of the textview so that it scrolls to the top automatically and disable the scrolling there.Then when I do the setContentOffset the drawable view of the background is visible and it draws on the right place of the textview. However the text that should be on top of it is not visible. This only happens when the switch button is set to off while I am out of the first page's range.How do I also make the text at that range visible?
Sorry if it's a really easy question I'm new to programming and got stuck for a considerable amount of time for this.Thank you.
You have to update the content size of the UIScrollView.
Like this:
scrollView.contentSize = CGSize(width: 100, height: 100)
"Content Size" determines the size of scrollable content, if it's not large enough to cover new views, you won't be able to see it in your scroll view.