UITableView 섹션 헤더의 기본 스크롤 동작 변경


147

두 섹션이있는 UITableView가 있습니다. 간단한 테이블 뷰입니다. viewForHeaderInSection을 사용하여 이러한 헤더에 대한 사용자 정의보기를 작성하고 있습니다. 여태까지는 그런대로 잘됐다.

기본 스크롤 동작은 섹션이 발견 될 때 다음 섹션이 스크롤 될 때까지 섹션 헤더가 탐색 모음 아래에 고정 된 상태로 유지되는 것입니다.

내 질문은 이것입니다 : 섹션 헤더가 맨 위에 고정되어 있지 않고 나머지 섹션 행과 함께 탐색 모음 아래로 스크롤하도록 기본 동작을 변경할 수 있습니까?

나는 분명한 것을 놓치고 있습니까?

감사.


1
이 사이트에서 가장 잘 쓰여진 질문 중 하나 여야합니다! :) 감사.
Fattie

1
이 효과를 달성하기 위해 올바른 방법 여기를 확인 stackoverflow.com/a/13735238/1880899
수밋 Anantwar

답변:


175

이 문제를 해결하는 방법은 contentOffset다음 contentInset과 같이 UITableViewControllerDelegate(extends UIScrollViewDelegate) 에 따라를 조정하는 것입니다.

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
       CGFloat sectionHeaderHeight = 40;
   if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) {
       scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
   } else if (scrollView.contentOffset.y>=sectionHeaderHeight) {
       scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0);
   }
}

여기서 문제는 맨 위로 스크롤 할 때 약간의 바운스가 느슨해진다는 것입니다.


{참고 : "40"은 섹션 0 헤더의 정확한 높이 여야합니다. 섹션 0 헤더 높이보다 큰 숫자를 사용하면 손가락 느낌이 영향을받는 것을 볼 수 있습니다 ( "1000"과 같이 시도하고 바운스 동작이 상단에서 이상하게 나타납니다). 숫자가 섹션 0 헤더 높이와 일치하면 손가락 느낌이 완벽하거나 거의 완벽 해 보입니다.}


1
위의 것보다 완벽한 솔루션.
prathumca

4
감사합니다! 이것은 완벽한 솔루션입니다. 섹션 바닥 글에 대한 솔루션이 있습니까?
Tuan Nguyen

12
이 솔루션은 탭온 메뉴 표시 줄을 올바르게 처리하지 않으므로 목록 맨 위로 스크롤해야합니다.
리드 엘리스

scrollView.contentInset = UIEdgeInsetsMake (0, 0, sectionHeaderHeight, 0) : 유 섹션 바닥 글보기에 대한 동일한 동작이 필요하면 그냥이 같은 마지막 라인 변경
알렉스

이것으로 충분합니다. scrollView.contentInset = UIEdgeInsetsMake (scrollView.contentOffset.y> = 0? -scrollView.contentOffset.y : 0, 0, 0, 0);
MacMark

85

맨 위에 행이없는 섹션을 추가하고 이전 섹션의 바닥 글을 다음에 대한 머리글로 간단히 사용할 수도 있습니다.


13
섹션이 2 개 이상인 경우 바닥 글은 바닥에 고정됩니다.
Joseph Lin

3
이것은 독창적이지만 NSFetchedResultsController를 사용하여 테이블을로드하는 경우 indexPath를 조정해야합니다.
XJones

지금까지 최고의 솔루션 +1-구현하는 데 3 줄을 가져갔습니다!
Jon

Brilliant Brilliant Brilliant :-)
iphonic

바닥 글 앵커에 어떻게 적용됩니까? 도움을 주셔서 감사합니다! 감사합니다
darwindeeds

36

이 작업을 수행 한 경우 Plain 스타일의 UITableViews에 끈적 끈적한 머리글이 있고 Grouped 스타일의 UITableViews가 없다는 사실을 이용합니다. 적어도 사용자 정의 테이블 셀을 사용하여 그룹 테이블의 일반 셀 모양을 모방하려고 시도합니다.

나는 실제로 이것을 시도하지 않았으므로 작동하지 않을 수도 있지만 그것이 내가 제안하는 것입니다.


아마도 효과가 있었지만 시도 되었습니까? 그리고 @voidStern의 답변이 완벽하게 작동하면 많은 일처럼 보입니다!
bentford

섹션이 두 개 이상인 경우 voidStern의 답변이 작동하지 않습니다. Colin의 답변은 섹션 번호를 수동으로 이동하고 섹션 수를 추가 할 필요없이 간단하고 우아합니다.
조셉 린

팁 : tableView.separatorColor = [UIColor clearColor];일반 테이블보기를 모방하는 데 사용하십시오 .
Joseph Lin

3
나는 이것을 시도했지만 그룹화 된 테이블 셀을 일반 셀처럼 보이게 할 수 없었을 때, 즉 셀의 왼쪽과 오른쪽 여백을 제거했다. 어떻게 했어요?
Adam Carter

1
UITableViewStyle에 대해 명확하게 정리해 주셔서 감사합니다. 즉 그룹화되고 일반화되어 테이블 뷰의 섹션 머리글 / 바닥 글이 고정되는지 여부를 결정합니다. 감사합니다 @Colin Barrett
Dhaval H. Nena

28

나는 그것이 늦다는 것을 알고 있지만 결정적인 해결책을 찾았습니다!

당신이하고 싶은 것은 10 개의 섹션이 있다면 dataSource가 20을 반환하도록하십시오. 섹션 헤더에는 짝수를 사용하고 섹션 내용에는 홀수를 사용하십시오. 이 같은

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section%2 == 0) {
        return 0;
    }else {
        return 5;
    }
}

-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    if (section%2 == 0) {
        return [NSString stringWithFormat:@"%i", section+1];
    }else {
        return nil;
    }
}

보일라! :디


좋은 생각입니다. 그러나 섹션 색인 제목이 있으면 제목이 엉망이 될 것입니다.
roocell

왜? 섹션 제목으로도 동일한 작업을 수행 할 수 있습니다. 홀수에 대해서는 nil을, 짝수에 대해서는 제목을 기억하십시오.
LocoMike

1
예-이 방법은 훌륭합니다. 그것은 많은 부기 (아마도 섹션 제목을 얻는 방법과 관련이 있음)였습니다. 그러나 그것은 효과가있었습니다. 트릭은 numberOfRowsInSection 및 cellForRowAtIndexPath가 if (section % 2! = 0 && section! = 0)를 사용하는 반면 titleForHeaderInSection 및 기타 섹션 인덱스 함수는 if (section % 2 == 0)
roocell

작성자는 이것을 답으로 선택해야합니다. uitableview를 서브 클래 싱하여 섹션 제목을 자동으로 고정하는 방법이 있다면 좋을 것입니다.
roocell

이것은 나를 위해 최선을 다했습니다. @Colin의 솔루션을 먼저 시도했지만 사용중인 심하게 맞춤 설정하면 제대로 작동하지 않았습니다 UITableView.
kubi

15

이 문제를 해킹되지 않은 방식으로 해결하기 위해 수행해야 할 몇 가지 사항이 있습니다.

  1. 테이블 뷰 스타일을 UITableViewStyleGrouped
  2. 테이블 뷰 backgroundColor[UIColor clearColor]
  3. backgroundView각 테이블 뷰 셀을 빈 뷰로 설정하십시오 .backgroundColor [UIColor clearColor]
  4. 필요한 경우 테이블보기를 rowHeight적절하게 설정 하거나 tableView:heightForRowAtIndexPath:개별 행의 높이가 다른 경우 대체 하십시오.

(+1) @Neil, 답변을 시도했지만 불행히도 UITableViewStyleGrouped테이블 셀에는 헤더와의 정렬을 변경하는 여분의 여백이 있기 때문에. 실제로 다중 열 테이블을 표시하고 머리글을 사용하여 열 제목을 표시 한 다음 개별 테이블 항목이 이러한 제목과 정렬되도록하려면 문제가됩니다.
brainjam

15

원래 IB를 사용한 빠른 솔루션 인 Here 게시했습니다 . 프로그래밍 방식으로 간단하게 수행 할 수 있습니다.

이것을 달성하는 가장 쉬운 방법은 (IB 사용) :

UIView를 TableView로 드래그하여 헤더 뷰로 만듭니다.

  1. 해당 헤더보기 높이를 100px로 설정하십시오.
  2. tableview contentInset (top)을 -100으로 설정하십시오.
  3. 섹션 헤더는 이제 일반 셀처럼 스크롤됩니다.

어떤 사람들은이 솔루션이 첫 번째 헤더를 숨기고 있다고 말했지만 그러한 문제는 발견하지 못했습니다. 그것은 나를 위해 완벽하게 작동했으며 지금까지 내가 본 가장 간단한 해결책이었습니다.


뷰의 배경색이 선명한 색을 사용하도록 설정해야합니다. 그렇지 않으면 상단을지나 스크롤하면 바운스에 흰색이 표시됩니다.
Doc

3
첫 번째 헤더를 숨 깁니다
Leena

Leena, 어떤 버전의 iOS를 사용하고 있습니까? 보기가 UITableViewController 또는 UITableView가 포함 된 UIView입니까? 왜 어떤 사람들에게는이 솔루션이 첫 번째 헤더를 숨기므로 불일치를 찾으려고합니다.
Doc

이 솔루션은 완벽합니다. 무한한 위쪽 및 아래쪽 셀 배경 모양을 찾고 있습니다. 좋은!
Taylor Halliday

이 솔루션은 우수합니다. 이 스레드의 다른 답변보다 달성하기 쉽습니다. 제 생각에는 이것이 받아 들여지는 대답이어야합니다.
존 로저스

15

지금까지 설명한 솔루션에 만족하지 않아서 결합하려고했습니다. 결과는 @awulf 및 @cescofry에서 영감을 얻은 다음 코드입니다. 실제 테이블 뷰 헤더가 없기 때문에 작동합니다. 테이블 뷰 헤더가 이미있는 경우 높이를 조정해야 할 수도 있습니다.

// Set the edge inset
self.tableView.contentInset = UIEdgeInsetsMake(-23.0f, 0, 0, 0);

// Add a transparent UIView with the height of the section header (ARC enabled)
[self.tableView setTableHeaderView:[[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 100.0f, 23.0f)]];

이것은 내가 찾은 가장 간단한 해결책이었습니다.
Zorayr

이것은 iOS9.2에서 저에게 효과적이므로 이전 답변이지만 여전히 유효합니다. 그리고 첫 번째 섹션 헤더를 숨기지 않았습니다. 작동하고 완벽하게 작동합니다.
idStar

완전한. 테이블 뷰에 이미 헤더가있는 경우 오프셋만큼 높이를 높이고 헤더 컨텐츠의 최대 구속 상수를 증가시켜 컨텐츠를 원래 위치로 이동하십시오
Jason

14

TableView 스타일을 변경하십시오.

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

UITableViewStyle 설명서 :

UITableViewStylePlain- 일반 테이블 뷰입니다. 섹션 머리글이나 바닥 글은 인라인 구분 기호로 표시되며 테이블 뷰를 스크롤하면 플로팅됩니다.

UITableViewStyleGrouped- 섹션이 고유 한 행 그룹을 나타내는 테이블보기입니다. 섹션 머리글과 바닥 글이 플로팅되지 않습니다.


큰 대답은 나를 위해 일했다. 해결 할 필요가 없습니다
Shams Ahmed

9

Grouped TableView 스타일 선택

스토리 보드의 tableView 속성 관리자에서 그룹화 된 테이블보기 스타일을 선택하십시오.


5

단면도의 머리글 높이와 동일한 투명 뷰로 테이블의 headerView를 설정하십시오. 또한 -height에서 ay 프레임을 사용하여 tableview를 시작하십시오.

self.tableview = [[UITableView alloc] initWithFrame:CGRectMake(0, - height, 300, 400)];

UIView *headerView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, width, height)] autorelease];
[self.tableView setTableHeaderView:headerView];

4

대체 솔루션을 찾았습니다. 각 섹션의 첫 번째 셀을 실제 헤더 섹션 대신 사용하십시오.이 솔루션은 그렇게 깨끗하게 보이지는 않지만 제대로 작동합니다. 헤더 섹션에 대해 정의 된 프로토 타입 셀을 사용하고 cellForRowAtIndexPath 메소드에서 indexPath.row == 0을 요청하고, true 인 경우 헤더 섹션 프로토 타입 셀을 사용하고, 그렇지 않으면 기본 프로토 타입 셀을 사용하십시오.


당신은 여전히 작업 할 경우 indexPath.rowindexPath.section, 당신이의 높이를 반환하기 0.0f위해 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section당신의 헤더가 보이지 않도록.
Soup

4

TableView 스타일을 변경하십시오.

self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];

UITableView에 대한 애플 문서에 따라 :

UITableViewStylePlain- 일반 테이블 뷰입니다. 섹션 머리글이나 바닥 글은 인라인 구분 기호로 표시되며 테이블 뷰를 스크롤하면 플로팅됩니다.

UITableViewStyleGrouped- 섹션이 고유 한 행 그룹을 나타내는 테이블보기입니다. 섹션 머리글과 바닥 글이 플로팅되지 않습니다. 이 작은 변화가 당신을 도울 수 있기를 바랍니다 ..


2

그룹화 된 스타일은 기본적으로 iOS 7의 평평한 스타일 (평평함 및 배경)과 동일하게 보입니다. 우리에게 가장 쉽고 가장 쉬운 (즉, 해키가 적은) 수정은 단순히 테이블보기의 스타일을 그룹화하는 것입니다. contentInsets와의 재킹은 스크롤 바 네비 바를 상단에 통합 할 때 항상 문제가되었습니다. 그룹화 된 테이블 뷰 스타일을 사용하면 셀과 함께 정확히 동일하게 보이고 섹션 헤더는 고정되어 있습니다. 스크롤이 이상하지 않습니다.


이것은 셀이 사용자 정의 인 경우 특히 가장 좋은 솔루션입니다. 스크롤이 맨 위에 닿을 때 섹션 헤더의 "보류"를 중지하는 것 같습니다.
재활용 된 철강

1

tableView에 음수 삽입을 지정하십시오. 22px 높이의 섹션 헤더가 있고 reloadData add 직후에 고정되지 않으려면 다음을 추가하십시오.

self.tableView.contentInset = UIEdgeInsetsMake(-22, 0, 0, 0); 
self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height+22); 

나를 위해 매력처럼 작동합니다. 섹션 바닥 글에도 적용됩니다. 대신 아래쪽에 음수 삽입을 지정하십시오.


이것은 첫 번째 헤더를 잘라냅니다.
cannyboy 2016

나를 위해 완벽하게 일했습니다!! 감사합니다
Daniel

0

테이블을 스크롤보기에 추가하면 잘 작동하는 것 같습니다.



0

@LocoMike의 대답은 내 tableView에 가장 적합하지만 바닥 글을 사용할 때도 깨졌습니다. 따라서 머리글과 바닥 글을 사용할 때 올바른 해결책입니다.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return (self.sections.count + 1) * 3;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section % 3 != 1) {
        return 0;
    }
    section = section / 3;
    ...
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return 0;
    }
    section = section / 3;
    ...
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return 0;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    if (section % 3 != 0) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    if (section % 3 != 2) {
        return nil;
    }
    section = section / 3;
    ...
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    int section = indexPath.section;
    section = section / 3;
    ...
}

0

@awulf 답변의 스위프트 버전은 훌륭합니다!

func scrollViewDidScroll(scrollView: UIScrollView) {
    let sectionHeight: CGFloat = 80
    if scrollView.contentOffset.y <= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake( -scrollView.contentOffset.y, 0, 0, 0)
    }else if scrollView.contentOffset.y >= sectionHeight {
        scrollView.contentInset = UIEdgeInsetsMake(-sectionHeight, 0, 0, 0)
    }
}

-2

tableHeaderView 속성을 설정하면됩니다.

 tableView.tableHeaderView = customView;

그리고 그게 다야.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.