NSScrollView: переопределить настройки отображения системы?

У меня есть NSScrollView, для которого установлено значение:

MyNSScrollView.hasHorizontalScroller = YES;
MyNSScrollView.hasVerticalScroller = YES;
MyNSScrollView.autohidesScrollers = YES;
MyNSScrollView.scrollerStyle = NSScrollerStyleOverlay;

Я заметил, что когда трекпад не подключается к OS X и по умолчанию, NSScrollView будет игнорировать мои настройки в коде и всегда показывать скроллеры:

Настройки

Я могу только либо изменить свои системные настройки на «При прокрутке», либо установить hasHorizontalScroller и т. д. на NO, чтобы скрыть это, а позднее отключит прокрутку мышью, что не является тем результатом, который мне нужен.

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

Разница между ними заключается в том, что «устаревший» стиль будет занимать места в прокрутке. Это было бы проблемой, если бы вы использовали значение visiableRect для расчета, или ваше содержимое должно оставаться определенным соотношением сторон через ограничения.

Есть ли способ принудительно скрыть их, не отключая?


person Cai    schedule 11.06.2016    source источник
comment
Я предлагаю вам прочитать то, что вы написали для себя. он проигнорирует мои настройки в программе и заставит их всегда отображаться =› Что это такое? Ваше приложение? Кто они такие? полосы прокрутки?   -  person El Tomato    schedule 11.06.2016
comment
есть 2 полосы прокрутки, горизонтальная и вертикальная, поэтому я сказал их, поскольку я не упомянул другие вещи, кроме этих 2 полос. Извините, если это звучит недостаточно ясно.   -  person Cai    schedule 11.06.2016
comment
Не обращайте внимания на Эль Помидора, в последнее время он немного сварливый.   -  person Willeke    schedule 11.06.2016
comment
Вместо того, чтобы игнорировать предпочтения пользователей, почему бы вам не найти способ поддержать скроллеры?   -  person Willeke    schedule 11.06.2016
comment
Поскольку размер скроллера может быть разным в разных системах, может возникнуть слишком много непредсказуемых ситуаций. Я думаю о том, чтобы получить рамку скроллера и изменить ее размер до нулевой ширины/высоты.   -  person Cai    schedule 12.06.2016
comment
Если вы не хотите видеть скроллеры, вы можете установить hasHorizontalScroller и hasVerticalScroller на NO.   -  person Willeke    schedule 12.06.2016
comment
Да, но это оставит прокрутку без возможности прокрутки. Мне нужно, чтобы их можно было прокручивать, но без полос, показывающих или занимающих пространство visiableRect.   -  person Cai    schedule 12.06.2016
comment
Я могу прокручивать прокрутку без скроллеров, используя колесо прокрутки на моей мыши.   -  person Willeke    schedule 12.06.2016
comment
Когда я устанавливаю для них значение НЕТ, колесо прокрутки моей Magic Mouse больше не может прокручивать вид. Было бы намного проще, если бы это было правдой. Я проверю это снова после WWDC.   -  person Cai    schedule 12.06.2016


Ответы (2)


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

В любом случае, я думаю, проблема в том, что вы просто неправильно понимаете, что делает autohidesScrollers. Установка этого значения в true просто означает, что скроллеры скрыты, когда представление документа не выходит за границы представления клипа (также известного как представление содержимого). То есть, если нет места для прокрутки, потому что все уже отображается.

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

person Ken Thomases    schedule 11.06.2016
comment
По умолчанию (автоматически на основе мыши или трекпада) всегда будет отображаться скроллер, если у пользователя нет трекпада, даже если размер содержимого не превышает размер кадра. Но если у вас есть трекпад, это будет стиль наложения, который независимо от того, показывает скроллер или нет, он находится над содержимым. Разница между ними заключается в том, что устаревший стиль будет занимать место в прокрутке. Это было бы проблемой, если бы вы использовали значение visiableRect для расчета, или ваше содержимое должно оставаться определенным соотношением сторон через ограничения. - person Cai; 11.06.2016
comment
и нет, я правильно понял, для чего предназначен autohidesScrollers. Просто в настройках OS X по умолчанию пользователи без трекпада всегда будут иметь скроллеры, независимо от того, прокручивается он или нет. Вот почему я задал этот вопрос, так как я ожидаю, что он должен скрыть скроллер, если он не должен быть там. Только отключив скроллеры в коде, можно скрыть эти полосы только для мыши, когда они не нужны. - person Cai; 11.06.2016

Вы можете заставить все приложение использовать оверлейные скроллеры, используя низкоуровневую магию Objective-C (метод swizzling):

#import <Cocoa/Cocoa.h>
#import <objc/runtime.h>

static IMP old_preferredScrollerStyle = NULL;
static NSScrollerStyle new_preferredScrollerStyle(id self, SEL _cmd) {
    // Always prefer overlay style.
    return NSScrollerStyleOverlay;
}

static IMP old_setScrollerStyle = NULL;
static void new_setScrollerStyle(id self, SEL _cmd, NSScrollerStyle style) {
    // Call old implementation but always with overlay style.
    void(*oldImp)(id self, SEL _cmd, NSScrollerStyle style)
        = (void(*)(id, SEL, NSScrollerStyle))old_setScrollerStyle;
    oldImp(self, _cmd, NSScrollerStyleOverlay);
}

/// Force the overlay style scrollers for this app.
@interface NSScrollView (ForceOverlay)
@end

@implementation NSScrollView (ForceOverlay)

+ (void)load
{
    [super load];

    // Replace the preferred style. This sets the style for app startup and new NSScroller
    // and NSScrollView instances.
    Method originalMethod = class_getClassMethod(
        [NSScroller class],
        @selector(preferredScrollerStyle)
    );
    old_preferredScrollerStyle = method_setImplementation(
        originalMethod,
        (IMP)new_preferredScrollerStyle
    );

    // Replace the NSScrollView setter. This prevents the change to the legacy style, for example
    // when the user switches the system setting.
    originalMethod = class_getInstanceMethod(
        [NSScrollView class],
        @selector(setScrollerStyle:)
    );
    old_setScrollerStyle = method_setImplementation(
        originalMethod,
        (IMP)new_setScrollerStyle
    );
}

@end
person DarkDust    schedule 05.04.2017
comment
Совсем не надо чихать. Просто создайте подкласс NSScrollView и переопределите scrollerStyle. - person Erik Aigner; 04.05.2018
comment
Конечно. Но вам нужно убедиться, что каждый вид прокрутки использует ваш подкласс. В зависимости от размера вашего проекта это может быть легкой задачей или серьезной проблемой (например, при использовании внешних компонентов). - person DarkDust; 04.05.2018