UITableView位于半透明导航栏下

时间:2014-06-28 16:32:19

标签: ios objective-c uitableview uinavigationbar

我正在尝试在IOS 7应用中使用透明导航栏。我的应用程序中有一个全屏图像。我也在该图像上有一个UITableView。当我使用下面的代码时,图像适合我想要的屏幕,但UITableView在导航栏下。

viewDidLoad

中的

我用

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

当我更改为self.navigationController.navigationBar.translucent = NO;时,它正常,但我在导航栏上失去了透明度。

14 个答案:

答案 0 :(得分:65)

您可以设置tableView的contentInsets,使其最初位于导航栏下方,但会在其后滚动(内容会重叠)

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

或者你可以偏移tableview的框架。然后滚动内容将在导航栏下面切断(看起来也不好看)

答案 1 :(得分:47)

我的案例帮助了这个(Bill Chan的代码的修改版本):

目标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);
}

关键是必须按下导航栏的高度(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)
    }
}

答案 2 :(得分:26)

我对iOS 9有类似的问题。当我第一次打开viewController时,tableView位于顶部栏下面。滚动后的表格看起来一切正常。

  1. 选择您的视图控制器
  2. 点击“参数检查器”标签
  3. 取消选中“在顶栏下”
  4. enter image description here

答案 3 :(得分:8)

将tableview的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自动调整为“滚动视图集”,并将其更改为“

self.automaticallyAdjustsScrollViewInsets =  NO;

如果您支持不同的方向更新框架和contentInset到(52),因为横向模式下的导航栏高度为32。

检查此Sample

答案 4 :(得分:7)

这适用于iOS8中的横向模式和纵向模式:

- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];

  CGRect rect = self.navigationController.navigationBar.frame;

  float y = -rect.origin.y;

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

答案 5 :(得分:5)

最好不要将Inset值硬编码,因为它可能基于设备的方向。

<强>代码:

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

答案 6 :(得分:3)

大多数情况下,引入魔术常量的解决方案并不会缩放,例如,如果下一个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)
  ])
}

注意:在iOS 11中不推荐使用topLayoutGuide,我们应该使用UIView的safeAreaLayoutGuide属性。

答案 7 :(得分:2)

简介

我是iOS开发和Stack Overflow的新手,所以请原谅我,如果我的帖子不完美。

我也有这个问题,当我使用内容插入我的UITableView时在首先加载或从其他标签访问它时完美地工作;但是,如果我导航回视图,它将有额外的“填充”。我想出了一个解决方法,以便每次都能正确放置我的UITableView。

问题

首次加载UITableView或选项卡时,需要使用insets正确启动导航栏下方的表格,但是当您向后导航时它不需要插入,因为由于某种原因,它正确计算为UITableView的位置。这就是为什么你可以得到额外的填充。

解决方案

解决方案涉及使用布尔值来确定您是否已导航,以便它可以正确地确定是否需要内容插入。

-(void)viewDidLoad我设置{{ 1}}。然后:

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

答案 8 :(得分:1)

我提出了以下解决方案,首次导航到视图控制器时,会调整表视图的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;
    }
}

答案 9 :(得分:1)

只有此代码才能解决问题:

  @IBOutlet weak var tableView: UITableView!

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

答案 10 :(得分:0)

我结合了@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);
    }
}

希望这可以帮助那些浪费几个小时来处理这种奇怪的UI行为的人。

答案 11 :(得分:0)

将表格视图限制在导航栏的底部。表视图将自动偏移44,但在代码中我们可以这样做:

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

条形图是透明的,没有颜色,但表格视图根本不重叠。请注意,尽管导航栏是透明的,但“Hook”这个词会被切断。这仅适用于将表视图上边缘约束为导航栏中的0。 <= p>,不是0

enter image description here

答案 12 :(得分:0)

所有您需要的是这个:

tableView.contentInsetAdjustmentBehavior = .automatic

从iOS 11开始,几乎不需要做丑陋的魔法常数胡子

我什至不需要将contentInsetAdjustmentBehavior设置为.none 修复导航栏重叠。

.automatic

以某种方式自动工作 让我想知道为什么这不是默认设置。

答案 13 :(得分:0)

尝试使用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))