iOS设置导航栏和状态栏

文章目录

      • iOS 15 之后导航栏背景色的设置
      • 1、状态栏设置
        • 1.1、没有导航栏
        • 1.2、有导航栏
      • 2、导航栏背景和字体颜色
        • 2.1、十六进制颜色转RGB
        • 2.2、生成纯色图片
      • 3、导航栏的另外一种设置方式
      • 4、导航栏右滑返回失效
      • 5、导航栏的一些设置会影响导航栏是否遮挡view
      • 6、总结导航栏和View布局问题
        • 6.1、view在导航栏下开始布局
        • 6.2、view从(0,0)开始布局,导航栏遮挡view
    • 更新
      • 7、关于 View 从导航栏顶部布局(被导航栏遮挡)和从导航栏底部布局的新的理解。
        • 7.1属性 translucent 的官方介绍
      • 8、View布局位置
      • 9、ScrollView的布局影响
      • 10、translucent=NO 的时候设置导航栏背景色透明

iOS 15 之后导航栏背景色的设置

iOS 13 开始新增了 standardAppearance 和 scrollEdgeAppearance 属性,不过在iOS 15(xcode13)的时候才真正需要适配。带滑动视图的页面,当滑动到最顶部时显示后者的属性,其他时候显示前者的属性。不带滑动视图的页面只显示前者的属性。

if (@available(iOS 15.0, *)) {
        UINavigationBarAppearance *barAppearance = [[UINavigationBarAppearance alloc] init];
        barAppearance.backgroundImage = backgroundImage;
        barAppearance.shadowImage = shadowImage;
        
        self.navigationController.navigationBar.standardAppearance = barAppearance;
        self.navigationController.navigationBar.scrollEdgeAppearance = barAppearance;
    }

1、状态栏设置

typedef NS_ENUM(NSInteger, UIStatusBarStyle) {
    UIStatusBarStyleDefault                                  = 0, // Automatically chooses light or dark content based on the user interface style
    UIStatusBarStyleLightContent     API_AVAILABLE(ios(7.0)) = 1, // Light content, for use on dark backgrounds
    UIStatusBarStyleDarkContent     API_AVAILABLE(ios(13.0)) = 3, // Dark content, for use on light backgrounds
    
    UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,
    UIStatusBarStyleBlackOpaque      NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,
} API_UNAVAILABLE(tvos);

UIStatusBarStyleDefault // 默认状态
UIStatusBarStyleLightContent // 状态栏文本和图标为白色
UIStatusBarStyleDarkContent // 状态栏文本和图标为黑色
另外两个已弃用

1.1、没有导航栏

在 ViewController 中,使用 -(UIStatusBarStyle)preferredStatusBarStyle 方法设置

// ViewController
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleLightContent;
}

1.2、有导航栏

self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
typedef NS_ENUM(NSInteger, UIBarStyle) {
    UIBarStyleDefault          = 0,
    UIBarStyleBlack            = 1,
    
    UIBarStyleBlackOpaque API_DEPRECATED("Use UIBarStyleBlack instead.", ios(2.0, 13.0)) = 1,
    UIBarStyleBlackTranslucent API_DEPRECATED("Use UIBarStyleBlack and set the translucent property to YES instead.", ios(2.0, 13.0)) = 2,
} API_UNAVAILABLE(tvos);

UIBarStyleDefault // 状态栏文本和图标为黑色
UIBarStyleBlack // 状态栏文本和图标为白色
另外两个已弃用

2、导航栏背景和字体颜色

	// 状态栏深色背景浅色字体(状态栏字体白色)
    [self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];
    // 导航栏背景色
    // self.navigationController.navigationBar.barTintColor = [UIColor blueColor];
    // 导航栏背景图片
    [self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:UIColorFromRGB(0xff3d3b)] forBarMetrics:UIBarMetricsDefault];
    // 导航栏标题颜色
    [self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
    // 导航栏按钮颜色
    [self.navigationController.navigationBar setTintColor:[UIColor whiteColor]];

2.1、十六进制颜色转RGB

	//3.获得RGB颜色
	#define UIColorFromRGBAlpha(rgbValue, rgbAlpha) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:rgbAlpha]
	#define UIColorFromRGB(rgbValue) UIColorFromRGBAlpha(rgbValue, 1.0f)

2.2、生成纯色图片

+(UIImage *)imageWithColor:(UIColor *)aColor
{
    return [self imageWithColor:aColor withFrame:CGRectMake(0, 0, 1, 1)];
}

+(UIImage *)imageWithColor:(UIColor *)aColor withFrame:(CGRect)aFrame
{
    UIGraphicsBeginImageContext(aFrame.size);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(context, [aColor CGColor]);
    CGContextFillRect(context, aFrame);
    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return img;
}

3、导航栏的另外一种设置方式

[UINavigationBar appearance] 获取的是当前已经展示的导航栏,在调用系统通讯录的时候(CNContactPickerViewController)使用这种方式修改通讯录导航栏样式

	UINavigationBar *navigationBar = [UINavigationBar appearance];
	// 状态栏深色背景浅色字体(状态栏字体白色)
    [navigationBar setBarStyle:UIBarStyleBlack];
    // 导航栏背景色
    [navigationBar setBackgroundImage:[UIImage imageWithColor:UIColorFromRGB(0xff3d3b)] forBarMetrics:UIBarMetricsDefault];
    // 导航栏标题颜色
    [navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]}];
    // 导航栏按钮颜色
    [navigationBar setTintColor:[UIColor whiteColor]];

4、导航栏右滑返回失效

导航栏设置了左侧按钮(self.navigationItem.leftBarButtonItem)右滑返回失效

	// 在interface声明代理 
	<UIGestureRecognizerDelegate>
	
	// 自定义左侧按钮后右滑返回失效,如下代码恢复右滑返回功能
 	self.navigationController.interactivePopGestureRecognizer.delegate = self;

5、导航栏的一些设置会影响导航栏是否遮挡view

	//设置导航栏透明,导航栏透明度默认为true,设置为No,view布局从导航栏底部开始
	[self.navigationController.navigationBar setTranslucent:true];
	//把背景设为空,image设为nil的话会有一个半透明黑色图层,设为一个没有内容的图片,导航栏就是透明的了,view的布局从0,0开始,会被遮挡。
	[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];

image为nil的效果
iOS设置导航栏和状态栏_第1张图片

导航栏遮住View问题

6、总结导航栏和View布局问题

(这里我对translucent属性的理解有些问题,文底做说明)

6.1、view在导航栏下开始布局

(1)导航栏不透明,navigationBar.translucent 设为YES(默认为YES),设置背景图片(不为nil,且有内容);

//    self.navigationController.navigationBar.translucent = YES;
    [self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:[UIColor redColor]] forBarMetrics:UIBarMetricsDefault];
    // 这里其实 self.navigationController.navigationBar.translucent = NO;
    // 文底会做说明

iOS设置导航栏和状态栏_第2张图片

(2) 导航栏不透明,navigationBar.translucent 设为NO,导航栏的背景图片颜色为黑色;

	self.navigationController.navigationBar.translucent = NO;

iOS设置导航栏和状态栏_第3张图片

(3)导航栏透明,navigationBar.translucent 设为YES(默认为YES),edgesForExtendedLayout 设为 UIRectEdgeNone。

// self.navigationController.navigationBar.translucent = YES;
	[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
	self.edgesForExtendedLayout = UIRectEdgeNone;

iOS设置导航栏和状态栏_第4张图片

6.2、view从(0,0)开始布局,导航栏遮挡view

(1)导航栏不透明,上述情况下设置extendedLayoutIncludesOpaqueBars属性为YES

//    self.navigationController.navigationBar.translucent = YES;
    [self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:[UIColor redColor]] forBarMetrics:UIBarMetricsDefault];
    self.extendedLayoutIncludesOpaqueBars = YES;

iOS设置导航栏和状态栏_第5张图片

(2) 导航栏不透明,navigationBar.translucent 设为NO,导航栏的背景图片颜色为黑色;

	self.navigationController.navigationBar.translucent = NO;
	self.extendedLayoutIncludesOpaqueBars = YES;

iOS设置导航栏和状态栏_第6张图片

(3)导航栏透明

	//    self.navigationController.navigationBar.translucent = YES;
    [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];

iOS设置导航栏和状态栏_第7张图片

更新

--------------------------------------------------------------------更新于21.03.16--------------------------------------------------------------------

7、关于 View 从导航栏顶部布局(被导航栏遮挡)和从导航栏底部布局的新的理解。

本来打算修改上面的文章,感觉自己走过的弯路保留一下吧,从这里开始。

7.1属性 translucent 的官方介绍

self.navigationController.navigationBar.translucent

下面是文档说明

When the navigation bar is translucent, configure the edgesForExtendedLayout and extendedLayoutIncludesOpaqueBars properties of your view controller to display your content underneath the navigation bar.
If the navigation bar doesn't have a custom background image, or if any pixel of the background image has an alpha value of less than 1.0, the default value of this property is YES. If the background image is completely opaque, the default value of this property is NO. If you set this property to YES and the custom background image is completely opaque, UIKit applies a system-defined opacity of less than 1.0 to the image. If you set this property to NO and the background image is not opaque, UIKit adds an opaque backdrop.

第一段是说导航栏为半透明的(translucent=YES),可以通过edgesForExtendedLayout 和 extendedLayoutIncludesOpaqueBars两个属性来控制view从导航栏的顶部还是底部开始布局。(这个后面再说,先理解第二段

第二段是说明导航栏透明度(translucent)和背景图片(backgroundImage)的关系。

translucent 默认值为 YES

不指定translucent的值,背景图为不透明的,translucent自动为NO;
背景图为透明的,translucent自动为yes;
背景图不透明,指定translucent为YES,则背景图自动变为半透明的;
背景图透明,指定translucent为NO,则背景图变为不透明的;

或者说,不指定或者先指定translucent的值,不管是YES还是NO,再设定背景图,translucent 的值以图片的透明度为准;
先指定背景图,再指定translucent,translucent的值以指定的值为准。

8、View布局位置

// View 从导航栏顶部开始布局,会被导航栏遮挡;
translucent=YES,
// View 从导航栏底部开始布局。
translucent=NO ,

// View 从导航栏底部开始布局。
translucent=YES 且
self.edgesForExtendedLayout = UIRectEdgeNone; 
// View 从导航栏顶部开始布局,会被导航栏遮挡;
translucent=NO  且
self.extendedLayoutIncludesOpaqueBars = YES;

9、ScrollView的布局影响

偷个懒,看这里吧。
导航栏遮住View问题

没有做处理的话,无论导航栏透明不透明都不会遮挡。

10、translucent=NO 的时候设置导航栏背景色透明

这里记录一个设置导航栏透明的方法,这个改变的是view的透明度,不影响导航栏背景图片,所以也不会修改 translucent 的值,如果有滑动控制导航栏透明度的需求可以设置这里。

[[[self.navigationController.navigationBar subviews] objectAtIndex:0] setAlpha:0];

你可能感兴趣的:(iOS,ios,xcode,objective-c)