web-dev-qa-db-ja.com

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;に変更しても問題ありませんが、ナビゲーションバーの透明性が失われます。

56
birdcage

TableViewのcontentInsetsは、最初はナビゲーションバーの下にあるように設定できますが、その後ろにスクロールします(コンテンツは重複します)

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

または、TableViewのフレームをオフセットできます。スクロールコンテンツはナビゲーションバーの下で途切れます(見た目も良くありません)

65
robert

私は私のケースがこれを助けました(ビルチャンのコードの修正版):

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

ポイントは、navigationBarの高さ(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)
    }
}
47
Eugene Rozhkov

IOS 9でも同様の問題がありました。viewControllerを最初に開いたとき、tableViewはトップバーの下にあります。 tableViewをスクロールした後、すべてが正常に機能します。

  1. View Controllerを選択してください
  2. [属性インスペクター]タブをクリックします
  3. 「トップバーの下」のチェックを外します

enter image description here

28
Malder

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 top制約の更新を変更するだけです。

また、viewControllerを自動的に変更しますAdjustsScrollViewInsetsをNOに変更します

self.automaticallyAdjustsScrollViewInsets =  NO;

異なる方向をサポートしている場合は、フレームとcontentInsetを(52)に更新します。これは、横向きモードのナビゲーションバーの高さが32であるためです。

これを確認してください サンプル

8
Yatheesha B L

これはiOS8の横向きモードと縦向きモードの両方で動作しています:

- (void)viewDidLayoutSubviews
{
  [super viewDidLayoutSubviews];

  CGRect rect = self.navigationController.navigationBar.frame;

  float y = -rect.Origin.y;

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

デバイスの向きに基づいている可能性があるため、インセット値をハードコードしない方が良いです。

コード:

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

ほとんどの場合、マジック定数を導入するソリューションはスケールしません。たとえば、次のiPhoneが異なるナビゲーションバーの高さを導入する場合、コードを更新する必要があります。

幸いなことに、Appleは、この問題をよりきれいに解決する方法を提供してくれました。たとえば、 topLayoutGuide

TopLayoutGuideプロパティは、View Controllerが画面の最前面にあるときに機能します。半透明または透明の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)
  ])
}

注:topLayoutGuideはiOS 11で非推奨になりました。代わりにUIViewの safeAreaLayoutGuide プロパティを使用する必要があります。

3
Madiyar

前書き

私はiOS開発とStack Overflowの両方に慣れていないので、投稿が完璧でない場合はご容赦ください。

この問題もありました。UITableViewのコンテンツインセットを使用した場合、最初に読み込んだとき、または他のタブからアクセスしたときに完全に機能しました。ただし、ビューに戻ると、余分な「パディング」があります。 UITableViewが毎回正しく配置されるように、回避策を考えました。

問題

UITableViewまたはタブを最初にロードするとき、ナビゲーションバーの下のテーブルを正しく開始するためにインセットが必要ですが、後ろに移動するときにインセットは必要ありません。何らかの理由で、 UITableView。これが余分なパディングを取得できる理由です。

ソリューション

ソリューションでは、ブールを使用して、離れて移動したかどうかを判断します。これにより、コンテンツのインセットが必要かどうかを正しく判断できます。

_-(void)viewDidLoadhasNavigatedFurther = 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];
}
2
Adam Farrell

このコードのみが問題を解決します。

  @IBOutlet weak var tableView: UITableView!

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

次のソリューションを思い付きました。これは、View Controllerに初めてナビゲートするときに、最上位セルにある可能性のあるパディングを考慮して、Table ViewのcontentInsetをナビゲーションバーの高さに合わせて調整します。別のView ControllerをスタックにプッシュしてこのView Controllerに戻ると、contentInsetUIEdgeInsetsZeroに再調整します。

- (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;
    }
}
1
Tash Pemhiwa

テーブルビューをナビゲーションバーの下部に制限します。テーブルビューは自動的に44オフセットされますが、コードではこれを行うことができます。

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

バーは透明で色はありませんが、テーブルビューはオーバーラップしません。ナビゲーションバーが透明であるにもかかわらず、「フック」という単語が途切れていることに注意してください。これは、テーブルビューの上部のエッジをナビゲーションバーから0に制限することでのみ機能します。上面図では0ではありません。

enter image description here

0
Jose Ramirez

@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の動作に数時間を費やす人々に役立つことを願っています。

0
yuchen