나는 이것이 일반적인 문제라고 생각하고 그것에 대한 일반적인 해결책이 있는지 궁금합니다.
기본적으로 내 UITableView에는 모든 셀에 대한 동적 셀 높이가 있습니다. UITableView 및 I의 맨 위에 있지 않으면 위로 tableView.reloadData()
스크롤이 급증합니다.
나는 이것이 데이터를 다시로드했기 때문에 스크롤 할 때 UITableView가 가시성에 도달하는 각 셀의 높이를 다시 계산한다는 사실 때문이라고 생각합니다. 이를 완화하는 방법 또는 특정 IndexPath에서 UITableView의 끝까지 만 데이터를 다시로드하는 방법은 무엇입니까?
또한 맨 위로 스크롤 할 때 점프하지 않아도 문제가 없습니다. UITableViewCell 높이가 이미 계산 되었기 때문일 수 있습니다.
답변
점프를 방지하기 위해 셀이로드 될 때 셀의 높이를 저장하고 정확한 값을 제공해야합니다 tableView:estimatedHeightForRowAtIndexPath
.
빠른:
var cellHeights = [IndexPath: CGFloat]()
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeights[indexPath] ?? UITableView.automaticDimension
}
목표 C :
// declare cellHeightsDictionary
NSMutableDictionary *cellHeightsDictionary = @{}.mutableCopy;
// declare table dynamic row height and create correct constraints in cells
tableView.rowHeight = UITableViewAutomaticDimension;
// save height
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cellHeightsDictionary setObject:@(cell.frame.size.height) forKey:indexPath];
}
// give exact height value
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSNumber *height = [cellHeightsDictionary objectForKey:indexPath];
if (height) return height.doubleValue;
return UITableViewAutomaticDimension;
}
답변
수락 된 답변의 신속한 3 버전.
var cellHeights: [IndexPath : CGFloat] = [:]
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeights[indexPath] ?? 70.0
}
답변
점프는 예상 높이가 잘못 되었기 때문입니다. 예상 RowHeight가 실제 높이와 다를수록 테이블을 다시로드 할 때 특히 테이블이 더 아래로 스크롤 될 때 테이블이 더 많이 점프 할 수 있습니다. 테이블의 예상 크기가 실제 크기와 크게 다르기 때문에 테이블의 내용 크기와 오프셋을 조정해야하기 때문입니다. 따라서 추정 높이는 임의의 값이 아니라 높이가 될 것으로 생각되는 것과 비슷해야합니다. UITableViewAutomaticDimension
당신의 세포가 같은 유형인지 설정했을 때도 경험했습니다.
func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 100//close to your cell height
}
다른 섹션에 다양한 셀이 있다면 더 좋은 곳은
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
//return different sizes for different cells if you need to
return 100
}
답변
이 경우 @Igor 답변이 제대로 작동Swift-4
합니다.
// declaration & initialization
var cellHeightsDictionary: [IndexPath: CGFloat] = [:]
다음과 같은 방법으로 UITableViewDelegate
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
// print("Cell height: \(cell.frame.size.height)")
self.cellHeightsDictionary[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
if let height = self.cellHeightsDictionary[indexPath] {
return height
}
return UITableView.automaticDimension
}
답변
위의 모든 해결 방법을 시도했지만 아무 효과가 없습니다.
몇 시간을 보내고 가능한 모든 좌절을 겪고 나서 이것을 고치는 방법을 알아 냈습니다. 이 솔루션은 구세주입니다! 매력처럼 일했다!
스위프트 4
let lastContentOffset = tableView.contentOffset
tableView.beginUpdates()
tableView.endUpdates()
tableView.layer.removeAllAnimations()
tableView.setContentOffset(lastContentOffset, animated: false)
코드를 깔끔하게 보이게하고 다시로드 할 때 마다이 모든 줄을 쓰지 않도록 확장 기능으로 추가했습니다.
extension UITableView {
func reloadWithoutAnimation() {
let lastScrollOffset = contentOffset
beginUpdates()
endUpdates()
layer.removeAllAnimations()
setContentOffset(lastScrollOffset, animated: false)
}
}
드디어 ..
tableView.reloadWithoutAnimation()
또는 실제로 UITableViewCell
awakeFromNib()
메소드에 이러한 행을 추가 할 수 있습니다
layer.shouldRasterize = true
layer.rasterizationScale = UIScreen.main.scale
그리고 정상적으로 reloadData()
답변
더 많은 방법으로 문제를 해결합니다.
뷰 컨트롤러의 경우 :
var cellHeights: [IndexPath : CGFloat] = [:]
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cellHeights[indexPath] = cell.frame.size.height
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return cellHeights[indexPath] ?? 70.0
}
UITableView의 확장으로
extension UITableView {
func reloadSectionWithouAnimation(section: Int) {
UIView.performWithoutAnimation {
let offset = self.contentOffset
self.reloadSections(IndexSet(integer: section), with: .none)
self.contentOffset = offset
}
}
}
결과는
tableView.reloadSectionWithouAnimation(section: indexPath.section)
답변
나는 오늘 이것을 만났고 관찰했다.
- 실제로 iOS 8 전용입니다.
- 재정의
cellForRowAtIndexPath
는 도움이되지 않습니다.
수정은 실제로 매우 간단했습니다.
재정의 estimatedHeightForRowAtIndexPath
하고 올바른 값을 반환하는지 확인하십시오.
이로 인해 UITableViews에서 모든 이상한 지터와 점프가 중단되었습니다.
참고 : 실제로 셀 크기를 알고 있습니다. 가능한 값은 두 가지뿐입니다. 셀이 실제로 가변 크기 인 경우 cell.bounds.size.height
from 을 캐시 할 수 있습니다tableView:willDisplayCell:forRowAtIndexPath: