Katakanlah saya telah menambahkan lebih banyak tampilan di UIStackView yang dapat ditampilkan, bagaimana saya bisa membuat UIStackView
gulir?
Katakanlah saya telah menambahkan lebih banyak tampilan di UIStackView yang dapat ditampilkan, bagaimana saya bisa membuat UIStackView
gulir?
Jawaban:
Jika ada yang mencari solusi tanpa kode , saya membuat contoh untuk melakukan ini sepenuhnya di storyboard, menggunakan Tata Letak Otomatis.
Anda bisa mendapatkannya dari github .
Pada dasarnya, untuk membuat ulang contoh (untuk pengguliran vertikal):
UIScrollView
, dan atur batasannya.UIStackView
keUIScrollView
Leading
, Trailing
, Top
& Bottom
harus sama dengan yang dariUIScrollView
Width
batasan yang sama antara UIStackView
dan UIScrollView
.UIStackView
UIViews
keUIStackView
Pertukaran Width
untuk Height
di langkah 4, dan set Axis
= Horizontal
pada langkah 5, untuk mendapatkan UIStackView horizontal.
Panduan Tata Letak Otomatis Apple mencakup seluruh bagian tentang Bekerja dengan Tampilan Gulir . Beberapa cuplikan yang relevan:
- Sematkan tepi tampilan bagian atas, bawah, depan, dan belakang ke tepi yang sesuai tampilan gulir. Tampilan konten sekarang menentukan area konten tampilan gulir.
- (Opsional) Untuk menonaktifkan gulir horizontal, atur lebar tampilan konten sama dengan lebar tampilan gulir. Tampilan konten sekarang mengisi tampilan gulir secara horizontal.
- (Opsional) Untuk menonaktifkan pengguliran vertikal, atur ketinggian tampilan konten sama dengan tinggi tampilan gulir. Tampilan konten sekarang mengisi tampilan gulir secara horizontal.
Selanjutnya:
Tata letak Anda harus sepenuhnya menentukan ukuran tampilan konten (kecuali jika ditentukan dalam langkah 5 dan 6). ... Saat tampilan konten lebih tinggi daripada tampilan gulir, tampilan gulir memungkinkan pengguliran vertikal. Ketika tampilan konten lebih lebar dari tampilan gulir, tampilan gulir memungkinkan pengguliran horizontal.
Untuk meringkas, tampilan konten tampilan gulir (dalam hal ini, tampilan tumpukan) harus disematkan ke tepinya dan memiliki lebar dan / atau tinggi dibatasi. Itu berarti bahwa isi tampilan tumpukan harus dibatasi (langsung atau tidak langsung) ke arah yang diinginkan untuk menggulir, yang mungkin berarti menambahkan batasan ketinggian untuk setiap tampilan di dalam tampilan tumpukan yang bergulir secara vertikal, misalnya. Berikut ini adalah contoh cara untuk memungkinkan bergulir vertikal tampilan gulir yang berisi tampilan tumpukan:
// 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.
Kesalahan ini hanya hilang jika Anda menetapkan batasan lebar dan tinggi untuk tampilan tumpukan, yang menonaktifkan pengguliran vertikal. Apakah kode ini masih berfungsi untuk Anda?
Hambatan dalam jawaban pilihan-utama di sini berfungsi untuk saya, dan saya telah menempelkan gambar kendala di bawah ini, sebagaimana dibuat di storyboard saya.
Saya memang menemukan dua masalah yang harus diperhatikan oleh orang lain:
Setelah menambahkan kendala serupa dengan yang ada di jawaban yang diterima, saya akan mendapatkan kesalahan autolayout merah Need constraints for: X position or width
. Ini diselesaikan dengan menambahkan UILabel sebagai subview dari tampilan stack.
Saya menambahkan subview secara terprogram, jadi saya awalnya tidak memiliki subview di storyboard. Untuk menghilangkan kesalahan autolayout, tambahkan subview ke storyboard, lalu lepaskan saat memuat sebelum menambahkan subview dan kendala Anda yang sebenarnya.
Saya awalnya mencoba menambahkan UIButtons
ke UIStackView. Tombol dan tampilan akan dimuat, tetapi tampilan gulir tidak akan bergulir . Ini diselesaikan dengan menambahkan UILabels
ke Stack View, bukan tombol. Menggunakan kendala yang sama, hierarki tampilan ini dengan gulungan UILabel tetapi UIButtons tidak.
Saya bingung dengan masalah ini, sebagai UIButtons yang tampaknya memiliki IntrinsicContentSize (digunakan oleh Stack View). Jika ada yang tahu mengapa tombolnya tidak berfungsi, saya ingin tahu mengapa.
Inilah hierarki dan batasan pandangan saya, untuk referensi:
Seperti kata Eik, UIStackView
dan UIScrollView
bermain bersama dengan baik, lihat di sini .
Kuncinya adalah bahwa UIStackView
menangani tinggi / lebar variabel untuk konten yang berbeda dan UIScrollView
kemudian melakukan tugasnya dengan baik untuk menggulir / memantulkan konten tersebut:
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)
}
Saya mencari untuk melakukan hal yang sama dan menemukan posting yang bagus ini . Jika Anda ingin melakukan ini secara terprogram menggunakan anchor API, inilah caranya.
Untuk meringkas, sematkan UIStackView
di Anda UIScrollView
, dan atur batasan jangkar UIStackView
untuk mencocokkan dengan 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
Miliki pemandangan layar penuh yang kosong
Tambahkan tampilan gulir. Kontrol-tarik dari tampilan gulir ke tampilan dasar , tambahkan kiri-kanan-atas-bawah, semuanya nol.
Tambahkan tampilan tumpukan di tampilan gulir. Kontrol-tarik dari tampilan tumpukan ke tampilan gulir , tambahkan kiri-kanan-atas-bawah, semuanya nol.
Masukkan dua atau tiga label di dalam tampilan tumpukan.
Untuk kejelasan, buat warna latar belakang label menjadi merah. Atur tinggi label menjadi 100.
Sekarang atur lebar masing-masing UILabel:
Anehnya, kontrol-tarik dari UILabel
ke tampilan gulir, bukan ke tampilan tumpukan, dan pilih lebar yang sama .
Mengulang:
Sesederhana itu. Itulah rahasianya.
Kiat rahasia - Bug Apple:
Itu tidak akan bekerja dengan hanya satu item! Tambahkan beberapa label untuk membuat demo berfungsi.
Kamu sudah selesai.
Kiat: Anda harus menambahkan tinggi untuk setiap item baru . Setiap item dalam tampilan tumpukan bergulir harus memiliki ukuran intrinsik (seperti label) atau menambahkan batasan ketinggian eksplisit.
Pendekatan alternatif:
Di atas: secara mengejutkan, atur lebar label UIL ke lebar tampilan gulir (bukan tampilan tumpukan).
Bergantian...
Jadi, Anda memiliki dua opsi:
atau
Agar jelas, lakukan SALAH satu dari metode itu, JANGAN lakukan keduanya.
Untuk pengguliran horizontal. Pertama, buat a UIStackView
dan a UIScrollView
dan tambahkan ke tampilan Anda dengan cara berikut:
let scrollView = UIScrollView()
let stackView = UIStackView()
scrollView.addSubview(stackView)
view.addSubview(scrollView)
Ingat untuk mengatur translatesAutoresizingMaskIntoConstraints
agar false
pada UIStackView
dan UIScrollView
:
stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false
Untuk membuat semuanya bekerja, jangkar trailing, leading, top dan bottom UIStackView
harus sama dengan UIScrollView
jangkar:
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
Tetapi lebar jangkar UIStackView
harus sama dengan atau lebih besar dari lebar UIScrollView
jangkar:
stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true
Sekarang jangkar Anda UIScrollView
, misalnya:
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
Selanjutnya, saya akan menyarankan mencoba pengaturan berikut untuk UIStackView
perataan dan distribusi:
topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center
topicStackView.spacing = 10
Akhirnya Anda harus menggunakan addArrangedSubview:
metode ini untuk menambahkan subview ke UIStackView Anda.
Salah satu fitur tambahan yang mungkin berguna bagi Anda adalah karena UIStackView
diadakan di dalam UIScrollView
Anda sekarang memiliki akses ke insets teks untuk membuat hal-hal terlihat sedikit lebih cantik.
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
Cukup tambahkan ini ke viewdidload
:
let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets
Anda dapat mencoba ScrollableStackView : https://github.com/gurhub/ScrollableStackView
Ini adalah library yang kompatibel dengan Objective-C dan Swift. Ini tersedia melalui CocoaPods .
Kode Sampel (Cepat)
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)
// ...
Kode Sampel (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];
// ...
Jika Anda memiliki kendala untuk memusatkan Stack View secara vertikal di dalam tampilan gulir, hapus saja.
Contoh untuk stackview / scrollview vertikal (menggunakan EasyPeasy
for autolayout):
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)
]
Pastikan setiap ketinggian subview Anda ditentukan!
Pertama dan terpenting, desain tampilan Anda, terutama dalam Sketsa atau dapatkan ide tentang apa yang Anda inginkan sebagai konten yang dapat digulir.
Setelah ini, buat formulir pengontrol tampilan bebas (pilih dari inspektur atribut) dan atur tinggi dan lebar sesuai ukuran konten intrinsik tampilan Anda (untuk dipilih dari inspektur ukuran).
Setelah ini di controller tampilan meletakkan tampilan gulir dan ini adalah logika, yang saya temukan bekerja hampir sepanjang waktu di iOS (mungkin perlu melalui dokumentasi kelas tampilan yang dapat diperoleh melalui perintah + klik pada kelas itu atau melalui googling)
Jika Anda bekerja dengan dua atau lebih tampilan maka pertama-tama mulailah dengan tampilan, yang telah diperkenalkan sebelumnya atau lebih primitif dan kemudian pergi ke tampilan yang telah diperkenalkan kemudian atau lebih modern. Jadi di sini sejak tampilan gulir telah diperkenalkan terlebih dahulu, mulailah dengan tampilan gulir pertama dan kemudian pergi ke tampilan tumpukan. Di sini taruh batasan tampilan gulir ke nol di semua arah vis-a-vis tampilan supernya. Masukkan semua tampilan Anda di dalam tampilan gulir ini dan kemudian taruh dalam tampilan tumpukan.
Saat bekerja dengan tampilan tumpukan
Pertama mulai dengan alasan (pendekatan bottoms up), yaitu., Jika Anda memiliki label, bidang teks dan gambar dalam tampilan Anda, maka lay out pandangan ini terlebih dahulu (di dalam tampilan gulir) dan setelah itu menempatkannya dalam tampilan tumpukan.
Setelah itu atur properti view stack. Jika tampilan yang diinginkan masih belum tercapai, maka gunakan tampilan tumpukan lainnya.
Setelah membuat tampilan Anda, beri batasan antara tampilan tumpukan ibu dan tampilan gulir, sementara kendala tampilan tumpukan anak dengan tampilan tumpukan ibu. Mudah-mudahan saat ini sudah berfungsi dengan baik atau Anda mungkin mendapatkan peringatan dari Xcode memberikan saran, membaca apa yang dikatakannya dan mengimplementasikannya. Semoga sekarang Anda harus memiliki pandangan kerja sesuai harapan Anda :).
Untuk tampilan gulir bersusun atau tunggal, tampilan gulir harus ditetapkan lebar tetap dengan tampilan root. Tampilan tumpukan utama yang berada di dalam tampilan gulir harus mengatur lebar yang sama. [Tampilan gulir saya di bawah Tampilan abaikan saja]
Siapkan batasan Lebar yang sama antara UIStackView dan UIScrollView.
Jika ada yang mencari scrollview secara horizontal
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()
}
Tempatkan tampilan gulir pada adegan Anda, dan ukurlah sehingga memenuhi adegan itu. Kemudian, tempatkan tampilan tumpukan di dalam tampilan gulir, dan tempatkan tombol tambah item di dalam tampilan tumpukan. Segera setelah semuanya ada, tetapkan batasan berikut:
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
kode: Stack View.Width = Scroll View.Width
adalah kuncinya.
Menambahkan beberapa perspektif baru untuk macOS Catalyst. Karena aplikasi macOS mendukung pengubahan ukuran jendela, ada kemungkinan Anda UIStackView
akan beralih dari status yang tidak dapat dikendalikan ke status yang dapat digulir, atau sebaliknya. Ada dua hal halus di sini:
UIStackView
dirancang agar sesuai dengan semua area yang ada.UIScrollView
akan mencoba mengubah ukuran batasnya untuk memperhitungkan area yang baru didapat / hilang di bawah bilah navigasi Anda (atau bilah alat dalam hal aplikasi macOS).Sayangnya ini akan membuat loop tak terbatas. Saya tidak terlalu mengenal UIScrollView
dan itu adjustedContentInset
, tetapi dari log saya dalam layoutSubviews
metodenya, saya melihat perilaku berikut:
UIScrollView
mencoba mengecilkan batasnya (karena tidak perlu area di bawah bilah alat).UIStackView
mengikuti.UIScrollView
tidak puas, dan memutuskan untuk mengembalikan ke batas yang lebih besar. Ini terasa sangat aneh bagi saya karena apa yang saya lihat dari log adalah itu UIScrollView.bounds.height == UIStackView.bounds.height
.UIStackView
mengikuti.Tampak bagi saya bahwa dua langkah akan memperbaiki masalah:
UIStackView.top
dengan UIScrollView.topMargin
.contentInsetAdjustmentBehavior
ke .never
.Di sini saya prihatin dengan tampilan yang dapat digulir secara vertikal dengan yang tumbuh secara vertikal UIStackView
. Untuk pasangan horizontal, ubah kode sesuai dengan itu.
Semoga ini bisa membantu siapa pun di masa depan. Tidak dapat menemukan orang yang menyebutkan ini di Internet dan butuh waktu cukup lama untuk mencari tahu apa yang terjadi.