Custom UINavigationBar does not honour given height
I have a custom UINavigationBar, called MapNavBar. This class is declared as follows:
class MapNavBar: UINavigationBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight: CGFloat = 44.0
return CGSize(width: screenSize.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
}
The custom navigation bar is assigned to the navigation controller like so:
navController.setValue(MapNavBar(), forKeyPath : "navigationBar")
Now when the orientation changes to landscape I would like to keep the navigation bar height to the standard (portrait orientation) height of 44. So in the MapController viewWillLayoutSubviews I do:
override func viewWillLayoutSubviews() {
if let navController = ... {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight = navController.navigationBar.sizeThatFits(screenSize).height
// Resize navBar
navController.navigationBar.frame = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(navBarHeight))
}
}
super.viewWillLayoutSubviews()
}
Despite all efforts, the custom navigation bar height remains at 32 points when in landscape. I have checked and the navigationBar property of the navigation controller is indeed an instance of my custom MapNavBar.
Does anyone know why this happens and how to fix it?
Thanks
ios swift uinavigationcontroller uinavigationbar
add a comment |
I have a custom UINavigationBar, called MapNavBar. This class is declared as follows:
class MapNavBar: UINavigationBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight: CGFloat = 44.0
return CGSize(width: screenSize.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
}
The custom navigation bar is assigned to the navigation controller like so:
navController.setValue(MapNavBar(), forKeyPath : "navigationBar")
Now when the orientation changes to landscape I would like to keep the navigation bar height to the standard (portrait orientation) height of 44. So in the MapController viewWillLayoutSubviews I do:
override func viewWillLayoutSubviews() {
if let navController = ... {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight = navController.navigationBar.sizeThatFits(screenSize).height
// Resize navBar
navController.navigationBar.frame = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(navBarHeight))
}
}
super.viewWillLayoutSubviews()
}
Despite all efforts, the custom navigation bar height remains at 32 points when in landscape. I have checked and the navigationBar property of the navigation controller is indeed an instance of my custom MapNavBar.
Does anyone know why this happens and how to fix it?
Thanks
ios swift uinavigationcontroller uinavigationbar
add a comment |
I have a custom UINavigationBar, called MapNavBar. This class is declared as follows:
class MapNavBar: UINavigationBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight: CGFloat = 44.0
return CGSize(width: screenSize.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
}
The custom navigation bar is assigned to the navigation controller like so:
navController.setValue(MapNavBar(), forKeyPath : "navigationBar")
Now when the orientation changes to landscape I would like to keep the navigation bar height to the standard (portrait orientation) height of 44. So in the MapController viewWillLayoutSubviews I do:
override func viewWillLayoutSubviews() {
if let navController = ... {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight = navController.navigationBar.sizeThatFits(screenSize).height
// Resize navBar
navController.navigationBar.frame = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(navBarHeight))
}
}
super.viewWillLayoutSubviews()
}
Despite all efforts, the custom navigation bar height remains at 32 points when in landscape. I have checked and the navigationBar property of the navigation controller is indeed an instance of my custom MapNavBar.
Does anyone know why this happens and how to fix it?
Thanks
ios swift uinavigationcontroller uinavigationbar
I have a custom UINavigationBar, called MapNavBar. This class is declared as follows:
class MapNavBar: UINavigationBar {
override func sizeThatFits(_ size: CGSize) -> CGSize {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight: CGFloat = 44.0
return CGSize(width: screenSize.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
}
The custom navigation bar is assigned to the navigation controller like so:
navController.setValue(MapNavBar(), forKeyPath : "navigationBar")
Now when the orientation changes to landscape I would like to keep the navigation bar height to the standard (portrait orientation) height of 44. So in the MapController viewWillLayoutSubviews I do:
override func viewWillLayoutSubviews() {
if let navController = ... {
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let navBarHeight = navController.navigationBar.sizeThatFits(screenSize).height
// Resize navBar
navController.navigationBar.frame = CGRect(x: 0, y: 0, width: Int(screenSize.width), height: Int(navBarHeight))
}
}
super.viewWillLayoutSubviews()
}
Despite all efforts, the custom navigation bar height remains at 32 points when in landscape. I have checked and the navigationBar property of the navigation controller is indeed an instance of my custom MapNavBar.
Does anyone know why this happens and how to fix it?
Thanks
ios swift uinavigationcontroller uinavigationbar
ios swift uinavigationcontroller uinavigationbar
asked Nov 13 '18 at 10:35
Don MiguelDon Miguel
546315
546315
add a comment |
add a comment |
1 Answer
1
active
oldest
votes
Try this:
class MapNavBar: UINavigationBar {
let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always
override func sizeThatFits(_ size: CGSize) -> CGSize {
let frame = self.frame
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
return CGSize(width: frame.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let y = UIApplication.shared.statusBarFrame.height
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: navBarHeight)
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
}
}
}
}
Have you tried this with auto layout? Will it work nicely withsafeAreaInsets
? (I'm not saying it won't, just wondering.)
– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279094%2fcustom-uinavigationbar-does-not-honour-given-height%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Try this:
class MapNavBar: UINavigationBar {
let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always
override func sizeThatFits(_ size: CGSize) -> CGSize {
let frame = self.frame
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
return CGSize(width: frame.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let y = UIApplication.shared.statusBarFrame.height
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: navBarHeight)
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
}
}
}
}
Have you tried this with auto layout? Will it work nicely withsafeAreaInsets
? (I'm not saying it won't, just wondering.)
– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
add a comment |
Try this:
class MapNavBar: UINavigationBar {
let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always
override func sizeThatFits(_ size: CGSize) -> CGSize {
let frame = self.frame
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
return CGSize(width: frame.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let y = UIApplication.shared.statusBarFrame.height
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: navBarHeight)
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
}
}
}
}
Have you tried this with auto layout? Will it work nicely withsafeAreaInsets
? (I'm not saying it won't, just wondering.)
– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
add a comment |
Try this:
class MapNavBar: UINavigationBar {
let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always
override func sizeThatFits(_ size: CGSize) -> CGSize {
let frame = self.frame
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
return CGSize(width: frame.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let y = UIApplication.shared.statusBarFrame.height
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: navBarHeight)
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
}
}
}
}
Try this:
class MapNavBar: UINavigationBar {
let navBarHeight: CGFloat = 64 //44 + 20 Where 20 is for status bar, it is hidden in landscape mode always
override func sizeThatFits(_ size: CGSize) -> CGSize {
let frame = self.frame
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
return CGSize(width: frame.width, height: navBarHeight)
}
return super.sizeThatFits(size)
}
override func layoutSubviews() {
super.layoutSubviews()
let screenSize = UIScreen.main.bounds.size
let landscape = screenSize.width > screenSize.height
if landscape {
let y = UIApplication.shared.statusBarFrame.height
frame = CGRect(x: frame.origin.x, y: y, width: frame.size.width, height: navBarHeight)
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarContent") {
subview.frame = CGRect(x: subview.frame.origin.x, y: 0, width: subview.frame.width, height: navBarHeight)
subview.backgroundColor = self.backgroundColor
}
}
}
}
}
edited Nov 13 '18 at 12:13
answered Nov 13 '18 at 12:07
SateeshSateesh
1,9541715
1,9541715
Have you tried this with auto layout? Will it work nicely withsafeAreaInsets
? (I'm not saying it won't, just wondering.)
– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
add a comment |
Have you tried this with auto layout? Will it work nicely withsafeAreaInsets
? (I'm not saying it won't, just wondering.)
– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
Have you tried this with auto layout? Will it work nicely with
safeAreaInsets
? (I'm not saying it won't, just wondering.)– dfd
Nov 13 '18 at 14:51
Have you tried this with auto layout? Will it work nicely with
safeAreaInsets
? (I'm not saying it won't, just wondering.)– dfd
Nov 13 '18 at 14:51
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
@Sateesh thanks! That seems to do the job. The Bar button items are misaligned though, stuck at the top. Would you know where to use the setBackgroundVerticalPositionAdjustment call for each bar button item so that it is centered vertically on the bar?
– Don Miguel
Nov 13 '18 at 16:37
1
1
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@dfd, Yes I've done. It is working fine.
– Sateesh
Nov 14 '18 at 7:37
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@DonMiguel, can you please share the code for how UIBarButtonItems are created.
– Sateesh
Nov 14 '18 at 7:41
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
@Sateesh the bar button items are created without any vertical position adjustment as their default placement is correct in portrait. However, when in landscape I try and update their position within layoutSubviews of the navigation bar: if let navigationItem = self.topItem { if let leftItems = navigationItem.leftBarButtonItems { for item: UIBarButtonItem in leftItems { item.setBackgroundVerticalPositionAdjustment(navBarHeight/2, for: .default) } }
– Don Miguel
Nov 14 '18 at 17:31
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53279094%2fcustom-uinavigationbar-does-not-honour-given-height%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown