簡體   English   中英

UITableView 在半透明導航欄下

[英]UITableView goes under translucent Navigation Bar

我試圖在 IOS 7 應用程序中有一個透明的導航欄。 我的應用程序中有一個全屏圖像。 我也在那個圖像上有一個 UITableView 。 當我使用下面的代碼時,圖像根據需要適合屏幕,但 UITableView 位於導航欄下方。

viewDidLoadviewDidLoad

我用

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

我在 iOS 9 上遇到了類似的問題。當我第一次打開 viewController 時,tableView 位於頂部欄下方。 然后在滾動 tableView 后一切正常。

  1. 選擇您的視圖控制器
  2. 單擊“屬性檢查器”選項卡
  3. 取消選中“在頂部欄下”

在此處輸入圖片說明

將 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 行為上浪費幾個小時的人。

將表格視圖限制在導航欄的底部。 表格視圖將自動偏移 44,但在代碼中我們可以這樣做:

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

bar 是透明的,沒有顏色,但是 table view 根本沒有重疊。 請注意,盡管導航欄是透明的,但“Hook”一詞還是被截斷了。 這只會在您將表格視圖頂部邊緣從導航欄中限制為 0 時起作用。 從頂視圖看不是 0。

在此處輸入圖片說明

你只需要喜歡這個:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM