Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/103.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 假设高度错误,将较大的行插入UITableView时的动画_Ios_Animation_Uitableview - Fatal编程技术网

Ios 假设高度错误,将较大的行插入UITableView时的动画

Ios 假设高度错误,将较大的行插入UITableView时的动画,ios,animation,uitableview,Ios,Animation,Uitableview,在UITableView中添加或删除与其他行具有不同高度的行时,我在设置动画时遇到问题 以下GIF演示了插入和删除默认高度(44点)的行和较大的行(100点)的问题。左边的一个是来自模拟器的屏幕记录(新单元最终覆盖第五行是另一个问题),右边的一个是模拟它应该做什么 在我的例子中,我有很多行,每行的高度为60分。当点击单元格中的按钮时,“编辑”单元格将从下方滑出,向下推动较低的单元格。此编辑单元格的高度为180分。当我调用InsertRowsAndExpaths:withRowAnimation

在UITableView中添加或删除与其他行具有不同高度的行时,我在设置动画时遇到问题

以下GIF演示了插入和删除默认高度(44点)的行和较大的行(100点)的问题。左边的一个是来自模拟器的屏幕记录(新单元最终覆盖第五行是另一个问题),右边的一个是模拟它应该做什么

在我的例子中,我有很多行,每行的高度为60分。当点击单元格中的按钮时,“编辑”单元格将从下方滑出,向下推动较低的单元格。此编辑单元格的高度为180分。当我调用
InsertRowsAndExpaths:withRowAnimation:
DeleteRowsAndExpaths:withRowAnimation:
时,动画假定的高度为60分,而不是180分
这意味着在
UITableViewRowAnimationTop
的情况下,新单元格显示在距离其结束位置-60点处,并向下滑动到其新位置;大约有三分之一的动画是它应该做的。同时,下面的行从其起始位置平滑地设置动画,向下180点,与它应该设置的完全一致

有人想出了解决这个问题的实际办法吗?有什么方法可以告诉新的一排动画应该有多高

下面是我用来隐藏和显示编辑行的代码。我正在使用一个
tlswipeforoptions单元格
来触发编辑,但它可以通过使用例如
tableView:didSelectRowAtIndexPath:

-(void)hideEditFields{
    [self.tableView beginUpdates];

    [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0]] withRowAnimation:UITableViewRowAnimationTop];
    editFormVisibleForRow = -1;

    [self.tableView endUpdates];
}

-(void)cellDidSelectMore:(TLSwipeForOptionsCell *)cell{
    NSIndexPath* indexPath = [self.tableView indexPathForCell:cell];
    // do nothing if this is the currently selected row
    if(editFormVisibleForRow != indexPath.row){
        if(editFormVisibleForRow >= 0){
            [self hideEditFields];
            // update the index path, as the cell positions (may) have changed
            indexPath = [self.tableView indexPathForCell:cell];
        }

        [self.tableView beginUpdates];

        editFormVisibleForRow = indexPath.row;
        [self.tableView insertRowsAtIndexPaths:@[
                                             [NSIndexPath indexPathForItem:editFormVisibleForRow+1 inSection:0]
                                             ] withRowAnimation:UITableViewRowAnimationTop];

        [self.tableView endUpdates];
    }
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _dataSource.count + (editFormVisibleForRow >= 0 ? 1 : 0);
}

-(CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    int row = indexPath.row;
    if(editFormVisibleForRow >= 0 && row > editFormVisibleForRow && row <= editFormVisibleForRow + 1){
        return 180.0f;
    }
    else return 60.0;
}
-(void)隐藏的字段{
[self.tableView开始更新];
[self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:editFormVisibleForRow+1配置:0]]带RowAnimation:UITableViewRowAnimationTop];
editFormVisibleForRow=-1;
[self.tableView endUpdates];
}
-(无效)单元格选择更多:(t选择选项单元格*)单元格{
nsindepath*indepath=[self.tableView indexPathForCell:cell];
//如果这是当前选定的行,则不执行任何操作
if(editFormVisibleForRow!=indexPath.row){
如果(editFormVisibleForRow>=0){
[自隐藏字段];
//更新索引路径,因为单元格位置(可能)已更改
indexPath=[self.tableView indexPathForCell:cell];
}
[self.tableView开始更新];
editFormVisibleForRow=indexPath.row;
[self.tableView insertRowsAtIndexPaths:@[
[NSIndexPath indexPathForItem:editFormVisibleForRow+1第0节]
]withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
}
}
-(NSInteger)表视图:(UITableView*)表视图行数节:(NSInteger)节{
返回_dataSource.count+(editFormVisibleForRow>=0?1:0);
}
-(CGFloat)tableView:(UITableView*)表视图行高度索引路径:(NSIndexPath*)索引路径{
int row=indexPath.row;

如果(editFormVisibleForRow>=0&&row>editFormVisibleForRow&&row,则使用didSelectRowAtIndexPath对我有效:

@interface TableController ()
@property (strong,nonatomic) NSArray *theData;
@property (strong,nonatomic) NSIndexPath *pathToEditCell;
@end

@implementation TableController 


- (void)viewDidLoad {
    [super viewDidLoad];
    self.theData = @[@"One",@"Two",@"Three",@"Four",@"Five",@"Six",@"Seven",@"Eight",@"Nine"];
    [self.tableView reloadData];
}


-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return ([indexPath isEqual:self.pathToEditCell])? 100: 44;
}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return (self.pathToEditCell == nil)? self.theData.count: self.theData.count + 1;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if ([indexPath isEqual:self.pathToEditCell]) {
        RDEditCell *cell = [tableView dequeueReusableCellWithIdentifier:@"EditCell" forIndexPath:indexPath];
        return cell;
    }else{
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = self.theData[indexPath.row];
        return cell;
    }
}


- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    if (self.pathToEditCell == nil) { // first time selecting a row
        self.pathToEditCell = [NSIndexPath indexPathForRow:indexPath.row +1 inSection:indexPath.section];
        [self.tableView insertRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationAutomatic];
    }else if ([self.pathToEditCell isEqual:indexPath]){ // deletes the edit cell if you click on it
        self.pathToEditCell = nil;
        [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

    }else{ // close the old edit cell and adds another if you click on another cell while the edit cell is on screen
        [self.tableView beginUpdates];
        [self.tableView deleteRowsAtIndexPaths:@[self.pathToEditCell] withRowAnimation:UITableViewRowAnimationFade];
        self.pathToEditCell = indexPath;
        [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        [self.tableView endUpdates];
    }
}

对于删除,我喜欢动画中“淡入淡出”选项的外观,但“顶部”也不错。

解决方案非常简单。您需要插入高度为
0
的单元格,然后将高度更改为预期大小,然后调用
beginUpdates
endUpdates

下面是一些伪代码

var cellHeight: CGFloat = 0

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    let dynamicHeightIndex = 2
    if indexPath.row == dynamicHeightIndex {
        return cellHeight
    } else {
        return tableView.rowHeight
    }
}

func insertCell() {
    // First update the data source before inserting the row
    tableView.insertRows(at: [someIndexPath], with: .none)

    cellHeight = 200

    tableView.beginUpdates()
    tableView.endUpdates()
}
要删除单元格,需要等待更新动画完成后,才能从表视图中删除

在iOS 11中,您有提供完成块的
func性能更新(uu:completion:)
。对于以前的版本,您可以尝试使用
CATransaction
完成

cellHeight = 0

CATransaction.begin()
CATransaction.setCompletionBlock({
    self.tableView.deleteRows(at: [someIndexPath], with: .none)
})

tableView.beginUpdates()
tableView.endUpdates()

CATransaction.commit()

你的代码也有同样的问题。编辑单元格只从-44点滑出,而不是从100点滑出,这使得单元格看起来像是从中心扩展而不是向下滑动。下面是一个gif来演示这个问题:@death_au,好吧,我想我误解了你的问题——我以为你只看到了新单元格的一部分。就我个人而言,我不这么认为那个动画有什么问题吗?在我看来没什么问题。我甚至没有注意到你在说什么,直到我放慢了速度。不管怎样,我不知道解决这个问题的方法。你明白了吗?尝试在这里做类似的事情…很巧,客户改变了我们的设计,不再需要这个功能,所以我从来没有解决过这个问题。如果我再次遇到它并解决它,我一定会回答这个问题。我遇到了同样的问题。有人解决了这个问题吗?所以没有解决办法吗?从两年前开始?