Как интерактивно переставлять элементы NSCollectionView при перетаскивании по ним?

Такие приложения, как Preview, указывают позицию для операций перетаскивания, интерактивно перемещая элементы в сторону. Выглядит так:

IIRC, это также поведение по умолчаниюUICollectionViewсо всеми стандартными планировками. Напротив, он предпочитает отображать индикатор вставки без изменения положения элементов, и я не могу понять, как заставить его делать это выше. Интересно, что снимок экрана в другом вопросе, похоже, показывает именно то поведение, которое я хочу (увы, обсуждение там не имеет отношения к делу).

Чтобы уточнить, настроен ли делегат для операций перетаскивания и каким образом:

      - (BOOL)collectionView:(NSCollectionView *)collectionView canDragItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths withEvent:(NSEvent *)event {
    return YES;
}

- (id<NSPasteboardWriting>)collectionView:(NSCollectionView *)collectionView pasteboardWriterForItemAtIndexPath:(NSIndexPath *)indexPath {
    NSPasteboardItem *pasteboardItem = [[NSPasteboardItem alloc] init];
    [pasteboardItem setString:@"Whatever is fine" forType:NSPasteboardTypeString];
    
    return pasteboardItem;
}

- (NSDragOperation)collectionView:(NSCollectionView *)collectionView validateDrop:(id<NSDraggingInfo>)draggingInfo proposedIndexPath:(NSIndexPath * _Nonnull __autoreleasing *)proposedDropIndexPath dropOperation:(NSCollectionViewDropOperation *)proposedDropOperation {
    *proposedDropOperation = NSCollectionViewDropBefore;
    
    return NSDragOperationMove;
}

Первоначально я понимал, что макет-layoutAttributesForDropTargetAtPoint:/-layoutAttributesForInterItemGapBeforeIndexPath:существовало для этой цели. Это не так, поскольку они служат только для размещения индикатора , который не влияет на поток предметов.

Точнее, установка произвольного прямоугольника (в подклассеNSCollectionViewFlowLayout):

      - (NSCollectionViewLayoutAttributes *)layoutAttributesForDropTargetAtPoint:(NSPoint)pointInCollectionView {
    NSCollectionViewLayoutAttributes *attributes = [[super layoutAttributesForDropTargetAtPoint:pointInCollectionView] copy];
    attributes.frame = NSMakeRect(60, 0, 200, 200);

    return attributes;
}

отобразит индикатор в {60, 0}, но это никак не повлияет на элементы.

Я мог бы, конечно, расширить макет дальше, чтобы он знал о перетаскивании сеансов, но это уже похоже на хак и необходимость вручную аннулировать его во время перетаскивания (не говоря уже о том, чтобы делать это внутри-performBatchUpdates:completionHandler:чтобы вызвать анимированный ответ) не оставляет в этом сомнений. В качестве альтернативы я мог бы напрямую манипулировать рамками элементов, но это также похоже на борьбу сNSCollectionViewвместо того, чтобы использовать его.

Учитывая, насколько широко распространен этот шаблон, должен быть правильный способ его реализации, не прибегая к хакам. Что мне не хватает?

Ваше здоровье.

0 ответов

Другие вопросы по тегам