답변:
나는 내가 작업하고있는 부작용으로 이것에 대한 정말 간단한 해결책을 찾았 UITableView
습니다 .....
을 통해 원래 높이를 정상적으로보고하는 변수에 셀 높이를 저장 한 tableView: heightForRowAtIndexPath:
다음 높이 변경에 애니메이션을 적용하려면 변수 값을 변경하고 이것을 호출하십시오.
[tableView beginUpdates];
[tableView endUpdates];
전체 재로드를 수행하지는 않지만 UITableView
셀을 다시 그려서 셀의 새 높이 값을 가져와야한다는 것을 알기에 충분합니다 . 그것은 당신을 위해 변화를 애니메이션합니다. 단.
내 블로그에 더 자세한 설명과 전체 코드 샘플이 있습니다 ... Animate UITableView 셀 높이 변경
You can also use this method followed by the endUpdates method to animate the change in the row heights without reloading the cell.
developer.apple.com/library/ios/documentation/UIKit/Reference/…
나는 Simon Lee의 답변을 좋아합니다. 실제로 해당 방법을 시도하지는 않았지만 목록의 모든 셀 크기가 변경되는 것처럼 보입니다. 나는 도청 된 세포의 변화를 바라고있었습니다. 나는 약간 시몬처럼 그것을 약간 차이가 있었어요. 셀 선택시 셀 모양이 변경됩니다. 그리고 그것은 움직입니다. 또 다른 방법입니다.
현재 선택된 셀 인덱스의 값을 보유 할 int를 작성하십시오.
int currentSelection;
그때:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
int row = [indexPath row];
selectedNumber = row;
[tableView beginUpdates];
[tableView endUpdates];
}
그때:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([indexPath row] == currentSelection) {
return 80;
}
else return 40;
}
tableView : cellForRowAtIndexPath :에서 유사한 유형을 변경하여 셀 유형을 변경하거나 셀의 xib 파일을로드 할 수 있다고 확신합니다.
이와 같이 currentSelection은 0에서 시작합니다. 목록의 첫 번째 셀 (인덱스 0)이 기본적으로 선택되어 표시되지 않게하려면 조정해야합니다.
선택한 셀을 추적하는 속성 추가
@property (nonatomic) int currentSelection;
(예를 들어)에서 센티넬 값으로 설정 viewDidLoad
하여 UITableView
시작이 '정상'위치에서 시작 되도록하십시오.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//sentinel
self.currentSelection = -1;
}
에서 heightForRowAtIndexPath
당신이 높이를 설정할 수 있습니다 당신이 선택한 셀에 대해 원하는
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
int rowHeight;
if ([indexPath row] == self.currentSelection) {
rowHeight = self.newCellHeight;
} else rowHeight = 57.0f;
return rowHeight;
}
에서 didSelectRowAtIndexPath
당신의 현재 선택 사항을 저장하고 동적 높이 저장, 경우 필요
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// set selection
self.currentSelection = indexPath.row;
// save height for full text label
self.newCellHeight = cell.titleLbl.frame.size.height + cell.descriptionLbl.frame.size.height + 10;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
에서는 didDeselectRowAtIndexPath
센티널 값 선택 인덱스를 다시 설정하고 정상 형태로 되돌아 셀 애니메이션
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {
// do things with your cell here
// sentinel
self.currentSelection = -1;
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
}
애니메이션이 없기 때문에 reloadData가 좋지 않습니다 ...
이것이 현재 시도중인 것입니다.
NSArray* paths = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:0]];
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:paths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];
거의 제대로 작동합니다. 거의. 셀 높이를 높이고 있으며 테이블 뷰의 일부 스크롤 위치가 유지되는 것처럼 셀이 교체 될 때 테이블 뷰에 약간의 "딸꾹질"이 있습니다. 새로운 셀 (첫 번째 셀) 표)의 오프셋이 너무 높으면 스크롤 뷰가 튀어 위치를 변경합니다.
beginUpdates / endUpdates를 연속적으로 호출하는 데 필요한 모든 내용이 무엇인지 모르겠습니다 -[UITableView reloadRowsAtIndexPaths:withAnimation:]
. 다음은 예제 프로젝트 입니다.
나는로 해결했다 reloadRowsAtIndexPaths
.
didSelectRowAtIndexPath
선택한 셀의 indexPath에 저장 reloadRowsAtIndexPaths
하고 마지막에 호출 합니다 (다시로드 할 요소 목록에 NSMutableArray를 보낼 수 있음).
에서 heightForRowAtIndexPath
indexPath가 목록에 있는지 여부를 expandIndexPath 셀과 보내기 높이가 아닌지 확인할 수 있습니다.
이 기본 예제를 확인할 수 있습니다 : https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam 간단한 해결책입니다.
도움이된다면 일종의 코드를 추가하십시오.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 20;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath*)indexPath
{
if ([indexPath isEqual:_expandIndexPath])
return 80;
return 40;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Celda";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
[cell.textLabel setText:@"wopwop"];
return cell;
}
#pragma mark -
#pragma mark Tableview Delegate Methods
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *modifiedRows = [NSMutableArray array];
// Deselect cell
[tableView deselectRowAtIndexPath:indexPath animated:TRUE];
_expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
}
beginUpdates()
/ 대신 endUpdates()
권장 통화는 다음과 같습니다.
tableView.performBatchUpdates(nil, completion: nil)
애플은 beginUpdates / endUpdates에 대해 : "가능한 경우이 방법 대신 performBatchUpdates (_ : completion :) 메소드를 사용하십시오."
참조 : https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates
이것은 색인 행을 확장하기위한 것입니다.
@property (nonatomic) NSIndexPath *expandIndexPath;
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
if ([indexPath isEqual:self.expandedIndexPath])
return 100;
return 44;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableArray *modifiedRows = [NSMutableArray array];
if ([indexPath isEqual:self.expandIndexPath]) {
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = nil;
} else {
if (self.expandedIndexPath)
[modifiedRows addObject:self.expandIndexPath];
self.expandIndexPath = indexPath;
[modifiedRows addObject:indexPath];
}
// This will animate updating the row sizes
[tableView reloadRowsAtIndexPaths:modifiedRows withRowAnimation:UITableViewRowAnimationAutomatic];
// Preserve the deselection animation (if desired)
[tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ViewControllerCellReuseIdentifier];
cell.textLabel.text = [NSString stringWithFormat:@"I'm cell %ld:%ld", (long)indexPath.section, (long)indexPath.row];
return cell;
}
BOOL flag;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
flag = !flag;
[tableView beginUpdates];
[tableView reloadRowsAtIndexPaths:@[indexPath]
withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView endUpdates];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES == flag ? 20 : 40;
}
Swift 3에 대한 더 짧은 버전의 Simons 답변입니다. 또한 셀 선택을 토글 할 수 있습니다
var cellIsSelected: IndexPath?
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
cellIsSelected = cellIsSelected == indexPath ? nil : indexPath
tableView.beginUpdates()
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if cellIsSelected == indexPath {
return 250
}
return 65
}
사이먼 리의 대답의 스위프트 버전.
// MARK: - Variables
var isCcBccSelected = false // To toggle Bcc.
// MARK: UITableViewDelegate
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
// Hide the Bcc Text Field , until CC gets focused in didSelectRowAtIndexPath()
if self.cellTypes[indexPath.row] == CellType.Bcc {
if (isCcBccSelected) {
return 44
} else {
return 0
}
}
return 44.0
}
그런 다음 didSelectRowAtIndexPath ()에서
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.tableView.deselectRowAtIndexPath(indexPath, animated: true)
// To Get the Focus of CC, so that we can expand Bcc
if self.cellTypes[indexPath.row] == CellType.Cc {
if let cell = tableView.cellForRowAtIndexPath(indexPath) as? RecipientTableViewCell {
if cell.tag == 1 {
cell.recipientTypeLabel.text = "Cc:"
cell.recipientTextField.userInteractionEnabled = true
cell.recipientTextField.becomeFirstResponder()
isCcBccSelected = true
tableView.beginUpdates()
tableView.endUpdates()
}
}
}
}
네 가능합니다.
UITableView
위임 방법이 있습니다 didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[UIView animateWithDuration:.6
delay:0
usingSpringWithDamping:UIViewAnimationOptionBeginFromCurrentState
initialSpringVelocity:0
options:UIViewAnimationOptionBeginFromCurrentState animations:^{
cellindex = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
NSArray* indexArray = [NSArray arrayWithObjects:indexPath, nil];
[violatedTableView beginUpdates];
[violatedTableView reloadRowsAtIndexPaths:indexArray withRowAnimation:UITableViewRowAnimationAutomatic];
[violatedTableView endUpdates];
}
completion:^(BOOL finished) {
}];
}
그러나 사용자가 다른 셀을 스크롤하여 선택하면 현재 선택한 셀 reloadRowsAtIndexPaths:
호출 을 축소하고 확장하려면 마지막으로 선택한 셀이 있어야 heightForRowAtIndexPath:
하므로 적절하게 처리하십시오.
다음은 다시로드하지 않고 키보드 포커스를 잃지 않고 테이블 셀에서 UITableView
확장되는 사용자 정의 하위 클래스 코드입니다 UITextView
.
- (void)textViewDidChange:(UITextView *)textView {
CGFloat textHeight = [textView sizeThatFits:CGSizeMake(self.width, MAXFLOAT)].height;
// Check, if text height changed
if (self.previousTextHeight != textHeight && self.previousTextHeight > 0) {
[self beginUpdates];
// Calculate difference in height
CGFloat difference = textHeight - self.previousTextHeight;
// Update currently editing cell's height
CGRect editingCellFrame = self.editingCell.frame;
editingCellFrame.size.height += difference;
self.editingCell.frame = editingCellFrame;
// Update UITableView contentSize
self.contentSize = CGSizeMake(self.contentSize.width, self.contentSize.height + difference);
// Scroll to bottom if cell is at the end of the table
if (self.editingNoteInEndOfTable) {
self.contentOffset = CGPointMake(self.contentOffset.x, self.contentOffset.y + difference);
} else {
// Update all next to editing cells
NSInteger editingCellIndex = [self.visibleCells indexOfObject:self.editingCell];
for (NSInteger i = editingCellIndex; i < self.visibleCells.count; i++) {
UITableViewCell *cell = self.visibleCells[i];
CGRect cellFrame = cell.frame;
cellFrame.origin.y += difference;
cell.frame = cellFrame;
}
}
[self endUpdates];
}
self.previousTextHeight = textHeight;
}
@Joy의 멋진 답변을 사용했으며 ios 8.4 및 XCode 7.1.1과 완벽하게 작동했습니다.
셀을 토글 가능하게 만들려면 -tableViewDidSelect를 다음과 같이 변경하십시오.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//This is the bit I changed, so that if tapped once on the cell,
//cell is expanded. If tapped again on the same cell,
//cell is collapsed.
if (self.currentSelection==indexPath.row) {
self.currentSelection = -1;
}else{
self.currentSelection = indexPath.row;
}
// animate
[tableView beginUpdates];
[tableView endUpdates];
}
이 중 하나가 도움이 되었기를 바랍니다.
Simon Lee의 답변의 신속한 버전 :
tableView.beginUpdates()
tableView.endUpdates()
높이 속성을 수정하기 전에 수정해야합니다 endUpdates()
.
입력-
tableView.beginUpdates () tableView.endUpdates () 이 함수는 호출하지 않습니다
func tableView (_ tableView : UITableView, cellForRowAt indexPath : IndexPath)-> UITableViewCell {}
그러나 그렇게하면 tableView.reloadRows (at : [selectedIndexPath! as IndexPath], .none)
그것은 호출 >있는 UITableViewCell {} - (IndexPath : jQuery과, cellForRowAt indexPath _있는 tableView) FUNC의있는 tableView를 이 기능을 사용하지 않음.
방금 약간의 해킹 으로이 문제를 해결했습니다.
static int s_CellHeight = 30;
static int s_CellHeightEditing = 60;
- (void)onTimer {
cellHeight++;
[tableView reloadData];
if (cellHeight < s_CellHeightEditing)
heightAnimationTimer = [[NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(onTimer) userInfo:nil repeats:NO] retain];
}
- (CGFloat)tableView:(UITableView *)_tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (isInEdit) {
return cellHeight;
}
cellHeight = s_CellHeight;
return s_CellHeight;
}
셀 높이를 확장해야 할 때 isInEdit = YES
메소드를 설정 하고 호출 [self onTimer]
하면 s_CellHeightEditing 값에 도달 할 때까지 셀 성장에 애니메이션을 적용합니다 :-)
선택된 행의 인덱스 경로를 가져옵니다. 테이블을 다시로드하십시오. UITableViewDelegate의 heightForRowAtIndexPath 메서드에서 선택한 행의 높이를 다른 높이로 설정하고 다른 행의 경우 일반 행 높이를 반환
[table reloadData]
하면 애니메이션이 아닌 높이 변화가 즉시 발생합니다.