UITableView의 tableHeaderView 크기를 조정하는 방법은 무엇입니까?


103

tableHeaderView 크기를 조정하는 데 문제가 있습니다. 간단하지 않습니다.

1) UITableView 및 UIView (100 x 320 px)를 만듭니다.

2) UIView를 UITableView의 tableHeaderView로 설정하십시오.

3) 빌드 앤 고. 모든 것이 괜찮습니다.

이제 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

답변:


180

참고 : 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];

13
+1 이것은 나를 위해 일했습니다. 하위보기의 크기가 변경된 후 'setTableHeaderView'를 호출하는 것이 핵심입니다. 문제는 내 하위 뷰가 애니메이션으로 1 초에 걸쳐 크기가 변경된다는 것입니다. 이제 tableHeaderView를 애니메이션으로 만드는 방법을 알아 내려고합니다.
앤드류

1
완벽합니다. 감사합니다. 나에게 이것은 Objective-C에서 덜 바람직한 속성 특성 중 하나의 예입니다. 헤더를 설정하면 높이를 다시 계산하는 부작용이 있다는 것을 알 수있는 방법이 없습니다 (알아야 할 이유도 없습니다). 헤더의 높이를 업데이트 할 때 자동으로 수행하거나 [tableView recalculateHeaderHeight]매번 같은 것을 호출해야합니다 .
jakeboxer

48
나는이 더 늦게 그 다음 결코 너무 늦게 거의 일년 없지만, 알고 앤드류 : 나는 포장하여 테이블 헤더보기의 변화 높이를 애니메이션 할 수 있었다 setTableHeaderView:으로 전화를 [tableview beginUpdates]하고[tableview endUpdates]
jasongregori

2
@jasongregori 편리한 주석 추가-동일한 기술 (beginUpdates + endUpdates)이 tableHeaderView와 같은 방식으로 tableFooterView의 높이 변경에 애니메이션을 적용하지 않는 것으로 나타났습니다. tableFooterView를 애니메이션하는 좋은 방법을 알아 냈습니까?
kris

1
인상적입니다.이 이벤트는 UIView 애니메이션 블록 내에서 수행 할 때 작동하지만 그 경우에는 매우 효율적이라고 생각하지 않습니다.
Can

12

이 답변은 오래되었으며 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를 스크롤하려고하면 머리글보기의 크기가 조정되지 않은 것처럼 스크롤이 애니메이션됩니다 (애니메이션이 빨리).


완벽하게 작동하고 필요하지 않았기 때문에 애니메이션을 제거했습니다.
강지호

iOS7이
발생할

1
WTF? 당신은 너무 많은 jQuery과의 내부와 당신이 정말 ...하지 않는 새로운 아이폰 OS 버전에서 작동 놀라지 것을 엉망으로하고 있습니다)
다니엘 린서을

10

변경 사항을 조건부로 애니메이션하려면 다음을 수행 할 수 있습니다.

- (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];
    }
}

애니메이션은 두 개로 접혀 있습니다.

  1. 아래에있는 셀의 애니메이션 tableHeaderView. 이것은 beginUpdates및 사용하여 수행됩니다.endUpdates
  2. 실제 헤더보기의 애니메이션입니다. 이것은 UIView애니메이션 블록을 사용하여 수행됩니다 .

이 두 애니메이션을 동기화하려면을 animationCurve로 설정 UIViewAnimationCurveEaseInOut하고 기간을 로 설정해야 합니다 0.3. 이는 UITableView가 애니메이션에 사용하는 것 같습니다.

최신 정보

나는 이것을하는 gihub에 Xcode 프로젝트를 만들었다. besi / ios-quickiesResizeTableHeaderViewAnimated 에서 프로젝트 확인

스크린 샷


2
이 기술은 작동하지만 섹션 머리글이있는 테이블보기에는 작동하지 않습니다. 업데이트 시작 / 업데이트 종료를 사용하면 애니메이션 블록을 방해하여 섹션 헤더가 중복됩니다.
BlueFish 2013-08-15

9

myHeaderView의 높이를 다음과 같이 설정하면 작동해야한다고 생각합니다.

CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;

self.tableView.tableHeaderView = myHeaderView;

이것은 실제로 작동하지만 viewDidLayoutSubviews에 사용되는 경우에만
KoCMoHaBTa

6

iOS 7까지 위의 @garrettmoon 솔루션을 사용했습니다.
다음은 @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];
}

5

이것은 iOS 7 및 8에서 저에게 효과적이었습니다.이 코드는 테이블 뷰 컨트롤러에서 실행 중입니다.

[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];
}];

4

tableHeaderView의 setter 때문입니다.

tableHeaderView를 설정하기 전에 UIView 높이를 설정해야합니다. (애플이이 프레임 워크를 오픈 소스한다면 훨씬 쉬울 것입니다 ...)


4

iOS 9 이하에서는 tableHeaderView크기를 조정 한 후 다시 레이아웃하지 않습니다. 이 문제는 iOS 10에서 해결되었습니다.

이 문제를 해결하려면 다음 코드를 사용하십시오.

self.tableView.tableHeaderView = self.tableView.tableHeaderView;

2

iOS 9.x에서는이 viewDidLoad작업을 잘 수행 합니다.

var frame = headerView.frame
frame.size.height = 11  // New size
headerView.frame = frame

headerView@IBOutlet var headerView: UIView!tableHeaderView로 작동하기 위해 tableView의 맨 위에 배치되는 스토리 보드에서 로 선언 되고 연결됩니다.


2

이는 자동 레이아웃을 사용 translatesAutoresizingMaskIntoConstraints = false하고 사용자 정의 헤더보기로 설정된 경우에만 해당됩니다 .

가장 좋고 가장 간단한 방법은 intrinsicContentSize. 내부적 으로 머리글 / 바닥 글 크기를 결정하는 UITableView데 사용 intrinsicContentSize됩니다. intrinsicContentSize사용자 정의보기에서 재정의 한 후 수행해야하는 작업은 다음과 같습니다.

  1. 사용자 지정 머리글 / 바닥 글보기의 레이아웃 (하위보기) 구성
  2. 호출 invalidateIntrinsicContentSize()
  3. 호출 tableView.setNeedsLayout()하고tableView.layoutIfNeeded()

그러면 UITableView의 머리글 / 바닥 글이 원하는대로 업데이트됩니다. 보기를 nil로 설정하거나 재설정 할 필요가 없습니다.

한 가지 정말 흥미로운 UITableView.tableHeaderView또는 .tableFooterViewUIStackView그 관리 할 수있는 능력을 잃게 arrangedSubviews. 당신이 사용하려는 경우 UIStackViewtableHeaderView 또는 tableFooterView, 당신은에 포함 stackView에있는 UIView및 재정 UIViewintrinsicContentSize.


2

신속한 5 테스트 코드

override func viewDidLayoutSubviews() {
      super.viewDidLayoutSubviews()

        guard let headerView = self.tblProfile.tableHeaderView else {
            return
        }

        let size = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)

        if headerView.frame.size.height != size.height {
            headerView.frame.size.height = size.height
            self.tblProfile.tableHeaderView = headerView
            self.tblProfile.layoutIfNeeded()
        }
    }

참고 : 모든 하위보기의 제약 조건을 상단, 하단, 선행, 후행 형식으로 제공해야합니다. 따라서 필요한 전체 크기를 얻을 수 있습니다.

출처 : https://useyourloaf.com/blog/variable-height-table-view-header/


1

설정 높이 헤더보기 속성 tableView.tableHeaderView에있는 것은 viewDidLoad예상대로되지 작업을 보인다 헤더보기 높이가 아직 변경되지.

많은 시도를 위해이 문제에 맞서 싸운 후. - (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];
    }
}

0

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

        // ...
    }
}

이것의 장점은 뷰 코드에 더 잘 캡슐화된다는 것입니다.


프레임을 가져 오는 UIScreen것은 나쁜 생각입니다. 뷰를 어떻게 재사용 하시겠습니까?
Zorayr

0

탭하면 전체 화면으로 확장되도록 테이블 헤더의 애니메이션 높이 변경을 구현했습니다. 그러나 코드는 다른 경우에 도움이 될 수 있습니다.

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

0

UITableView 크기 조정 헤더-범위 표시 줄이있는 UISearchBar

테이블에 대한 헤더로 UITableViewa UISearchBar를 원했기 때문에 다음과 같은 계층 구조가 있습니다.

UITableView
  |
  |--> UIView
  |     |--> UISearchBar
  |
  |--> UITableViewCells

UISearchBarDelegate 메서드

다른 곳에서 언급했듯이, 변경 후 TableViewHeader를 설정하지 않으면 아무 일도 일어나지 않습니다.

- (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;
}

0

사용자 정의 headerView가 자동 레이아웃을 사용하여 설계되고 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()
} 

0

분명히 지금까지 Apple은 tableHeaderView 및 tableFooterView에 대해 UITableViewAutomaticDimension을 구현해야합니다.

다음은 레이아웃 제한을 사용하여 나를 위해 작동하는 것 같습니다.

CGSize   s  = [ self  systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ];
CGRect   f  = [ self  frame ];

f.size   = s;

[ self  setFrame : f ];

0

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에서 테스트했으며 잘 작동했습니다.


-3

[self.tableView reloadData]키를 바꾸고 해보 셨나요 ?


1
그것은 정적 뷰인 tableHeaderView에 관한 것입니다. - [UITableView reloadData]단지 동적 뷰 (세포) 또한위한 것입니다 sectionHeaders 당신은 분명 의미가 있다고 생각)
줄리안 F. Weinert에게
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.