У меня есть базовое приложение Cocoa Mac с представлением, которое содержит подпредставление.Подпредставление можно перетаскивать, и я бы хотел, чтобы у пользователя создалось впечатление, что он фактически перемещает представление, оставляя местозаполнитель в его исходном местоположении при перетаскивании.
Подход по умолчанию заключается в создании нового NSDraggingItem
со снимком подпредставления, так что при перетаскивании представления действительно происходит его перемещение.
По умолчанию подпредставление остается видимым в своем исходном местоположении, так чтодва экземпляра вида на экране:
Теперь я бы хотел дать пользователю иллюзию «выбора вида» и его перемещения.вокруг, оставляя заполнитель в исходном положении.Я делаю это, меняя цвет фона подпредставления на серый, когда вид перетаскивается.Вот результат:
Почти идеально!За исключением того, что, когда перетаскивание отменено, и представление возвращается в исходное положение, оно мигает один раз.
Это потому, что я возвращаю фоновый цвет подпредставления обратно в NSDraggingSource.draggingSession(_ session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation)
, который, в свою очередь, называется крошечной дробью послеанимация перетаскивания завершена.
Вот порядок событий:
- Пользователь начинает перетаскивать подпредставление
- Снимок представления берется и используется для сеанса перетаскивания.
- Цвет фона представления изменяется на темно-серый для имитации «заполнителя»
- Пользователь перетаскивает представление вокруг и нажимает клавишу Esc, чтобы отменить перетаскивание
- Изображение снимка скользит назадв исходное положение
- После возвращения изображение снимка исчезает над фактическим видом элемента (анимация, предоставляемая системой)
dragginSession(endedAt)
вызывается и фон изменяется обратно
Моя проблема в том, что мне придется восстанавливать исходный цвет фона сразу после # 5, а не после шага # 6.Есть ли способ получить уведомление сразу, когда анимация перетаскивания заканчивается?
Исходный код:
class HomebaseView: NSView, NSDraggingSource {
@IBOutlet var itemView:ItemView!
override func mouseDragged(with event: NSEvent) {
startDraggingItem(with: event)
}
func draggingSession(_ session: NSDraggingSession, willBeginAt screenPoint: NSPoint) {
itemView.isBeingDragged = true
}
func draggingSession(_ session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) {
itemView.isBeingDragged = false
}
func draggingSession(_ session: NSDraggingSession, sourceOperationMaskFor context: NSDraggingContext) -> NSDragOperation {
return .copy
}
private func startDraggingItem(with event:NSEvent) {
let item = itemView!
let pasteboardItem = NSPasteboardItem()
let draggingItem = NSDraggingItem(pasteboardWriter: pasteboardItem)
let itemFrame = item.convert(item.bounds, to: self)
draggingItem.setDraggingFrame(itemFrame, contents: item.snapshot())
beginDraggingSession(with: [draggingItem], event: event, source: self)
}
}
extension NSView {
public func snapshot() -> NSImage {
let pdfData = dataWithPDF(inside: bounds)
let image = NSImage(data: pdfData)
return image ?? NSImage()
}
}
РЕДАКТИРОВАТЬ:
В качестве доказательства того, что это должно быть как-то возможно, приведу анимацию из Keynote.Это немного сложно увидеть, но слайд «скользит» назад без анимации затухания в своем начале.