NSScrollView не рисует вид документа?

Я создал собственное представление, которое реализует initWithFrame и drawRect. В IB я создал окно и поместил пользовательский вид в центр окна. Затем я использовал "Редактор"> "Встроить"> "Представление прокрутки", чтобы поместить настраиваемое представление в представление прокрутки. А потом ничего? Сообщение initWithFrame отправляется в пользовательское представление, но сообщение drawRect никогда не отправляется.

Подобное поведение может быть произведено без моего специального пользовательского представления. Если метка обтекания встроена в скролл-вид таким же образом, она также не будет нарисована.

Как получить скроллвью для рисования его содержимого?

Кроме того, на некотором родственном замечании, как правильно программно изменить размер представления, встроенного в представление прокрутки?

Спасибо!

2 ответа

NSScrollView не похож на другие представления. Он делает вещи достаточно по-разному, что поначалу сводит всех с ума, особенно после того, как вы привыкли думать об Auto Layout. Это также один из тех видов (наряду с NSTableView, NSOutlineView и NSCollectionView и т. Д.), Где нужно настроить множество элементов, прежде чем вы сможете увидеть, как все работает. Auto Layout тоже немного добавляет к этому.

NSScrollView содержит как минимум 3 подпредставления по умолчанию:

  • Один объект NSClipView. (Apple называет это представлением содержимого. Это то, что видно.)
  • Два объекта NSScroller.

Объект NSClipView или Content View содержит некоторый вид NSView.

(Apple называет это видом документа)

Если вы добавите простой NSScrollView в свою Xib из библиотеки объектов, он будет иметь размер в Интерфейсном Разработчике, но во время выполнения он будет иметь нулевой размер. Это будет пинать твою задницу каждый раз. Вы можете увидеть это, добавив запись в журнал.

NSLog(@" size of document view:%@", NSStringFromRect(_myScrollView.documentView.frame);

Даже если вы добавите подпредставление и позвоните setNeedsDisplay:YES целый день ты не увидишь ни черта.

Есть вещи, которые вы можете сделать, хотя. Во-первых, вы можете установить размер document View с помощью setFrameSize:NSMakeSize(somePointsWide, somePointsHigh)

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

Вы также можете просто сказать, что все подпредставления должны иметь как минимум N точек из document View или более на каждом ребре с Auto Layout. VFL (язык визуального формата) будет выглядеть так: @"H:|-nPoints-[aSubviewOfDocumentView]-nPoints-|" и это @"V:|-nPoints-[aSubviewOfDocumentView]-nPoints-|"(убедитесь, что ваши подпредставления имеют собственный размер или какое-то собственное подпредставление, которое дает им минимальный размер... и реализует - (BOOL)translatesAutoresizingMaskIntoConstraints { return NO; } и отключите автоматическое изменение размеров подпредставлений для вашего Document View с помощью флажка в IB или по телефону setAutoResizesSubviews:NO или ты будешь ненавидеть жизнь.)

Теперь это приводит к странной вещи. С Auto Layout, как правило, лучше перестать думать о фреймах и кадрах как можно больше, но с NSScrollView documentView вы можете рассмотреть возможность не использовать Auto Layout для позиционирования подпредставлений. В некоторых случаях это может быть проще не делать, а просто позволить document View расти в соответствии с требованиями. Если вы используете вышеупомянутый подход "nPoints", и ваши подпредставления перетаскиваются, вы хотите просто захватить NSPoint для источника кадра подпредставления (используйте его, чтобы определить вашу дельту) и затем точку mouseDown, и когда перетаскивание закончено, захватите мышь укажите и вычислите дельту для вашей новой исходной точки кадра. Затем вызовите setFrameOrigin: с новой точкой.

Вы используете autolayout или старомодное изменение размера представления? Если вызывается ваш метод init, но не метод draw, он звучит так, будто весь ваш scrollView или ваш пользовательский вид имеют нулевой размер.

Если у вас есть пользовательское представление и вы используете autolayout, реализовали ли вы метод -intrinsicContentSize в своем подклассе пользовательского представления?

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

Есть две вещи, на которые нужно обратить внимание, и обе можно исправить в drawRect() вашего customView.

  1. Когда окно снова сжимается, увеличенный вид документа не сжимается вместе с ним, и полосы прокрутки будут иметь неправильный размер.
  2. Иногда при энергичном изменении размера область настраиваемого представления становится немного больше, чем фактический documentVisibleRect. Это ошибка. Как только это произойдет, независимо от того, насколько велико вы перетаскиваете вид прокрутки, полосы прокрутки никогда не исчезнут.

Чтобы бороться с этим, мое пользовательское представление (которое прокручивается только по вертикали) проверяет эти случаи в drawRect() и корректирует размеры в зависимости от того, увеличились мы или уменьшились.

 if scrollView.documentVisibleRect.size.height >= actualDocumentHeight {
        //
        // Sometimes the scroller machinery can enlarge the document rect a little
        // extra when resizing the window quickly.  We should check for that.
        //
        if self.bounds.size.height > scrollView.contentSize.height {
            self.frame.size.height = scrollView.contentSize.height
            self.bounds.size.height = scrollView.contentSize.height
        }
    } else {
        //
        // If it's smaller, set our size to the actual size and the scroll
        // bars will pop on.
        //
        self.frame.size.height = actualDocumentHeight
        self.bounds.size.height = actualDocumentHeight
    }
Другие вопросы по тегам