Как я могу заставить NSScrollView соблюдать обтравочный контур

Я пытаюсь сделать NSScrollView с обрезанными углами, как в приложении Twitter:

введите здесь описание изображения

У меня есть подкласс NSScrollView, в который я добавил следующий код:

- (void)drawRect:(NSRect)dirtyRect {
    NSBezierPath *pcath = [NSBezierPath bezierPathWithRoundedRect:[self bounds] xRadius:kDefaultCornerRadius yRadius:kDefaultCornerRadius];
    [path setClip];

    [super drawRect:dirtyRect];
}

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




ОБНОВЛЕНИЕ И ПОЯСНЕНИЕ
Я знаю, как сделать кастомный NSScroller, я знаю, как сделать его прозрачным наложением. Все, о чем я спрашиваю, это как сделать углы NSSCrollView клипа, включая все, что в нем содержится. NSScrollView находится внутри NSView, фон которого может меняться, а это означает, что наложение вида для имитации закругленных углов не вариант.


person coneybeare    schedule 11.03.2011    source источник
comment
Вполне возможно, что суперреализация drawRect объявляет наборы новостей. Попробуйте рисовать части одну за другой, а не вызывать super, и посмотрите, изменится ли что-нибудь.   -  person sosborn    schedule 11.03.2011
comment
Вы имеете в виду рисовать contentView и documentView самостоятельно, вместо того, чтобы просить super сделать это? Кажется, для этого мне придется заново реализовать всю логику прокрутки NSScrollView. Я надеюсь, что есть способ не изобретать велосипед.   -  person coneybeare    schedule 11.03.2011
comment
Проверьте документы для NSScroller. Обычно NSScrollView будет иметь два NSScroller, x и y. Класс NSScroller предоставляет методы для рисования. Если вы собираетесь выглядеть так же, как клиент Twitter, вам все равно придется создать подкласс NSScroller.   -  person sosborn    schedule 11.03.2011
comment
Ваши комментарии не относятся к вопросу. Я уже реализовал собственный скроллер и знаю, как рисовать эти части. Чего я не знаю, как сделать, так это убедиться, что documentView получает закругленные углы, соблюдая clippedPath.   -  person coneybeare    schedule 11.03.2011
comment
Извините, но из вашего вопроса не было ясно, как далеко вы продвинулись. Я немного поиграл с этим, и кажется очевидным, что вам придется создать подкласс либо NSClipView, либо базового представления документов, чтобы это работало.   -  person sosborn    schedule 11.03.2011
comment
Я пытался добавить клип в клип, вид документа… везде. Я должен что-то упустить, или это невозможно. Запускаем награду...   -  person coneybeare    schedule 14.03.2011
comment
Я не уверен, поможет ли это, но недавно я просмотрел красивую демонстрацию с примером закругленных углов, см. github.com/bobmccune/Core-Animation-Demo   -  person Piotr Byzia    schedule 15.03.2011


Ответы (3)


Вы можете применить маску к слою представления:

[myScrollView setWantsLayer: YES];
[myScrollView layer].mask = ...;

Маска другая CALayer. Итак, в этом случае вы должны создать CALayer, установить непрозрачный цвет фона, установить его границы в соответствии с прокруткой и присвоить ему cornerRadius, скажем, 8.0.

В результате вид прокрутки и все его содержимое будут казаться замаскированными до прямоугольника с радиусом угла 8 пикселей.

person Jonathan Grynspan    schedule 14.03.2011
comment
Кажется, это работает, но мне нужно больше гибкости в углах. Мне нужно закруглить только два угла, приведенный выше код округления — это просто пример. Не только это, но когда я делаю это в прокрутке, все внутреннее содержимое перестает рисовать, и я не уверен, как воссоздать все это без использования drawRect. - person coneybeare; 14.03.2011
comment
Вы можете установить свойство содержимого слоя маски практически на что угодно. Взгляните на Поваренную книгу Core Animation — она должна помочь вам в рисовании Core Animation. (К сожалению, под рукой нет URL.) - person Jonathan Grynspan; 15.03.2011
comment
Это работает, но приносит с собой массу дополнительных проблем (мерцание nsview в прокрутках, странные артефакты, отображаемые в обрезанных углах, и проблемы с изменением размера слоя в реальном времени). Я надеюсь, что есть другой ответ, поскольку усилия, необходимые для этого, кажутся довольно большими. Вот краткий скринкаст проблем, которые я вижу в этой реализации: screencast.com/t/wKt5vCjoWPu - person coneybeare; 16.03.2011
comment
Я тоже использовал этот подход, и он вроде работает. Однако, похоже, есть артефакты, и это зависит от того, что еще находится в иерархии представлений. Кроме того, если вы используете несколько масок, скажем, в суперпредставлении, которое имеет общий край границ, между масками возникает некоторый эффект соединения. Я бы предложил отправить отчет об ошибке в Apple и запросить возможность округления NSScrollView с помощью стандартного подхода CALayer, предоставив ему резервный слой и установив его свойство cornerRadius. Кажется, для округленного NSScrollView полезного применения довольно много. - person Dalmazio; 03.04.2012

После долгих возни я только что обнаружил, что NSScrollView можно сделать со скругленными углами, просто назначив ему фоновый слой и установив радиус угла этого слоя при условии, что вы также сделаете то же самое с его внутренним NSClipView. Требуются оба, что теперь имеет смысл, так как именно представление клипа фактически обеспечивает просматриваемое окно в представлении документа NSScrollView.

NSScrollView * scrollView = ...;

// Give the NSScrollView a backing layer and set it's corner radius.
[scrollView setWantsLayer:YES];
[scrollView.layer setCornerRadius:10.0f];

// Give the NSScrollView's internal clip view a backing layer and set it's corner radius.
[scrollView.contentView setWantsLayer:YES];
[scrollView.contentView.layer setCornerRadius:10.0f];
person Dalmazio    schedule 03.04.2012
comment
Однако обратите внимание, что это не работает для NSScrollView, которые содержат NSTextView. В этом случае нам нужно вернуться к подходу маскирующего слоя. - person Dalmazio; 03.04.2012

Вы пытались переопределить

- (BOOL)isOpaque {
  return NO;
}

И установите вид прокрутки -setDrawsBackground: на NO и просто оставьте вид без обрезки и просто нарисуйте углы с помощью [NSColor clearColor], так как это также очистит основной цвет и имитирует эффект округления.

person Erik Aigner    schedule 18.03.2011
comment
Просто прочитайте свой обновленный фон требований, который может измениться, поэтому я думаю, что мой ответ устарел. - person Erik Aigner; 18.03.2011