Скажімо, я додав більше переглядів у UIStackView, які можна відобразити, як я можу зробити UIStackView
прокрутку?
Скажімо, я додав більше переглядів у UIStackView, які можна відобразити, як я можу зробити UIStackView
прокрутку?
Відповіді:
У випадку, якщо хтось шукає рішення без коду , я створив приклад, щоб це зробити повністю на дошці розкадрування, використовуючи функцію автоматичного макета.
Ви можете отримати його з github .
В основному, щоб відтворити приклад (для вертикальної прокрутки):
UIScrollView
і встановіть його обмеження.UIStackView
доUIScrollView
Leading
, Trailing
, Top
і Bottom
повинні бути рівні ті зUIScrollView
Width
обмеження між UIStackView
та UIScrollView
.UIStackView
UIViews
доUIStackView
Обмін Width
на Height
кроці 4, і набір Axis
= Horizontal
на етапі 5, щоб отримати горизонтальну UIStackView.
Посібник з автоматичного розміщення Apple містить цілий розділ щодо роботи з видами прокрутки . Деякі відповідні фрагменти:
- Закріпіть верхній, нижній, ведучий та кінцеві краї перегляду вмісту до відповідних країв прокрутки. Перегляд вмісту тепер визначає область вмісту перегляду прокрутки.
- (Необов’язково) Щоб відключити горизонтальну прокрутку, встановіть ширину подання вмісту рівну ширині подання прокрутки. Перегляд вмісту тепер горизонтально заповнює подання прокрутки.
- (Необов’язково) Щоб відключити вертикальну прокрутку, встановіть висоту перегляду вмісту рівну висоті подання прокрутки. Перегляд вмісту тепер горизонтально заповнює подання прокрутки.
Крім того:
Ваш макет повинен повністю визначати розмір перегляду вмісту (за винятком випадків, визначених у кроках 5 та 6). … Коли подання вмісту вище, ніж перегляд прокрутки, подання прокрутки дозволяє вертикальне прокручування. Якщо подання вмісту ширше, ніж перегляд прокрутки, подання прокрутки дозволяє горизонтальне прокручування.
Підводячи підсумок, вигляд вмісту подання прокрутки (в даному випадку подання стека) повинен бути прикріплений до його країв, а ширина та / або висота в іншому випадку обмежені. Це означає, що вміст подання стека має бути обмеженим (прямо чи опосередковано) у напрямку (іх), в якому бажано прокручувати, що може означати додавання обмеження висоти до кожного виду всередині вертикально прокручуваного виду стека. Нижче наведено приклад того, як дозволити вертикальне прокручування подання прокрутки, що містить подання стека:
// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
Need constraints for: Y position or height.
Ця помилка знищується лише в тому випадку, якщо для перегляду стеки встановлено як обмеження ширини, так і висоти, що вимикає вертикальне прокручування. Чи все ще працює цей код для вас?
Обмеження у відповіді, що голосує тут, спрацювали для мене, і я вставив зображення обмежень нижче, як це було створено в моїй розгортці.
Я торкнувся двох питань, хоча інші повинні знати:
Після додавання обмежень, аналогічних тим, що у прийнятій відповіді, я отримаю червону помилку авторозмітки Need constraints for: X position or width
. Це було вирішено, додавши UILabel як підпогляд подання стека.
Я додаю підпогляди програмно, тож у мене спочатку не було підглядів на дошці розкадрувань. Щоб позбутися від помилок автоматичного розкладу, додайте підрозділ до дошці розкадрування, після чого видаліть його під час завантаження, перш ніж додавати реальні підгляди та обмеження.
Я спочатку намагався додати UIButtons
до UIStackView. Кнопки та види завантажуватимуться, але подання прокрутки не прокручується . Це було вирішено шляхом додавання UILabels
до перегляду стека замість кнопок. Використовуючи ті самі обмеження, ця ієрархія перегляду з UILabels прокручується, але кнопки UIB не мають.
Мене бентежить це питання, оскільки , здається, UIButtons має IntrinsicContentSize (використовується в режимі перегляду стека). Якщо хтось знає, чому кнопки не працюють, я хотів би знати, чому.
Ось моя ієрархія поглядів та обмежень для довідки:
Як каже Ейк, UIStackView
і UIScrollView
грати разом добре, дивіться тут .
Ключовим моментом є те, що UIStackView
обробляє змінну висоту / ширину для різного вмісту, а UIScrollView
потім добре виконує свою роботу прокрутки / підстрибування цього вмісту:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
Я хотів зробити те саме і натрапив на цю чудову посаду. Якщо ви хочете зробити це програмно за допомогою API прив'язки, це шлях.
Для підведення підсумків, вставте своє UIStackView
у своє UIScrollView
та встановіть обмеження якоря для, UIStackView
щоб відповідати цим UIScrollView
:
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
Порожня сцена на весь екран
Додати перегляд прокрутки. Перетягніть контроль із перегляду прокрутки до базового виду , додайте ліво-право-вгорі-вниз, усі нулі.
Додайте подання стека у вікно прокрутки. Перетягніть контроль із перегляду стека до подання прокрутки , додайте ліво-право-вгорі-вниз, усі нулі.
Поставте дві або три мітки всередині подання стека.
Для наочності зробіть колір тла етикетки червоним. Встановіть висоту етикетки на 100.
Тепер встановіть ширину кожного UILabel:
Дивно, але перетягніть курсор від UILabel
перегляду прокрутки, а не до виду стека, і виберіть однакові ширини .
Повторювати:
Це так просто. У цьому секрет.
Підказка - помилка Apple:
Він не працюватиме лише з одним предметом! Додайте кілька міток, щоб демонстрація працювала.
Ви закінчили.
Порада. Кожному новому елементу потрібно додати висоту . Кожен елемент у будь-якому перегляді стека прокрутки повинен мати або внутрішній розмір (наприклад, мітка), або додавати явне обмеження по висоті.
Альтернативний підхід:
У вищесказаному: напрочуд, встановіть ширину міток UIL на ширину подання прокрутки (не вигляд стека).
По черзі ...
Отже, у вас є два варіанти:
або
Щоб було зрозуміло, виконайте ОДИН із цих методів, НЕ робіть обох.
Для горизонтальної прокрутки. Спочатку створіть a UIStackView
і a UIScrollView
та додайте їх у свій погляд таким чином:
let scrollView = UIScrollView()
let stackView = UIStackView()
scrollView.addSubview(stackView)
view.addSubview(scrollView)
Згадавши , щоб встановити , translatesAutoresizingMaskIntoConstraints
щоб false
на UIStackView
і UIScrollView
:
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
Щоб все працювало, кінцеві, провідні, верхні та нижні анкери корпусу UIStackView
повинні дорівнювати UIScrollView
якорям:
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
Але ширина якоря UIStackView
сусла повинна дорівнює або більше ширини UIScrollView
якоря:
stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
Тепер прикріпіть UIScrollView
, наприклад:
scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true
Далі я б запропонував спробувати наступні налаштування для UIStackView
вирівнювання та розподілу:
topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center
topicStackView.spacing = 10
Нарешті, вам потрібно буде скористатися addArrangedSubview:
методом для додавання підпрезентацій до вашого UIStackView.
Ще однією додатковою функцією, яка може виявитися корисною, є те, що UIStackView
у UIScrollView
вас є доступ до текстових вкладок, щоб зробити вигляд гарнішим.
let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset
// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true
Просто додайте це до viewdidload
:
let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets
Ви можете спробувати ScrollableStackView : https://github.com/gurhub/ScrollableStackView
Це сумісна бібліотека Objective-C і Swift. Він доступний через CocoaPods .
Приклад коду (Swift)
import ScrollableStackView
var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)
// add your views with
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...
Приклад коду (Objective-C)
@import ScrollableStackView
ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];
UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];
// add your views with
[scrollable.stackView addArrangedSubview:rectangle];
// ...
Якщо у вас є обмеження центром перегляду стека вертикально всередині вікна прокрутки, просто вийміть його.
Приклад вертикального перегляду стека / прокрутки (використовуючи EasyPeasy
для автоматичного вимикання):
let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
Edges(),
Width().like(self.view)
]
let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
Edges(),
Width().like(self.view)
]
Просто переконайтеся, що висота кожного з ваших підписів визначена!
Перш за все, спроектуйте свій погляд, бажано на щось на зразок ескізу або отримайте уявлення про те, що ви хочете як вміст, який можна прокручувати.
Після цього зробіть контролер перегляду вільною формою (виберіть інспектор атрибутів) та встановіть висоту та ширину відповідно до внутрішнього розміру вмісту вашого перегляду (вибирайте з інспектора розміру).
Після цього в контролер подання виберіть прокрутку, і це логіка, яка, як я виявила, працює в iOS майже весь час (можливо, це потребує перегляду документації цього класу перегляду, яку можна отримати за допомогою команди + натисніть на клас чи через Google)
Якщо ви працюєте з двома або більше переглядами, то спочатку почніть з представлення, яке було введено раніше або є більш примітивним, а потім перейдіть до представлення, яке було введено пізніше або є більш сучасним. Отже, оскільки спочатку було запроваджено перегляд прокрутки, спочатку почніть з подання прокрутки, а потім перейдіть до подання стека. Тут встановіть обмеження перегляду прокрутки до нуля в усіх напрямках відносно його суперзору. Помістіть усі перегляди всередині цього вікна прокрутки, а потім поставте їх у подання стека.
Працюючи з поданням стека
Спочатку почніть з основи (підхід знизу), тобто, якщо у вас є мітки, текстові поля та зображення, то спочатку викладіть ці подання (всередині вікна прокрутки), а потім поставте їх у подання стека.
Після цього налаштувати властивість подання стека. Якщо бажаного перегляду все ще не досягнуто, використовуйте інший вигляд стека.
Зробивши перегляд, поставте обмеження між поданням материнської стеки та поданням прокрутки, тоді як діти обмежують перегляд стека з поданням стеки матері. Сподіваємось, до цього моменту це справно спрацює, інакше ви можете отримати попередження від Xcode, що дає пропозиції, прочитайте, що він пише, і реалізуйте їх. Сподіваємось, тепер у вас має бути робочий вид відповідно до ваших очікувань :).
Для вкладеного або одинарного виду прокрутки стеку потрібно встановити фіксовану ширину з видом кореня. Вид основного стека, який знаходиться всередині подання прокрутки, повинен задавати однакову ширину. [Мій перегляд прокрутки нижче Погляду ігнорує його]
Встановіть рівне обмеження по ширині між UIStackView і UIScrollView.
Якщо хтось шукає горизонтальне прокручування
func createHorizontalStackViewsWithScroll() {
self.view.addSubview(stackScrollView)
stackScrollView.translatesAutoresizingMaskIntoConstraints = false
stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
stackScrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true
stackView.distribution = .equalSpacing
stackView.spacing = 5
stackView.axis = .horizontal
stackView.alignment = .fill
for i in 0 ..< images.count {
let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
// set button image
photoView.translatesAutoresizingMaskIntoConstraints = false
photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true
stackView.addArrangedSubview(photoView)
}
stackView.setNeedsLayout()
}
Розмістіть вигляд прокрутки на своїй сцені та розміріть її так, щоб вона заповнювала сцену. Потім помістіть подання стека всередину вікна прокрутки та помістіть кнопку додавання елемента всередині подання стека. Як тільки все на місці, встановіть такі обмеження:
Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width
код: Stack View.Width = Scroll View.Width
є ключем.
Додаємо нову перспективу для macOS Catalyst. Оскільки програми macOS підтримують зміну розміру вікон, можливо, ваш стан UIStackView
перейде з некерованого статусу до прокручуваного або навпаки. Тут є дві тонкі речі:
UIStackView
розроблений так, щоб відповідати всій площі, яку він може.UIScrollView
буде здійснено спробу змінити розмір меж для врахування нещодавно здобутої / втраченої області під панеллю навігації (або панелі інструментів у разі додатків macOS).Це, на жаль, створить нескінченну петлю. Я не дуже знайомий з UIScrollView
його та його вмінням adjustedContentInset
, але з мого журналу в його layoutSubviews
методі я бачу таку поведінку:
UIScrollView
намагається зменшити межі (оскільки немає необхідності в області під панеллю інструментів).UIStackView
випливає.UIScrollView
незадоволений, і вирішимо відновити в більші рамки. Мені це дуже дивно, оскільки те, що я бачу з журналу, - це те UIScrollView.bounds.height == UIStackView.bounds.height
.UIStackView
випливає.Мені здається, що два кроки вирішили б проблему:
UIStackView.top
до UIScrollView.topMargin
.contentInsetAdjustmentBehavior
для .never
.Тут я переймаюся вертикально прокручуваним видом з вертикально зростаючим UIStackView
. Для горизонтальної пари відповідно змініть код.
Сподіваюся, це допоможе комусь у майбутньому. В Інтернеті ніхто не міг згадати про це, і це коштувало мені досить довго, щоб зрозуміти, що сталося.