Запретить NSCollectionView «поднимать» элемент во время перетаскивания

Я понимаю, как заставить работать перетаскивание для NSCollectionView, но я не могу остановить его «подъем» элементов за пределы представления.

Мое текущее решение состоит в том, чтобы не реализовывать

func collectionView(_ collectionView: NSCollectionView, pasteboardWriterForItemAt indexPath: IndexPath) -> NSPasteboardWriting?

от NSCollectionViewDelegate, чтобы убедиться, что

func collectionView(_ collectionView: NSCollectionView, draggingImageForItemsAt indexPaths: Set<IndexPath>, with event: NSEvent, offset dragImageOffset: NSPointPointer) -> NSImage

Вызывается IS, где я могу предоставить свои собственные перетаскиваемые изображения. Однако они не стекаются и не отображают значок, показывающий, сколько элементов перетаскивается.

Проблема в том, что когда я реализую предыдущий метод, кажется, что ничего из того, что я делаю (включая переопределение draggingImageComponents NSCollectionViewItem), не мешает перетаскиванию «поднять» элемент из представления коллекции, оставляя после себя пустое пространство.

Перетаскивание изображений в Photos.app и файлов в Finder.app (представление значков) не поднимает элемент, поэтому, надеюсь, это возможно.


person Rik    schedule 31.01.2019    source источник
comment
lldb + hopper показывает, что это пользовательская реализация перетаскивания imgur.com/a/BSBqOUz   -  person Marek H    schedule 17.03.2019
comment
Ух ты! Большое спасибо за расследование этого. Я так понимаю, это означает, что я не могу сделать что-то подобное с публичными API?   -  person Rik    schedule 18.03.2019
comment
Я проверял Preview.app, в котором есть PVSidebarThumbnailController, где вы можете сделать то же самое. Он использует только публичные функции. Так что да, это возможно с публикой. Используйте Hopperapp, чтобы заглянуть внутрь. Также lldb для установки точек останова (-n или -a). Также установите флаг для отладки типов элементов в монтажном столе (предварительная версия), используя po [NSUserDefaults standardUserDefaults] setValue:@(4) forKey:@NSDragManagerLogLevel]. Воспроизведение функции занимает слишком много времени. Нетрудно посмотреть на псевдокод Apple в хоппере, чтобы понять, что происходит. imgur.com/a/15VCVtI (элементы вставки Photos.app)   -  person Marek H    schedule 18.03.2019
comment
Вы решили это?   -  person Stuart Carnie    schedule 20.11.2019
comment
Нет. В конце концов, я сделал свой собственный стек из выбранных предметов.   -  person Rik    schedule 20.11.2019


Ответы (1)


По сути, это тот же вопрос, что и NSCollectionView - перетаскивание показывает «отверстие» — хотите, чтобы оно выглядело как Finder

Моим первоначальным решением было использовать настраиваемое представление для элемента представления коллекции. В моем подклассе я переопределяю setHidden:, чтобы представление коллекции не скрывало представление моего элемента во время перетаскивания элемента. Это имело некоторые нежелательные побочные эффекты. Похоже, что NSCollectionView также скрывает представления элементов при изменении макета.

Следующая идея (пока) отлично работает в моем приложении. Я открываю вид элемента, когда начинается перетаскивание.

@interface HGImagesCollectionViewDelegate : NSObject <NSCollectionViewDelegate>

@end

@implementation HGImagesCollectionViewDelegate

- (void)collectionView:(NSCollectionView *)collectionView
       draggingSession:(NSDraggingSession *)session
      willBeginAtPoint:(NSPoint)screenPoint
  forItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths
{
    //  Prevent item from being hidden (creating a hole in the grid) while being dragged
    for (NSIndexPath *indexPath in indexPaths) {
        [[[collectionView itemAtIndexPath:indexPath] view] setHidden:NO];
    }

    // …

}  

@end
person Pierre Bernard    schedule 24.01.2020