TableHeaderViewのサイズ変更に問題があります。簡単ではありません。
1)UITableViewとUIView(100 x 320 px)を作成します;
2)UIViewをUITableViewのtableHeaderViewとして設定します。
3)Build and Go。全て大丈夫。
ここで、tableHeaderViewのサイズを変更するため、viewDidLoadに次のコードを追加します。
self.tableView.autoresizesSubviews = YES;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;
TableHeaderViewの高さは200で表示されますが、100で表示されます。
私が書いた場合:
self.tableView.autoresizesSubviews = YES;
CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
それから、私が望むように、200の高さから始まります。しかし、実行時に変更できるようにしたいです。
私も成功せずにこれを試しました:
self.tableView.autoresizesSubviews = YES;
self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;
CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;
[self.tableView.tableHeaderView setNeedsLayout];
[self.tableView.tableHeaderView setNeedsDisplay];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];
ここでのポイントは次のとおりです。実行時にtableHeaderViewのサイズを変更する方法???
誰でもこれを行うことができますか?
ありがとう
iMe
参考:tableHeaderViewを変更して再設定することで、これが機能するようになりました。この場合、UIWebViewサブビューの読み込みが完了したときにtableHeaderViewのサイズを調整しています。
[webView sizeToFit];
CGRect newFrame = headerView.frame;
newFrame.size.height = newFrame.size.height + webView.frame.size.height;
headerView.frame = newFrame;
[self.tableView setTableHeaderView:headerView];
この回答は古く、明らかにiOS 7以降では機能しません。
私は同じ問題に遭遇し、アニメーション化する変更も必要だったので、ヘッダービューのUIViewのサブクラスを作成し、これらのメソッドを追加しました。
- (void)adjustTableHeaderHeight:(NSUInteger)newHeight{
NSUInteger oldHeight = self.frame.size.height;
NSInteger originChange = oldHeight - newHeight;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1.0f];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
self.frame = CGRectMake(self.frame.Origin.x,
self.frame.Origin.y,
self.frame.size.width,
newHeight);
for (UIView *view in [(UITableView *)self.superview subviews]) {
if ([view isKindOfClass:[self class]]) {
continue;
}
view.frame = CGRectMake(view.frame.Origin.x,
view.frame.Origin.y - originChange,
view.frame.size.width,
view.frame.size.height);
}
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
[(UITableView *)self.superview setTableHeaderView:self];
}
これは基本的に、呼び出し側クラスと同じクラス型ではないUITableViewのすべてのサブビューをアニメーション化します。アニメーションの最後に、スーパービュー(UITableView)でsetTableHeaderViewを呼び出します。これがないと、ユーザーが次にスクロールしたときにUITableViewの内容がジャンプして戻ります。これに関して私がこれまでに見つけた唯一の制限は、アニメーションの実行中にユーザーがUITableViewをスクロールしようとすると、ヘッダービューのサイズが変更されていないかのようにスクロールすることです(アニメーションがクイック)。
条件付きで変更をアニメーション化する場合は、次を実行できます。
- (void) showHeader:(BOOL)show animated:(BOOL)animated{
CGRect closedFrame = CGRectMake(0, 0, self.view.frame.size.width, 0);
CGRect newFrame = show?self.initialFrame:closedFrame;
if(animated){
// The UIView animation block handles the animation of our header view
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
// beginUpdates and endUpdates trigger the animation of our cells
[self.tableView beginUpdates];
}
self.headerView.frame = newFrame;
[self.tableView setTableHeaderView:self.headerView];
if(animated){
[self.tableView endUpdates];
[UIView commitAnimations];
}
}
アニメーションは2つ折りになっていることに注意してください。
tableHeaderView
の下のセルのアニメーション。これはbeginUpdates
およびendUpdates
を使用して行われますUIView
アニメーションブロックを使用して行われます。これらの2つのアニメーションを同期するには、animationCurve
をUIViewAnimationCurveEaseInOut
に設定し、期間を0.3
に設定する必要があります。これはUITableViewがアニメーションに使用するものと思われます。
Gihubでこれを行うXcodeプロジェクトを作成しました。 besi/ios-quickies のプロジェクトResizeTableHeaderViewAnimated
を確認してください。
MyHeaderViewの高さを次のように設定するだけで機能するはずです。
CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;
self.tableView.tableHeaderView = myHeaderView;
上記の@garrettmoonソリューションをiOS 7まで使用しました。
@ garrettmoonに基づいた更新されたソリューションは次のとおりです。
- (void)adjustTableHeaderHeight:(NSUInteger)newHeight animated:(BOOL)animated {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:[CATransaction animationDuration]];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];
self.frame = CGRectMake(self.frame.Origin.x,
self.frame.Origin.y,
self.frame.size.width,
newHeight);
[(UITableView *)self.superview setTableHeaderView:self];
[UIView commitAnimations];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
[(UITableView *)self.superview setTableHeaderView:self];
}
これはiOS 7および8で機能しました。このコードはTable View Controllerで実行されています。
[UIView animateWithDuration:0.3 animations:^{
CGRect oldFrame = self.headerView.frame;
self.headerView.frame = CGRectMake(oldFrame.Origin.x, oldFrame.Origin.y, oldFrame.size.width, newHeight);
[self.tableView setTableHeaderView:self.headerView];
}];
その理由は、tableHeaderViewのセッターです。
TableHeaderViewを設定する前に、UIViewの高さを設定する必要があります。 (Appleこのフレームワークをオープンソースにすると...)
IOS 9以前では、tableHeaderView
はサイズ変更後に再レイアウトしませんでした。この問題はiOS 10で解決されています。
この問題を解決するには、次のコードを使用してください。
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
IOS 9.xでは、viewDidLoad
でこれを行うと問題なく動作します。
var frame = headerView.frame
frame.size.height = 11 // New size
headerView.frame = frame
headerView
は@IBOutlet var headerView: UIView!
として宣言され、ストーリーボード上で接続され、tableViewの上部に配置されて、tableHeaderViewとして機能します。
これは、自動レイアウトを使用して_translatesAutoresizingMaskIntoConstraints = false
_をカスタムヘッダービューに設定する場合にのみ使用します。
最良かつ最も簡単な方法は、intrinsicContentSize
をオーバーライドすることです。内部的にUITableView
はintrinsicContentSize
を使用してヘッダー/フッターのサイズを決定します。カスタムビューでintrinsicContentSize
をオーバーライドしたら、次のようにする必要があります
invalidateIntrinsicContentSize()
を呼び出しますtableView.setNeedsLayout()
およびtableView.layoutIfNeeded()
を呼び出しますその後、UITableView
のヘッダー/フッターが必要に応じて更新されます。ビューを設定したりリセットしたりする必要はありません。
_UITableView.tableHeaderView
_または_.tableFooterView
_にとって本当に興味深いことの1つは、UIStackView
がarrangedSubviews
を管理する能力を失うことです。 UIStackView
をtableHeaderViewまたはtableFooterViewとして使用する場合は、UIView
にstackViewを埋め込み、UIView
のintrinsicContentSize
をオーバーライドする必要があります。
viewDidLoad
のヘッダービュープロパティ_tableView.tableHeaderView
_にheightを設定しても機能しないようです。ヘッダービューの高さは期待どおりに変わりません。
多くの試みのためにこの問題と戦った後。 - (void)didMoveToParentViewController:(UIViewController *)parent
メソッド内のヘッダービュー作成ロジックを呼び出すことで、高さを変更できることがわかりました。
したがって、サンプルコードは次のようになります。
_- (void)didMoveToParentViewController:(UIViewController *)parent {
[super didMoveToParentViewController:parent];
if ( _tableView.tableHeaderView == nil ) {
UIView *header = [[[UINib nibWithNibName:@"your header view" bundle:nil] instantiateWithOwner:self options:nil] firstObject];
header.frame = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), HeaderViewHeight);
[_tableView setTableHeaderView:header];
}
}
_
明らかに、今ではAppleはtableHeaderViewとtableFooterViewのUITableViewAutomaticDimensionを実装しているはずです...
以下は、レイアウトの制約を使用してうまくいくようです:
CGSize s = [ self systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ];
CGRect f = [ self frame ];
f.size = s;
[ self setFrame : f ];
TableHeaderViewがコンテンツ調整可能なWebViewである場合、次を試すことができます。
[self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
self.webView.height = self.webView.scrollView.contentSize.height;
self.tableView.tableHeaderView = self.webView;
}
IOS9とiOS11でテストし、うまく機能しました。
UIViewのinitWithFrameイニシャライザーが、渡したrectを適切に受け入れないことがわかりました。そのため、次のように完璧に機能しました。
- (id)initWithFrame:(CGRect)aRect {
CGRect frame = [[UIScreen mainScreen] applicationFrame];
if ((self = [super initWithFrame:CGRectZero])) {
// Ugly initialization behavior - initWithFrame will not properly honor the frame we pass
self.frame = CGRectMake(0, 0, frame.size.width, 200);
// ...
}
}
これの利点は、ビューコードにより適切にカプセル化されることです。
テーブルのヘッダーとしてUITableView
を持つUISearchBar
が欲しかったので、このような階層があります
UITableView
|
|--> UIView
| |--> UISearchBar
|
|--> UITableViewCells
別の場所で述べたように、変更後にsetTableViewHeaderを設定しないと、何も起こりません。
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = YES;
[UIView animateWithDuration:0.2f animations:^{
[searchBar sizeToFit];
CGFloat height = CGRectGetHeight(searchBar.frame);
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = height;
self.tableHeaderView.frame = frame;
self.tableView.tableHeaderView = self.tableHeaderView;
}];
[searchBar setShowsCancelButton:YES animated:YES];
return YES;
}
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = NO;
[UIView animateWithDuration:0.f animations:^{
[searchBar sizeToFit];
CGFloat height = CGRectGetHeight(searchBar.frame);
CGRect frame = self.tableView.tableHeaderView.frame;
frame.size.height = height;
self.tableHeaderView.frame = frame;
self.tableView.tableHeaderView = self.tableHeaderView;
}];
[searchBar setShowsCancelButton:NO animated:YES];
return YES;
}
テーブルのヘッダーのアニメーション化された高さの変更を実装して、タップすると画面全体に拡大します。ただし、コードは他の場合に役立ちます。
// Swift
@IBAction func tapped(sender: UITapGestureRecognizer) {
self.tableView.beginUpdates() // Required to update cells.
// Collapse table header to original height
if isHeaderExpandedToFullScreen {
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.scrollView.frame.size.height = 110 // original height in my case is 110
})
}
// Expand table header to overall screen
else {
let screenSize = self.view.frame // "screen" size
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.scrollView.frame.size.height = screenSize.height
})
}
self.tableView.endUpdates() // Required to update cells.
isHeaderExpandedToFullScreen= !isHeaderExpandedToFullScreen // Toggle
}
Autolayoutを使用してカスタムheaderViewが設計されており、web-fetchまたは同様の遅延タスクの後にheaderViewを更新する必要がある場合。次に、iOS-Swiftでこれを行い、以下のコードを使用してheaderViewを更新しました。
//to reload your cell data
self.tableView.reloadData()
dispatch_async(dispatch_get_main_queue(),{
// this is needed to update a specific tableview's headerview layout on main queue otherwise it's won't update perfectly cause reloaddata() is called
self.tableView.beginUpdates()
self.tableView.endUpdates()
}