在 iOS11 上看到带有 navigationItem.titleView 的行为,其中 titleView 的宽度不是屏幕的全宽。
我有一个自定义视图,我设置为 titleView。在 iOS11 之前,视图将填充导航栏区域。但是 iOS 11 并没有调整大小来填充屏幕的宽度。
我在设置 titleView 之前尝试设置视图的框架,但没有运气。我也尝试强制 titleViews 超级视图进行布局约束,但没有运气。
附上截图:
iOS10:
iOS11:
还有人经历过这个吗?
在 iOS11 上看到带有 navigationItem.titleView 的行为,其中 titleView 的宽度不是屏幕的全宽。
我有一个自定义视图,我设置为 titleView。在 iOS11 之前,视图将填充导航栏区域。但是 iOS 11 并没有调整大小来填充屏幕的宽度。
我在设置 titleView 之前尝试设置视图的框架,但没有运气。我也尝试强制 titleViews 超级视图进行布局约束,但没有运气。
附上截图:
iOS10:
iOS11:
还有人经历过这个吗?
我想到了。我必须覆盖视图的 intrinsicContentSize 吸气剂和文本字段。
我将宽度设置为 CGFloat.greatestFiniteMagnitude 所以它总是和屏幕一样宽。
更新:
由于我在这个问题上花了几个小时,希望其他人能通过将所有事情紧密结合起来更快地赶上
我创建了一个TitleView
名为 的自定义子类,CustomTitleView
代码如下:
import UIKit
class CustomTitleView: UIView {
override var intrinsicContentSize: CGSize {
return UIView.layoutFittingExpandedSize
}
}
我从一开始就错过的最重要的部分是:
使用@falkon 的答案是代码:
将此代码添加到用作 titleView 的视图中
override var intrinsicContentSize: CGSize {
return UILayoutFittingExpandedSize
}
设置intrinsicContentSize
为UILayoutFittingExpandedSize
也可以正常工作
我必须将 UIImageView 设置为 navigationItem.titleView。纵横比确实合适,但intrinsicContentSize 使它变大了。缩放图像会导致图像质量不佳。设置布局锚对我有用:
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 80, 30)];
[imageView setImage:image];
[imageView.widthAnchor constraintEqualToConstant:80].active = YES;
[imageView.heightAnchor constraintEqualToConstant:30].active = YES;
[imageView setContentMode:UIViewContentModeScaleAspectFit];
self.navigationItem.titleView = imageView;
如果您的自定义标题视图是默认情况下已经具有内在内容大小的视图(除了.zero
),例如 a UILabel
、 aUITextView
或 a UIButton
,您可以简单地设置
yourCustomTitleView.translatesAutoresizingMaskIntoConstraints = false
它会自动调整为仅包含其内容,但不会与左右项目视图重叠。
例如,您可以将一个按钮拖到 Interface Builder 中导航栏的标题视图区域,titleButton
在您的视图控制器中为它创建一个插座,然后执行
override func viewDidLoad() {
super.viewDidLoad()
titleButton.translatesAutoresizingMaskIntoConstraints = false
}
Yedy回答的Swift 4.2版本
let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 80, height: 30))
imageView.image = image
imageView.widthAnchor.constraint(equalToConstant: 80).isActive = true
imageView.heightAnchor.constraint(equalToConstant: 30).isActive = true
imageView.contentMode = .scaleAspectFit
navigationItem.titleView = imageView
在Swiftify的帮助下转换。
最重要的是您需要覆盖 customTitleView 作为您的 titleView:
self.navigationItem.titleView = [self titleView];
#pragma mark - getter
- (UIView *)titleView {
UIView *navTitleView = [HFCalenderTitleView new];
navTitleView.frame = CGRectMake(0.0, 0.0, HorizontalFrom750(200.0), 44.0);
[navTitleView addSubview:self.titleLabel];
[self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(navTitleView);
}];
CGFloat btnWidth = 30.0;
[navTitleView addSubview:self.previousButton];
self.previousButton.imageEdgeInsets = UIEdgeInsetsMake(0.0, 0.0, 0.0, 15.0);
[self.previousButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(navTitleView);
make.top.bottom.equalTo(navTitleView);
make.width.equalTo(@(btnWidth));
}];
[navTitleView addSubview:self.nextBtn];
self.nextBtn.imageEdgeInsets = UIEdgeInsetsMake(0.0, 15.0, 0.0, 0.0);
[self.nextBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(navTitleView);
make.top.bottom.equalTo(navTitleView);
make.width.equalTo(@(btnWidth));
}];
return navTitleView;
}
#pragma mark - customTitleView
#import "HFCalenderTitleView.h"
@implementation HFCalenderTitleView
- (CGSize)intrinsicContentSize{
return CGSizeMake(HorizontalFrom750(200.0), 40); // the target size
}
当您在 CustomTitleView 中有 UIView 作为子视图时,intrinsicContentSize 解决方案不起作用,仅适用于 iOS 11 中的 XCODE 9。所以我确实喜欢下面,对我来说很好,这可能对某人有帮助。
@interface CustomTitleView : UIView
@property (weak, nonatomic) IBOutlet UIView *doubleTitleView;
@end
@implementation CustomTitleView
- (void)awakeFromNib {
[super awakeFromNib];
int width = _doubleTitleView.frame.size.width;
int height = _doubleTitleView.frame.size.height;
if (width != 0 && height != 0) {
NSLayoutConstraint *widthConstraint = [_doubleTitleView.widthAnchor constraintEqualToConstant:width];
NSLayoutConstraint *heightConstraint = [_doubleTitleView.heightAnchor constraintEqualToConstant:height];
[_doubleTitleView addConstraint:heightConstraint];
[_doubleTitleView addConstraint:widthConstraint];
[heightConstraint setActive:TRUE];
[widthConstraint setActive:TRUE];
}
}
如果您不想覆盖,也可以使用约束intrinsicContentSize
。这是 SnapKit 的演示
self.navigationItem.titleView = titleView
if #available(iOS 11, *) {
titleView.snp.makeConstraints({ (make) in
make.width.equalTo(250) // fixed width
make.height.equalTo(30) // less than 44(height of naviagtion bar)
})
}else {
titleView.frame = ...
}
但是如果任何一侧(左侧或右侧)导航栏上有多个导航条,则应使用intrinsicContentSize;
这门课可以解决问题。确保将自定义视图的类设置为这个:
import UIKit
class TitleView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
translatesAutoresizingMaskIntoConstraints = false
}
required init?(coder: NSCoder) {
super.init(coder: coder)
translatesAutoresizingMaskIntoConstraints = false
}
override var intrinsicContentSize: CGSize {
CGSize(width: UIView.layoutFittingExpandedSize.width, height: self.bounds.height)
}
}
尝试使用标准 UISearchBar / UISearchController
实际上你需要做的 - 如果你可以使用标准 UISearchBar / UISearchController 是按照以下方式显示搜索栏,它尊重安全区域,因此在 iPhone X 和每个设备方向上看起来都很完美:
func presentSearchController() {
let searchController = UISearchController(searchResultsController: nil)
searchController.searchResultsUpdater = self
searchController.obscuresBackgroundDuringPresentation = false
searchController.searchBar.text = "any text"
if #available(iOS 11.0, *) {
self.navigationItem.searchController = searchController
searchController.isActive = true
} else {
present(searchController, animated: true, completion: nil)
}
}
参考
https://developer.apple.com/videos/play/fall2017/201/ https://medium.com/@PavelGnatyuk/large-title-and-search-in-ios-11-514d5e020cee
我有同样的问题,但设置UIImage
为navigationItem
titleView
我所做的是使用以下命令将图像缩放到所需的大小:
-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
并调用如下:
-(void)setHeaderImage{
UIImage * image = [self imageWithImage:[UIImage imageNamed:@"headerImage"] scaledToSize:CGSizeMake(150, 27)];
UIImageView * imageView = [[UIImageView alloc]initWithImage:image];
imageView.frame = CGRectMake(0, 0, 150, 27);
imageView.contentMode = UIViewContentModeScaleAspectFit;
self.navigationItem.titleView = imageView;
}
return UILayoutFittingExpandedSize
对我没有帮助,因为视图被垂直添加了几次以填充布局。
解决方案是将自定义视图设置宽度覆盖intrinsicContentSize
为最大屏幕宽度:
- (CGSize)intrinsicContentSize {
//fills empty space. View will be resized to be smaller, but if it is too small - then it stays too small
CGRect frame = self.frame;
frame.size.width = MAX(SCREEN_WIDTH, SCREEN_HEIGHT);
return frame.size;
}
在设置您的导航控制器时
您所要做的就是将 translatesAutoresizingMaskIntoConstraints 设置为 false 检查苹果文档
请注意,自动调整掩码约束完全指定了视图的大小和位置;因此,您不能添加额外的约束来修改此大小或位置而不引入冲突。如果要使用 Auto Layout 动态计算视图的大小和位置,则必须将此属性设置为 false
然后将其分配给您想要的宽度
navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = false
lazy var titleWidth = view.frame.size.width / 2
navigationItem.titleView?.constrainWidth(constant: titleWidth)