iOS 가 셀 행 높이 에 적응 하 는 것 에 대해 서.

머리말
사실 이 글 을 쓰 려 고 했 는데 관련 데 모 를 체계적으로 정리 하지 못 한 데다 가 최근 이 직 하면 서 여러 가지 일이 좀 답답 해 져 서 계속 꾸 물 거 렸 다.집에 가서 한동안 쉬 었 더 니 데 모 를 반 이나 썼 다 는 생각 이 들 었 다.아직 일자 리 를 찾 지 못 한 이 빈 시간 에 시간 을 내 서 보완 하고 설명 문 서 를 써 서 잊 어 버 렸 다.
필요 배경
iOS 의 cell 행 높 은 적응 은 매우 흔히 볼 수 있 는 수요 이자 매우 간단 한 수요 입 니 다.전에 저 는 많은 동료 들 을 만 나 어떻게 실현 해 야 할 지 몰 랐 습 니 다.여기 서 한 걸음 한 걸음 분석 하여 여러분 께 참고 하도록 하 겠 습 니 다.
문제 분석
다른 실현 장면 은 말 하지 않 겠 습 니 다.우 리 는 지금 구체 적 인 수 요 를 분석 하 겠 습 니 다.그림 에서 보 듯 이:

사실은 주로 이 몇 가 지 를 실현 하면 이른바 자가 적응 이 높 은 문 제 를 해결 할 수 있 고 다음 에 우 리 는 이 수 요 를 점차적으로 실현 할 수 있다.
UITableView Cell 의 높이 를 계산 합 니 다.
고도 계산 하면 모두 가 낯 설 지 않 습 니 다.가장 간단 하고 흔히 볼 수 있 는 것 은 모든 하위 보기 의 높이 를 계산 하여 우리 가 필요 로 하 는 cell 높이 로 돌아 간 다음 에 UITable View Delegate 에서 호출 하 는 것 입 니 다.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 666;
}
아니면 높이 가 고정 되 어 있 는 상태 에서 바로...

self.tableView.rowHeight = 666;
그러나 이 는 model 의 데 이 터 를 미리 가 져 와 모든 컨트롤 의 높이 를 수 동 으로 계산 해 야 합 니 다.그러면 번 거 롭 고 통용 되 지 않 기 때문에 autolayot 가 나 온 후에 우 리 는 cell 의 contentView 의 상하 좌우 에 제약 을 추가 하면 시스템 은 자동 으로 고도 의 적응 을 실현 할 수 있 습 니 다.cell 의 높이 가 이불 보 기 를 펼 칠 수 있 도록 해 야 한 다 는 것 입 니 다.systemLayoutSizeFitting Size 라 는 API 를 이용 합 니 다.
iOS 8 이후 더욱 간단 해 졌 습 니 다.바로 사용:

self.tableView.estimatedRowHeight = 666;
self.tableView.rowHeight = UITableViewAutomaticDimension;
됐 습 니 다.그 중에서 estimated Row Height 는 예상 높이 입 니 다.delegate 에서 의 반환 높이 방법 은 더 이상 쓰 지 않 아 도 됩 니 다.
이 방면 의 글 에 대하 여 UITableView+FDTemplate LayoutCel 의 저자 가 쓴 글 은 매우 상세 하 므 로 먼저 알 아 보 는 것 을 권장 합 니 다(UITableViewCell 의 고도 계산 을 최적화 하 는 일 들)
그러나 이 방법 은 실제 적 으로 여러 개의 키 보기 가 있 는 cell 에서 미 끄 러 지 는 것 이 매우 어렵다.특히 iOS 8,특히 iOS 10 에서 카드 가 걸 리 는 것 이 특히 뚜렷 하 다.이것 은 시스템 의 높 은 계산 체제 와 일정한 관계 가 있 고 구체 적 으로 위의 글 을 볼 수 있 으 며 여기 서 더 이상 설명 하지 않 는 다.
autolayot 에서 벗 어 나 평소 높이 를 계산 하면 처음에는 cell 내 서브 컨트롤 내용 의 높이 에 따라 수 동 으로 누적 되 었 으 나 이 방법 은 매번 수 동 으로 그 중의 높 은 논 리 를 처리 하고 가로 세로 화면 전환 을 할 때 다시 계산 해 야 하기 때문에 평소에 개발 할 때 불필요 한 정력 을 많이 낭비 할 수 있다.그래서 나중에 저 는 프로젝트 에서 layoutSubviews 를 호출 하여 하위 컨트롤 의 실제 frame 을 얻 었 습 니 다.그러면 우리 가 필요 로 하 는 cell 높이 값 을 얻 을 수 있 습 니 다.다음 코드 는 다음 과 같 습 니 다.

cell.frame = CGRectSetWidth(cell.frame, contentViewWidth);
cell.contentView.frame = CGRectSetWidth(cell.contentView.frame, CGRectGetWidth(tableView.frame));
[cell layoutIfNeeded];

UIView *cellBottomView = nil;
if (cell.FS_cellBottomView) {
cellBottomView = cell.FS_cellBottomView;
}else if (cell.FS_cellBottomViews && cell.FS_cellBottomViews.count > 0) {
cellBottomView = cell.FS_cellBottomViews[0];
for (UIView *view in cell.FS_cellBottomViews) {
if (CGRectGetMaxY(view.frame) > CGRectGetMaxY(cellBottomView.frame)) {
cellBottomView = view;
}
}
}else {
NSArray *contentViewSubViews = cell.contentView.subviews;
if (contentViewSubViews.count == 0) {
cellBottomView = cell.contentView;
}else{
cellBottomView = contentViewSubViews[0];
for (UIView *view in contentViewSubViews) {
if (CGRectGetMaxY(view.frame) > CGRectGetMaxY(cellBottomView.frame)) {
cellBottomView = view;
}
}
}
}

CGFloat cellHeight = CGRectGetMaxY(cellBottomView.frame) + bottomOffset;
이 중 cellBottomView 는 cell 의 맨 아래 에 있 는 하위 보기 로 계산 효율 을 높이 기 위해 가장 좋 은 입력 입 니 다.어떤 하위 보기 가 맨 아래 에 있 는 지 확인 하지 않 으 면 보기 배열 contentView SubViews 에 들 어 갈 수 있 습 니 다.자세 한 사용 방식 은 demo 를 볼 수 있 습 니 다.
캐 시 셀 높이
고도 로 계산 한 후에 정상 적 으로 볼 때 우리 의 수 요 는 이미 달성 되 었 습 니 다.그러나 이 고도 값 이 미 끄 러 질 때마다 cell 의 재 활용 체제 로 인해 다시 계산 합 니 다.만약 에 이 cell 의 사용자 정의 스타일 이 복잡 하고 서브 보기 가 너무 많 으 면 대량의 계산 은 반드시 성능 을 손실 시 켜 뚜렷 한 카드 를 초래 할 수 있 기 때문에 캐 시 체 제 는 필요 한 조치 입 니 다.더구나 사과 도 이렇게 하 자고 제안 했다.
demo 는 두 개의 계산 줄 이 높 은 API 를 제공 합 니 다.

/**
cell      

@param tableView tableView
@param indexPath indexPath
@param contentViewWidth cell    ,     0
@return cell  
*/
+ (CGFloat)FSCellHeightForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath cellContentViewWidth:(CGFloat)contentViewWidth bottomOffset:(CGFloat)bottomOffset;

/**
cell         

@param tableView tableView
@param indexPath indexPath
@param cacheKey   cell     
@param contentViewWidth cell    ,     0
@return cell  
*/
+ (CGFloat)FSCellHeightForTableView:(UITableView *)tableView indexPath:(NSIndexPath *)indexPath cacheKey:(NSString *)cacheKey cellContentViewWidth:(CGFloat)contentViewWidth bottomOffset:(CGFloat)bottomOffset;
첫 번 째 는 배열 을 사용 하여 캐 시 를 하고 해당 cell 의 indexPath 를 배열 색인 값 으로 전송 합 니 다.두 번 째 는 사전 으로 데 이 터 를 캐 시 하고 유일한 식별 자 cacheCey 로 구분 해 야 합 니 다.
두 가지 방식 모두 cell 높이 를 정확하게 얻 을 수 있 습 니 다.첫 번 째 는 더욱 간결 하 게 실현 할 수 있 습 니 다.단점 은 데이터 원본 이 변화 할 때 모든 캐 시 를 비우 고 다시 계산 한 후에 캐 시 를 하 는 것 입 니 다.예 를 들 어 reloadData 등 입 니 다.두 번 째 는 전 자 를 바탕 으로 서로 다른 cell 을 구분 하 는 식별 자 를 추가 하 는 것 입 니 다.사용 할 때 두 번 째 를 사용 하 는 것 을 권장 합 니 다.캐 시 데 이 터 를 비우 지 않 고 경량급 페이지 는 다 를 것 이 없습니다.한 마디 로 하면 두 가지 방법 모두 캐 시 데이터 의 잘못 처 리 를 했 고 다음 과 같은 방법 을 지원 합 니 다.

@selector(reloadData),
@selector(insertSections:withRowAnimation:),
@selector(deleteSections:withRowAnimation:),
@selector(reloadSections:withRowAnimation:),
@selector(moveSection:toSection:),
@selector(insertRowsAtIndexPaths:withRowAnimation:),
@selector(deleteRowsAtIndexPaths:withRowAnimation:),
@selector(reloadRowsAtIndexPaths:withRowAnimation:),
@selector(moveRowAtIndexPath:toIndexPath:)
호 환 가로 세로 화면
이 수 요 는 비교적 간단 하 다.즉,가로 화면 과 세로 화면 은 각각 두 개의 캐 시 데 이 터 를 사용 하여 서로 영향 을 주지 않 고 가로 화면 을 전환 할 때 데이터 원본 을 자동 으로 전환 하 는 것 이다.

- (NSMutableArray *)indexCacheArrForCurrentOrientation
{
return UIDeviceOrientationIsPortrait([UIDevice currentDevice].orientation) ? self.indexCacheArr_Portrait: self.indexCacheArr_Landscape;
}
마지막 으로 실 현 된 효 과 는 그림 과 같다.

한 마디 로 하면 문제 풀이 방향 은 바로 이런 것 입 니 다.사용 하기에 편리 하고 관심 이 있 는 것 은 이동 해서 demo 를 다운로드 하여 볼 수 있 습 니 다FSAutoAdjust-cellHeightDemo ( 로 컬 다운로드
총결산
이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기