ios 选择时,您可以为 UITableViewCell 上的高度变化设置动画吗?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/460014/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 15:34:01  来源:igfitidea点击:

Can you animate a height change on a UITableViewCell when selected?

ioscocoa-touchuitableview

提问by Simon Lee

I'm using a UITableViewin my iPhone app, and I have a list of people that belong to a group. I would like it so that when the user clicks on a particular person (thus selecting the cell), the cell grows in height to display several UI controls for editing the properties of that person.

UITableView在我的 iPhone 应用程序中使用 a ,并且我有一个属于某个组的人员列表。我希望这样当用户单击特定的人(从而选择单元格)时,单元格的高度会增加以显示多个用于编辑该人属性的 UI 控件。

Is this possible?

这可能吗?

回答by Simon Lee

I found a REALLY SIMPLE solution to this as a side-effect to a UITableViewI was working on.....

我找到了一个非常简单的解决方案,作为UITableView我正在研究的副作用......

Store the cell height in a variable that reports the original height normally via the tableView: heightForRowAtIndexPath:, then when you want to animate a height change, simply change the value of the variable and call this...

将单元格高度存储在一个通常通过 报告原始高度的变量中tableView: heightForRowAtIndexPath:,然后当您想要动画高度变化时,只需更改变量的值并调用它...

[tableView beginUpdates];
[tableView endUpdates];

You will find it doesn't do a full reload but is enough for the UITableViewto know it has to redraw the cells, grabbing the new height value for the cell.... and guess what? It ANIMATES the change for you. Sweet.

你会发现它并没有完全重新加载,但足以UITableView让它知道它必须重绘单元格,获取单元格的新高度值......你猜怎么着?它为您带来变化。甜的。

I have a more detailed explanation and full code samples on my blog... Animate UITableView Cell Height Change

我的博客上有更详细的解释和完整的代码示例...动画 UITableView Cell Height Change

回答by Mark A.

I like the answer by Simon Lee. I didn't actually try that method but it looks like it would change the size of all the cells in the list. I was hoping for a change of just the cell that is tapped. I kinda did it like Simon but with just a little difference. This will change the look of a cell when it is selected. And it does animate. Just another way to do it.

我喜欢 Simon Lee 的回答。我实际上并没有尝试这种方法,但看起来它会改变列表中所有单元格的大小。我希望只更改被点击的单元格。我有点像西蒙,但只是有一点不同。这将更改单元格被选中时的外观。它确实有动画效果。只是另一种方式来做到这一点。

Create an int to hold a value for the current selected cell index:

创建一个 int 来保存当前选定单元格索引的值:

int currentSelection;

Then:

然后:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    int row = [indexPath row];
    selectedNumber = row;
    [tableView beginUpdates];
    [tableView endUpdates];
}

Then:

然后:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    if ([indexPath row] == currentSelection) {
        return  80;
    }
    else return 40;


}

I am sure you can make similar changes in tableView:cellForRowAtIndexPath: to change the type of cell or even load a xib file for the cell.

我相信您可以在 tableView:cellForRowAtIndexPath: 中进行类似的更改以更改单元格的类型,甚至为单元格加载一个 xib 文件。

Like this, the currentSelection will start at 0. You would need to make adjustments if you didn't want the first cell of the list (at index 0) to look selected by default.

像这样,currentSelection 将从 0 开始。如果您不希望列表的第一个单元格(索引 0)在默认情况下看起来被选中,则需要进行调整。

回答by Joy

Add a property to keep track of the selected cell

添加属性以跟踪所选单元格

@property (nonatomic) int currentSelection;

Set it to a sentinel value in (for example) viewDidLoad, to make sure that the UITableViewstarts in the 'normal' position

将其设置为 (例如) 中的哨兵值viewDidLoad,以确保UITableView在“正常”位置开始

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    //sentinel
    self.currentSelection = -1;
}

In heightForRowAtIndexPathyou can set the height you want for the selected cell

heightForRowAtIndexPath你可以设置高度要用于选定单元格

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int rowHeight;
    if ([indexPath row] == self.currentSelection) {
        rowHeight = self.newCellHeight;
    } else rowHeight = 57.0f;
    return rowHeight;
}

In didSelectRowAtIndexPathyou save the current selection and save a dynamic height, if required

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

In didDeselectRowAtIndexPathset the selection index back to the sentinel value and animate the cell back to normal form

didDeselectRowAtIndexPath将选择索引设置回标记值并将单元格动画恢复为正常形式

- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath {       
        // do things with your cell here

        // sentinel
        self.currentSelection = -1;

        // animate
        [tableView beginUpdates];
        [tableView endUpdates];
    }
}

回答by lawrence

reloadData is no good because there's no animation...

reloadData 不好,因为没有动画...

This is what I'm currently trying:

这是我目前正在尝试的:

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

It almost works right. Almost. I'm increasing the height of the cell, and sometimes there's a little "hiccup" in the table view as the cell is replaced, as if some scrolling position in the table view is being preserved, the new cell (which is the first cell in the table) ends up with its offset too high, and the scrollview bounces to reposition it.

它几乎可以正常工作。几乎。我正在增加单元格的高度,有时在单元格被替换时表格视图中会出现一些“打嗝”,好像表格视图中的某些滚动位置被保留,新单元格(这是第一个单元格在表中)最终其偏移量太高,并且滚动视图会反弹以重新定位它。

回答by axiixc

I don't know what all this stuff about calling beginUpdates/endUpdates in succession is, you can just use -[UITableView reloadRowsAtIndexPaths:withAnimation:]. Here is an example project.

我不知道关于连续调用 beginUpdates/endUpdates 的所有这些东西是什么,你可以使用-[UITableView reloadRowsAtIndexPaths:withAnimation:]. 这是一个示例项目

回答by fermin

I resolved with reloadRowsAtIndexPaths.

我解决了reloadRowsAtIndexPaths

I save in didSelectRowAtIndexPaththe indexPath of cell selected and call reloadRowsAtIndexPathsat the end (you can send NSMutableArray for list of element's you want reload).

我保存在didSelectRowAtIndexPath所选单元格的 indexPath 中并reloadRowsAtIndexPaths在最后调用(您可以发送 NSMutableArray 以获取要重新加载的元素列表)。

In heightForRowAtIndexPathyou can check if indexPath is in the list or not of expandIndexPath cell's and send height.

heightForRowAtIndexPath您可以检查是否indexPath在列表与否的expandIndexPath细胞的和发送的高度。

You can check this basic example: https://github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetamIt's a simple solution.

您可以查看这个基本示例:https: //github.com/ferminhg/iOS-Examples/tree/master/iOS-UITableView-Cell-Height-Change/celdascambiadetam这是一个简单的解决方案。

i add a sort of code if help you

如果对您有帮助,我会添加一种代码

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

回答by raf

Instead of beginUpdates()/endUpdates(), the recommended call is now:

而不是beginUpdates()/ endUpdates(),现在推荐的调用是:

tableView.performBatchUpdates(nil, completion: nil)

Apple says, regarding beginUpdates/endUpdates: "Use the performBatchUpdates(_:completion:) method instead of this one whenever possible."

Apple 说,关于 beginUpdates/endUpdates:“尽可能使用 performBatchUpdates(_:completion:) 方法而不是这个方法。”

See: https://developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

请参阅:https: //developer.apple.com/documentation/uikit/uitableview/1614908-beginupdates

回答by Roman Solodyashkin

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

回答by Nagarjun

Try this is for expanding indexwise row:

试试这是为了扩展索引行:

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

回答by aBikis

Heres a shorter version of Simons answer for Swift 3. Also allows for toggling of the cell's selection

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