UITableView进入半透明的导航栏
我想在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;
但后来我在导航栏上失去了透明度。
你可以设置你的tableView的contentInsets,所以它最初位于导航栏的下方,但会在它后面滚动(内容会重叠)
self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);
或者你可以抵消tableview的框架。 然后,滚动内容将被切断在导航栏下面(这也不会很好看)
我的案子帮助了这个(比尔的代码的修改版本):
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); }
重点是该表必须下推导航栏的高度( rect.origin.y
)加上状态栏的高度( 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) } }
将tableview的y位置设置为导航栏的高度加上状态栏的height
(让它为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顶部约束,而不是更改框架。
并自动更改viewControllerAdjustsScrollViewInsets为NO
self.automaticallyAdjustsScrollViewInsets = NO;
如果您支持不同的方向更新框架和contentInset为(52),因为横向模式下的导航栏高度为32。
检查这个示例
这在iOS8的横向模式和纵向模式下都可以工作:
- (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; CGRect rect = self.navigationController.navigationBar.frame; float y = -rect.origin.y; self.tableView.contentInset = UIEdgeInsetsMake(y ,0,0,0); }
我有类似的问题为iOS 9.当我第一次打开viewController,tableView是在顶部栏。 滚动tableView后,一切工作正常。
- select你的视图控制器
- 点击“属性检查器”选项卡
- 取消勾选“顶部酒吧”
最好不要硬编码插入值,因为它可能基于设备的方向。
码:
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() }
介绍
我是iOS开发和堆栈溢出的新手,所以请原谅我,如果我的post不完美。
我也有这个问题,当我用我的UITableView的内容插入它完美加载第一,或从我的其他选项卡访问时,完美的工作; 但是,如果我导航回到视图,它将有额外的“填充”。 我想出了一个解决办法,以便我的UITableView将被正确放置每次。
问题
当你第一次加载UITableView或者Tab时,需要使用insets来正确的在导航栏下面启动表格,但是当你回到页面时并不需要insets,因为某些原因, UITableView。 这就是为什么你可以得到额外的填充。
解决scheme
解决scheme涉及使用布尔值来确定您是否已经导航,以便它可以正确地确定是否需要内容插入。
在-(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]; }
我想出了以下的解决scheme,第一次导航到视图控制器,调整表视图的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; } }
只有这个代码解决了这个问题:
@IBOutlet weak var tableView: UITableView! func viewDidLoad() { super.viewDidLoad() self.tableView.contentInset = UIEdgeInsetsZero }
我结合了@Adam Farrell和@Tash Pemhiwa的解决scheme,最后下面的代码适用于我:
- (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行为的人。
将表视图限制在导航栏的底部。 表视图会自动偏移44,但是在代码中我们可以这样做:
tableView.contentInset = UIEdgeInsets(top: -44, left: 0, bottom: 0, right: 0)
酒吧是透明的,没有颜色,但表视图根本不重叠。 请注意,尽pipe导航栏是透明的,但“钩子”一词也会被切断。 这只会使你在导航栏中限制表视图顶边为0。 不是从顶视图0。
大多数情况下,引入魔术常量的解决scheme并不会扩展,例如,如果下一个iPhone引入了不同的导航栏高度,我们将不得不更新我们的代码。
幸运的是,苹果为我们提供了克服这个问题的更清晰的方法,例如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属性。