Есть ли подходящий способ справиться с перекрывающимися братьями и сестрами NSView?

Я работаю над приложением Cocoa, и я столкнулся с ситуацией, когда мне хотелось бы, чтобы два объекта NSView перекрывались. У меня есть родительский NSView, который содержит два подзаголовка (NSView A и NSView B), каждый из которых может иметь несколько собственных надстроек.

Есть ли подходящий способ справиться с подобным перекрытием? NSView B всегда будет «выше» NSView A, поэтому я хочу, чтобы перекрывающиеся части NSView A были замаскированы.

Если ваше приложение составляет только 10,5, включите слои для просмотров, и он должен просто работать.

Если вы хотите поддержать 10.4 и ниже, вам нужно найти способ не перекрывать представления, потому что перекрывающиеся представления для сестер – это неопределенное поведение. В Руководстве по программированию:

По соображениям производительности, Cocoa не обеспечивает принудительное обрезание среди представлений братьев и сестер или гарантирует правильное поведение недействительности и рисования при совпадении взглядов братьев и сестер. Если вы хотите, чтобы представление было обращено перед другим видом, вы должны сделать вид спереди подвью (или потомок) заднего вида.

Я видел некоторые хаки, которые могут иногда делать это любопытно, но на это вы не можете положиться. Вам нужно либо сделать View A подзаголовком View B, либо сделать один гигантский вид, который обрабатывает обе свои обязанности.

Крис, единственное решение – использовать CALayers. Это, безусловно, единственное решение.

NSViews просто сломаны в OSX (сентябрь 2010): братья и сестры не работают должным образом. Один или другой будет случайным образом отображаться сверху.

Чтобы повторить, проблема связана с братьями и сестрами .

Чтобы проверить это: используйте NSViews и / или nsimageviews. Сделайте приложение с представлением, которое представляет собой одно большое изображение (1000×1000). В представлении разместите три или четыре маленьких изображения / NSView здесь и там. Теперь добавьте еще одно большое изображение 1000×1000. Создавайте и запускайте приложение повторно – вы увидите, что он просто сломан. Часто нижние (маленькие) слои появляются поверх большого покровного слоя. если вы включите поддержку слоев в NSViews, это не поможет, независимо от того, какую комбинацию вы попробуете. Так что это окончательный тест.

Вы должны отказаться от NSViews и использовать CALayers, и все.

Единственное раздражение с CALayers заключается в том, что вы не можете использовать IB для настройки своего материала. Вы должны установить все позиции слоя в коде,

yy = [CALayer layer]; yy.frame = CGRectMake(300,300, 300,300); 

Сделайте только один NSView, единственная цель – удерживать свой первый CALayer (возможно, называемый «сзади»), а затем просто поместить все ваши CALayers в тыл.

 rear = [CALayer layer]; rear.backgroundColor = CGColorCreateGenericRGB( 0.75, 0.75, 0.75, 1.0 ); [yourOnlyNsView setLayer:rear]; // these two lines must be in this order [yourOnlyNsView setWantsLayer:YES]; // these two lines must be in this order [rear addSublayer:rr]; [rear addSublayer:yy]; [yy addSublayer:s1]; [yy addSublayer:s2]; [yy addSublayer:s3]; [yy addSublayer:s4]; [rear addSublayer:tt]; [rear addSublayer:ff]; 

все работает отлично, вы можете вложить и сгруппировать все, что угодно, и все это безупречно работает со всем, что появляется выше / ниже всего, что должно появляться выше / ниже, независимо от сложности вашей структуры. Позже вы можете сделать что-либо для слоев или перетасовать вещи по-разному,

 -(void) shuff { [CATransaction begin]; [CATransaction setValue:[NSNumber numberWithFloat:0.0f] forKey:kCATransactionAnimationDuration]; if .. [rear insertSublayer:ff below:yy]; else [rear insertSublayer:ff above:yy]; [CATransaction commit]; } 

(Единственная причина для раздражающей обертки «в нулевых секундах» для всего, что вы делаете, заключается в том, чтобы предотвратить анимацию, которая предоставляется вам бесплатно – если вы не хотите анимацию!)

Кстати, в этой цитате от Apple,

По соображениям производительности, Cocoa не обеспечивает принудительное обрезание среди представлений братьев и сестер или гарантирует правильное поведение недействительности и рисования при совпадении взглядов братьев и сестер.

Их следующее предложение …

Если вы хотите, чтобы представление было обращено перед другим видом, вы должны сделать вид спереди подвью (или потомок) заднего вида.

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

Так что это CALayers! Наслаждайтесь!

Есть способ сделать это, не используя CALayers и приложение, над которым я работал, может это доказать. Создайте два windows и используйте это:

 [mainWindow addChildWindow:otherWindow ordered:NSWindowAbove]; 

Чтобы удалить « otherWindow », используйте:

 [mainWindow removeChildWindow:otherWindow]; [otherWindow orderOut:nil]; 

И вы, вероятно, захотите взять строку заголовка windows с помощью:

 [otherWindow setStyleMask:NSBorderlessWindowMask]; 

Чтобы гарантировать, что NSView B всегда перекрывает NSView A , убедитесь, что вы используете правильный NSWindowOrderingMode когда вы добавляете subview:

 [parentView addSubview:B positioned:NSWindowAbove relativeTo:A]; 

Вы также должны иметь в виду, что скрытые части A не будут запрашиваться для перерисовки, если вид B на 100% непрозрачен.

Если вы перемещаете subviews, вам также нужно убедиться, что вы вызываете -setNeedsDisplayInRect: для областей видимости, которые вы открываете.

Как писал Нейт, можно использовать:

 self.addSubview(btn2, positioned: NSWindowOrderingMode.Above, relativeTo: btn1) 

Тем не менее, упорядочение представлений не соблюдается, как только вы просите любой из мнений перерисовать его через вызов «needDisplay = true»

Братья и сестры не получат вызов drawRect, только прямые ссылки на представления.

Обновление 1

Чтобы решить эту проблему, мне пришлось прорываться глубоко, очень глубоко. Вероятно, неделя исследований и Ive распространила мои выводы на несколько статей. Окончательный прорыв в этой статье: http://eon.codes/blog/2015/12/24/The-odd-case-of-luck/

Обновление 2

Будьте осторожны, хотя концепция трудно понять, но она работает, и она отлично работает. Вот конечный результат и код для его поддержки, ссылки на repository github и т. Д.: http://eon.codes/blog/2015/12/30/Graphic-framework-for-OSX/

  • Почему обесцвечиваются зонтичные frameworks?
  • Где разместить «Core Data Stack» в приложении Cocoa / Cocoa Touch
  • Исходный вариант суффикса месяца в день для NSDateFormatter setDateFormat
  • NSString tokenize в Objective-C
  • Лучший способ удалить из NSMutableArray во время итерации?
  • Что такое NSCFDictionary?
  • Как использовать performSelector: withObject: afterDelay: с примитивными типами в cocoa?
  • Настройка действия для кнопки «Назад» в навигационном controllerе
  • «Коллекция была мутирована при перечислении» в executeFetchRequest
  • Каков наилучший фильтр Core Image для получения черно-белых эффектов?
  • Как сравнить две даты в Objective-C
  • Interesting Posts

    Могу ли я подключить собственный маршрутизатор к использованию ISP'router?

    Ядро ASP.NET: исключение или включение файлов в публикацию

    Подозрительный трафик имен NetBios

    Как захватить событие отправки, используя jQuery в приложении ASP.NET?

    Как восстановить таблицу разделов при восстановлении всего диска с помощью Clonezilla?

    Firebase и индексирование / поиск

    Можете ли вы сделать MS Word черным фоном с белым текстом, но напечатать инверсный?

    Как установить динамическое значение в моем атрибуте

    `pg_tblspc` отсутствует после установки последней версии OS X (Yosemite или El Capitan)

    Получение специального источника ABS от ABAddressBook в iOS 4+

    Создание файловой системы FAT и сохранение ее в файл в GNU / linux?

    конвертировать шестнадцатеричный код в имя цвета

    Функция закладок с помощью функции «Просмотр параметров»

    Плакат с 8 этапами перевода на языке C

    Попытка добавить adb к переменной PATH OSX

    Давайте будем гением компьютера.