bagaimana cara menggunakan UIScrollView di Interface Builder?

95

Meskipun saya telah UIScrollViewberhasil menggunakannya di masa lalu dengan memanipulasinya secara terprogram, saya mengalami kesulitan untuk membuatnya berfungsi dengan menyiapkannya secara eksklusif di Interface Builder.

Saya memiliki halaman "tentang" sederhana di aplikasi iPhone saya. Ini memiliki UITextView, beberapa ikon, dan tautan ke aplikasi saya yang lain. Saya telah menambahkan semua tampilan ini ke saya UIScrollView, mengaturnya sehingga ukuran totalnya> 480. Saat saya meluncurkan aplikasi saya, tampilan gulir hanya menampilkan konten yang pas di layar, dan tidak ada yang bergulir.

Apakah mungkin untuk melakukan ini sepenuhnya melalui IB, atau haruskah saya memanipulasi contentSize melalui kode?

George Armhold
sumber

Jawaban:

130

Anda lupa menyetel properti contentSize dari UIScrollView. Anehnya Anda tidak dapat melakukan ini dari Interface Builder. Anda harus melakukannya dari pengontrol tampilan yang mengelola tampilan gulir ini.

Stefan Arentz
sumber
42
Wow, agak membuat IB agak, tidak ada gunanya ... Ini berhasil, terima kasih.
George Armhold
20
Anda bisa membuat subclass UIScrollvView yang memeriksa apakah hanya ada satu subview di (0,0) lalu secara otomatis menyetel contentSize berdasarkan subview tersebut.
Stefan Arentz
1
Itu adalah nasihat terbaik yang pernah saya terima. Saya tidak tahu mengapa tampilan gulir saya tidak berfungsi, dan tidak menemukan info tentang contentSize di tempat lain. Terima kasih.
Tarikan C
46
Saya mencoba mencari cara untuk menyetel contentSize di Interface Builder, dan menemukan diskusi ini. Setidaknya bagi saya, di Xcode 4.5, saya dapat menyetelnya menggunakan "Atribut Waktu Proses yang Ditentukan Pengguna", dengan menambahkan entri bernama contentSizetipe Size, dan menyetel nilai yang diinginkan.
nlogax
5
Saya masih bingung tentang mengapa iOS tidak hanya secara otomatis mengatur contentSizetampilan gulir berdasarkan dimensi subviewnya , setidaknya sebagai perilaku default.
Apakah
113

Jawaban Boby_Wan membuat saya berpikir, dan saya menemukan solusi berikut untuk mengkonfigurasi contentSize UIScrollView dari Interface Builder:

  1. Pilih UIScrollViewdi adegan Papan Cerita
  2. Pergi ke Identity inspector , buat User Defined Runtime Attribute baru (klik tombol +)
  3. Ubah atribut Key Path menjadicontentSize
  4. Ubah Jenis atribut menjadiSize
  5. Sekarang setel Nilai ke { lebar konten yang diinginkan , tinggi konten yang diinginkan }

mis. menyetel nilai ke {320, 920} akan membuat pengguna menggulir ke bawah seluruh layar ekstra pada iPhone.

(Saya menggunakan xcode 4.3.3, Target Penerapan iOS proyek adalah 5.1)

Ketika saya pertama kali melakukan ini, saya menerima kesalahan berikut:

Konfigurasi Ilegal:
     Jenis ukuran atribut runtime yang ditentukan pengguna dengan versi Xcode sebelum 4.3
     MainStoryboard.storyboard

Jika Anda juga mendapatkan kesalahan ini, mudah untuk memperbaikinya: pilih Storyboard di Project Navigator , dan buka File inspector . Temukan / perluas bagian Dokumen Pembuat Antarmuka , dan ada drop-down untuk Pengembangan . Pastikan ini disetel keXcode 4.3

Herr Grumps
sumber
7
Temuan luar biasa! PS: Saya terkejut bahwa ini adalah yang terbaik yang bisa dilakukan Apple. Saya rasa ini menunjukkan bahwa bahkan staf Apple tidak pernah menggunakan alat mereka sendiri (pembuat antarmuka) :).
Adam
Luar biasa, ini baru saja berfungsi untuk saya di Xcode 4.4. Tapi sekarang bagaimana cara meletakkan tombol pada bagian tampilan gulir yang tidak bisa "dilihat" di IB?
Robert Atkins
1
Saya baru saja menyelesaikannya – Anda harus melepaskan tarikan saat penunjuk masih berada di dalam "layar", jika tidak maka akan kembali ke saat Anda memulai. Sakit sekali.
Robert Atkins
Saya mencobanya seperti itu, tetapi saya mendapatkan kesalahan, "this class is not key value coding-compliant for the key keyPath"bisakah Anda membantu saya apa yang saya lakukan salah? harap dicatat bahwa saya menggunakan xamarin-ios-c #
SoftSan
25

Dengan Autolayout (iOS6 +), Anda dapat menghindari pengaturan contentSize. Tetapkan batasan berikut sebagai gantinya:

  1. Sematkan bagian atas tampilan gulir ke bagian atas turunannya yang paling atas.
  2. Dan sematkan bagian bawah ke bagian bawah anak paling bawah.
Danyal Aytekin
sumber
1
Terima kasih - pengaturan contentSizetidak berfungsi dengan Xcode 5 dan iOS 7
colincameron pada
18

Anda dapat melakukannya hanya dengan menggunakan Interface Builder, buka Identity Inspector (tab inspector ketiga) dan tambahkan atribut User Defined Runtime baru dengan

  • Jalur Kunci: contentSize
  • Jenis: Ukuran
  • Nilai: {width, height}
Anton Banchev
sumber
14

Sekarang ada cara untuk membuat UIScrollViewscroll tanpa meninggalkan Storyboard :

  1. Pilih UIScrollViewdi Storyboard, pergi ke Size inspector dan ubah nilai Bottom (atau nilai lain apa pun yang perlu Anda ubah) di bagian Content Insets ke ketinggian area konten.
  2. Sekarang pergi ke inspektur Identitas dan buat Atribut Waktu Proses yang Ditentukan Pengguna baru (dengan mengklik tombol +) dan beri nama contentSize. Tidak masalah Jenis atau Nilai apa yang Anda isi (Anda bahkan dapat membiarkan nilai defaultnya).

Ini akan membuat UIScrollViewpekerjaan berjalan dengan baik, meskipun saya tidak tahu mengapa langkah kedua diperlukan (saya mengetahuinya secara kebetulan). :(

RoberRM
sumber
Ubah nilai Bawah menjadi apa?
zakdances
Ubah ke ketinggian area konten. Tampaknya berfungsi, dan mengganti nilai yang Anda berikan untuk atribut "contentSize" yang ditentukan pengguna.
Reid Ellis
Ya, Reid, Anda benar: Anda harus mengubah nilai Bawah ke ketinggian area konten. Saya telah mengedit posting asli saya untuk mencerminkan ini. Terima kasih!
RoberRM
4

satu pendekatan yang telah saya gunakan di masa lalu adalah menyeret tampilan gulir dari tampilan yang berisi di pembuat antarmuka, dan menyetel ukuran sebenarnya ke ukuran yang diinginkan oleh contentSize.

Apa yang tidak jelas secara inheren tentang pembuat antarmuka adalah Anda dapat memiliki tampilan tak terkait yang disimpan di ujung pena, tetapi bukan bagian dari tampilan utama tujuan utama pena.

dalam tampilan di mana Anda ingin tampilan gulir hidup, tempatkan UIView sederhana, yang Anda gunakan sebagai placeholder. (ini hanya agar Anda dapat merancang lokasinya secara visual. jika Anda hanya menggunakan seluruh tampilan, Anda dapat melewati langkah ini dan menggunakan potongan kode kedua yang saya berikan di akhir jawaban ini).

Anda kemudian dapat mengisi tampilan gulir dengan kontrol, secara visual menatanya seperti yang Anda inginkan. berikan placeholder dan properti scrollview di dalam pengontrol tampilan sehingga Anda dapat mengaksesnya saat runtime.

saat runtime, di - (void) viewDidLoad

scrollView.contentSize = scrollView.frame.size;
scrollView.frame = placeholder.frame;
[placeholder.superview addSubView:scrollView];
[placeholder removeFromSuperview];

alternatifnya (jika Anda tidak menggunakan placeholder):

CGRect f = self.view.frame;
scrollView.contentSize = f.size;
f.origin.x = 0;
f.origin.y = 0;
scrollView.frame = f;
[self.view addSubView:scrollView];

terakhir, jika Anda "kehilangan" tampilan gulir di pembuat antarmuka (Anda dapat menutupnya sehingga menghilang dari kisi desain), jangan panik. klik saja di daftar objek di sebelah kiri kisi desain.

tidak tersinkronisasi
sumber
1
Terima kasih - ini bekerja dengan baik. Juga perlu mendeklarasikan IBOutlets di YourViewController.h untuk tampilan placeholder dan scroll, dan menghubungkannya di Interface Builder. Dan terakhir, dot.notation tidak dihargai oleh xCode untuk baris ke-3, jadi gunakan sintaks pengiriman pesan normal - maka semuanya bekerja dengan baik!
jiy
jangan khawatir. selalu ada bahaya saat memposting cuplikan kode karena beberapa orang tidak dapat menggunakannya untuk mendapatkan konsep, daripada mengharapkan kode "tepat" berfungsi dalam setiap situasi.
tidak tersinkronisasi
Ini adalah metode yang sebenarnya saya gunakan. Saya bahkan tidak perlu mengubah ukuran program ini sama sekali. Saya pikir itu cara yang dimaksudkan untuk dilakukan. Itu satu-satunya jawaban yang benar.
pengguna4951
Setelah menggambarnya di luar, saya akan memindahkannya ke tampilan super. Tada.
pengguna4951
Saya benar-benar mulai menggunakan desain beberapa tampilan di luar adegan untuk scratchpads dan itu membuat hidup jauh lebih mudah dalam beberapa situasi bahkan tidak terkait dengan yang satu ini. Terima kasih atas jawaban ini.
Benjamin
4

Di Xcode 4.5 menggunakan Autolayout saya tidak memiliki bagian Insets Konten di inspektur ukuran saya. Jadi saya harus menambahkannya di bawah User Defined Runtime Attributes dan kemudian berfungsi dengan baik.

Apa yang Anda tambahkan dalam "Atribut Waktu Proses yang Ditentukan Pengguna" adalah keyPath == contentInset yang berjenis "Rect" (UIEdgeInsets, yang memiliki input yang sama dengan Rect) dan didefinisikan sebagai {top, left}, {bottom, right}. ContentSize hanya menentukan wilayah jendela scrollview. contentInset mendefinisikan area yang dapat digulir.

Saya harap ini membantu seseorang dalam situasi yang sama.

Robert Wasmann
sumber
Untuk UITextView, gunakan "textContainerInset" keyPath
Dima Deplov
4

Banyak jawaban di atas yang menyesatkan atau ketinggalan zaman. Pada 2017 (mungkin lebih awal) interface builder tidak scrollviews dukungan dengan konten secara otomatis berukuran. Triknya adalah XCode memberikan arti khusus dan non-standar pada batasan antara scrollview dan konten di dalamnya. Batasan "ke dalam" ini tidak akan benar - benar memengaruhi ukuran konten seperti yang Anda harapkan.

Ini berarti bahwa Anda dapat, misalnya, membuat tampilan gulir Anda disematkan ke bagian bawah tampilan utama dengan margin nol, dan juga konten tampilan gulir Anda disematkan ke bagian bawah tampilan gulir dengan margin nol, tetapi konten sebenarnya tidak akan ditarik oleh ini. Sebaliknya, konten akan mendapatkan ukuran yang ditentukan sendiri (selengkapnya di bawah) dan ini juga akan menjadi ukuran area yang dapat digulir dalam tampilan gulir.

Anggap saja seperti ini - Ada asimetri dalam batasan yang mengikat ke tampilan gulir: Batasan dari tampilan gulir ke dunia "luar" (induk) menentukan ukuran dan posisi tampilan gulir seperti biasa. Namun batasan "di dalam" scrollview sebenarnya adalah menyetel ukuran dan posisi area scrollable scrollview, dengan mengikatnya ke konten.

Ini sama sekali tidak jelas karena ketika Anda pergi untuk mengatur batasan XCode akan selalu menyarankan jarak saat ini dan mungkin tidak pernah terpikir oleh Anda untuk secara sengaja mengubah kendala yang dihadapi ke dalam dan ke luar dengan cara yang bertentangan. Tapi Anda bisa dan mereka memiliki arti yang dijelaskan di atas: satu mengontrol tata letak tampilan gulir dan satu mengontrol ukuran area konten yang dapat digulir.

Saya tersandung pada ini secara tidak sengaja dan kemudian melihat bagaimana tampaknya bekerja membawa saya ke artikel ini yang menjelaskannya secara lengkap dan mengutip sumber dokumen Apple untuk ini:

https://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

Satu informasi penting terakhir, tentang ukuran konten yang ditentukan sendiri: Anda mungkin merasa bahwa Anda berada di tangkapan-22 di sini karena Anda biasanya mengukur konten Anda misalnya, lebar tampilan induk, tetapi dalam kasus ini induknya adalah scrollview dan seperti yang dijelaskan di atas - batasan tidak akan memengaruhi ukuran konten Anda. Jawabannya di sini adalah untuk mengingat bahwa Anda dapat membatasi item ke item yang tidak secara langsung bersebelahan dalam hierarki tampilan Anda: misalnya Anda dapat menyetel lebar tampilan konten Anda ke lebar tampilan utama daripada mencoba sia-sia untuk mendapatkan tampilan gulir untuk melakukannya untukmu.

Pat Niemeyer
sumber
2

Jika Anda mengklik ikon Properties dari setiap View Controller di Interface Builder, Anda dapat mengaturnya ke ukuran "Freeform" di Simulated Metrics dan mengubah ukuran View utama menjadi ukuran konten yang Anda inginkan.

Dengan cara ini Anda bisa membuat konten ScrollView Anda seolah-olah itu adalah satu tampilan besar. Karena ini hanya metrik simulasi Pengontrol Tampilan Anda akan diubah ukurannya ke batas jendela saat dimuat.

oliland
sumber
2

Menyiapkan UIScrollView melalui Interface Builder tidak intuitif. Berikut adalah daftar periksa saya untuk menyiapkannya:

  1. Pilih file XIB UIViewController. Dalam "Identity Inspector" pembuat antarmuka, ubah UIView menjadi jenis kelas UIScrollView

  2. Di bawah "File Inspector", hapus centang Autolayout

  3. Di bawah "Attributes Inspector", ubah ukurannya menjadi Bentuk Bebas. Anda kemudian dapat meregangkan Tampilan Gulir secara manual atau Anda dapat menentukan lebar dan tinggi khusus di bawah "Pemeriksa Ukuran".

  4. Di "Identity Inspector", tambahkan Atribut Waktu Proses Buatan Pengguna baru yang disebut "contentSize" dengan jenis "Ukuran" dan ubah ke nilai seperti {320, 1000}. Anda tidak dapat mengatur ini secara programatik lagi dan oleh karena itu memerlukan langkah ini sehingga Tampilan Gulir mengetahui bahwa konten Tampilan Gulir lebih besar dari jendela.

Mason Gratis
sumber
2

Hapus saja autoLayout di scrollview Anda. maka kodenya sesederhana ini:

scrollviewName.contentSize = CGSizeMake(0, 650);

cukup buat properti iboulet pada file .h lalu lakukan sintesis pada file .m. Pastikan bahwa pengguliran diaktifkan.

Aldrin Equila
sumber
1

Ya, st3fan benar, properti contentSize UIScrollView harus disetel. Tetapi Anda tidak harus mematikan tata letak otomatis untuk tujuan ini. Anda dapat dengan mudah mengatur contentSize dari UIScrollView dengan autolayout hanya di IB, tanpa kode apa pun.

Penting untuk dipahami bahwa saat menggunakan autolayout contentSize dari UIScrollView tidak disetel secara langsung, ini dihitung berdasarkan batasan dari semua subview UIScrollView. Dan yang Anda butuhkan hanyalah memberikan batasan yang tepat untuk subview untuk kedua arah.

Misalnya jika Anda hanya memiliki satu subview, Anda dapat mengatur tinggi dan ruangnya dari atas dan bawah ke superview (misalnya scrollView dalam kasus kami) contentSize.height dihitung sebagai jumlah

Vertical Space (aSubview.top to Superview.top) + aSubview.height + Vertical Space (aSubview.top to Superview.top)

contentSize.width dihitung dengan cara yang sama dari batasan horizontal.

Jika ada terlalu sedikit batasan untuk menghitung contentSize dengan benar, tombol merah kecil ditampilkan di dekat item View Controller Scene untuk menginformasikan tentang ambiguitas layout.

Jika ada banyak subview maka mungkin saja "chain" of constraint: subview dari atas ke atas, ketinggian dan jarak antara subview dan subview paling bawah ke bawah seperti pada jawaban Danyal Aytekin .

Namun dalam praktiknya dalam banyak kasus, lebih mudah hanya menambahkan tampilan kosong dengan ukuran yang diperlukan dan mengatur spasi ke atas, kiri, bawah, kanan scrollView ke 0. Anda dapat menggunakan tampilan ini sebagai "Tampilan konten", yaitu meletakkan semua subview lainnya di atasnya atau jika Anda sudah memiliki banyak subview dan tidak ingin memindahkannya dan mengatur layout lagi, Anda dapat menambahkan tampilan tambahan ini ke subview yang ada dan membuatnya tersembunyi.

Untuk membuat scrollView konten terhitung yang dapat digulir harus lebih besar dari ukuran scrollView.

Vladimir
sumber
1

Anda dapat memiliki UIScrollView di StoryBoard dengan Autolayouts. Pada dasarnya yang Anda butuhkan adalah:

  1. Tambahkan UIScrollView
  2. Tambahkan semua batasan ke dalamnya (seperti sisipan dari tepi atas, kiri, kanan, bawah)
  3. Tambahkan UIView 'container' ke UIScrollView
  4. Jika Anda hanya menginginkan scroll satu arah (misalnya, vertikal): setel tinggi secara eksplisit (misalnya 600) dan lebar link ke lebar UIScrollView.
  5. Jika Anda ingin gulir dua arah, cukup atur lebar dan tinggi.

penyiapan storyboard

Eugene Braginets
sumber
0

Berikut adalah solusi untuk mendesain ScrollView dengan konten yang lebih besar dari layar seluruhnya di Storyboard (yah, hampir seluruhnya, Anda juga perlu menambahkan 1 baris kode)

https://stackoverflow.com/a/19476991/1869369

Ronny Webers
sumber
0

Saya menemukan cara yang lebih nyaman.

1: Skala ukuran tampilan gulir untuk memuat semua UI di dalamnya.

2: Tambahkan outlet kecil tampilan gulir.

3: Dalam viewDidLoad, simpan ukuran frame dari tampilan gulir.
(misalnya _scrollSize = _scrollView.frame.size;)

4: Dalam viewWillAppear, setel contentSize dengan CGSize yang Anda simpan sebelumnya.
(misalnya _scrollView.contentSize = _scrollSize;)

5: Selesai ~

Agas
sumber
0
  1. Tambahkan UIViewController
  2. Dalam UIViewController 'Attribute Inspector -> Simulated Metrics' set size Freeform
  3. Dalam UIViewController 'Size Inspector -> View Controller' setel tinggi 800
  4. Tambahkan UIScrollView di UIViewController
  5. Tambahkan semua batasan ke UIScrollView (atas, kiri, kanan, bawah) dan tambahkan perataan X = tengah
  6. Tambahkan UIView di UIScrollView
  7. Tambahkan semua batasan ke UIView (atas, kiri, kanan, bawah) dan tambahkan perataan X = tengah. Ya, sama seperti untuk UIScrollView di # 3, tetapi untuk UIView
  8. Tambahkan batasan ketinggian ke UIView. Misalnya 780
  9. Lari

Papan cerita

Alexander
sumber
0

Buat Proyek Xcode baru

Arahkan ke file Main.storyboard

Pilih ScrollView dari perpustakaan objek.

Atur bingkai untuk ScrollView.

Tambahkan tampilan lain untuk menggulir tampilan dan menjaga frame tetap sama dengan ScrollView.

Sekarang untuk mengatur tinggi dan lebarnya secara dinamis Anda dapat mengkonfigurasi UIScrollView Menggunakan Tata Letak Otomatis Di XIB

Dilraj Singh
sumber