Подтвердить что ты не робот

UITableView находится под прозрачной навигационной панелью

Я пытаюсь создать прозрачную панель навигации в приложении IOS 7. В моем приложении есть полноэкранное изображение. У меня также есть UITableView над этим изображением. Когда я использую приведенный ниже код, изображение подходит для экрана, как я хочу, но UITableView находится под панелью навигации.

in viewDidLoad

Я использую

self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.view.backgroundColor = [UIColor clearColor];

это нормально, когда я переключаюсь на self.navigationController.navigationBar.translucent = NO;, но затем теряю прозрачность на панели навигации.

4b9b3361

Ответ 1

Вы можете установить contentInsets вашего tableView так, чтобы он находился под панелью навигации, но прокручивался позади него (содержимое будет перекрываться)

self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);

Или вы можете компенсировать рамку таблицы. Затем прокручиваемое содержимое будет отрезано под навигационной панелью (что тоже плохо выглядело)

Ответ 2

Мне помог этот случай (модифицированная версия кода Билла Чена):

Версия Objective C:

- (void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];   
    CGRect rect = self.navigationController.navigationBar.frame;
    float y = rect.size.height + rect.origin.y;
    self.tableView.contentInset = UIEdgeInsetsMake(y, 0, 0, 0);
}

Дело в том, что таблица должна быть сдвинута вниз для высоты навигацииBar (rect.size.height) плюс высота строки состояния (rect.origin.y);

версия Swift (также совместимая с Swift 2):

override func viewDidLayoutSubviews() {
    if let rect = self.navigationController?.navigationBar.frame {
        let y = rect.size.height + rect.origin.y
        self.tableView.contentInset = UIEdgeInsetsMake( y, 0, 0, 0)
    }
}

Ответ 3

У меня была аналогичная проблема для iOS 9. Когда я впервые открываю viewController, tableView находится под верхней панелью. Чем после прокрутки tableView все работает нормально.

  • Выберите контроллер просмотра
  • Перейдите на вкладку "Инспектор атрибутов"
  • Снимите флажок "Под верхними барами"

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

Ответ 4

Установите y-позицию таблицы для высоты навигационной панели плюс высоту строки состояния (пусть это будет height)

то есть,

  height = 64; // height of navigation bar = 44(In portait), height of status bar = 20
  tableView.frame = CGRectMake(tableView.frame.origin.x, height , tableView.frame.size.width, tableView.frame.size.height);

Если вы используете автозапуск, просто измените обновление верхнего ограничения tableView вместо изменения фрейма.

а также изменить viewController автоматическиAdjustsScrollViewInsets на NO

self.automaticallyAdjustsScrollViewInsets =  NO;

Если вы поддерживаете разные рамки обновления для ориентации и contentInset (52), поскольку высота полосы навигации в альбомном режиме составляет 32.

проверьте этот Пример

Ответ 5

Это работает как в ландшафтном режиме, так и в портретном режиме в iOS8:

- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];

  CGRect rect = self.navigationController.navigationBar.frame;

  float y = -rect.origin.y;

  self.tableView.contentInset = UIEdgeInsetsMake(y ,0,0,0);
}

Ответ 6

Лучше не жестко указывать значения вставки, поскольку это может быть основано на ориентации устройства.

Код:

func setTableViewContentInset() {

    let contentInsetHeight = topLayoutGuide.length
    let contentInset = UIEdgeInsetsMake(contentInsetHeight, 0, 0, 0)

    tableView.contentInset = contentInset
    tableView.scrollIndicatorInsets = contentInset
}

func scrollToTop() {

    if tableView.indexPathsForVisibleRows?.count > 0 {

        let topIndexPath = NSIndexPath(forRow: 0, inSection: 0)

        tableView.scrollToRowAtIndexPath(topIndexPath, atScrollPosition: .Top, animated: false)
    }
}

func scrollToTopOfVisibleCells() {

    if let visibleIndexPaths = tableView.indexPathsForVisibleRows where tableView.indexPathsForVisibleRows?.count > 0 {

        let topMostVisibleIndexPath = visibleIndexPaths[0]

        tableView.scrollToRowAtIndexPath(topMostVisibleIndexPath, atScrollPosition: .Top, animated: false)

    }        
}

//MARK: Load Views
override func viewDidLoad() {
    super.viewDidLoad()

    setTableViewContentInset()
}

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

    scrollToTop()
}

//MARK: Trait collection change
override func traitCollectionDidChange(previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    setTableViewContentInset()
    scrollToTopOfVisibleCells()
}

Ответ 7

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

К счастью, Apple предоставила нам более чистые способы преодоления этой проблемы, например topLayoutGuide:

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

Программно вы можете достичь с помощью следующего фрагмента кода (то же самое можно сделать и с помощью IB):

override func viewDidLoad() {
  super.viewDidLoad()

  automaticallyAdjustsScrollViewInsets = false
  tableView.translatesAutoresizingMaskIntoConstraints = false
  NSLayoutConstraint.activate([
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    tableView.topAnchor.constraint(equalTo: 
       topLayoutGuide.bottomAnchor),
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
  ])
}

Примечание. topLayoutGuide устарел в iOS 11, мы должны использовать свойство safeAreaLayoutGuide UIView,

Ответ 8

Введение

Я новичок в разработке iOS и переполнении стека, поэтому простите меня, если мой пост не идеален.

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

Проблема

Когда вы сначала загружаете UITableView или вкладку, ему нужны вставки, чтобы правильно запустить таблицу под панелью навигации, но когда вы перемещаетесь назад, ей не нужны вставки, потому что по какой-то причине она правильно вычисляет для размещение UITableView. Вот почему вы можете получить дополнительное дополнение.

Решение

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

В -(void)viewDidLoad я установил hasNavigatedFurther = NO. Тогда:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    if (!hasNavigatedFurther) {
        self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
    } else {
        self.tableView.contentInset = UIEdgeInsetsZero;
        //In order to allow visiting between tabs and retaining desired look
        hasNavigatedFurther = NO;
    }
}

Чтобы выполнить эту работу, вам нужно установить hasNavigatedFurther = YES непосредственно перед вашим кодом, который подталкивает другое представление к стеку навигации.

-(void)btnTouched:(id)sender {
    hasNavigatedFurther = YES;
    NextViewController* nvc = [NextViewController new];
    [self.navigationController pushViewController:nvc animated:YES];
}

Ответ 9

Я придумал следующее решение, которое при первом переходе к контроллеру представления настраивает табличное представление contentInset для высоты навигационной панели с учетом любого дополнения, которое может иметь верхняя ячейка. Когда вы возвращаетесь к этому контроллеру представления после нажатия другого контроллера представления в стек, я затем повторно настраиваю contentInset на UIEdgeInsetsZero:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self adjustEdgeInsetsForTableView];
}

- (void)adjustEdgeInsetsForTableView {
    if(self.isMovingToParentViewController) {
        self.tableViewForm.contentInset = UIEdgeInsetsMake(self.navigationController.navigationBar.frame.size.height + padding, 0, 0, 0);
    } else {
        self.tableViewForm.contentInset = UIEdgeInsetsZero;
    }
}

Ответ 10

Только этот код решает проблему:

  @IBOutlet weak var tableView: UITableView!

  func viewDidLoad() {
      super.viewDidLoad()
      self.tableView.contentInset = UIEdgeInsetsZero
  }

Ответ 11

Я объединил решения @Adam Farrell и @Tash Pemhiwa, и, наконец, приведенный ниже код работает для меня:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    [self adjustEdgeInsetsForTableView];
}



- (void)adjustEdgeInsetsForTableView
{
    if(self.isMovingToParentViewController) {
        self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
    } else {
        self.tableView.contentInset = UIEdgeInsetsMake(64, 0, 0, 0);
    }
}

Надеюсь, это поможет людям, которые тратят пару часов на это странное поведение пользовательского интерфейса.

Ответ 12

Ограничьте представление таблицы в нижней части панели навигации. Вид таблицы автоматически будет смещен на 44, но затем в коде мы можем просто сделать это:

tableView.contentInset = UIEdgeInsets(top: -44, left: 0, bottom: 0, right: 0)

Панель прозрачна и не имеет цвета, но вид таблицы не перекрывает ее вообще. Обратите внимание, что слово "Крюк" отключается, несмотря на то, что панель навигации прозрачна. Это будет работать только из-за того, что верхний край таблицы должен быть 0 из панели навигации. НЕ 0 из верхнего вида.

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

Ответ 13

попробуйте использовать layoutguide, чтобы исправить

var constraints = [NSLayoutConstraint]()   
let guide = view.safeAreaLayoutGuide
            constraints.append(self.tableView.leadingAnchor.constraint(equalTo: guide.leadingAnchor))
            constraints.append(self.tableView.trailingAnchor.constraint(equalTo: guide.trailingAnchor))
            constraints.append(self.tableView.topAnchor.constraint(equalTo: guide.topAnchor))
            constraints.append(self.tableView.bottomAnchor.constraint(equalTo: guide.bottomAnchor))

Ответ 14

Все, что вам нужно, это любовь это:

assert(tableView.contentInsetAdjustmentBehavior == .automatic)

нет нужды делать некрасивую магическую защиту от iOS 11 и выше

Мне даже не нужно было устанавливать contentInsetAdjustmentBehavior в .none исправить перекрытие navbar.

.automatic

работал автоматически