iOS 11 navigationItem.ширина titleView не установлена
просмотр поведения на iOS11 с помощью navigationItem.titleView, где ширина titleView не является полной шириной экрана.
У меня есть пользовательский вид, который я установил как titleView. До iOS11 вид будет заполнять область панели навигации. Но iOS 11 не изменяет размер, чтобы заполнить ширину экрана.
Я попытался установить рамку представления перед установкой titleView, но не повезло. Я попытался принудить titleviews superview к ограничениям макета тоже, но не повезло.
рисунки:
iOS10:
iOS11:
кто-нибудь еще испытать это?
12 ответов
я понял. Мне пришлось переопределить геттер intrinsicContentSize для представления и текстовое поле.
Я установил ширину в CGFloat.greatestFiniteMagnitude, поэтому он всегда будет таким же широким, как экран.
обновление:
Так как я потратил пару часов на этот вопрос, надеюсь, что некоторые другие догонят быстрее, имея все вещи плотно вместе
Я создал пользовательский подкласс TitleView
, под названием CustomTitleView
, вот код:
import UIKit
class CustomTitleView: UIView {
override var intrinsicContentSize: CGSize {
return UILayoutFittingExpandedSize
}
}
и самая важная часть, которую я пропустил с самого начала, была такая:
используя ответ @falkon вот код:
добавьте этот код в представление, которое используется как titleView
override var intrinsicContentSize: CGSize {
return UILayoutFittingExpandedSize
}
исправлено путем создания подкласса UIView и присвоено ему представление заголовка UINavigationController
Цель-C:
#import "FLWCustomTitleView.h"
@implementation FLWCustomTitleView
- (CGSize )intrinsicContentSize {
return UILayoutFittingExpandedSize;
}
@end
Я должен был соответствовать 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;
самое главное, что вам нужно перезаписать 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
}
вы также можете использовать ограничения, если не хотите переопределять 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 = ...
}
но если есть более одного navigationbaritems на любой стороне (слева или справа) navigationbar, вы должны использовать intrinsicContentSize;
когда у вас есть UIView как subview внутри CustomTitleView, решение intrinsicContentSize не работает, для меня в XCODE 9 только в iOS 11. так что мне понравилось ниже, отлично работает для меня, может это кому-то поможет.
@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];
}
}
у меня была та же проблема, но с установкой 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;
}
попробуйте использовать стандартный 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
дополнение к существующим ответы:
если ваш пользовательский вид заголовка является видом это уже имеет внутренний размер контента по умолчанию (кроме .zero
), например a UILabel
, a UITextView
или UIButton
, вы можете просто установить
yourCustomTitleView.translatesAutoresizingMaskIntoConstraints = false
и он будет автоматически настраиваться, чтобы просто заключать его содержимое, но никогда не перекрываться с представлениями левого и правого элементов.
для например, вы можете перетащить кнопку в область просмотра заголовка панели навигации в Interface Builder, создать выход titleButton
для него в вашем контроллере зрения, а затем сделайте
override func viewDidLoad() {
super.viewDidLoad()
titleButton.translatesAutoresizingMaskIntoConstraints = false
}