ios - estimatedrowheight - 你選擇時可以在UITableViewCell上設置動畫高度變化嗎?




cocoa-touch (13)

我在我的iPhone應用程序中使用UITableView ,並且擁有屬於一個組的人員列表。 我希望這樣,當用戶點擊某個特定的人(從而選擇單元格)時,單元格會高度增長以顯示多個UI控件以編輯該人員的屬性。

這可能嗎?


Heres是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
  }

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

它幾乎是正確的。 幾乎。 我正在增加單元格的高度,有時表格視圖中會有一點點“呃逆”,因為單元格被替換了,就好像表格視圖中的某個滾動位置正在保存一樣,新單元格(這是第一個單元格在表中)以偏移量過高而結束,並且滾動視圖反彈以重新定位它。


在iOS 7及更高版本之後檢查此方法。

- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return UITableViewAutomaticDimension;
}

iOS 8已經對此進行了改進。我們可以將它設置為表視圖本身的屬性。


我不知道所有關於調用beginUpdates / endUpdates的東西是什麼,你可以使用-[UITableView reloadRowsAtIndexPaths:withAnimation:]這是一個示例項目


我只是用一點小竅門解決了這個問題:

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] ,它[self onTimer]單元格增長直到它達到s_CellHeightEditing值:-)


我喜歡西蒙李的回答。 我沒有真正嘗試這種方法,但它看起來會改變列表中所有單元格的大小。 我只希望改變被挖掘的細胞。 我有點像西蒙,但只有一點區別。 當它被選中時,這將改變單元格的外觀。 它確實有動畫。 只是另一種方式來做到這一點。

創建一個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處)默認顯示為選中狀態,則需要進行調整。


我發現一個真正簡單的解決方案,作為我正在研究的UITableView的副作用.....

通過tableView: heightForRowAtIndexPath:將單元格高度存儲在一個報告原始高度的變量中,然後當您想要設置高度變化的動畫時,只需更改該變量的值並調用此...

[tableView beginUpdates];
[tableView endUpdates];

你會發現它並沒有完全重新加載,但足以讓UITableView知道它必須重繪單元格,為單元格獲取新的高度值......並猜測是什麼? 它為您的動畫改變。 甜。

我在我的博客上有更詳細的解釋和完整的代碼示例... Animate UITableView Cell Height Change


是的可能。

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:如此處理。


獲取所選行的索引路徑。 重新載入表格。 在UITableViewDelegate的heightForRowAtIndexPath方法中,將所選行的高度設置為不同的高度,其他高度則返回正常行高


西蒙李的答案迅速版本。

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

試試這是為了擴展索引行:

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

輸入 -

tableView.beginUpdates()tableView.endUpdates()這些函數不會調用

func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath) - > UITableViewCell {}

但是,如果你這樣做, tableView.reloadRows(在:[selectedIndexPath!as IndexPath],使用:.none)

它會調用func tableView(_ tableView:UITableView,cellForRowAt indexPath:IndexPath) - > UITableViewCell {}這個函數。


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




uitableview