ios UITableView 在半透明导航栏下
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24468831/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
UITableView goes under translucent Navigation Bar
提问by birdcage
I am trying to have a transparent navigation bar in IOS 7 app. There is a full screen image in my application. I am also having a UITableView over that image. When I use the code below, image fits the screen as I want but UITableView goes under navigation bar.
我试图在 IOS 7 应用程序中有一个透明的导航栏。我的应用程序中有一个全屏图像。我也在那个图像上有一个 UITableView 。当我使用下面的代码时,图像根据需要适合屏幕,但 UITableView 位于导航栏下方。
in viewDidLoad
在 viewDidLoad
i use
我用
self.navigationController.navigationBar.shadowImage = [UIImage new];
self.navigationController.navigationBar.translucent = YES;
self.navigationController.view.backgroundColor = [UIColor clearColor];
it is being ok when I change to self.navigationController.navigationBar.translucent = NO;
but then I lose transparency at navigation bar.
当我更改为时没问题,self.navigationController.navigationBar.translucent = NO;
但随后我在导航栏上失去了透明度。
回答by robert
You could set the contentInsets of your tableView so it is initially below the navigation bar, but would scroll behind it (content would be overlapping)
您可以设置 tableView 的 contentInsets,使其最初位于导航栏下方,但会在其后面滚动(内容会重叠)
self.tableView.contentInset = UIEdgeInsetsMake(44,0,0,0);
Or you could offset the frame of the tableview. Then the scrolling content would be cut off below the navigation bar (which wouldn't look good, too)
或者您可以偏移 tableview 的框架。然后滚动内容将在导航栏下方被切断(这看起来也不太好)
回答by Eugene Rozhkov
I my case helped this one (modified version of Bill Chan's code):
我的案例帮助了这个(Bill Chan 代码的修改版本):
Objective C version:
目标 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);
}
The point is that table have to be pushed down for the height of navigationBar (rect.size.height
) plus status bar height (rect.origin.y
);
关键是表格必须向下推导航rect.size.height
栏的高度(rect.origin.y
)加上状态栏的高度();
Swift version (also compatible with Swift 2):
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)
}
}
回答by Malder
I had the similar problem for iOS 9. When I first open viewController, tableView is under top bar. Than after scrolling tableView everything works fine.
我在 iOS 9 上遇到了类似的问题。当我第一次打开 viewController 时,tableView 位于顶部栏下方。比滚动 tableView 后一切正常。
- Select your view controller
- Click the 'Attributes Inspector' tab
- Uncheck 'Under Top Bars'
- 选择您的视图控制器
- 单击“属性检查器”选项卡
- 取消选中“在顶部栏下”
回答by Yatheesha B L
Set the y-position of tableview to height of the navigation bar plus height of the status bar (let it be height
)
将 tableview 的 y 位置设置为导航栏的高度加上状态栏的高度(让它成为height
)
i.e,
IE,
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);
If you are using autolayout just change the update the tableView top constraint instead of changing frame.
如果您使用自动布局,只需更改更新 tableView 顶部约束而不是更改框架。
and also change viewController automaticallyAdjustsScrollViewInsets to NO
并自动将 viewControllerAdjustsScrollViewInsets 更改为 NO
self.automaticallyAdjustsScrollViewInsets = NO;
If you are supporting different orientation update frame and contentInset to (52) because navigation bar height in landscape mode is 32.
如果您支持不同方向的更新 frame 和 contentInset 为(52),因为横向模式下的导航栏高度为 32。
check this Sample
检查这个样本
回答by Bill Chan
This is working in both landscape mode and portrait mode in iOS8:
这在 iOS8 的横向模式和纵向模式下都有效:
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
CGRect rect = self.navigationController.navigationBar.frame;
float y = -rect.origin.y;
self.tableView.contentInset = UIEdgeInsetsMake(y ,0,0,0);
}
回答by user1046037
Better not to hardcode the Inset values as it might based on the orientation of the device.
最好不要对 Inset 值进行硬编码,因为它可能基于设备的方向。
Code:
代码:
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()
}
回答by Madiyar
Most of the time, solutions that introduce a magic constant doesn't scale, for example if the next iPhone introduces a different navigation bar height we'll have to update our code.
大多数情况下,引入魔法常数的解决方案不会缩放,例如,如果下一代 iPhone 引入不同的导航栏高度,我们将不得不更新我们的代码。
Fortunately, Apple provided us cleaner ways of overcoming this issue, for example topLayoutGuide:
幸运的是,Apple 为我们提供了更简洁的方法来克服这个问题,例如topLayoutGuide:
The topLayoutGuide property comes into play when a view controller is frontmost onscreen. It indicates the highest vertical extent for content that you don't want to appear behind a translucent or transparent UIKit bar (such as a status or navigation bar)
当视图控制器位于屏幕最前面时,topLayoutGuide 属性就会发挥作用。它表示您不希望出现在半透明或透明 UIKit 栏(例如状态栏或导航栏)后面的内容的最高垂直范围
Programmatically you can achieve with the following code snippet (the same can be achieved via IB too):
您可以通过以下代码片段以编程方式实现(同样可以通过 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)
])
}
Note:topLayoutGuide is deprecated in iOS 11, we should use the safeAreaLayoutGuideproperty of UIView instead.
注意:在 iOS 11 中不推荐使用topLayoutGuide,我们应该使用UIView的safeAreaLayoutGuide属性代替。
回答by Adam Farrell
Introduction
介绍
I am new to both iOS development and Stack Overflow, so forgive me if my post isn't perfect.
I also had this issue, and when I used the content insets for my UITableView it worked perfectly upon loading first, or when visiting it from my other tabs; however, if I navigated back to the view, it would have the extra "padding". I figured out a work around, so that my UITableView will be correctly placed every time.
我是 iOS 开发和 Stack Overflow 的新手,如果我的帖子不完美,请原谅我。
我也有这个问题,当我为我的 UITableView 使用内容插入时,它在加载时完美地工作,或者从我的其他选项卡访问它时;但是,如果我导航回视图,它将有额外的“填充”。我想出了一个解决办法,这样我的 UITableView 每次都会被正确放置。
The Issue
问题
When you first load the UITableView, or tab to it, it needs the insets to correctly start the table below the navigation bar, but when you navigate back it does not need the insets, because for some reason, it correctly calculates for the placement of the UITableView. This is why you can get the extra padding.
当您第一次加载 UITableView 或选项卡时,它需要插入以正确启动导航栏下方的表格,但是当您向后导航时它不需要插入,因为出于某种原因,它正确计算了UITableView。这就是为什么你可以获得额外的填充。
The Solution
解决方案
The solution involves using a boolean to determine whether you have navigated away, so that it can correctly determine whether it needs the content insets or not.
In -(void)viewDidLoad
I set hasNavigatedFurther = NO
. Then:
该解决方案涉及使用布尔值来确定您是否已导航离开,以便它可以正确确定是否需要内容插入。
在-(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;
}
}
In order to make this work, you need to set hasNavigatedFurther = YES
just before your code that pushes another view onto the navigation stack.
为了使这项工作,您需要hasNavigatedFurther = YES
在将另一个视图推送到导航堆栈的代码之前进行设置。
-(void)btnTouched:(id)sender {
hasNavigatedFurther = YES;
NextViewController* nvc = [NextViewController new];
[self.navigationController pushViewController:nvc animated:YES];
}
回答by Tash Pemhiwa
I came up with the following solution, which, on navigating to the view controller for the first time, adjusts the table view's contentInset
for the navigation bar's height, taking into account any padding that the top cell might have. When returning to this view controller after pushing another view controller onto the stack, I then re-adjust the contentInset
to UIEdgeInsetsZero
:
我想出了以下解决方案,在第一次导航到视图控制器时,根据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;
}
}
回答by aKANJ
Only this code solves the problem:
只有这段代码解决了这个问题:
@IBOutlet weak var tableView: UITableView!
func viewDidLoad() {
super.viewDidLoad()
self.tableView.contentInset = UIEdgeInsetsZero
}