Наложение NSView поверх NSScrollView

У меня есть NSScrollView, который заполняет все окно и отображает огромное изображение. Теперь я хотел бы наложить пользовательский NSView на части прокрутки (например, высоту верхних 20 пикселей и ширину окна) для отображения дополнительной информации. Когда пользователь прокручивает представление прокрутки, настраиваемый NSView вверху должен оставаться на своем месте.

Я пробовал следующее:

  1. Создайте экземпляр NSView размером с мое окно
  2. Добавить NSScrollView как подвид ранее созданного NSView
  3. Добавить мое пользовательское представление в качестве подпредставления в NSView на шаге 1

Это работает вначале, вид прокрутки отображается правильно, и мой собственный NSView тоже. Однако, как только я начинаю перемещать представление прокрутки (прокрутку), настраиваемый NSView прокручивается вместе с содержимым NSScrollView и в конечном итоге исчезает, когда он перемещается за пределы границ, и часть представления прокрутки, где она была расположена, перерисовывается. . Как я могу эффективно расположить свой собственный NSView поверх NSScrollView и убедиться, что он остается на месте?

Спасибо!


person Robin    schedule 18.01.2011    source источник
comment
Я знаю, что об этом спрашивали еще в 2011 году, но это просто намек, если вы ответите на этот вопрос сегодня. Вы, вероятно, можете решить эту проблему, просто создав все виды с поддержкой слоев. Просто установите wantLayer для NSView, созданного на шаге 1., который сделает все дочерние элементы рекурсивно поддерживаемыми слоями.   -  person Radu Simionescu    schedule 22.01.2016


Ответы (2)


Я знаю, что у вас уже есть рабочее решение для этого, но я сам недавно искал то же самое и наткнулся на LKOverlayWindow Луи Клаассена, который, кажется, обеспечивает простое решение для такого типа наложения.

Как описано в вики-странице CocoaDev, вам просто нужно создать новый NSWindow в Interface Builder, пусть он будет экземпляром LKOverlayWindow, и либо прикрепите NSScrollView через выход, либо укажите его в коде. После присоединения к представлению прокрутки содержимое LKOverlayWindow будет перекрывать представление прокрутки и отслеживать его по мере его перемещения и изменения размера (последнее, похоже, работает только с NSScrollView как выходом окна). Образец проекта предоставлен автором здесь.

Я собирался создать подкласс NSScrollView, но в моем случае это оказалось намного проще.

person Brad Larson    schedule 15.02.2011
comment
Очень хорошо, воспользуюсь этим в следующий раз. Спасибо, что поделились этим! - person Robin; 17.02.2011

У вас есть два варианта:

Сначала отключите «Копировать при прокрутке». Вы можете сделать это непосредственно в IB или установив параметр copiesOnScroll в contentView члене NSScrollView. Эта опция, которая включена по умолчанию, делает так, чтобы представление прокрутки «копировало существующее визуализированное изображение при прокрутке (рисование только открытых частей представления документа)». Если он выключен, «заставляет каждый раз перерисовывать свое содержимое». Так что, если производительность не является большой проблемой, можно просто отключить ее.

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

Второй вариант - оставить включенным «Копировать при прокрутке», а затем создать окно без полей, содержащее ваш наложенный вид. На самом деле это не так хакерски, как может показаться, поскольку вы можете добавить экземпляр NSWindow в качестве дочернего элемента вашего текущего окна, чтобы он автоматически перемещался вместе с главным окном при его перемещении.

Образец RoundTransparentWindow станет отличным примером следуйте инструкциям по созданию окна, в котором будет находиться ваш оверлей. Затем просто используйте addChildWindow NSWindow, чтобы прикрепить его к главному окну.

Обратите внимание, что при таком подходе вам нужно будет обрабатывать время презентации и скрытие окна наложения. Также кажется, что когда вы максимизируете родительское окно, положение дочернего окна не регулируется автоматически. Так что вам тоже придется с этим справиться. Но это отличное решение, если вы не хотите жертвовать тем, что иногда приводит к значительному повышению производительности при использовании «Копировать при прокрутке».

person Ben Dolman    schedule 21.01.2011
comment
Спасибо за решение, а пока я решил проблему. Сначала у меня тоже было решение для вас, однако, как вы говорите, версия подокна имеет ряд недостатков. Более простой способ сделать это - создать подкласс NSScrollView и добавить туда подпредставление. Теперь я мог просто отрегулировать положение моего подпредставления в моей перезаписанной реализации RefleScrolledClipView и вуаля, отлично работало :) - person Robin; 22.01.2011
comment
Ах, очень красивое решение. Это определенно лучшее решение для вашего случая использования. В моем случае мне нужно было представление, которое только частично перекрывало прокрутку, поэтому я не мог нарисовать его внутри. Вместо этого мне пришлось использовать подход подокна. - person Ben Dolman; 22.01.2011