How to center the popupview that contain dynamic height content ?? - ios

I am now implementation the pop up dialog for my iOS app according to this youtube video "https://www.youtube.com/watch?v=FgCIRMz_3dE".But the problem is I can't set my pop up view to fixed height because there is dynamic height label in my popup view which is inside my popup view controller.Can anyone tell me how to solve this solution?Thanks for your attention.
Here is my code to open popup view controller from parent view controller.
let PopUpVC = UIStoryboard(name:"Main", bundle:nil).instantiateViewController(withIdentifier: "FeedPopUpViewController") as! FeedPopUpViewController
self.addChildViewController(PopUpVC)
PopUpVC.view.frame = self.view.frame
self.view.addSubview(PopUpVC.view)
PopUpVC.didMove(toParentViewController: self)
Here is my code for FeedPopUpView Controller
import UIKit
class FeedPopUpViewController: UIViewController {
#IBOutlet weak var action_Label: UILabel!
#IBAction func dismiss(_ sender: Any) {
print("pop up is dismissed")
self.view.removeFromSuperview()
}
override func viewDidLoad() {
self.showAnimate()
super.viewDidLoad()
print("pop up is created")
}
override func viewWillAppear(_ animated: Bool) {
print("pop up is appeared")
}
func showAnimate(){
}
}

PopUpVC.view.centerXAnchor.constraint(equalTo: self.view.centerXAnchor).isActive = true
This should do the work :)

Related

Add a view controller as a subview in another view controller

I have already read this LINK , but not working for me. I want to show a viewController as a subview in another viewController.
Here is my code -
import UIKit
import CarbonKit
class ViewController: UIViewController, CarbonTabSwipeNavigationDelegate {
#IBOutlet weak var containerView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let items = ["All", "WOMEN", "MEN", "KIDS", "HOME", "CITY"]
let carbonTabSwipeNavigation = CarbonTabSwipeNavigation(items: items, delegate: self)
carbonTabSwipeNavigation.insert(intoRootViewController: self)
}
func carbonTabSwipeNavigation(_ carbonTabSwipeNavigation: CarbonTabSwipeNavigation, viewControllerAt index: UInt) -> UIViewController {
// let screen = self.storyboard?.instantiateViewController(withIdentifier: "demo") as! demo
// showSubViewContrller(subViewController: vc)
// return screen
let storyBoard = getStoryBoardByIndentifier(identifier: "All")
let vc = storyBoard.instantiateViewController(withIdentifier: "AllViewController") as! AllViewController
showSubViewContrller(subViewController: vc)
return vc
}
//Subview Controller
func showSubViewContrller(subViewController:UIViewController) {
self.addChildViewController(subViewController)
subViewController.view.frame = containerView.frame
self.containerView.addSubview(subViewController.view)
subViewController.didMove(toParentViewController: self)
}
func getStoryBoardByIndentifier(identifier:String)->UIStoryboard {
return UIStoryboard.init(name: identifier, bundle: nil)
}
}
I have a NavigationBar and a tapBar. Would like to show the viewController inside the view in a container.
But when the view loads it's coverUp/hide the tabBar.
How to solve this and show the viewController in my specified container.
Project Link - GitHub
Somehow i am able to fix your issue with below changes:
Replace this method carbonTabSwipeNavigation.insert(intoRootViewController: self) with carbonTabSwipeNavigation.insert(intoRootViewController: self, andTargetView: containerView) in viewDidLoad
Note : Give UITaBar bottom constraint to SuperView not SafeArea:
Add below code in ViewController:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tabbar.invalidateIntrinsicContentSize()
}
After doing this when you run you will UITabBar:

Transition with Hero not working

I'm using the Hero library to do a transition between view controllers.
First view controller:
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var people = [Person]()
override func viewDidLoad() {
super.viewDidLoad()
hero.isEnabled = true
hero.modalAnimationType = .push(direction: .right)
}
#IBAction func handleButton(){
let view = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! UIViewController
present(view, animated: true, completion: nil)
}
}
Second view controller:
class Second: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
hero.isEnabled = true
// Do any additional setup after loading the view.
}
#IBAction func handleBackButton(){
hero.modalAnimationType = .push(direction: .left)
hero.dismissViewController()
}
}
It presents the new view without any animation. When I dismiss the second controller, it will apply the correct animation. How do I present the second view with an animation?
Okay found the solution.
In the first case where I have:
#IBAction func handleButton() {
let view = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! UIViewController
present(view, animated: true, completion: nil)
}
I have to set the animation there on the view.
#IBAction func handleButton() {
let view = self.storyboard?.instantiateViewController(withIdentifier: "secondVC") as! UIViewController
view.hero.modalAnimationType = .push(direction: .right)
present(view, animated: true, completion: nil)
}
works
Set the modal animation type by setting the Hero extension heroModalAnimationType:
hero.heroModalAnimationType = .push(direction: .right)
Don't forget to disable the default animation for the transition using the Hero.shared object's methods :
func disableDefaultAnimationForNextTransition()
func setDefaultAnimationForNextTransition(_ animation: HeroDefaultAnimationType)

Finish editing UITextField on back button tap

I have 2 controllers inside NavigationController. First pushes the second one to the stack and user can interact with the text field there. Then (in one scenario) user will tap on back button to be taken to the previous screen. Assuming that loading of second one is 'heavy', so I will be keeping only one instance of it once it is needed.
Expected:
I would like to have keyboard hidden once back button is pressed.
Actual:
First responder keeps being restored when I go back to the second for the second time. How to prevent that? Resigning first responder also doesn't do the trick there...
Problem demo:
https://gitlab.com/matrejek/TestApp
Major code parts:
class FirstViewController: UIViewController {
var child: UIViewController = {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc = storyboard.instantiateViewController(withIdentifier: "child")
return vc
}()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func onButtonTap(_ sender: Any) {
self.navigationController?.pushViewController(child, animated: true)
}
}
class SecondViewController: UIViewController {
#IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
view.endEditing(true)
}
}
This does seem odd --- and it seems like your approach should work.
Apparently (based on quick testing), since you are not allowing the Navigation Controller to release the SecondVC, the text field is remaining "active."
If you add this to SecondViewController, it will prevent the keyboard from "auto re-showing" the next time you navigate to the controller - not sure it will be suitable for you, but it will do the job:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
DispatchQueue.main.async {
self.view.endEditing(true)
}
}
Edit: Jan 25 2020
Based on new comments, yes, this seems to be a bug.
My previous work-around answer worked -- sort of. The result was the keyboard popping up and then disappearing on subsequent pushes of child.
Following is a better work-around. We have SecondViewController conform to UITextFieldDelegate and add a BOOL class var / property that will prevent the text field from becoming first responder. Comments should be clear:
class FirstViewController: UIViewController {
var child: UIViewController = {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let vc = storyboard.instantiateViewController(withIdentifier: "child")
return vc
}()
#IBAction func onButtonTap(_ sender: Any) {
self.navigationController?.pushViewController(child, animated: true)
}
}
// conform to UITextFieldDelegate
class SecondViewController: UIViewController, UITextFieldDelegate {
#IBOutlet weak var textField: UITextField!
// bool var to prevent text field re-becoming first responder
// when VC is pushed a second time
var bResist: Bool = false
override func viewDidLoad() {
super.viewDidLoad()
// assign text field delegate
textField.delegate = self
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// view has appeared, so allow text field to become first responder
bResist = false
}
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
return !bResist
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// end editing on this view
view.endEditing(true)
// we want to resist becoming first responder on next push
bResist = true
}
}

Button action is not working on subView

In one of my iOS project, I have added a subview for Filter ViewController(subview) on my Feed ViewController(main view) programmatically.
There are few button on Filter ViewController to select price, city etc.
The outlets are connected but when I am trying to shoot button action, it is not working.
I have also enabled the isUserInteractionEnabled but still it is not working.
Acc. to me, this is something related to subview on a view !! but to resolve this. Can you suggest me how to shoot a button action of subview it happen ?
class FilterViewController: BaseUIViewController{
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
cityButton.isUserInteractionEnabled = true
}
#IBAction func selectCity(_ sender: Any)
{
print("selectCity action")
}
}
Add your FilterViewController as subview to your ViewController using the code below
filterViewController.willMove(toParentViewController: self)
self.view.addSubview(filterViewController.view)
self.addChildViewController(filterViewController)
filterViewController.didMove(toParentViewController: self)
#SandeepBhandari solution is still valid for similar issues.
These UIViewController extensions will be useful.
extension UIViewController {
func add(asChildViewController viewController: UIViewController, containerView: UIView) {
addChild(viewController)
containerView.addSubview(viewController.view)
viewController.view.frame = containerView.bounds
viewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
viewController.didMove(toParent: self)
}
func remove(asChildViewController viewController: UIViewController) {
viewController.willMove(toParent: nil)
viewController.view.removeFromSuperview()
viewController.removeFromParent()
}
}

Interactive view controller transition from view controller with status bar hidden

Here is my demo project.
I have two view controllers. The main one has the status bar hidden while the second one hasn't.
I created a custom driven transition animation to go from controller one to controller two.
When I'm on the child view controller (the orange one), I start the driven transition by panning from top to bottom. You can see that the status bar is coming back when dragging. And the UIButton "Hello" is moving as well.
I cancel the transition. Then I start it again and you can see the status bar is coming back as well but this time, my button isn't moving, it stays at the same location, as if the status bar was still hidden.
Any idea why it would behave like this once the transition has been cancelled at least once?
(I'm not even talking about the weird thing with the animation that is kind of doubled when cancelling (maybe a bug with the simulator as it doesn't do it on my iphone 6 9.1 and my iphone 5 8.4.)
Add: import Foundation
Then add an outlet:
class ViewController: UIViewController {
#IBOutlet weak var topConstraint: NSLayoutConstraint!
...
}
Then change the value to 0 when the view disappears and then to 20 when it will appear:
override func viewWillAppear(animated: Bool) {
topConstraint.constant = 20.0
}
override func viewWillDisappear(animated: Bool) {
topConstraint.constant = 0.0
}
Full code (make sure to remember to connect the constraint to the outlet):
import UIKit
import Foundation
class ViewController: UIViewController {
#IBOutlet weak var topConstraint: NSLayoutConstraint!
let controllerTransition = InteractiveControllerTransition(gestureType: .Pan)
let controllerTransitionDelegate = ViewController2Transition()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
controllerTransition.delegate = controllerTransitionDelegate
controllerTransition.edge = .Bottom
}
override func viewWillAppear(animated: Bool) {
topConstraint.constant = 20.0
}
override func viewWillDisappear(animated: Bool) {
topConstraint.constant = 0.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func unwindToViewController(sender: UIStoryboardSegue) { }
override func prefersStatusBarHidden() -> Bool {
return false
}
#IBAction func helloButtonAction(sender: UIButton) {
// let storyBoard = UIStoryboard(name: "Main", bundle: nil)
// let vc = storyBoard.instantiateViewControllerWithIdentifier("ViewController2") as! ViewController2
//
// vc.transitioningDelegate = controllerTransition
// controllerTransition.toViewController = vc
//
// self.presentViewController(vc, animated: true, completion: nil)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
// let nvc = storyBoard.instantiateViewControllerWithIdentifier("NavigationViewController2") as! UINavigationController
// let vc = nvc.topViewController as! ViewController2
let vc = storyBoard.instantiateViewControllerWithIdentifier("ViewController2") as! ViewController2
// nvc.transitioningDelegate = controllerTransition
vc.transitioningDelegate = controllerTransition
controllerTransition.toViewController = vc
// self.presentViewController(nvc, animated: true, completion: nil)
self.presentViewController(vc, animated: true, completion: nil)
}
}

Resources