奇怪的UITableView插入/删除行动画

时间:2014-04-11 19:57:12

标签: ios uitableview animation

我在使用动画(UITableViewRowAnimationTop)在UITableView中插入/删除UITableViewCell时看到了一个奇怪的效果。

当要插入的单元格比上面的单元格大得多时,会发生动画故障。

This video显示了模拟器中的故障,黄色单元突然出现在它应该从顶部滑动的位置。

Here是视频中的Xcode项目。

Bellow是细胞插入/动画代码。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2 + self.thirdCellVisible;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    if (indexPath.row == 1)
    {
        if (self.thirdCellVisible)
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];
        }
        else
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];
        }
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == self.thirdCellIndexPath.row)
    {
        return 100.0f;
    }

    return 44.0f;
}

4 个答案:

答案 0 :(得分:4)

您必须致电

[tableView beginUpdates] 

[tableView endUpdates] 

调用插入/删除方法之前和之后如下:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 2 + self.thirdCellVisible;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:NO];

    if (indexPath.row == 1)
    {
        if (self.thirdCellVisible)
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [self.tableView beginUpdates];

            [tableView deleteRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];

            [self.tableView endUpdates];

        }
        else
        {
            self.thirdCellVisible = !self.thirdCellVisible;
            [self.tableView beginUpdates];

            [tableView insertRowsAtIndexPaths:@[self.thirdCellIndexPath]
                             withRowAnimation:UITableViewRowAnimationTop];

            [self.tableView endUpdates];

        }
    }
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.row == self.thirdCellIndexPath.row)
    {
        return 100.0f;
    }

    return 44.0f;
}

答案 1 :(得分:2)

根据Apple here

  

动画批量插入,删除和重新加载行和   在动画块中调用相应的方法   由连续调用beginUpdates和endUpdates定义。如果你   不要在其中调用插入,删除和重新加载方法   块,行和段索引可能无效。调用beginUpdates   和endUpdates可以嵌套;所有索引都被视为有   只有外部更新块。

     

在一个块结束时 - 也就是说,在endUpdates返回之后   表视图查询其数据源并像往常一样委托行和   部分数据。因此,支持表视图的集合对象   应该更新以反映新的或删除的行或部分。

您必须分别在调用插入/删除方法之前和之后调用[tableView beginUpdates][tableView endUpdates]

Apple在上述链接中提供了一个示例。

注意:如果你的数组和表视图项不同步,没有开始/结束调用,将抛出异常。

建议:先尝试withRowAnimation:UITableViewRowAnimationAutomatic

答案 2 :(得分:2)

以下是我的工作代码视频的链接:https://dl.dropboxusercontent.com/u/30316681/480.mov

以下是我的工作代码:

(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
require('./module.js');
angular
    .module('app')
    .controller('myController', 

function () {
    var vm = this;

    vm.title = 'test';

    activate();

    function activate() { }
});

function test() {
    var vm = 'test';
}

},{"./module.js":2}],2:[function(require,module,exports){
angular.module('app', []);

},{}]},{},[1])

答案 3 :(得分:1)

使用package me.mortadelle2.turrets; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerMoveEvent; public class CreateTurretEvent implements Listener{ Turrets getter; public CreateTurretEvent(Turrets plugin){ plugin.getServer().getPluginManager().registerEvents(this, plugin); getter = plugin; } @EventHandler public void playerPlacesBlockToBecomeTurret(BlockPlaceEvent e){ Player p = e.getPlayer(); if (getter.playersThatShouldPlaceBlock.contains(p.getName())){ p.sendMessage(getter.turretsMsg + "That block is now turretified!"); getter.getServer().getScheduler().cancelTask(getter.waitForPlacement); getter.playersThatShouldPlaceBlock.remove(p.getName()); Location blockLocation = e.getBlock().getLocation(); getter.getConfig().set("Turrets." + getter.turretName.get(p.getName()), blockLocation); } } @EventHandler public void playerStepsOnTurret(PlayerMoveEvent e){ Player p = e.getPlayer(); if (getter.getConfig().contains("test")){ //I will add something more specific than test later p.sendMessage("This is a test"); } } } [tableView beginUpdates],如下所示

[tableView endUpdates]