i have a navigation Bar Item. When the app loads, i have this code so the navbar has the height that i want...
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
let height: CGFloat = 38
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
}
The problem is that when i press the homeButton and then i return to the app, the navbar changes the height, and i want the height to be like the first time you run the app
It seems like when i first run the app, the height of the navbar takes the value that i want, but then, when i close and reopen the app, it takes the original value (the default height value of the navbar).
What should i do? Should i implement another method?? Thanks!!!
I would recommend use autolayout constraint properly in your storyboard file. And then you do not have to set the height programmatically. But if you would like to manipulate programmatically then move your code in ViewDidload instead of ViewDidAppear method.
let height: CGFloat = 38
let bounds = self.navigationController!.navigationBar.bounds
self.navigationController?.navigationBar.frame = CGRect(x: 0, y: 0, width: bounds.width, height: bounds.height + height)
In Storyboard select your Navaigation Item > Prompt Field add space to increase the height of Navigation bar
And have your code in either viewDidAppear(As you have today) or viewWillAppear
viewWillAppear or viewDidAppear methods are not designed to work like that. If your application goes to inactive and become active again while a UIViewController on the foreground it won't call any of those methods.
You can track that from applicationDidBecomeActive method in AppDelegate.
But if you want to know that in a specific view controller you can use the notification named UIApplicationDidBecomeActive
I think you should subclass the UINavigationController, but keep the navigationbar it self is the best, if you wat to add something on the bar, you can add a uitoolbar on the ViewController's view, and toolBar.frame = (0,64,screenWidth, 30), then delete the hair line of navigationbar , and it will look like the navigationbar been extended
Related
Hi every one I am stuck somewhere. Need your help. I wanna implement custom tab bar
What I have done so far.
I added tab bar controller but unable to give constraints.
Also added tab bar in view controller but failed to add actions to
navigate to other controllers.
Whether its possible to modify the tab bar to look like this, i'm not sure. I can confirm its not possible to do it via storyboard.
Storyboards are very powerful tools, but only give limited ability to customise controls, through the options along the right hand side. For a tababr, all you can do is set the background color, tab selectedColor etc. To do something like this, at a minimum you would need to run some code inside the tabBarController to modify the UIViews to create that special button in the middle and then round the edges etc.
For example, I previously needed to create a special, bigger middle button, with the tabbar's top left and right corners rounded. Heres a piece of that code as a rough ida:
import UIKit
class HomeTabBarController: UITabBarController {
private let middleButton = UIButton(frame: CGRect(x: 0, y: 0, width: 40, height: 40))
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
guard let tabItems = tabBar.items else { return }
tabItems[0].titlePositionAdjustment = UIOffset(horizontal: -25, vertical: 0)
tabItems[1].titlePositionAdjustment = UIOffset(horizontal: 25, vertical: 0)
middleButton.setBackgroundImage(UIImage(named: "middle-tab-button"), for: .normal)
middleButton.setBackgroundImage(UIImage(named: "middle-tab-button")?.maskWithColor(color: .lightGray), for: .highlighted)
middleButton.tintColor = UIColor.black
middleButton.center = CGPoint(x: tabBar.frame.width/2, y: 25)
self.tabBar.addSubview(middleButton)
self.view.backgroundColor = UIColor(named: "background")
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
self.tabBar.roundCorners(corners: [.topLeft, .topRight], radius: 28)
}
}
You might be able to use this as a start and add to it. The other alternative being to completely build a custom control from scratch, and make all the interactions work the same.
But this would be a lot easier if the designer behind this would agree to stick to a more iOS-y style control. It takes a significant amount of time and effort to build and maintain these things. Often the slightly different appearance of the inbuilt control barely changes anything at all, making it not worth it.
Hey I am trying to add a custom view to a navigation bar. The current result is like so:
I initialise this navigation bar like so:
func setupNavBar() {
navigationController?.navigationBar.isTranslucent = false
let navBarView = ExamCoachNavBarView(frame: CGRect(x: 0, y: 0, width: 236, height: 45))
navigationItem.titleView = navBarView
}
I want to move the custom view down to the bottom of the nav bar. I have tried changing the y value for the navBarView frame. This make absolutely no difference those. Regardless to what that value is the frame always stays in the same position at the top of the bar. What am I doing wrong here? How can I move the bar to the bottom of the screen?
I implement a solution to put a bottom border to a textfield which works good but i have following Problem. If i start the app on bigger sizes (iPad mini, iPad Pro) or landscape (iPhone6, 6s) the line under the textfield is not correct stretched.
I have create a extension for the textfields:
extension UITextField {
/**
Customize the UITextField for App
- parameter isPasswordField: Boolean to check if this field is a password field
- author: Simon Zwicker <simon.zwicker#gmail.com>
*/
func customize(isPasswordField: Bool) {
let bottomLine = UIView()
bottomLine.frame = CGRect(x: 0.0, y: self.frame.size.height - 1, width: self.frame.size.width, height: 1.0)
bottomLine.backgroundColor = UIColor.grayColor()
self.addSubview(bottomLine)
self.tintColor = UIColor.grayColor()
if isPasswordField {
self.textColor = UIColor.blueColor()
}
}
I call the customize() function on the textfields in viewWillLayoutSubviews()
Did i make somewhere a mistake? After i put device in portrait and back to landscape it works.
The size of the textfield is initial correct but the self.frame.size.width in the customize function is initial too small. Do you know what happened maybe?
I was able to replicate your issue, and it seems like at the moment of calling viewWillLayoutSubviews the text field did not have the width that's shown on the screen in the end (or constraints weren't applied).
Calling customize in viewDidLayoutSubviews scaled the line properly. I am not sure if you are happy with this solution.
I have created my own subclass of UIPresentationController and I am presenting a navigation controller using it. The purpose is to somewhat mimic the behavior of UIPopoverPresentationController but allow for more customization.
So the problem I am experiencing is that on iPad when the user adjusts the size of the app using splitview, the navigation bar's height doesn't update correctly.
When the view is in a popover style it is supposed to use a height of 44 for the nav bar and when it is in fullscreen style it uses a height of 64. This is happening correctly upon first presenting the controller. However if the user adjusts the app using splitview the nav bar height does not update at all.
In my UIPresentationController subclass I am doing the following:
I set the frame based on the container view's width:
override func frameOfPresentedViewInContainerView() -> CGRect {
if let containerView = containerView {
if containerView.bounds.width > 500 {
let preferredSize = presentedViewController.preferredContentSize
return CGRect(x: containerView.bounds.width - preferredSize.width - 20, y: 16, width: preferredSize.width, height: preferredSize.height)
} else {
return containerView.bounds
}
} else {
return CGRectZero
}
}
Then I update the frame whenever I get the willLayoutSubviews call:
override func containerViewWillLayoutSubviews() {
presentedViewController.view.frame = frameOfPresentedViewInContainerView()
}
When I examine the presentedViewController's view, it is getting all the correct values and visually is the right size. The only problem is that the nav bar will remain the height that it was originally presented at (whether that is 44 or 64) and will either leave a gap or extend passed its bounds.
It appears I found a solution that works. Inside my containerViewWillLayoutSubviews function I simply access the navigation controller's navigationBar property and manually set its frame correctly.
if let navigationController = presentedViewController as? UINavigationController {
navigationController.navigationBar.frame = CGRect(x: 0,
y: 0,
width: presentedViewController.view.frame.size.width,
height: containerView.bounds.width > 500 ? 44 : 64)
}
This does seem a bit fragile though, but its working fine for me.
I want to create a simple view over keyboard, when users tap "Attach" button in inputAccessoryView.
Something like this:
Is there an easy way to do it? Or i should create my custom keyboard?
You can add that new subview to your application window.
func attach(sender : UIButton)
{
// Calculate and replace the frame according to your keyboard frame
var customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height-300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.redColor()
customView.layer.zPosition = CGFloat(MAXFLOAT)
var windowCount = UIApplication.sharedApplication().windows.count
UIApplication.sharedApplication().windows[windowCount-1].addSubview(customView);
}
Swift 4 version:
let customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height - 300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.red
customView.layer.zPosition = CGFloat(Float.greatestFiniteMagnitude)
UIApplication.shared.windows.last?.addSubview(customView)
The trick is to add the customView as a top subview to the UIWindow that holds the keyboard - and it happens to be the last window in UIApplication.shared.windows.
Swift 4.0
let customView = UIView(frame: CGRect(x: 0, y: self.view.frame.size.height-300, width: self.view.frame.size.width, height: 300))
customView.backgroundColor = UIColor.red
customView.layer.zPosition = CGFloat(MAXFLOAT)
let windowCount = UIApplication.shared.windows.count
UIApplication.shared.windows[windowCount-1].addSubview(customView)
As Tamás Sengel said, Apple's guidelines does not support adding a view over the keyboard. The recommended way to add a view over keyboard in Swift 4 & 5 is:
1) Add view with your "Next" button in your storyboard as external view and connect in your class (see Explain Image), in my case:
IBOutlet private weak var toolBar: UIView!
2) For the textfield you want to add your custom view over keyboard, add it as accessory view in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
phoneNumberTextField.inputAccessoryView = toolBar
}
3) Add action for "Next" button:
#IBAction func nextButtonPressed(_ sender: Any) {
descriptionTextView.becomeFirstResponder()
// or -> phoneNumberTextField.resignFirstResponder()
}
Explain Image:
Method 2: Result with image
In TableView Controller - add stricked view at bottom
Please follow this great link to handle safe area for screens like iPhone X if you want to use this method(2). Article: InputAccessoryView and iPhone X
override var inputAccessoryView: UIView? {
return toolBar
}
override var canBecomeFirstResponder: Bool {
return true
}
Do you have find some effective method to solve this problem? In iOS9,you put your customView on the top of the windows:
UIApplication.sharedApplication().windows[windowCount-1].addSubview(customView);
But if the keyboard dismisses, the top Windows will be removed, so your customView will be removed.
Looking forward for your help!
Thank you for your help!
You can definitely add the view to your application’s window, and you can also add another window entirely. You can set its frame and level. The level could be UIWindowLevelAlert.
While this can be possible with accessing the topmost window, I would avoid doing this, as it clearly interferes with Apple's guidelines.
What I would do is dismissing the keyboard and replacing its frame with a view with same dimensions.
The keyboard's frame can be accessed from keyboard notifications listed here, their userInfo contain a key that can be accessed with UIKeyboardFrameEndUserInfoKey.