如果有人来这里寻找 MonoTouch 的答案,这就是我通过翻译Gareth 的答案得到的。
一个基类,定义EnableAnimationFix
了两个虚拟方法:ApplyAnimationFixToAppearingItem
和ApplyAnimationFixToDisappearingItem
.
public class CollectionViewFlowLayout : UICollectionViewFlowLayout
{
protected List<int> _insertedItems = new List<int> ();
protected List<int> _deletedItems = new List<int> ();
protected virtual bool EnableAnimationFix {
get { return false; }
}
protected virtual void ApplyAnimationFixToAppearingItem (int index, UICollectionViewLayoutAttributes attrs)
{
throw new NotImplementedException ();
}
protected virtual void ApplyAnimationFixToDisappearingItem (int index, UICollectionViewLayoutAttributes attrs)
{
throw new NotImplementedException ();
}
public override UICollectionViewLayoutAttributes InitialLayoutAttributesForAppearingItem (NSIndexPath path)
{
var attrs = base.InitialLayoutAttributesForAppearingItem (path);
if (!EnableAnimationFix) {
return attrs;
}
attrs = attrs ?? LayoutAttributesForItem (path);
if (attrs != null)
ApplyAnimationFixToAppearingItem (path.Row, attrs);
return attrs;
}
public override UICollectionViewLayoutAttributes FinalLayoutAttributesForDisappearingItem (NSIndexPath path)
{
var attrs = base.FinalLayoutAttributesForDisappearingItem (path);
if (!EnableAnimationFix) {
return attrs;
}
if (attrs == null && _deletedItems.Contains (path.Row)) {
// Calling LayoutAttributesForItem will cause an exception so we return now.
// I think this happens when last and only item is deleted, and there are no other cells in cell pool.
return null;
}
attrs = attrs ?? LayoutAttributesForItem (path);
if (attrs != null)
ApplyAnimationFixToDisappearingItem (path.Row, attrs);
return attrs;
}
public override void PrepareForCollectionViewUpdates (UICollectionViewUpdateItem [] updateItems)
{
base.PrepareForCollectionViewUpdates (updateItems);
if (!EnableAnimationFix)
return;
_insertedItems.Clear ();
_deletedItems.Clear ();
foreach (var update in updateItems) {
if (update.UpdateAction == UICollectionUpdateAction.Insert) {
_insertedItems.Add (update.IndexPathAfterUpdate.Row);
} else if (update.UpdateAction == UICollectionUpdateAction.Delete) {
_deletedItems.Add (update.IndexPathBeforeUpdate.Row);
}
}
}
public override void FinalizeCollectionViewUpdates ()
{
base.FinalizeCollectionViewUpdates ();
if (!EnableAnimationFix)
return;
_insertedItems.Clear ();
_deletedItems.Clear ();
}
}
还有我实际的集合视图布局代码:
public class DraftsLayout : CollectionViewFlowLayout
{
// ...
protected override bool EnableAnimationFix {
get { return true; }
}
protected override void ApplyAnimationFixToAppearingItem (int index, UICollectionViewLayoutAttributes attrs)
{
if (_insertedItems.Contains (index)) {
SetXByIndex (attrs, index);
attrs.ZIndex = -1;
}
int deletedToTheLeft = _deletedItems.Count (i => i < index);
if (deletedToTheLeft > 0) {
SetXByIndex (attrs, index + deletedToTheLeft);
}
}
protected override void ApplyAnimationFixToDisappearingItem (int index, UICollectionViewLayoutAttributes attrs)
{
SetXByIndex (attrs, index);
if (_deletedItems.Contains (index)) {
attrs.Alpha = 0;
}
}
const int SnapStep = 150;
static void SetXByIndex (UICollectionViewLayoutAttributes attrs, int index)
{
var frame = attrs.Frame;
frame.X = index * SnapStep;
attrs.Frame = frame;
}
}
请注意,此代码应该可以很好地处理一批中的多个删除。
向加雷斯致敬。