I am trying to make a drawing app and I want to add the activity view controller. It works on the iPhone, but it will not show the entire view controller on the iPad. I have tried many different approaches based off what I have read, but the result is the same. Any help is appreciate.
Code:
#IBAction func actionsTapped(_ sender: Any) {
// Setting description
let message = "Actions for your drawing"
// Get the image to save
let image = getImage()
let activityViewController : UIActivityViewController = UIActivityViewController(activityItems: [message, image], applicationActivities: nil)
// Ipad popup
activityViewController.popoverPresentationController?.sourceView = (self.view)
// Remove Ipad arrow
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
// Pre-configuring activity items
activityViewController.activityItemsConfiguration = [
UIActivity.ActivityType.message,
UIActivity.ActivityType.print,
UIActivity.ActivityType.saveToCameraRoll,
UIActivity.ActivityType.airDrop
] as? UIActivityItemsConfigurationReading
// Exclude
activityViewController.excludedActivityTypes = [
UIActivity.ActivityType.postToWeibo,
UIActivity.ActivityType.addToReadingList,
UIActivity.ActivityType.postToFlickr,
UIActivity.ActivityType.postToVimeo,
UIActivity.ActivityType.postToTencentWeibo,
UIActivity.ActivityType.postToFacebook
]
activityViewController.isModalInPresentation = true
self.present(activityViewController, animated: true, completion: nil)
}
As someone pointed out, which I tried changing the height and width in the sourceRect does not work. See below where I changed
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 0, height: 0)
to
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: 150, y: 150, width: 500, height: 500)
My initial thought was that x and y would change the position of the popup and height and width change the size, but it seems that it's the reverse in sourceRect.
It sounds like you're misunderstanding what the sourceRect is. It has nothing to do, in and of itself, with the size of the activity view controller. It determines where the arrow points to.
The activity view controller always has its own full size. I suspect that what's going wrong here is due to this line:
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection.down
That forces the whole activity view controller to appear above the source rect (i.e. more toward the top of the screen) — but there isn't room. If you just cut that line, the activity view controller may be able to appear where there is room.
Related
Navigation bar overlaps the image after user back from segue.
When the view first loaded it looks ok but after performing the segue and come back it looks like this.
here is the code for that image
let logoContainer = UIView(frame: CGRect(x: 0, y: 0, width: 200, height: 67))
let imageView = UIImageView(frame: CGRect(x: 0, y: -30, width: 200, height: 67))
imageView.contentMode = .scaleAspectFit
let image = UIImage(named: "navbarlogo")
imageView.image = image
logoContainer.addSubview(imageView)
navigationItem.titleView = logoContainer
Honestly, your problem is the fact you are creating an overlap of the ImageView by specifying a -30 y coordinate. It's higher in the z-order (compared to your navigation bar) in one case but lower in the z-order in the segue scenario.
I suspect if you use "Debug View Hierarchy" in XCode in both scenarios, you would be able to see this is what is happening.
I would change your approach as to how the logo container is being laid out
Here's a GIF showing the issue:
When presenting a UIImagePickerController like this:
self.present(imagePicker, animated: true, completion: nil)
the status bar disappears before the image picker is full screen.
The issue I have with this is that as the status bar disappears in a cloud of smoke, the navigation bar jumps up occupying the void left by the status bar. When UIImagePickerController is dismissed, the status bar shows up in its rightful place.
I'm currently not customizing the status bar in any way, all default.
Is there a way to prevent UIStatusBar from disappearing, at the very least until UIImagePickerController animation is complete?
If you want your status bar to stay at the top of your screen, you should create a custom window and apply animations manually. This may help:
var newWindow = UIWindow()
let newController = viewControllerToPresent()
var animationDuration = 0.4 // or whatever you want.
// setting newController as root of new window.
self.window.rootViewController = newController
self.window.windowLevel = UIWindowLevelStatusBar
self.window.backgroundColor = .clear
self.window.frame = CGRect(x: 0, y: UIScreen.main.bounds.height, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
self.window.isHidden = false
UIView.animate(withDuration: animationDuration) {
self.window.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
}
let obj = MainStoryboard().instantiateViewController(withIdentifier: "SomeVC") as! SomeVC
obj.delegate = self
obj.modalPresentationStyle = .popover
obj.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
self.present(obj, animated: true, completion: nil)
On setting up breakpoints, debugger goes good till last line. After that, it directly goes to AppDelegate class first line.
I have set exception break point properly. Where I might be making a mistake? Is it related to sourceView for popoverPresentationController? I am not sure.
What I want to do is set up the popoverPresentationController in center. Any help?
EDIT:
I added the sourceView to the code like following & now it's working:
obj.popoverPresentationController?.sourceView = self.view
obj.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 1, height: 1)
However, it's not in the center of the screen. Putting screen shot for reference. How do I make it to the center and remove the direction arrow?
After doing the following code changes I was able to make it work.
let obj = MainStoryboard().instantiateViewController(withIdentifier: "SomeVC") as! SomeVC
obj.delegate = self
obj.modalPresentationStyle = .popover
obj.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
obj.popoverPresentationController?.sourceView = self.view
obj.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 1, height: 1)
self.present(obj, animated: true, completion: nil)
Thank You all for your efforts.
You have to use sourceView in conjunction with sourceRect to provide anchor point for pop over, like following:
obj.popoverPresentationController?.sourceView = self.view
obj.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 1, height: 1)
Also, If you don't want the anchor point arrow to be there, then use:
obj.popoverPresentationController?.permittedArrowDirections = .init(rawValue: 0)
It will make your pop over appear in center with no arrow/anchor point.
Try this:
let obj = MainStoryboard().instantiateViewController(withIdentifier: "SomeVC") as! SomeVC
obj.delegate = self
obj.modalPresentationStyle = .overCurrentContext
self.navigationController?.present(obj, animated: false, completion: {
})
I have this class:
extension UIViewController {
func waiting() -> UIView{
let strLabel = UILabel(frame: CGRect(x: 50, y: 0, width: 200, height: 50))
strLabel.text = "Aguarde..."
strLabel.textColor = UIColor.whiteColor()
let messageFrame = UIView(frame: CGRect(x: view.frame.midX - 90, y: view.frame.midY - 25 , width: 180, height: 50))
messageFrame.layer.cornerRadius = 15
messageFrame.backgroundColor = UIColor(white: 0, alpha: 0.40)
let activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.White)
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.startAnimating()
messageFrame.addSubview(activityIndicator)
messageFrame.addSubview(strLabel)
view.addSubview(messageFrame)
return messageFrame
}
}
When I need use this class I use:
class MyController: UIViewController{
....
func x(){
let messageFrame = waiting()
//my code
messageFrame.removeFromSuperview()
}
}
The problem is when the frame is showed if I touch anywhere on my app this frame is hidden. I need that when this frame is showed other options staying disabled, when I finish the frame, the options of app is enabled again. How can I do it?
Change the view that you are returning a bit:
Make a "container" view that has the same frame as the view controller's view. Give this view a "clear" background.
Make a "background" view, same size as the "container" view and add it to the container. Give this view a black background and an alpha of, say, 0.4.
Now put the view that you are currently building in your "waiting" method, and add it to the "container" view (NOT to the background view, this should be a sibling of the background view, otherwise your alert will also be transparent).
Make sure all user interaction is disabled on your views (might only need it disabled on the "container" view).
This gives you a container view that covers the entire screen, and it has 2 children: a transparent background of the same size, and your current "waiting" alert thing.
Now if you add the "container" view to your view controller's view, the user can only touch on the container view which does nothing.
(Keep in mind that this doesn't handle screen rotation...you will have to do that yourself if needed.)
When you display a UIActionSheet on the iPad, it appears as a centered UIPopover with no arrow.
I have a UIDocumentInteractionController, and when I call presentOpenInMenuFromRect:inView:animated:, I am looking for the same behavior with the popover that appears there. Anyway to do that? I know you can have no arrow on a popover by setting the PermittedArrowDirections to 0, but that doesn't seem to be an option here.
You can use UIActivityController instead
let url = #Your File URL#
var activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil)
activityViewController.popoverPresentationController?.permittedArrowDirections = UIPopoverArrowDirection(rawValue: 0)
activityViewController.popoverPresentationController?.sourceView = view
activityViewController.popoverPresentationController?.sourceRect = CGRect(x: view.frame.midX, y: view.frame.midY,
width: 0, height: 0)