[英]UITableView goes under translucent Navigation Bar
我試圖在 IOS 7 應用程序中有一個透明的導航欄。 我的應用程序中有一個全屏圖像。 我也在那個圖像上有一個 UITableView 。 當我使用下面的代碼時,圖像根據需要適合屏幕,但 UITableView 位於導航欄下方。
在viewDidLoad
中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 的框架。 然后滾動內容將在導航欄下方被切斷(這看起來也不太好)
我的案例幫助了這個(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)
}
}
將 tableview 的 y 位置設置為導航欄的高度加上狀態欄的height
(讓它成為height
)
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);
如果您使用自動布局,只需更改更新 tableView 頂部約束而不是更改框架。
並自動將 viewControllerAdjustsScrollViewInsets 更改為 NO
self.automaticallyAdjustsScrollViewInsets = NO;
如果您支持不同方向的更新 frame 和 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);
}
最好不要對 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()
}
引入神奇常數的解決方案在大多數情況下無法擴展。 例如,如果下一代 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屬性代替。
我是 iOS 開發和 Stack Overflow 的新手,如果我的帖子不完美,請原諒我。
我也有這個問題,當我為我的 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];
}
我想出了以下解決方案,在第一次導航到視圖控制器時,將表格視圖的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;
}
}
我正在嘗試在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;
但隨后我在導航欄上失去了透明度。
我結合了 @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 行為上浪費幾個小時的人。
你只需要喜歡這個:
assert(tableView.contentInsetAdjustmentBehavior == .automatic)
從 iOS 11 開始,零需要做丑陋的魔術常量胡子
我什至不需要將 contentInsetAdjustmentBehavior 設置為 .none 來修復導航欄重疊。
.automatic
自動工作
嘗試使用 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))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.