Мак*_*ляр 62 uinavigationbar ios ios11
现在在iOS 11中,sizeThatFits不从UINavigationBar子类调用该方法.更改UINavigationBar导致故障和错误插入的框架.那么,现在如何定制导航栏高度的任何想法?
fra*_*yan 30
根据Apple开发人员(在此处,此处和此处),不支持更改iOS 11中的导航栏高度.在这里,他们建议做一些变通办法,例如在导航栏下面(但在其外面),然后删除导航栏边框.因此,您将在故事板中拥有此内容:
在设备上看起来像这样:
现在你可以做到这一点在其他答案提出了一个解决办法:创建一个自定义子类UINavigationBar,定制大子视图添加到它,覆盖sizeThatFits和layoutSubviews,然后设置additionalSafeAreaInsets.top为导航的顶级控制器的差异customHeight - 44px,但酒吧视图仍将是默认44px,即使在视觉上一切都会看起来很完美.我没有尝试覆盖setFrame,也许它有效,但是,正如Apple开发人员在上面的一个链接中所写:"......并且[支持]都没有改变UINavigationController拥有的导航栏的框架(导航)只要它认为合适,控制器就会愉快地踩踏你的框架变化.)
在我的情况下,上面的解决方法使视图看起来像这样(调试视图显示边框):
正如您所看到的,视觉外观相当不错,additionalSafeAreaInsets正确推送内容,大导航栏可见,但是我在此栏中有一个自定义按钮,只有标准44像素导航栏下面的区域是可点击的(图中的绿色区域).标准导航栏高度以下的触摸不会到达我的自定义子视图,因此我需要调整导航栏本身的大小,Apple开发人员说不支持.
Sha*_*aek 22
2018年1月7日更新
此代码支持XCode 9.2,iOS 11.2
我有同样的问题.以下是我的解决方案.我假设身高是66.
如果有帮助,请选择我的答案.
创建CINavgationBar.swift
import UIKit
@IBDesignable
class CINavigationBar: UINavigationBar {
//set NavigationBar's height
@IBInspectable var customHeight : CGFloat = 66
override func sizeThatFits(_ size: CGSize) -> CGSize {
return CGSize(width: UIScreen.main.bounds.width, height: customHeight)
}
override func layoutSubviews() {
super.layoutSubviews()
print("It called")
self.tintColor = .black
self.backgroundColor = .red
for subview in self.subviews {
var stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("UIBarBackground") {
subview.frame = CGRect(x: 0, y: 0, width: self.frame.width, height: customHeight)
subview.backgroundColor = .green
subview.sizeToFit()
}
stringFromClass = NSStringFromClass(subview.classForCoder)
//Can't set height of the UINavigationBarContentView
if stringFromClass.contains("UINavigationBarContentView") {
//Set Center Y
let centerY = (customHeight - subview.frame.height) / 2.0
subview.frame = CGRect(x: 0, y: centerY, width: self.frame.width, height: subview.frame.height)
subview.backgroundColor = .yellow
subview.sizeToFit()
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
设置故事板
设置自定义NavigationBar类
添加TestView + Set SafeArea
ViewController.swift
import UIKit
class ViewController: UIViewController {
var navbar : UINavigationBar!
@IBOutlet weak var testView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
//update NavigationBar's frame
self.navigationController?.navigationBar.sizeToFit()
print("NavigationBar Frame : \(String(describing: self.navigationController!.navigationBar.frame))")
}
//Hide Statusbar
override var prefersStatusBarHidden: Bool {
return true
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(false)
//Important!
if #available(iOS 11.0, *) {
//Default NavigationBar Height is 44. Custom NavigationBar Height is 66. So We should set additionalSafeAreaInsets to 66-44 = 22
self.additionalSafeAreaInsets.top = 22
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Run Code Online (Sandbox Code Playgroud)
SecondViewController.swift
import UIKit
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// Create BackButton
var backButton: UIBarButtonItem!
let backImage = imageFromText("Back", font: UIFont.systemFont(ofSize: 16), maxWidth: 1000, color:UIColor.white)
backButton = UIBarButtonItem(image: backImage, style: UIBarButtonItemStyle.plain, target: self, action: #selector(SecondViewController.back(_:)))
self.navigationItem.leftBarButtonItem = backButton
self.navigationItem.leftBarButtonItem?.setBackgroundVerticalPositionAdjustment(-10, for: UIBarMetrics.default)
}
override var prefersStatusBarHidden: Bool {
return true
}
@objc func back(_ sender: UITabBarItem){
self.navigationController?.popViewController(animated: true)
}
//Helper Function : Get String CGSize
func sizeOfAttributeString(_ str: NSAttributedString, maxWidth: CGFloat) -> CGSize {
let size = str.boundingRect(with: CGSize(width: maxWidth, height: 1000), options:(NSStringDrawingOptions.usesLineFragmentOrigin), context:nil).size
return size
}
//Helper Function : Convert String to UIImage
func imageFromText(_ text:NSString, font:UIFont, maxWidth:CGFloat, color:UIColor) -> UIImage
{
let paragraph = NSMutableParagraphStyle()
paragraph.lineBreakMode = NSLineBreakMode.byWordWrapping
paragraph.alignment = .center // potentially this can be an input param too, but i guess in most use cases we want center align
let attributedString = NSAttributedString(string: text as String, attributes: [NSAttributedStringKey.font: font, NSAttributedStringKey.foregroundColor: color, NSAttributedStringKey.paragraphStyle:paragraph])
let size = sizeOfAttributeString(attributedString, maxWidth: maxWidth)
UIGraphicsBeginImageContextWithOptions(size, false , 0.0)
attributedString.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Run Code Online (Sandbox Code Playgroud)
黄色是barbackgroundView.黑色不透明度是BarContentView.
我删除了BarContentView的backgroundColor.
而已.
补充:问题在iOS 11 beta 6中得到解决,因此下面的代码没用^ _ ^
原始答案:
解决了以下代码:
(我总是希望navigationBar.height + statusBar.height == 64 statusBar的隐藏是否为true)
@implementation P1AlwaysBigNavigationBar
- (CGSize)sizeThatFits:(CGSize)size {
CGSize sizeThatFit = [super sizeThatFits:size];
if ([UIApplication sharedApplication].isStatusBarHidden) {
if (sizeThatFit.height < 64.f) {
sizeThatFit.height = 64.f;
}
}
return sizeThatFit;
}
- (void)setFrame:(CGRect)frame {
if ([UIApplication sharedApplication].isStatusBarHidden) {
frame.size.height = 64;
}
[super setFrame:frame];
}
- (void)layoutSubviews
{
[super layoutSubviews];
if (![UIApplication sharedApplication].isStatusBarHidden) {
return;
}
for (UIView *subview in self.subviews) {
NSString* subViewClassName = NSStringFromClass([subview class]);
if ([subViewClassName containsString:@"UIBarBackground"]) {
subview.frame = self.bounds;
}else if ([subViewClassName containsString:@"UINavigationBarContentView"]) {
if (subview.height < 64) {
subview.y = 64 - subview.height;
}else {
subview.y = 0;
}
}
}
}
@end
Run Code Online (Sandbox Code Playgroud)
小智 9
这对我有用:
- (CGSize)sizeThatFits:(CGSize)size {
CGSize sizeThatFit = [super sizeThatFits:size];
if ([UIApplication sharedApplication].isStatusBarHidden) {
if (sizeThatFit.height < 64.f) {
sizeThatFit.height = 64.f;
}
}
return sizeThatFit;
}
- (void)setFrame:(CGRect)frame {
if ([UIApplication sharedApplication].isStatusBarHidden) {
frame.size.height = 64;
}
[super setFrame:frame];
}
- (void)layoutSubviews
{
[super layoutSubviews];
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) containsString:@"BarBackground"]) {
CGRect subViewFrame = subview.frame;
subViewFrame.origin.y = 0;
subViewFrame.size.height = 64;
[subview setFrame: subViewFrame];
}
if ([NSStringFromClass([subview class]) containsString:@"BarContentView"]) {
CGRect subViewFrame = subview.frame;
subViewFrame.origin.y = 20;
subViewFrame.size.height = 44;
[subview setFrame: subViewFrame];
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用Swift 4进行了简化。
class CustomNavigationBar : UINavigationBar {
private let hiddenStatusBar: Bool
// MARK: Init
init(hiddenStatusBar: Bool = false) {
self.hiddenStatusBar = hiddenStatusBar
super.init(frame: .zero)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// MARK: Overrides
override func layoutSubviews() {
super.layoutSubviews()
if #available(iOS 11.0, *) {
for subview in self.subviews {
let stringFromClass = NSStringFromClass(subview.classForCoder)
if stringFromClass.contains("BarBackground") {
subview.frame = self.bounds
} else if stringFromClass.contains("BarContentView") {
let statusBarHeight = self.hiddenStatusBar ? 0 : UIApplication.shared.statusBarFrame.height
subview.frame.origin.y = statusBarHeight
subview.frame.size.height = self.bounds.height - statusBarHeight
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
虽然它在 beta 4 中得到了修复,但导航栏的背景图像似乎并未随实际视图缩放(您可以通过在视图层次结构查看器中查看来验证这一点)。layoutSubviews目前的解决方法是在您的自定义中覆盖UINavigationBar,然后使用以下代码:
- (void)layoutSubviews
{
[super layoutSubviews];
for (UIView *subview in self.subviews) {
if ([NSStringFromClass([subview class]) containsString:@"BarBackground"]) {
CGRect subViewFrame = subview.frame;
subViewFrame.origin.y = -20;
subViewFrame.size.height = CUSTOM_FIXED_HEIGHT+20;
[subview setFrame: subViewFrame];
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您注意到,栏背景实际上有一个偏移量,-20使其出现在状态栏后面,因此上面的计算将其添加进来。
| 归档时间: |
|
| 查看次数: |
43078 次 |
| 最近记录: |