Индикатор межэлементного разрыва NSCollectionView имеет неправильную высоту

Я реализую приложение для macOS, в котором использую NSCollectionViewкак своего рода временная шкала. Для этого я использую собственный подклассNSCollectionViewFlowLayout по следующим причинам:

  1. Я хочу, чтобы элементы можно было прокручивать только по горизонтали без переноса на следующую строку
  2. Только NSCollectionViewFlowLayout кажется способным сказать NSCollectionViewне прокручивать по вертикали (вдохновение отсюда)

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

override func layoutAttributesForInterItemGap(before indexPath: IndexPath) -> NSCollectionViewLayoutAttributes?
{
    var result: NSCollectionViewLayoutAttributes? = nil

    // The itemLayoutAttributes dictionary is created in prepare() and contains
    // the layout attributes for every item in the collection view
    if indexPath.item < itemLayoutAttributes.count
    {
        if let itemLayout = itemLayoutAttributes[indexPath]
        {
            result = NSCollectionViewLayoutAttributes(forInterItemGapBefore: indexPath)
            result?.frame = NSRect(x: itemLayout.frame.origin.x - 4, y: itemLayout.frame.origin.y, width: 3, height: itemLayout.size.height)
        }
    }
    else
    {
        if let itemLayout = itemLayoutAttributes.reversed().first
        {
            result = NSCollectionViewLayoutAttributes(forInterItemGapBefore: indexPath)
            result?.frame = NSRect(x: itemLayout.value.frame.origin.x + itemLayout.value.frame.size.width + 4, y: itemLayout.value.frame.origin.y, width: 3, height: itemLayout.value.size.height)
        }
    }

    return result
}

Согласно документации indexPathпередаваемый в метод, может быть от 0 до количества элементов в представлении коллекции, в том числе, если мы пытаемся отбросить после последнего элемента. Как видите, я возвращаю прямоугольник для индикатора промежутка между элементами, который должен иметь ширину 3 пикселя и такую ​​же высоту, как и элемент.

Хотя индикатор отображается в правильном x-положении с правильной шириной, его высота составляет всего 2 пикселя, независимо от того, какую высоту я ввожу.

Как это исправить?

NB: Если я временно изменю макет на NSCollectionViewFlowLayout индикатор отображается правильно.

Я отменяю следующие методы / свойства в NSCollectionViewFlowLayout:

  • подготовить()
  • collectionViewContentSize
  • layoutAttributesForElements(in rect: NSRect) -> [NSCollectionViewLayoutAttributes]
  • layoutAttributesForItem (в indexPath: IndexPath) -> NSCollectionViewLayoutAttributes?
  • shouldInvalidateLayout(forBoundsChange newBounds: NSRect) -> Bool
  • layoutAttributesForInterItemGap(перед indexPath: IndexPath) -> NSCollectionViewLayoutAttributes?

1 ответ

Вам также может потребоваться переопределитьlayoutAttributesForDropTarget(at pointInCollectionView: NSPoint) -> NSCollectionViewLayoutAttributes.

В документации упоминается, что фрейм атрибутов, возвращаемых этим методом provides a bounding box for the gap, that will be used to position and size a drop target indicator (Посмотреть).

Вы можете установить точку останова в своем коде перетаскивания после того, как отобразится индикатор перетаскивания (например, collectionView(:acceptDrop:indexPath:dropOperation:)а затем, когда точка останова будет достигнута во время сеанса перетаскивания, запустите отладчик представления Xcode, чтобы проверить представление индикатора перетаскивания после его добавления в представление коллекции. Таким образом, вы можете быть уверены, что иерархия представлений верна и любые проблемы визуально очевидны.

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