誰かが MonoTouch の回答を探してここに来た場合、これがガレスの回答を翻訳して得たものです。
EnableAnimationFix
および 2 つの仮想メソッドを定義する基本クラス: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;
}
}
このコードは、バッチ内の複数の削除を適切に処理する可能性があることに注意してください。
ガレスに敬意を表します。