I want to make the screen like the following.
In source class, I write this code and push to side menu controller.
let vc = self.storyboard?.instantiateViewController(withIdentifier: "SidemenuController")as! SidemenuController
self.navigationController?.pushViewController(vc, animated: false)
I write the following code in destination controller view did load method but just color opacity is decreased data is not visible.
override func viewDidLoad() {
self.view.backgroundColor = self.hexStringToUIColor(hex: "BE8790").withAlphaComponent(0.4)
}
Instead of using .withAlphaComponent(0.4)
Try this Adjust the number as needed
self.view.alpha = 0.5
You show present your SideViewController. Maybe custom how it shows
let sideVC = // Your init
sideVC.modalPresentationStyle = .fullScreen
present(sideVC, animated: true, completion: nil)
In your SideViewController,
override func viewDidLoad() {
super.viewDidLoad()
view.alpha = 0.5
view.backgroundColor = // Your color
tableView.backgroundColor = .clear
}
Related
I would like to use blur background for my view controller but as soon as the view is loaded, the whole thing turns into gray.
I present the view controller by performing a segue from another view, and in the viewDidLoad() method of the view controller, I implement the blur effect as given below
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
let blurBgView = UIVisualEffectView(effect: UIBlurEffect(style: .extraLight))
blurBgView.translatesAutoresizingMaskIntoConstraints = false
view.insertSubview(blurBgView, at: 0)
NSLayoutConstraint.activate([
blurBgView.heightAnchor.constraint(equalTo: view.heightAnchor),
blurBgView.widthAnchor.constraint(equalTo: view.widthAnchor),
])
}
This is how it looks like
How can I implement a blur background for my view controller?
I use XCode 9.3, Swift 4.1
Thanks
Present your view controller and set its modalPresentationStyle from your initial vc:
let newController = NewViewController()
newController.modalPresentationStyle = .overCurrentContext
present(newController, animated: true, completion: nil)
Or, if you are preparing for the segue:
let newController: NewViewController = segue.destination as! NewViewController
newController.modalPresentationStyle = .overCurrentContext
And in the NewViewController class in viewDidLoad() add your code.
Now I have two Controller, one is FirstViewController,and one is SecondViewController.
In FirstViewController
var secondViewController: SecondViewController!
let textView: UITextView = {
let textView = UITextView()
//textView.font = UIFont.systemFont(ofSize: 20)
textView.isEditable = true
textView.keyboardDismissMode = .interactive
textView.allowsEditingTextAttributes = true
return textView
}()
override func viewDidLoad() {
super.viewDidLoad()
secondViewController = SecondViewController()
secondViewController.firstViewController = self
setUpLayout()
addKeyboardObserver()
// Do any additional setup after loading the view, typically from a nib.
}
then I add a button to show secondViewController's view as a custom keyboard
#objc func showSecondView() {
textView.resignFirstResponder()
textView.inputView = secondViewController.view
textView.becomeFirstResponder()
}
then in SecondViewController, as the pic show, now I wanna add a navigation bar in SecondViewController, how?(I can do it using storyboard, but I can't do it using code).
and I wanna show the ThirdViewController when the tableView in SecondViewController(the red area) is selected, and the ThirdViewController's view will show in the red area, not the whole screen,(just like the storyboard's "show" connection) how can I do that?
You have to take navigation controller from root view controller so you can hide and show whenever you want, Another thing you can do is, take navigation view controller for particular view controller. But you can not navigate (pushing) any navigation view controller. You can only present it. Check my code below
import UIKit
class ViewControllerWithoutNavigation: UIViewController { // This is without navigation
override func viewDidLoad() {
super.viewDidLoad()
}
func gotoNextViewController(){
let nvc = UINavigationController(rootViewController: ViewControllerWithNavigation())
let transition = CATransition()
transition.duration = 0.25
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
self.view.window!.layer.add(transition, forKey: kCATransition)
//transition is to show like pushing, Without it it will look like presenting from bottom
self.present(nvc, animated: false, completion: nil)
}
}
class ViewControllerWithNavigation: UIViewController { // This is with navigation
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .white
}
}
Adding NavigationController
Select the viewcontroller in storyboard and goto Editor -> Embedd In -> Navigation Controller
To show another view controller
*Add storyboard id to Navigation Controller
*Then add this code in action
let storyBoard = UIStoryboard(name: "storyboard_name", bundle: nil)
let destination = storyBoard.instantiateViewController(withIdentifier: "storyboard_id")
self.navigationController?.pushViewController(destination, animated: true)
There is such code, if user logged on - ViewController changes :
func ifLogged() {
let preferences = UserDefaults.standard
let token = "token"
if preferences.object(forKey: token) == nil {
// Doesn't exist and stop at the same viewController
} else {
let newViewController = GeneralChooser()
self.navigationController?.pushViewController(newViewController, animated: false)
// push new generalChooser when logged
}
}
But in this case I do not see view elements, just background color from ViewHelper class
class GeneralChooser: UIViewController{
override func viewDidLoad() {
super.viewDidLoad()
ViewHelper.BackGroundColor(view: self.view)
There is BackgroundColor func below
class func BackGroundColor(view: UIView){
let startColor = UIColor(red:0.15, green:0.50, blue:0.70, alpha:1.0)
let endColor = UIColor(red:0.58, green:0.65, blue:0.81, alpha:1.0)
let newLayer = CAGradientLayer()
newLayer.colors = [startColor.cgColor,endColor.cgColor]
newLayer.zPosition = -1
newLayer.frame = view.frame
view.layer.addSublayer(newLayer)
If i do not call this function in GeneralChooser class, the screen is black and there are not view elements, but in initial ViewController i see view elements, just background color is default.
What am I doing wrong. Thanks for all.
The problem is in this line
let newViewController = GeneralChooser()
this line doesn't load xib or reference the storyboard object associated with that class
Use instantiateViewController and give the viewController storyboard ID in storyboard say GeneralChooserView
let vc = self.storyboard?.instantiateViewController(withIdentifier:"GeneralChooserView")
self.navigationController?.pushViewController(vc!, animated: true)
Or if you are using xibs with GeneralChooser as xib file for GeneralChooser class
let vc = GeneralChooser(nibName: "GeneralChooser", bundle: nil)
self.navigationController?.pushViewController(vc, animated: true)
I have a FirstViewController and a SecondViewController. They have different colors for their UINavigationBar. When I show SecondViewController, the color fades in fine. I recorded the animation with the simulator and slow animations.
However, when I go back from SecondViewController to FirstViewController, the color does not animate and everything just changes at once.
This is how I set the code for the UINavigationBar in SecondViewController.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let navBar = self.navigationController?.navigationBar {
navBar.barStyle = UIBarStyle.black
navBar.barTintColor = NavBarColor.red
navBar.backgroundColor = NavBarColor.red
navBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navBar.isTranslucent = false
navBar.tintColor = .white
}
}
In my FirstViewController class, I created a struct NavBarSettings and save the information of the UINavigationBar. I then apply them in viewWillAppear.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
if let navBar = self.navigationController?.navigationBar,
let navBarSettings = self.navBarSettings {
navBar.barStyle = navBarSettings.barStyle
navBar.barTintColor = navBarSettings.barTintColor
navBar.backgroundColor = navBarSettings.backgroundColor
navBar.titleTextAttributes = navBarSettings.titleTextAttributes
navBar.isTranslucent = navBarSettings.isTranslucent
navBar.tintColor = navBarSettings.tintColor
}
}
I also tried to change the UINavigationBar information in SecondViewController viewWillDisappear but it had the same effect.
I've also tried to set a backgroundColor but it had did not change anything either.
How do I get the second animation to work like the first one?
Update
The segue to SecondViewController is of kind show.
I simply call it with self.performSegue(withIdentifier: "SecondViewControllerSegue", sender: nil)
I didn't add any custom code to the back button, it's the default UINavigationController implementation.
Try replacing the back button with a custom back button and add an action to it.
let backButton = UIButton()
backButton.addTarget(self, action: #selector(self.backButtonClicked), for: UIControlEvents.touchUpInside)
navBar.navigationItem.leftBarButtonItem = barButton
func backButtonClicked() {
// try implementing the same thing here but with the self.navigationController?.popViewController(animated: true)
}
I'm developing an ios app. I have a a main view and in this view
im trying to present a modal view controller with dimmed background(black with opacity).
The problem is that the status bar is not affected by this color and remains the same.
This is how i present the view controller:
let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController
shareViewController.battle = battle
shareViewController.delegate = self
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.addAnimation(animation, forKey: kCATransition)
presentViewController(shareViewController, animated: false) {
() in
// nothing here
}
Here are some screenshots to demonstrate the problem:
This is the problem(status bar color):
Problem illustration
This is the modal view in storyboard:
storyboard
I cannot reproduce your problem, the following code works without problems in my single view app:
let viewController = UIViewController()
viewController.modalPresentationStyle = .overFullScreen
viewController.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
let animation = CATransition()
animation.duration = 1
animation.type = kCATransitionFade
self.view.window?.layer.add(animation, forKey: kCATransition)
self.present(viewController, animated: false, completion: nil)
However note that you should be presenting over the root controller of the view. Sometimes you can get strange effects when presenting from your internal controllers:
self.view.window?.rootViewController?.present(viewController, animated: false, completion: nil)
Also make sure you are using the correct modalPresentationStyle.
Set your view controller as the root view controller of a UIWindow, then present the window at the UIWindowLevelAlert level.
Below is a Swift 3 class used to animate a modal popup over all other UI elements, including the status bar. A scrim view is used to shade background UI and intercept touches to dismiss the view.
import UIKit
class ModalViewController: UIViewController {
private let scrimView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = UIColor.black
view.alpha = 0.0
return view
}()
private var myWindow: UIWindow?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.clear
// Setup scrim View
view.addSubview(scrimView)
view.topAnchor.constraint(equalTo: scrimView.topAnchor).isActive = true
view.leftAnchor.constraint(equalTo: scrimView.leftAnchor).isActive = true
view.rightAnchor.constraint(equalTo: scrimView.rightAnchor).isActive = true
view.bottomAnchor.constraint(equalTo: scrimView.bottomAnchor).isActive = true
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismiss as (Void) -> Void))
scrimView.addGestureRecognizer(tapGestureRecognizer)
// Layout custom popups or action sheets
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
UIView.animate(withDuration: 0.25) {
self.scrimView.alpha = 0.5
// Animate in custom popups or action sheets
}
}
func present() {
myWindow = UIWindow(frame: UIScreen.main.bounds)
myWindow?.windowLevel = UIWindowLevelAlert
myWindow?.backgroundColor = UIColor.clear
myWindow?.rootViewController = self
myWindow?.isHidden = false
}
func dismiss() {
UIView.animate(
withDuration: 0.25,
animations: {
self.scrimView.alpha = 0.0
// Animate out custom popups or action sheets
},
completion: { success in
self.myWindow = nil
}
)
}
}
To present the view:
let modalView = ModalViewController()
modalView.present()
To dismiss the view, tap anywhere on the scrim.
this code works for me, when I am presenting UIViewController with alpha != 1. present UIViewController like:
let storyBoard = UIStoryboard(name: "Main", bundle: nil)
let destinationVC = storyBoard.instantiateViewController(withIdentifier: "AddComment") as! AddCommentViewController
destinationVC.modalPresentationStyle = .overCurrentContext //this line is important
destinationVC.delegate = self
destinationVC.restId = self.restaurant.id
self.present(destinationVC, animated: true, completion: nil)
then in destinationVC view controller
override func viewWillDisappear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = .clear
})
super.viewWillDisappear(true)
}
override func viewWillAppear(_: Bool) {
UIView.animate(withDuration: 1, animations: { () in
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.5)
})
super.viewWillAppear(true)
}
and set its backgroundColor to .clear in viewDidLoad or storyboard. So UIViewController covers whole screen including status bar.
Here is the solution you might be looking for:
if let window = UIApplication.shared.keyWindow {
window.windowLevel = UIWindowLevelStatusBar + 1
}
The main idea behind this code is, window of your application has a window level which is lower than status bar window level. And what this code does is, just put your window's window level higher than status bar window level, and your window can now cover the status bar. Don't forget, this code has to be called on main thread, just before presenting your view controller. Good luck!
Custom animation transitions should be performed using UIViewControllerAnimatedTransitioning. Here is a tutorial for this purpose:
https://www.raywenderlich.com/110536/custom-uiviewcontroller-transitions
If all you want is a fade animation you can have it by changing the modalTransitionStyle property of the viewController you are going to display.
Try by fixing your code this way:
guard let shareViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ShareViewController") as! ShareViewController else {
//Fallback in case of nil?
return
}
shareViewController.modalTransitionStyle = .crossDissolve
presentViewController(shareViewController, animated: true, completion: nil)
Also please note that presentViewController(shareViewController, animated: true, completion: nil) is for swift 2. The equivalent swift 3 would be present(shareViewController, animated: true, completion: nil)
you can add this code to view controller for Swift 3:
let statusView: UIView = UIView(frame: CGRect(x: 0.0, y: -20.0, width: UIScreen.main.bounds.size.width, height: 20.0))
statusView.backgroundColor = UIColor.black
statusView.alpha = 0.8
self.addSubview(self.statusView)
You could be extremely practical and simply hide the status bar when your modal view controller is up:
override func prefersStatusBarHidden() -> Bool {
return true
}