IOS 7: UITableView отображается в строке состояния

Первым экраном моего приложения является UITableViewController без панели навигации, что означает, что содержимое перетекает в строку состояния, поэтому есть много текстовых коллизий. Я скорректировал оба свойства для Under top bars и Adjust scroll view insets, которые фактически не позволяют его прокручивать, но за счет сохранения верхней части представления таблицы. Я попытался установить фрейм UITableView на 20 пикселей, но он не вступает в силу, и поскольку в настоящее время мне нужно приложение для совместимости с iOS 6, я не могу перейти на iOS 7 Storiesboards, чтобы заставить autolayout использовать верхнюю направляющую высоты. Кто-нибудь нашел решение, которое работает для обеих версий?

Вещи, которые я пробовал: установили edgesForExtendedLayout, изменив настройки в Storyboard на Under top bars и Adjust scroll view, заставив кадр в новую область.

Картинка стоит тысячи слов: Status bar flow under

Ответ 1

Для всех, кто заинтересован в повторном копировании, просто выполните следующие действия:

  • Создайте новый проект iOS
  • Откройте основную раскадровку и удалите стандартный/начальный UIViewController
  • Вытащите новый UITableViewController из библиотеки объектов
  • Установите его как контроллер начального представления
  • Подготовьте таблицу к некоторым тестовым данным.

Если вы выполните описанные выше шаги, при запуске приложения вы увидите, что ничего, в том числе настройка галочек Xcode на "Расширение границ в верхних, нижних, непрозрачных барах" работает, чтобы остановить появление первой строки под и вы не можете обращаться к этому программному обеспечению.

например. В приведенном выше сценарии следующее будет иметь эффект нет:

// These do not work
self.edgesForExtendedLayout=UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars=NO;
self.automaticallyAdjustsScrollViewInsets=NO;

Эта проблема может быть очень неприятной, и я считаю, что это ошибка на конце Apple, особенно потому, что она отображается в их собственном предварительно подключенном UITableViewController из библиотеки объектов.

Я не согласен со всеми, кто пытается решить это, используя любую форму "Магических чисел", например. "используйте дельта 20px". Такой тип тесно связанного программирования определенно не то, что Apple хочет, чтобы мы здесь сделали.

Я обнаружил два решения этой проблемы:

  • Сохранение сцены UITableViewController:
    Если вы хотите сохранить UITableViewController в раскадровке, не помещая вручную его в другое представление, вы можете вставить UITableViewController в UINavigationController (Редактоp > Вставить > Контроллер навигации) и снять флажок "Показывать панель навигации", в инспекторе. Это решает проблему без дополнительной настройки, а также сохраняет вашу сцену UITableViewController в раскадровке.

  • Использование AutoLayout и вставка UITableView в другое представление (я полагаю, именно так Apple хочет, чтобы мы это сделали):
    Создайте пустой UIViewController и перетащите его UITableView в него. Затем, Ctrl-перетащите из UITableView в строку состояния. Когда мышь попадает в нижнюю часть строки состояния, вы увидите пузырь Autolayout, в котором говорится "Руководство по началу макета". Отпустите мышь и выберите "Вертикальный интервал". Это скажет системе макета, чтобы она была расположена под панелью состояния.

Я тестировал оба пути в пустом приложении, и они оба работают. Возможно, вам понадобится сделать дополнительную настройку, чтобы заставить их работать для вашего проекта.

Ответ 2

Если вы делаете что-то программно и используете 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);

UITableViewController по-прежнему будет прокручиваться за панель состояния, но не будет находиться под ней при прокрутке вверх.

Ответ 3

Обратите внимание: Это работало для меня для следующей конфигурации:

  • В верхней части экрана нет панели навигации (представление таблицы соответствует строке состояния)
  • Вид таблицы не прокручивается

Если вышеуказанные два требования не выполняются, ваше перемещение может меняться.

Оригинальная публикация

Я создал свое представление программно, и это закончилось для меня работой:

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

Источник (в разделе topLayoutGuide внизу страницы стр. 39).

Ответ 4

Добавление в верхний ответ:

после того, как 2-й метод изначально не работал, я немного потрудился и нашел решение.

TL;DR; верхний ответ 2-го решения почти работает, но для некоторых версий xCode ctrl + перетаскивание в "Руководство по верхнему макету" и выбор вертикального интервала ничего не делает. Однако, сначала отрегулировав размер Table View, а затем выбрав "Top Space to Top Layout Guide", выполните


  • Перетащите пустой ViewController на раскадровку. View Controller

  • Перетащите объект UITableView в представление. (Не UITableViewController). Расположите его в самом центре, используя синие направляющие макета.

Table ViewCenter Image

  1. Перетащите UITableViewCell в TableView. Это будет ваша ячейка повторного использования прототипа, поэтому не забудьте установить ее "Идентификатор повторного использования" на вкладке "Атрибуты" или вы получите сбой.

Add Table View CellReuse Identifier

  1. Создайте свой собственный подкласс UIViewController и добавьте протоколы <UITableViewDataSource, UITableViewDelegate>. Не забудьте установить свой раскадровщик ViewController в этот класс в Identity Inspector.

  2. Создайте выход для своего TableView в вашем файле реализации и назовите его "tableView"

Create OutlettableView

  1. Щелкните правой кнопкой мыши TableView и перетащите как источник данных, так и делегат в свой ViewController.

dataSource delegate

Теперь для части не обрезания в строке состояния.

  1. Захватите верхний край вашего вида таблицы и переместите его вниз к одному из прошивных синих руководств по автоматической компоновке, которые находятся в верхней части

resize

  1. Теперь вы можете управлять перетаскиванием из табличного представления вверху и выбрать "Руководство по верхнему пространству в верхнем макете"

Top Space to Top Layout Guide

  1. Это даст вам ошибку в отношении двусмысленного макета TableView, просто добавьте недостающие ограничения и сделанные вами.

Add Missing Constraints

Теперь вы можете настроить представление таблицы как обычно, и оно не будет обрезать строку состояния!

Ответ 5

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

https://developer.apple.com/library/ios/documentation/userexperience/conceptual/TransitionGuide/SupportingEarlieriOS.html#//apple_ref/doc/uid/TP40013174-CH14-SW1

Ответ 6

Вот как это записать в "Swift" Коррекция ответа @lipka:

tableView.contentInset = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)

Ответ 7

Выберите UIViewController на вашем раскадровке и снимите флажок "Расширять края под верхними барами". Работал для меня. :)

Ответ 8

Для Xcode 7, без отметки "полупрозрачная" галочка для панели навигации, работала для меня.

введите описание изображения здесь

Ответ 9

Это исправит его для UITableViewController (без каких-либо магических чисел). Единственное, что я не мог исправить, это если вы звоните по телефону, и в этом случае верхняя часть таблицыView слишком сильно сдвинута. Если кто-то знает, как это решить, сообщите нам.

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

Ответ 10

В Swift 3:

edgesForExtendedLayout = []
extendedLayoutIncludesOpaqueBars = false
automaticallyAdjustsScrollViewInsets = false

Ответ 11

Я не знаю, как это кошерно, но я обнаружил, что эта схема перемещает вид 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 на любой цвет, который вы хотите для фона.

Вы должны отдельно выполнить один из swizzles, чтобы установить цвет символов/символов в строке состояния. Я использую View controller-based status bar appearance = NO и Status bar style = Opaque black style в plist, чтобы сделать это глобально.

Кажется, работает, и мне было бы интересно услышать о любых ошибках или проблемах с ним.

Ответ 12

Ответ chappjc отлично работает при работе с XIB.

Я нашел самое чистое решение при создании 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]];

Приветствия, Бен

Ответ 13

Я думаю, что подход к использованию UITableViewController может немного отличаться от того, что вы делали раньше. Он работал у меня, но вы, возможно, не поклонник этого. То, что я сделал, это иметь контроллер представления с видом контейнера, который указывает на мой UItableViewController. Таким образом, я могу использовать TopLayoutGuide для моего раскадровки. Просто добавьте ограничение в представление контейнера, и вам следует позаботиться о iOS7 и iOS6.

Ответ 14

В итоге я использовал один дополнительный вид с желаемым фоном, добавленный после 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

Ответ 15

Следующее решение работает достаточно хорошо в коде без использования магических констант и учитывает пользователя, изменяющего класс размера, например. через вращения или бок о бок приложения на ipads:

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

Ответ 16

У меня был UISearchBar в верхней части моего UITableView и работало следующее:

self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
self.tableView.contentOffset = CGPointMake(0, -20);

Поделитесь и наслаждайтесь...

Ответ 17

Я сделал это для отображения Retina/Non-Retina как

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

Ответ 18

Я получил работу, установив размер в произвольную форму

enter image description here

Ответ 19

Решение Абрахамчеза https://developer.apple.com/library/ios/qa/qa1797/_index.html работал у меня следующим образом. У меня был единственный UITableviewcontroller в качестве моего первоначального представления. Я пробовал код смещения и встраивания в navcon, но не решил прозрачность прозрачности.

Добавьте Viewcontroller и сделайте его начальным. Это должно показать вам критические руководства для верхней и нижней макетов.

Перетащите старый Tableview в представление в новом контроллере.

Сделайте все, чтобы обновить таблицу до нового контроллера:

Измените свой старый файл view.h. view на inherit/subclass из UIViewController вместо UITableViewController.

Добавьте UITableViewDataSource и UITableViewDelegate в диспетчер представления .h.

Восстановите все, что необходимо в раскадровке, например, в Searchbar.

Самое главное - установить ограничения, как в Apple Q & A. Я не стал вставлять панель инструментов. Не определен точная последовательность. Но красный значок появился в макетах, возможно, когда я построил. Я щелкнул его и позвол Xcode установить/очистить ограничения.

Затем я щелкнул всюду, пока не нашел ограничение по вертикальному пространству и изменил его верхнее значение от -20 до 0, и он отлично работал.

Ответ 20

Я использую UISplitViewController с навигационным контроллером и контроллером tableview. Это сработало для меня в главном представлении после того, как вы использовали множество решений:

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, но применяет subview к navigationController.

Ответ 21

override func viewDidLoad() {
 // your code

 if let nc = self.navigationController {
   yourView.frame.origin.y = nc.navigationBar.frame.origin.y + nc.navigationBar.frame.height
  }
}

Ответ 22

Вот Swift 2.3. (Xcode 8.0). Я создал подкласс UITableView.

class MYCustomTableView: UITableView
{   
    override func drawRect(rect: CGRect) {
        super.drawRect(rect)
        contentInset    = UIEdgeInsetsZero
    }
}

Вставка содержимого всегда должна быть нулевой (по умолчанию). Я устанавливаю его ноль вручную. Вы также можете добавить метод проверки, который делает проверку, и если это что-то другое, кроме того, что вы хотите, чтобы он просто получил правильный прямоугольник. Это изменение будет отражать только при рисовании таблицы (что часто случается).

Не забудьте обновить TableView в своем IB (в TableViewController или просто TableView внутри вашего ViewController).

Ответ 23

Работает для быстрого 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. Дает индикатор прокрутки той же вставки, поэтому он отображается под строкой состояния.

Ответ 24

Я столкнулся с этой проблемой в ios 11, но макет был правильным для ios 8-10.3.3. Для моего случая я установил вертикальное пространственное ограничение для Superview.Top Margin вместо Superview.Top, которое работает для ios 8-11.

введите описание изображения здесь

Ответ 25

см. все решения: мой проект просто использует xib, поэтому решение с раскадрой не сработало для меня. self.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;
    }
}

Помогите, это сработает.

Ответ 26

Если вам также необходимо поддерживать iOS 6, вам придется условно переместить его. То есть, в iOS 7 вы должны просто сдвинуть его на 20 пунктов (либо с помощью frame манипуляции, либо с помощью автоматической компоновки), и в iOS 6 вы оставите его в покое. Я не верю, что вы можете сделать это в IB, так что вам придется делать это в коде.

ИЗМЕНИТЬ

Фактически вы можете сделать это в IB, используя дельта iOS6/iOS7. Установите свою позицию в iOS 7, затем для iOS 6 установите дельта Y в -20 точек. См. этот вопрос SO для получения дополнительной информации.

Ответ 27

Просто установите фрейм для таблицы. и положил его на 44p сверху. в iOS 7 Все началось с верхнего левого окна. Также строка состояния является частью окна.

Ответ 28

Кто ищет быстрый взлом

self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 20)];