简体   繁体   English

iOS 11 navigationItem.titleView 宽度未设置

[英]iOS 11 navigationItem.titleView Width Not Set

Seeing a behavior on iOS11 with a navigationItem.titleView where the width of the titleView is not the full width of the screen.使用 navigationItem.titleView 在 iOS11 上看到一个行为,其中 titleView 的宽度不是屏幕的整个宽度。

I have a custom view that I set as the titleView.我有一个自定义视图,我将其设置为 titleView。 Previous to iOS11 the view would fill the navigation bar area.在 iOS11 之前,视图将填充导航栏区域。 But iOS 11 it is not resizing to fill the width of the screen.但是 iOS 11 并没有调整大小来填充屏幕的宽度。

I've tried setting the frame of the view before setting titleView but no luck.我试过在设置 titleView 之前设置视图的框架,但没有成功。 I've tried to force the titleViews superview to layout constraints as well but no luck.我也试图强制 titleViews 超级视图布局约束,但没有成功。

Screenshots attached:附上截图:

iOS10: iOS10:

在此处输入图像描述

iOS11: iOS11:

在此处输入图像描述

Anyone else experience this?还有其他人遇到过这个吗?

I figured it out.我想到了。 I had to override the intrinsicContentSize getter for the view, and the text field.我必须覆盖视图和文本字段的 intrinsicContentSize getter。

I set the width to CGFloat.greatestFiniteMagnitude so it'll always be as wide as the screen.我将宽度设置为 CGFloat.greatestFiniteMagnitude 所以它总是和屏幕一样宽。

Update:更新:

Since I've spent couple of hours on this issue, hope that some else will catch up faster by having all things tight up together因为我在这个问题上花了几个小时,希望其他人能通过把所有事情都紧密地放在一起来更快地赶上

I've created a custom sub class of TitleView , called CustomTitleView , here's the code:我创建了TitleView的自定义子类,称为CustomTitleView ,代码如下:

import UIKit

class CustomTitleView: UIView {

  override var intrinsicContentSize: CGSize {
    return UIView.layoutFittingExpandedSize
  }
}

and the most important part which I missed from the start was this:我从一开始就错过的最重要的部分是:

在此处输入图像描述

Using @falkon's answer here's the code:使用@falkon 的答案是代码:

Add this code to the view that is used as titleView将此代码添加到用作 titleView 的视图

override var intrinsicContentSize: CGSize {
    return UILayoutFittingExpandedSize
} 

Fixed it by creating a subclass of UIView and assigned it to a title view of UINavigationController通过创建 UIView 的子类并将其分配给 UINavigationController 的标题视图来修复它

Objective-C:目标-C:

#import "FLWCustomTitleView.h"

@implementation FLWCustomTitleView

- (CGSize )intrinsicContentSize {
  return UILayoutFittingExpandedSize;
}

@end

在此处输入图像描述 在此处输入图像描述

setting intrinsicContentSize to UILayoutFittingExpandedSize works fine as wellintrinsicContentSize设置为UILayoutFittingExpandedSize也可以正常工作

I had to fit an UIImageView as navigationItem.titleView.我必须将 UIImageView 设置为 navigationItem.titleView。 The aspect ratio did fit but the intrinsicContentSize made it to large.纵横比确实合适,但 intrinsicContentSize 使其变大了。 Scaling the image led to poor image quality.缩放图像导致图像质量差。 Setting layout anchors worked for me:设置布局锚点对我有用:

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;

Addition to the existing answers:除了现有的答案:

If your custom title view is a view that already has an intrinsic content size by default (other than .zero ), for example a UILabel , a UITextView or a UIButton , you can simply set如果您的自定义标题视图是默认情况下已经具有固有内容大小的视图(除了.zero ),例如UILabelUITextViewUIButton ,您可以简单地设置

yourCustomTitleView.translatesAutoresizingMaskIntoConstraints = false

and it will automatically adjust to just enclose its contents, but never overlap with the left and right item views.并且它会自动调整以仅包含其内容,但不会与左右项目视图重叠。


For example, you can drag a button into the title view area of a navigation bar in Interface Builder, create an outlet titleButton for it in your view controller and then do例如,您可以将一个按钮拖到 Interface Builder 中导航栏的标题视图区域,在您的视图控制器中为它创建一个插座titleButton然后执行

override func viewDidLoad() {
    super.viewDidLoad()
    titleButton.translatesAutoresizingMaskIntoConstraints = false
}

Swift 4.2 Version of Yedy's answer 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

Converted with the help of Swiftify .Swiftify的帮助下转换。

The most important is that you need overwrite customTitleView as your titleView:最重要的是你需要覆盖 customTitleView 作为你的 titleView:

self.navigationItem.titleView = [self 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
}

在此处输入图像描述

在此处输入图像描述

When you have a UIView as subview inside CustomTitleView, intrinsicContentSize solution does not work, for me in XCODE 9 in iOS 11 only.当您在 CustomTitleView 中有一个 UIView 作为子视图时,intrinsicContentSize 解决方案不起作用,仅对我在 iOS 11 的 XCODE 9 中。 so I did like below, works fine for me, might this help someone.所以我确实喜欢下面的内容,对我来说效果很好,这可能对某人有帮助。

@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];
    }
}

This class will do the trick.这个类会做的伎俩。 Make sure you set your custom view's class to this one:确保将自定义视图的类设置为此:

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)
    }

}

You can also use constraints if you don't want to override intrinsicContentSize .如果您不想覆盖intrinsicContentSize ,也可以使用约束。 Here's a demo of SnapKit这是 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 = ...
}

But if there are more than one navigationbaritems on any side(left or right) navigationbar, you should use intrinsicContentSize;但是,如果在任何一侧(左侧或右侧)导航栏上有多个导航栏项目,则应使用 intrinsicContentSize;

I had the same issue but with setting an UIImage as the navigationItem titleView我遇到了同样的问题,但是将UIImage设置为navigationItem titleView

What i did is i scaled the image to the needed size by using the below:我所做的是使用以下方法将图像缩放到所需的大小:

-(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;
}

And call it as follows:并按如下方式调用它:

-(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 not helped me, because view was added vertically few more times to fill layout. return UILayoutFittingExpandedSize对我没有帮助,因为视图被垂直添加了几次以填充布局。

The solution was to override intrinsicContentSize in custom view setting width to max screen width:解决方案是将自定义视图设置宽度中的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;
}

Try using the Standard UISearchBar / UISearchController尝试使用标准 UISearchBar / UISearchController

Actually what you need to do - if you can use a standard UISearchBar / a UISearchController is to display the search bar the following way which respects the safe area and thus looks perfect on iPhone X and in each device orientation:实际上你需要做的 - 如果你可以使用标准的 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)
    }
}

References参考

https://developer.apple.com/videos/play/fall2017/201/ https://medium.com/@PavelGnatyuk/large-title-and-search-in-ios-11-514d5e020cee https://developer.apple.com/videos/play/fall2017/201/ https://medium.com/@PavelGnatyuk/large-title-and-search-in-ios-11-514d5e020cee

on setup -ing your navigation controller在设置您的导航控制器时

all you have to do is setting translatesAutoresizingMaskIntoConstraints to false check apple doc您所要做的就是将 translatesAutoresizingMaskIntoConstraints 设置为 false check apple doc

Note that the autoresizing mask constraints fully specify the view's size and position;请注意,自动调整掩码约束完全指定了视图的大小和位置; therefore, you cannot add additional constraints to modify this size or position without introducing conflicts.因此,您不能在不引入冲突的情况下添加额外的约束来修改此大小或位置。 If you want to use Auto Layout to dynamically calculate the size and position of your view, you must set this property to false如果你想使用自动布局来动态计算视图的大小和位置,你必须将这个属性设置为 false

then assign it to the width you wish然后将它分配给你想要的宽度

navigationItem.titleView?.translatesAutoresizingMaskIntoConstraints = false

lazy var titleWidth =  view.frame.size.width / 2

navigationItem.titleView?.constrainWidth(constant: titleWidth)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM