データソースメソッドは、実際にはテーブルビューのプロパティtableView:heightForHeaderInSection:
に関連付けられているビューとは何の関係もありません。tableViewHeader
ここには2つの異なるタイプのヘッダーがあります。1つは検索バーなどを配置できるtableViewの上部にあるヘッダーで、もう1つはテーブルビュー内のセクションごとに1つずつ発生させることができる複数のヘッダーです。
私の知る限り、tableViewHeader
ビューは通常nibファイルで構成されますが、テーブルビューが、その構成を許可するデータソースメソッドを呼び出すことはわかりません。そのため、手動で行う必要があります。率直に言って、コードが機能する場合、それはそれを行うための良い方法です。それを非表示にすると、テーブルビューはまだそこにあるかのように動作します...完全に削除すると、割り当てが解除されるため、元に戻すことができなくなります。
(ただし、あなたが言ったように、強力な参照を作成する限り、ヘッダービューを指すIBOutletを使用できます。その後、後でテーブルに再挿入できます。...うーん、方法の仕組みはテーブルビューのスクロールビューにビューを追加し、それを正しく配置するのは、おそらく面倒です。)
私の唯一の提案は、フレームの高さをゼロにアニメーション化して、 animateWithDurationのような素晴らしいトランジション効果を得るというものです。しかし、ええ、私はあなたがすでに考え出された最良の方法を持っていると言うでしょう。
編集:
コード、あなたは言いますか?私はそれを挑戦として受け止めます:)
- (void)setTableViewHeaderHidden:(BOOL)hide
{
// Don't want to muck things up if we are mid an animation.
if (self.isAnimatingHeader) {
return;
}
// This is our IBOutlet property, I am just saving a bit of typing.
UIView *theHeader = self.theHeaderView;
if (hide) {
// Save the original height into the tag, should only be done once.
if (!theHeader.tag) {
theHeader.tag = theHeader.frame.size.height;
}
// Transform and hide
if (theHeader.frame.size.height > 0) {
self.isAnimatingHeader = YES;
// New frame...
CGRect frame = theHeader.frame;
frame.size.height = 0;
// Figure out some offsets here so we prevent jumping...
CGPoint originalOffset = self.tableView.contentOffset;
CGPoint animOffset = originalOffset;
animOffset.y += MAX(0, theHeader.tag - animOffset.y);
CGPoint newOffset = originalOffset;
newOffset.y = MAX(0, newOffset.y - theHeader.tag);
// Perform the animation
[UIView animateWithDuration:0.35
delay:0.0
options: UIViewAnimationCurveEaseOut
animations:^{
theHeader.frame = frame;
self.tableView.contentOffset = animOffset;
}
completion:^(BOOL finished){
if (finished) {
// Hide the header
self.tableView.tableHeaderView = nil;
theHeader.hidden = YES;
// Shift the content offset so we don't get a jump
self.tableView.contentOffset = newOffset;
// Done animating.
self.isAnimatingHeader = NO;
}
}
];
}
} else {
// Show and transform
if (theHeader.frame.size.height < theHeader.tag) {
self.isAnimatingHeader = YES;
// Set the frame to the original before we transform, so that the tableview corrects the cell positions when we re-add it.
CGRect originalFrame = theHeader.frame;
originalFrame.size.height = theHeader.tag;
theHeader.frame = originalFrame;
// Show before we transform so that you can see it happen
self.tableView.tableHeaderView = theHeader;
theHeader.hidden = NO;
// Figure out some offsets so we don't get the table jumping...
CGPoint originalOffset = self.tableView.contentOffset;
CGPoint startOffset = originalOffset;
startOffset.y += theHeader.tag;
self.tableView.contentOffset = startOffset; // Correct for the view insertion right off the bat
// Now, I don't know if you want the top header to animate in or not. If you think about it, you only *need* to animate the header *out* because the user might be looking at it. I figure only animate it in if the user is already scrolled to the top, but hey, this is open to customization and personal preference.
if (self.animateInTopHeader && originalOffset.y == 0) {
CGPoint animOffset = originalOffset;
// Perform the animation
[UIView animateWithDuration:0.35
delay:0.0
options: UIViewAnimationCurveEaseIn
animations:^{
self.tableView.contentOffset = animOffset;
}
completion:^(BOOL finished){
// Done animating.
self.isAnimatingHeader = NO;
}
];
} else {
self.isAnimatingHeader = NO;
}
}
}
}
これは、Xcodeに付属のテーブルビューテンプレートに組み込まれています。それを一緒に投げるために、私はUILongPressGestureRecognizer
このメソッドを指すセレクターアウトレットでを使用しました:
- (IBAction)longPress:(UIGestureRecognizer *)sender
{
if (sender.state != UIGestureRecognizerStateBegan) {
return;
}
if (self.hidingHeader) {
self.hidingHeader = NO;
[self setTableViewHeaderHidden:NO];
} else {
self.hidingHeader = YES;
[self setTableViewHeaderHidden:YES];
}
}
そして、これらをヘッダーに追加しました。
@property (strong, nonatomic) IBOutlet UIView *theHeaderView;
@property (nonatomic) BOOL hidingHeader;
@property (nonatomic) BOOL isAnimatingHeader;
@property (nonatomic) BOOL animateInTopHeader;
- (IBAction)longPress:(id)sender;
とにかく、それはうまくいきます。私が発見したのは、ヘッダービューへのテーブルビューの参照を完全に削除する必要があることです。そうしないと、テーブルビューは、ヘッダーのフレームの高さに基づいてセルの位置をシフトします。ヘッダープロパティに割り当てられます。さらに、IBOutletを介してヘッダーへの強力な参照を維持する必要があります。そうしないと、テーブルビューのヘッダーへの参照がなくなると破棄されます。
乾杯。