Custom popup over UITableViewController is swipe-able - how to prevent - Swift - ios

I am trying to make a custom pop up over a UITableViewController that is embedded in a UINavigationController but I am experiencing two problems:
The opacity that i determined by designating an alpha value to the background colour of the UIViewcontroller for the pop up appears not to function.
The UIViewcontroller for the popup is swipe-able. If I make a left to right gesture on the screen I am able to push off the pop up. How do I prevent it from behaving like this? I am trying to show a file upload progress so it is important that the pop up is not able to be swiped away.
Please see screen shot below.
func showProgrssBarPopUp(){
let popUp = self.storyboard?.instantiateViewController(withIdentifier: "uploadPopUp") as! ProgressBarPopUpViewController
self.navigationController?.pushViewController(popUp, animated: true)
}
The lower viewcontroller content is not viewable, even though alpha value of overlaying popup viewcontroller is set to 0.5:
The entire viewcontroller for popup is swipe-able:

You can set alpha of background
self.view.backgroundColor = UIColor.white.withAlphaComponent(0.2)
You can Present ProgressBar View with modalPresentationStyle as overCurrentContext
let popUp = self.storyboard?.instantiateViewController(withIdentifier: "uploadPopUp") as! ProgressBarPopUpViewController
popUp.modalPresentationStyle = .overCurrentContext
self.present(popUp, animated: true, completion: nil)

Just override view controller's appear/dismiss method
class PopUpController: UIViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if animated {
view.backgroundColor = .clear
UIView.animate(withDuration: animationTime) {
self.view.layer.backgroundColor = UIColor.black.withAlphaComponent(0.75).cgColor
}
}
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
if flag {
UIView.animate(withDuration: animationTime, animations: {
self.view.layer.backgroundColor = UIColor.clear.cgColor
}, completion: { (bool) in
super.dismiss(animated: false, completion: completion)
})
} else {
super.dismiss(animated: flag, completion: completion)
}
}
}
Use
let popUp = PopUpController()
popUp.modalPresentationStyle = .overCurrentContext
self.present(popUp, animated: true, completion: nil)

Related

Pause animation when modal view controller is presented

I have two animation which play on my home screen view controller. They are both animations from LottieFiles. One is an alpha colored changing background and the other is an infinite loop with different colors. When a new modal view over current context is selected I want to pause both animations and start them up again once the modal view is dismissed.
I have tried calling the animationView.pause method however they still continue to play in the background. I would like to pause them for better energy efficiency.
class HomeScreen: UIViewController{
let animationView = AnimationView()
let animationTwo = AnimationView()
func showSupport() {
let modalViewController = SupportViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: true, completion: nil)
}
func showSInfo() {
let modalViewController = InfoViewController()
modalViewController.modalPresentationStyle = .overCurrentContext
present(modalViewController, animated: true, completion: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
animationView.play(fromProgress: 0,
toProgress: 1,
loopMode: LottieLoopMode.loop,
completion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
animationTwo.play(fromProgress: 0,
toProgress: 1,
loopMode: LottieLoopMode.loop,
completion: { (finished) in
if finished {
print("Animation Complete")
} else {
print("Animation cancelled")
}
})
}
override func viewDidLoad() {
let animation = Animation.named("bg12")
animationView.animation = animation
animationView.contentMode = .scaleAspectFill
view.addSubview(animationView)
let animationViewTwo = Animation.named("infi2")
animationTwo.animation = animationViewTwo
animationTwo.contentMode = .scaleAspectFit
animationTwo.alpha = 0.7
view.addSubview(animationTwo)
}
}
class SupportViewController: UIViewController {
let homeVC = HomeScreen()
override func viewDidLoad() {
homeVC.animationView.pause()
homeVC.animationTwo.pause()
super.viewDidload()
}
}
Can't you put the pausing to the completion handler of the present, like:
present(modalViewController, animated: true) {
self.animationView.pause()
}

PresentViewController does not work: view is not in the window hierarchy in TabBarController

I have created a CustomAlertView.
protocol CustomAlertViewControllerDelegate{
func retryToFetchData()
}
class CustomAlertViewController: UIViewController {
#IBOutlet weak var alertView: UIView!
var delegate: CustomAlertViewControllerDelegate!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.alertView.alpha = 0
self.alertView.frame.origin.y = self.alertView.frame.origin.y + 50
UIView.animate(withDuration: 0.4) {
self.alertView.alpha = 1.0
self.alertView.frame.origin.y = self.alertView.frame.origin.y - 50
}
}
#IBAction func retryButton(_ sender: UIButton) {
delegate?.retryToFetchData()
self.dismiss(animated: true, completion: nil)
}
}
I have created a static function to show that view. The view is just a UIViewController that will have a child View which will act as a popUP, with a transparent background.
func showErrorBox(view: UIViewController, message: String, delegate: CustomAlertViewControllerDelegate){
let customAlert = view.storyboard?.instantiateViewController(withIdentifier: "customAlertViewController") as! CustomAlertViewController
customAlert.providesPresentationContextTransitionStyle = true
customAlert.definesPresentationContext = true
customAlert.modalPresentationStyle = UIModalPresentationStyle.overCurrentContext
customAlert.modalTransitionStyle = UIModalTransitionStyle.crossDissolve
customAlert.delegate = delegate
view.present(customAlert, animated: true, completion: nil)
}
Now, I am calling this VC anywhere I needed to show a popUP with showErrorBox(view: self, message: message, delegate: self) now my issue is I need to show this popup in a ViewController which is inside of a TabBarController, when I change the view between the UITabBar, and try pressing the reload button, the app throws an error,
presentViewController does not work: view is not in the window
hierarchy
Edit:
There is a Retry button on the ErrorBox(popUp). The error happens only when the error box is loaded and I changed the view to different tab and then hit the reload button. In normal scenario like, hitting the reload button when I am in the same page works fine.
I am not sure of issue, but it has something to do with when I change the view between tabs when the error box is present.
try self.present(customAlert, animated: true, completion: nil) instead view.present(customAlert, animated: true, completion: nil). If I understand your problem, should works
Solution,
The problem was, when I changed the views in TabController the reference to the customAlertView was removed from the window hierarchy. So, As soon as I leave the TabView which was loading the CustomAlertView need to be removed.
So to solve the issue, I have added following code in CustomAlertViewController
override func viewWillDisappear(_ animated: Bool) {
super. viewWillDisappear(animated)
self.dismiss(animated: true, completion: nil)
}
Try to getting the TopMost ViewController and presenting CustomAlertViewController from it instead of "self".
refer this link to :
GetTopMostViewController

Transparent view background turns black

I want to make the view of a view controller semi-transparent. For that I have set the background color like this in the viewDidLoad method.
view.backgroundColor = UIColor(white: 0, alpha: 0.5)
When the view controller is presented, the background appears as I need it and then it turns black right away.
Why is this happening?
This is the code for showing the PopupViewController:
#IBAction func didTapShowButton(_ sender: UIButton) {
let navController = UINavigationController(rootViewController: PopupViewController())
present(navController, animated: true, completion: nil)
}
I uploaded a demo project here as well.
You may add the flag overCurrentContext (or custom), so your present might be something like:
#IBAction func didTapShowButton(_ sender: UIButton) {
let navController = UINavigationController(rootViewController: PopupViewController())
navController.modalPresentationStyle = .overCurrentContext
present(navController, animated: true, completion: nil)
}

Add Transition effect without using navigationController- IOS

I want to add a transition effect to my app from a ViewController to another.
I want use the transition effect that the Navigation Controller usually add (sliding effect) but without using the Navigation Controller.
What is the simplest and easiest way to achieve that? (I'm using swift 3)
EDIT:
My Code Now:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func GoToMenu(_ sender: UIButton) {
//TRANSITION EFFECT
let nextVCID="010101"
guard let presentedController = self.storyboard?.instantiateViewController(withIdentifier: nextVCID) else { return }
presentedController.modalTransitionStyle = UIModalTransitionStyle.coverVertical
self.present(presentedController, animated: true, completion: nil)
}
}
You can present it modaly and set modal transition style you like.
guard let presentedController = self.storyboard?.instantiateViewController(withIdentifier: nextVCID) else { return }
presentedController.modalTransitionStyle = UIModalTransitionStyle.coverVertical
self.present(presentedController, animated: true, completion: nil)

Swift: Not able to dismiss modally presented LoginViewController

As SplitViewController loads, I am showing a Login Screen. On successful login, I need to go back to parent view controller. Somehow dismissal is not working for me. Here is the code:
ParentViewController:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if !appDelegate.loggedIn {
self.performSegueWithIdentifier("loginScreen", sender: self)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
Child ViewController:
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
appDelegate.loggedIn = true
self.dismissViewControllerAnimated(true, completion: nil)
The dismissal part never works. It just hangs on Login Screen.
Try one of the following:
1) remove self. keep only dismissViewControllerAnimated(true, completion: nil)
or remove self. and make it:
2) presentingViewController.dismissViewControllerAnimated(true, completion: nil)
or remove self. and try:
3) presentedViewController.dismissViewControllerAnimated(true, completion: nil)
Try this in your parent view controller:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
if !appDelegate.loggedIn {
let loginVC: UIViewController = self.storyboard!.instantiateViewControllerWithIdentifier("LoginViewController") as UIViewController
loginVC = UIModalTransitionStyle.CoverVertical
self.parentViewController?.presentViewController(loginVC, animated: true, completion: nil)
}
}
You're instantiating the new view controller by its own name rather than by the segue name.

Resources