1. ホーム
  2. iphone

[解決済み] UITableViewのtableHeaderViewでAutoLayoutを使用することはできますか?

2022-09-25 12:23:31

質問

私が AutoLayout を発見して以来、私はあらゆるところでそれを使っていますが、今、私はそれを tableHeaderView .

を作りました。 subclassUIView に、必要なものすべて(ラベルなど)を制約付きで追加し、次に、この CustomViewUITableView ' tableHeaderView .

を除いて、すべてうまく動作します。 UITableView が常に表示されます。 の上に の上に表示されます。 CustomView によって 上記 を意味します。 CustomView の下に UITableView の下にあるので、見えません。

どうやら、何をやっても heightUITableView ' tableHeaderView 常に 0です(幅、x、yも同様)。

私の質問:それは、次のことを達成するためにまったく可能ですか? フレームを手動で設定することなく ?

EDIT : また CustomView ' subview という制約があります。

_title = [[UILabel alloc]init];
_title.text = @"Title";
[self addSubview:_title];
[_title keep:[KeepTopInset rules:@[[KeepEqual must:5]]]]; // title has to stay at least 5 away from the supperview Top
[_title keep:[KeepRightInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepLeftInset rules:@[[KeepMin must:5]]]];
[_title keep:[KeepBottomInset rules:@[[KeepMin must:5]]]];

制約を手動で書くと時間がかかるし、1つの制約に対して行数が多すぎるので、便利なライブラリ 'KeepLayout' を使っていますが、メソッドは自明です。

そして UITableView にはこのような制約があります.

_tableView = [[UITableView alloc]init];
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor clearColor];
[self.view addSubview:_tableView];
[_tableView keep:[KeepTopInset rules:@[[KeepEqual must:0]]]];// These 4 constraints make the UITableView stays 0 away from the superview top left right and bottom.
[_tableView keep:[KeepLeftInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepRightInset rules:@[[KeepEqual must:0]]]];
[_tableView keep:[KeepBottomInset rules:@[[KeepEqual must:0]]]];

_detailsView = [[CustomView alloc]init];
_tableView.tableHeaderView = _detailsView;

に直接何らかの制約を設定しなければならないかどうかはわかりません。 CustomView の制約によってCustomViewの高さが決定されると思います。 UILabel "title"の中にあります。

EDIT 2: 再度調査したところ、CustomViewの高さと幅は正しく計算されているようですが、CustomViewの上部がUITableViewの上部と同じ高さになったまま、スクロールすると一緒に移動してしまうようです。

どのように解決するのですか?

同じような質問をしたことがあります。 ここで . 要約すると、私はヘッダーを一度追加し、必要な高さを見つけるためにそれを使用します。そしてその高さはヘッダーに適用することができ、ヘッダーは変更を反映するために2回目に設定されます。

- (void)viewDidLoad
{
    [super viewDidLoad];

    self.header = [[SCAMessageView alloc] init];
    self.header.titleLabel.text = @"Warning";
    self.header.subtitleLabel.text = @"This is a message with enough text to span multiple lines. This text is set at runtime and might be short or long.";

    //set the tableHeaderView so that the required height can be determined
    self.tableView.tableHeaderView = self.header;
    [self.header setNeedsLayout];
    [self.header layoutIfNeeded];
    CGFloat height = [self.header systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].height;

    //update the header's frame and set it again
    CGRect headerFrame = self.header.frame;
    headerFrame.size.height = height;
    self.header.frame = headerFrame;
    self.tableView.tableHeaderView = self.header;
}

複数行のラベルがある場合、これもカスタムビューが各ラベルのpreferredMaxLayoutWidthを設定することに依存します。

- (void)layoutSubviews
{
    [super layoutSubviews];

    self.titleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.titleLabel.frame);
    self.subtitleLabel.preferredMaxLayoutWidth = CGRectGetWidth(self.subtitleLabel.frame);
}

とか、もっと一般的な

override func layoutSubviews() {
    super.layoutSubviews()  
    for view in subviews {
        guard let label = view as? UILabel where label.numberOfLines == 0 else { continue }
        label.preferredMaxLayoutWidth = CGRectGetWidth(label.frame)
    }
}

2015年1月更新

残念ながらこれはまだ必要なようです。ここでは、レイアウト処理の迅速なバージョンを紹介します。

tableView.tableHeaderView = header
header.setNeedsLayout()
header.layoutIfNeeded()
header.frame.size = header.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
tableView.tableHeaderView = header

これをUITableViewの拡張に移すと便利なことがわかりました。

extension UITableView {
    //set the tableHeaderView so that the required height can be determined, update the header's frame and set it again
    func setAndLayoutTableHeaderView(header: UIView) {
        self.tableHeaderView = header
        self.tableHeaderView?.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            header.widthAnchor.constraint(equalTo: self.widthAnchor)
        ])
        header.setNeedsLayout()
        header.layoutIfNeeded()
        header.frame.size =  header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
        self.tableHeaderView = header
    }
}

使用方法

let header = SCAMessageView()
header.titleLabel.text = "Warning"
header.subtitleLabel.text = "Warning message here."
tableView.setAndLayoutTableHeaderView(header)