iOS 7: UITableView показывает в строке состояния
первый экран моего приложения UITableViewController
без панели навигации, что означает, что содержимое течет под строкой состояния, так что есть много текстовых коллизий. Я настроил оба свойства для Under top bars
и Adjust scroll view insets
которые на самом деле останавливают его от прокрутки вниз, но за счет сохранения верхней части представления таблицы. Я попытался установить UITableView
кадр для смещения на 20 пикселей, но он, похоже, не вступает в силу, и в настоящее время мне нужно, чтобы приложение было совместимо с iOS 6 я не могу перейти на iOS 7 раскадровки, чтобы заставить autolayout использовать руководство по верхней высоте. Кто-нибудь нашел решение, которое работает для обеих версий?
вещи, которые я пробовал: задание edgesForExtendedLayout
, изменение настроек в раскадровке для Under top bars
и Adjust scroll view
, заставляя кадр в новую область.
картинка стоит тысячи слов:
25 ответов:
для тех, кто заинтересован в тиражировании этого, просто выполните следующие действия:
- создать новый проект iOS
- откройте основную раскадровку и удалите значение по умолчанию / initial
UIViewController
- перетащите новый
UITableViewController
из библиотеки объектов- установите его в качестве начального контроллера вида
- накормите таблицу некоторыми тестовыми данными
если вы выполните описанные выше шаги, при запуске приложения, вы увидите, что ничего, в том числе настройка флажков Xcode для "расширения краев под {Top, Bottom, Opaque} Bars" работает, чтобы остановить появление первой строки в строке состояния, и вы не можете решить это программно.
например, в приведенном выше сценарии следующее будет иметь нет эффект:
// These do not work self.edgesForExtendedLayout=UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars=NO; self.automaticallyAdjustsScrollViewInsets=NO;
эта проблема может быть очень неприятно, и я считаю, что это ошибка на конце Apple, особенно потому, что она появляется в их собственной предварительно проводной
UITableViewController
из объекта библиотека.Я не согласен со всеми, кто пытается решить эту проблему с помощью любой формы "магических чисел", например "использовать дельту 20px". Такого рода тесно связанное Программирование, безусловно, не то, что Apple хочет, чтобы мы здесь делали.
я нашел два решения этой проблемы:
сохранение
UITableViewController
С места:
Если вы хотите сохранитьUITableViewController
в раскадровке, без ручного размещения его в другой вид, вы можете встроитьUITableViewController
наUINavigationController
(редактор > встроить в > навигационный контроллер) и снимите флажок "показывает панель навигации" в инспекторе. Это решает проблему без необходимости дополнительной настройки, а также сохраняет свойUITableViewController
сцена в раскадровке.С помощью автозапуска и встраивания
UITableView
в другой вид(я считаю, что именно так Apple хочет, чтобы мы это сделали):
Создать пустойUIViewController
и перетащите вашUITableView
в нем. Затем, Ctrl-перетащите из вашегоUITableView
к строке состояния. Когда мышь попадает в нижнюю часть строки состояния, вы увидите пузырь автозапуска, который говорит "Top Layout Guide". Отпустите кнопку мыши и выберите "вертикальный интервал". Это подскажет системе компоновки разместить его прямо под строкой состояния.Я проверил оба способа на пустом приложении, и они оба работают. Возможно, вам придется сделать некоторые дополнительные настройки, чтобы заставить их работать на ваш проект.
если вы делаете вещи программно и с помощью
UITableViewController
безUINavigationController
лучше всего сделать следующее вviewDidLoad
:Swift 3
self.tableView.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)
Ранее Swift
self.tableView.contentInset = UIEdgeInsetsMake(20.0f, 0.0f, 0.0f, 0.0f);
The
UITableViewController
будет по-прежнему прокручиваться за строку состояния, но не будет под ней при прокрутке вверх.
обратите внимание: это работало для меня для следующей конфигурации:
- нет панели навигации в верхней части экрана (вид таблицы соответствует строке состояния)
- вид таблицы не прокручивается
Если вышеуказанные два требования не выполняются, ваш пробег может отличаться.
Оригинальное Сообщение
Я создал свое представление программно, и это в конечном итоге работает для я:
- (void) viewDidLayoutSubviews { // only works for iOS 7+ if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; // snaps the view under the status bar (iOS 6 style) viewBounds.origin.y = topBarOffset * -1; // shrink the bounds of your view to compensate for the offset viewBounds.size.height = viewBounds.size.height + (topBarOffset * -1); self.view.bounds = viewBounds; } }
источник (in topLayoutGuide раздел в нижней части страницы.39).
добавление к верхнему ответу:
после того, как 2-й метод изначально не работал, я сделал некоторые дополнительные манипуляции и нашел решение.
TLDR; 2-е решение верхнего ответа почти работает, но для некоторых версий Xcode ctrl+перетаскивание в "Top Layout Guide" и выбор вертикального интервала ничего не делает. Однако сначала отрегулируйте размер табличного представления, а затем выберите " верхнее пространство для верхнего руководства по компоновке" работает
перетащите пустой ViewController на раскадровку.
перетащите UITableView объект в поле зрения. (Не UITableViewController). Расположите его в самом центре с помощью синих направляющих макета.
- перетащите UITableViewCell в TableView. Это будет ваша ячейка повторного использования прототипа, поэтому не забудьте установить ее Повторно используйте идентификатор на вкладке атрибуты или вы получите сбой.
создайте свой собственный подкласс UIViewController и добавьте
<UITableViewDataSource, UITableViewDelegate>
протоколов. Не забудьте установить ViewController раскадровки в этот класс в Инспекторе идентификации.создайте выход для вашего TableView в файле реализации и назовите его "таблица"
- щелкните правой кнопкой мыши TableView и перетащите как источник данных, так и делегат на ваш ViewController.
теперь для части не обрезки в строке состояния.
- возьмите верхний край представления таблицы и переместите его вниз к одной из пунктирных синих направляющих автоматической компоновки, которые находятся рядом с топ
- теперь вы можете управлять перетаскиванием из табличного представления в верхнюю часть и выбрать Top Space to Top Layout Guide
- это даст вам ошибку о неоднозначной компоновке TableView, просто добавьте отсутствующие ограничения и ваше дело.
теперь вы можете настроить свой вид таблицы как обычно, и он не будет обрезать строку состояния!
- (void) viewDidLayoutSubviews { if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) { self.navigationController.navigationBar.barStyle = UIBarStyleBlackOpaque; if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) self.edgesForExtendedLayout = UIRectEdgeNone; // iOS 7 specific CGRect viewBounds = self.view.bounds; CGFloat topBarOffset = self.topLayoutGuide.length; viewBounds.origin.y = topBarOffset * -1; self.view.bounds = viewBounds; self.navigationController.navigationBar.translucent = NO; } }
вот как это написать в " Swift" Поправка к ответу @ lipka:
tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
выберите UIViewController на раскадровке снимите флажок расширить края под верхней панели. Работать на меня. :)
это исправит его для UITableViewController (без каких-либо магических чисел). Единственное, что я не мог заставить его исправить, это если вы находитесь на телефонном звонке, и в этом случае верхняя часть tableView слишком сильно нажата. Если кто-то знает, как решить эту проблему, пожалуйста, дайте нам знать.
class MyTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() configureTableViewTop() } override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) { super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator) coordinator.animateAlongsideTransition({ (context) -> Void in }, completion: { (context) -> Void in self.configureTableViewTop() }) } func configureTableViewTop() { tableView.contentInset.top = UIApplication.sharedApplication().statusBarFrame.height } }
Я не знаю, насколько это кошерно, но я обнаружил, что эта схема перемещает представление ViewController вниз и предоставляет строку состояния с твердым фоном:
- (void)viewDidLoad { [super viewDidLoad]; // Shove everything down if iOS 7 or later float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { // Move the view down 20 pixels CGRect bounds = self.view.bounds; bounds.origin.y -= 20.0; [self.view setBounds:bounds]; // Create a solid color background for the status bar CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20); UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame]; statusBar.backgroundColor = [UIColor redColor]; [self.view addSubview:statusBar]; }
конечно, заменить
redColor
С любым цветом, который вы хотите для фона.вы должны отдельно сделать один из поворотов, чтобы установить цвет символов / символов в строке состояния. Я использую
View controller-based status bar appearance = NO
иStatus bar style = Opaque black style
в plist, чтобы сделать это глобально.кажется, работает, и я был бы интересно услышать о каких-либо ошибок или проблем с ним.
ответ chappjc отлично работает при работе с XIBs.
Я нашел самое чистое решение при создании tableviewcontrollers программно, обернув экземпляр UITableViewController в другой UIViewController и установив соответствующие ограничения.
вот это:
UIViewController *containerLeftViewController = [[UIViewController alloc] init]; UITableViewController *tableViewController = [[UITableViewController alloc] init]; containerLeftViewController.view.backgroundColor = [UIColor redColor]; hostsAndMoreTableViewController.view.translatesAutoresizingMaskIntoConstraints = NO; [containerLeftViewController.view addSubview:tableViewController.view]; [containerLeftViewController addChildViewController:tableViewController]; [tableViewController didMoveToParentViewController:containerLeftViewController]; NSDictionary * viewsDict = @{ @"tableView": tableViewController.view , @"topGuide": containerLeftViewController.topLayoutGuide, @"bottomGuide": containerLeftViewController.bottomLayoutGuide, }; [containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[tableView]|" options:0 metrics:nil views:viewsDict]]; [containerLeftViewController.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:[topGuide][tableView][bottomGuide]" options:0 metrics:nil views:viewsDict]];
Ура, Бен
Я думаю, что подход к использованию UITableViewController может немного отличаться от того, что вы делали раньше. Это сработало для меня, но вы не можете быть поклонником этого. То, что я сделал, это иметь контроллер вида с видом контейнера, который указывает на мой UItableViewController. Таким образом, я могу использовать TopLayoutGuide, предоставленный моему в раскадровке. Просто добавьте ограничение в представление контейнера, и вы должны позаботиться как о iOS7, так и о iOS6.
в итоге я использовал один дополнительный вид с желаемым фоном, добавленный после TableView и помещенный в строку состояния:
self.CoverView = [[UIView alloc]init]; if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0) { self.CoverView.frame = CGRectMake(0,0,self.view.bounds.size.width,20); } self.CoverView.backgroundColor = [UIColor whiteColor]; self.TableView = [[UITableView alloc]initWithFrame:CGRectMake(0, self.CoverView.bounds.size.height,XXX, YYY)]; [self.view addSubview:self.TableView]; [self.view addSubview:self.CoverView];
это не очень красиво, но это довольно простое решение, если вам нужна работа с xib-менее представлениями, и как IOS6, так и IOS7
Я сделал это для Retina / Non-Retina display как
BOOL isRetina = FALSE; if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { if ([[UIScreen mainScreen] scale] == 2.0) { isRetina = TRUE; } else { isRetina = FALSE; } } if (isRetina) { self.edgesForExtendedLayout=UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars=NO; self.automaticallyAdjustsScrollViewInsets=NO; }
следующее решение достаточно хорошо работает в коде без использования магических констант и учитывает изменение пользователем класса размера, например, путем вращения или бок о бок приложений на iPad:
- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection { [super traitCollectionDidChange:previousTraitCollection]; // Fix up content offset to ensure the tableview isn't underlapping the status bar. self.tableView.contentInset = UIEdgeInsetsMake(self.topLayoutGuide.length, 0.0, 0.0, 0.0); }
работает для swift 3-In viewDidLoad ();
let statusBarHeight = UIApplication.shared.statusBarFrame.height let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0) tableView.contentInset = insets tableView.scrollIndicatorInsets = insets
этот код: 1. Возвращает высоту строки состояния 2. В верхней части таблицы отображается вставка содержимого, равная высоте строки состояния. 3. Дает индикатору прокрутки ту же вставку, поэтому он появляется под строкой состояния.
У меня был UISearchBar в верхней части моего UITableView и следующее работало;
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0); self.tableView.contentOffset = CGPointMake(0, -20);
поделиться и наслаждаться...
Abrahamchez по https://developer.apple.com/library/ios/qa/qa1797/_index.html работал для меня следующим образом. У меня был один UITableviewcontroller в качестве моего первоначального представления. Я попробовал код смещения и встраивание в navcon, но ни один не решил прозрачность строки состояния.
добавьте Viewcontroller и сделайте его начальным видом. Это должно показать вам критические верхние и нижние направляющие макета.
перетащите старый Tableview в представление в новом контроллер.
сделайте все, чтобы обновить таблицу в новый контроллер:
измените свой старый контроллер вида.H файл для наследования / подкласса от UIViewController вместо UITableViewController.
добавьте UITableViewDataSource и UITableViewDelegate в viewcontroller .з.
повторно подключите все необходимое в раскадровке, например панель поиска.
самое главное - настроить ограничения, как в Apple Q&A. я этого не делал потрудитесь вставить панель инструментов. Не уверен в точной последовательности. Но красный значок появился на направляющих макета, возможно, когда я построил. Я щелкнул его и позволил Xcode установить/очистить ограничения.
затем я щелкнул везде, пока не нашел ограничение вертикального пространства и не изменил его верхнее значение от -20 до 0, и он работал отлично.
Я использую UISplitViewController с navigationcontroller и tableviewcontroller. Это сработало для меня в главном представлении после попытки многих решений здесь:
float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { // Move the view down 20 pixels CGRect bounds = self.view.bounds; bounds.origin.y -= 20.0; [self.navigationController.view setBounds:bounds]; // Create a solid color background for the status bar CGRect statusFrame = CGRectMake(0.0, -20.0, bounds.size.width, 20); UIView* statusBar = [[UIView alloc] initWithFrame:statusFrame]; statusBar.backgroundColor = [UIColor whiteColor]; [statusBar setAlpha:1.0f]; [statusBar setOpaque:YES]; [self.navigationController.view addSubview:statusBar]; }
это похоже на решение Hot Licks, но применяет подвид к navigationController.
override func viewDidLoad() { // your code if let nc = self.navigationController { yourView.frame.origin.y = nc.navigationBar.frame.origin.y + nc.navigationBar.frame.height } }
вот Swift 2.3. Решение (Xcode версии 8.0). Я создал подкласс UITableView.
class MYCustomTableView: UITableView { override func drawRect(rect: CGRect) { super.drawRect(rect) contentInset = UIEdgeInsetsZero } }
вставка содержимого всегда должна быть равна нулю (по умолчанию). Я устанавливаю его ноль вручную. Вы также можете добавить метод проверки, который делает проверку, и если это что-то другое, чем вы хотите, чтобы это было просто получить правильный рект. Изменение будет отражаться только тогда, когда tableview рисуется (что происходит не часто).
Не забудьте обновить TableView в вашем IB (в TableViewController или просто TableView внутри вашего ViewController).
показать все решения: мой проект просто использует xib, поэтому решение с раскадровкой не сработало для меня. личность.edgesForExtendedLayout = UIRectEdgeNone; просто работает для контроллера, если навигационная панель видна. но если ваше представление просто имеет строку состояния, это не будет работать. так что я совмещаю два условия.
- (void) viewDidLayoutSubviews { float systemVersion = [[[UIDevice currentDevice] systemVersion] floatValue]; if (systemVersion >= 7.0f) { CGRect bounds = self.view.bounds; if(self.navigationController == nil || self.navigationController.isNavigationBarHidden == YES){ bounds.origin.y -= 20.0; [self.view setBounds:bounds]; } else{ self.edgesForExtendedLayout = UIRectEdgeNone; } }
помогите это работает.
Если вам нужна поддержка iOS 6, вам придется условно переместить его вниз. То есть, в iOS 7 Вы должны просто переместить его вниз на 20 пунктов (либо через
frame
манипуляция или использование авто-макета), а в iOS 6 Вы оставляете его в покое. Я не верю, что вы можете сделать это в IB, поэтому вам придется сделать это в коде.EDIT
вы можете сделать это в IB, используя дельты iOS6/iOS7. Установите свою позицию в iOS 7, Затем для iOS 6 Установите delta Y в -20points. Смотрите это так вопрос для получения дополнительной информации.