Untuk memastikan lajur label dan status tetingkap Mac kekal stabil sementara keterangannya berkembang, tetapkan lebar eksplisit pada lajur luar dan bingkai fleksibel pada lajur keterangan. Gunakan keutamaan susun atur apabila adik-beradik berebut ruang, dan kekalkan saiz ideal hanya pada paksi yang memerlukannya.
Tutorial ini membina tetingkap kecil yang boleh diubah saiznya, yang mengandungi label dan keterangan item sintetik. Tugasnya ialah memastikan lajur sejajar sambil membolehkan keterangan yang lebih panjang membalut apabila tetingkap dikecilkan. Semuanya tergolong dalam app contoh; susun aturnya menggunakan paparan SwiftUI biasa.
Kawalan saiz yang manakah patut digunakan oleh setiap subview?
Susun atur SwiftUI bermula dengan induk yang mencadangkan saiz. Setiap anak membalas dengan saiz pilihannya, kemudian bekas menyusun hasilnya. Titik permulaan yang berguna ialah menentukan dimensi yang boleh diubah oleh setiap anak. Apple menerangkan proses cadangan dan balasan ini dalam Panduan kepada susun atur dalam SwiftUI.
Untuk tetingkap ini, tetapkan tiga peranan: lajur label dengan lebar yang dipilih, lajur keterangan yang menyerap perubahan lebar, dan lajur status dengan lebar yang dipilih. Bezakan lebar tetap berangka itu daripada saiz ideal paparan: kedua-duanya menyatakan keperluan yang berbeza.
| Keperluan | Kawalan | Kesan praktikal |
|---|---|---|
| Peruntukkan lebar lajur tertentu | .frame(width: 96) |
Bingkai yang terhasil mempunyai lebar tersebut. |
| Benarkan keterangan menyerap lebar yang tersedia | .frame(minWidth: 160, maxWidth: .infinity, alignment: .leading) |
Bingkai menerima lebar yang dicadangkan tertakluk pada nilai minimumnya. |
| Kekalkan saiz ideal kandungan pada paksi terpilih | .fixedSize(horizontal: false, vertical: true) |
Lebar boleh bertindak balas terhadap susun atur sementara ketinggian mengekalkan saiz idealnya. |
| Utamakan satu adik-beradik ketika memperuntukkan ruang | .layoutPriority(1) |
Induk mengutamakan anak itu berbanding adik-beradik yang berkeutamaan lebih rendah. |
Apple mendokumenkan dimensi berangka dalam pengubah suai bingkai tetap, kekangan minimum dan maksimum dalam pengubah suai bingkai fleksibel, penetapan saiz ideal khusus mengikut paksi dalam fixedSize(horizontal:vertical:), dan keutamaan adik-beradik dalam layoutPriority(_:).
Had maksimum tak terhingga ialah kebenaran untuk berkembang dalam cadangan saiz; ia tidak meminta tetingkap yang lebarnya tidak terhingga. Dengan memberikan kedua-dua kekangan minimum dan maksimum, bingkai menerima dimensi yang dicadangkan, dihadkan oleh kekangan tersebut. Parameter penjajaran meletakkan anak di dalam bingkai itu. Perincian ini penting apabila teks itu sendiri lebih sempit daripada ruang yang diperuntukkan kepada lajurnya. Dokumentasi bingkai fleksibel Apple
Bina contoh macOS lengkap yang boleh diubah saiznya
Cipta projek app macOS dalam Xcode menggunakan SwiftUI dan tetapkan sasaran penggunaan kepada macOS 13 atau lebih baharu. Gantikan pengisytiharan app dan paparan kandungan yang dijana dengan satu fail ini, dan biarkan hanya satu titik masuk app. Contoh ini menggunakan kawalan kebolehubahan saiz tetingkap dalam macOS 13. Dokumentasi WindowResizability Apple
Berikut ialah contoh app yang lengkap. Ia merangkumi rentetan sampel dan togol untuk bertukar antara keterangan pendek dengan keterangan panjang. App SwiftUI ini tidak dapat dikompil dalam persekitaran penyelidikan kerana toolchain Swift tidak tersedia; periksa kelakuannya dalam Xcode sebelum menyepadukannya ke dalam projek sedia ada.
import SwiftUI
@main
struct ColumnAllocationApp: App {
var body: some Scene {
WindowGroup {
AllocationView()
.frame(minWidth: 420, minHeight: 260)
}
.windowResizability(.contentMinSize)
}
}
struct AllocationView: View {
@State private var showLongDescriptions = true
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text("Item overview")
.font(.title2)
Toggle(
"Show longer descriptions",
isOn: $showLongDescriptions
)
ScrollView {
VStack(alignment: .leading, spacing: 16) {
AllocationRow(
label: "Item A",
summary: showLongDescriptions
? "A blue folder with several sample notes and a longer descriptive label."
: "Blue folder",
status: "Ready"
)
AllocationRow(
label: "Item B",
summary: showLongDescriptions
? "A green notebook containing a short list of synthetic example entries."
: "Green notebook",
status: "Draft"
)
}
.frame(maxWidth: .infinity, alignment: .leading)
}
}
.padding(16)
}
}
struct AllocationRow: View {
let label: String
let summary: String
let status: String
var body: some View {
HStack(alignment: .top, spacing: 12) {
Text(label)
.frame(width: 96, alignment: .leading)
Text(summary)
.fixedSize(horizontal: false, vertical: true)
.frame(
minWidth: 160,
maxWidth: .infinity,
alignment: .leading
)
Text(status)
.fixedSize(horizontal: true, vertical: false)
.frame(width: 72, alignment: .trailing)
}
}
}
Keterangan ialah satu-satunya lajur yang fleksibel secara mendatar. Panggilan fixedSize membiarkan saiz mendatar bertindak balas sambil mengekalkan ruang menegak yang diperlukan oleh teks berbalut. Bingkai fleksibelnya kemudian memenuhi lajur yang diperuntukkan. Status mengekalkan lebar teks idealnya dalam bingkai 72 poin yang berasingan. Apple mengingatkan bahawa kandungan bersaiz ideal boleh melangkaui sempadan induknya, jadi pengendalian status ini mengandaikan nilai pendek yang diberikan, Ready dan Draft. Dokumentasi fixedSize Apple
Baris tidak mempunyai ketinggian tetap. Ini disengajakan: keterangan yang lebih sempit mungkin memerlukan lebih banyak baris. Paparan tatal menyediakan cara untuk mencapai baris apabila jumlah ketinggiannya melebihi kawasan yang tersedia. Elakkan menambah ketinggian baris yang mengehadkan hanya untuk menjadikan susunan awal kelihatan seragam.
Tetingkap menggunakan .contentMinSize, yang memperoleh dimensi minimumnya daripada kandungan dan tidak mengenakan saiz maksimum. Di sini, lebar minimum akar sebanyak 420 poin menetapkan had bawah yang praktikal untuk contoh ini. Kawalan ini terpakai pada tetingkap yang dicipta oleh scene app. Dokumentasi contentMinSize Apple
Pengisytiharan yang mengembalikan some View menggunakan jenis hasil legap Swift: jenis konkritnya kekal tersembunyi sementara pematuhannya kepada View masih tersedia. Anda boleh melaraskan rantaian pengubah suai tanpa menyatakan jenis pulangan tersarang. Bahasa Pengaturcaraan Swift: Jenis Protokol Legap dan Berkotak
Kira belanjawan lebar sebelum mengubah keutamaan
Belanjawan lebar menjelaskan had susun atur. Dalam contoh ini, tolak padding mendatar, kedua-dua jarak, dan dua lajur tetap daripada lebar kandungan tetingkap. Baki lebarnya diperuntukkan kepada keterangan. Ini ialah dimensi reka bentuk ilustratif, bukannya ukuran kawalan natif.
Lebar keterangan
= lebar kandungan - padding mendatar - jarak - lajur tetap
= lebar kandungan - (2 × 16) - (2 × 12) - 96 - 72
= lebar kandungan - 224
Pada 640 poin: 416 poin berbaki untuk keterangan.
Pada 420 poin: 196 poin berbaki untuk keterangan.
Belanjawan minimum baris:
32 + 24 + 96 + 160 + 72 = 384 poin.
Pengiraan ini disemak menggunakan pengiraan setempat yang deterministik. Ia menerangkan baris ini apabila menerima lebar kandungan ditolak padding yang dinyatakan; ia tidak merangkumi hiasan tetingkap. Lebar minimum tetingkap yang dipilih, iaitu 420 poin, menyediakan ruang melebihi minimum 384 poin yang dikira untuk baris tersebut. Jika bekas di sekeliling menambah inset, masukkannya dalam belanjawan juga.
Pengiraan ini turut mengenal pasti permintaan yang mustahil. Di bawah jumlah belanjawan minimum, ketiga-tiga lajur tidak dapat mengekalkan lebar dan jaraknya serentak. Pilih lebar minimum tetingkap yang lebih besar, dimensi minimum yang lebih kecil, atau susunan yang berbeza. Meningkatkan keutamaan tidak dapat mencipta ruang tambahan.
Bilakah keutamaan susun atur membantu?
Keutamaan berguna apabila dua adik-beradik boleh mengecil dan anda mahu salah satunya mengekalkan lebih banyak ruang. Contohnya, tajuk deskriptif mungkin patut diutamakan berbanding anotasi sekunder. Letakkan .layoutPriority(1) pada anak yang terlibat dalam keputusan peruntukan induk tersebut. Apple menyatakan bahawa paparan berkeutamaan lebih tinggi mengecil kemudian dan meregang lebih awal, sambil ruang diperuntukkan untuk keperluan minimum anak berkeutamaan lebih rendah. Dokumentasi layoutPriority Apple
Contoh lengkap ini tidak memerlukan pengubah suai keutamaan: dasar peruntukannya sudah dinyatakan melalui dua lajur tetap dan satu lajur fleksibel. Nilai keutamaan juga bukan pemberat berkadar. Menetapkan keutamaan 2 dan 1 tidak menghasilkan nisbah lebar dua kepada satu; tujuan yang didokumenkan ialah keutamaan semasa peruntukan. Dokumentasi layoutPriority Apple
Elakkan menambah Spacer mendatar antara keterangan dengan status, melainkan anda mahukan jarak fleksibel yang berasingan. Spacer berkembang sepanjang paksi utama tindanannya dan menolak adik-beradik supaya berjauhan. Oleh sebab bingkai keterangan sudah menyerap perubahan lebar, peserta tambahan itu tidak diperlukan di sini. Dokumentasi Spacer Apple
Apakah yang patut berlaku apabila teks tidak lagi muat?
Tentukan secara berasingan sama ada setiap medan teks patut membalut, dipotong atau memerlukan susunan berbeza. Keterangan dalam contoh ini boleh membalut tanpa had baris. Menggunakan .lineLimit(1) akan mengehadkan setiap elemen teks yang terlibat kepada satu baris, lalu mengubah keperluan. Had baris nil menghapuskan sekatan itu, tetapi tidak menghapuskan kekangan yang dikenakan oleh bingkai yang mengandungi teks tersebut. Dokumentasi lineLimit Apple
Untuk nilai status yang lebih panjang, pertimbangkan semula lajur 72 poin itu. Buang pengekalan saiz ideal mendatar jika pembalutan boleh diterima, besarkan lebar lajur, atau pindahkan status ke bawah keterangan. Mengekalkan .fixedSize(horizontal: true, vertical: false) sambil mengecilkan bingkai yang mengandunginya boleh menyebabkan teks melangkaui bingkai tersebut. Dokumentasi fixedSize Apple
Jika tetingkap padat patut menyusun semula kandungan, macOS 13 dan versi lebih baharu menyediakan ViewThatFits. Sediakan susunan mendatar dahulu dan susunan bertindan selepasnya. Ia memilih anak pertama yang saiz idealnya muat pada paksi yang dikekang, jadi nilai ruang mendatar dengan ViewThatFits(in: .horizontal) apabila lebar menjadi faktor penentu. Pastikan calon terakhir boleh digunakan pada lebar minimum yang disokong. Dokumentasi ViewThatFits Apple
Anggap itu sebagai dasar susun atur alternatif. Contoh semasa sengaja mengekalkan lajur dan menetapkan lebar minimum tetingkap. Gunakan susun atur bertindan sandaran apabila mengekalkan susunan mendatar kurang penting berbanding membenarkan tetingkap yang lebih sempit.
Bagaimanakah paparan AppKit dan TextKit terbenam mengubah pendekatan ini?
Jika keterangan kemudian menjadi komponen teks AppKit, gunakan NSViewRepresentable untuk menyepadukan paparan itu. Apple menyatakan dengan jelas bahawa SwiftUI mengawal frame dan bounds bagi paparan yang diwakilkan; mengubah sifat tersebut secara terus daripada kod anda sendiri bercanggah dengan susun atur SwiftUI. Konfigurasikan kandungan melalui kitar hayat representable dan nyatakan saiz luar melalui SwiftUI. Dokumentasi NSViewRepresentable Apple
Pada macOS 13 dan versi lebih baharu, kaedah sizeThatFits(_:nsView:context:) representable boleh mengembalikan saiz pilihannya berdasarkan cadangan saiz. Kaedah ini mungkin dipanggil beberapa kali dengan cadangan yang berbeza dalam satu laluan susun atur. Mengembalikan nil meminta algoritma saiz lalai. Pengukuran komponen yang membalut teks patut mengambil kira lebar yang dicadangkan, bukannya sentiasa mengembalikan lebar teks tanpa balutan. Dokumentasi saiz representable Apple
Bezakan dimensi yang tidak ditentukan daripada sifar: SwiftUI menggunakan cadangan yang tidak ditentukan untuk meminta saiz ideal, manakala sifar boleh menguji saiz minimum. Rutin pengukuran tersuai mesti mengendalikan kes tersebut dengan sengaja. Dokumentasi ProposedViewSize Apple
Dalam susun atur AppKit, rintangan pemampatan mengawal sejauh mana NSView menolak daripada menjadi lebih kecil daripada saiz intrinsiknya. Periksa tetapan itu apabila komponen berbalut teks menolak pemampatan, bersama-sama dengan kelakuan saiz SwiftUI-nya. Dokumentasi setContentCompressionResistancePriority Apple
Untuk NSTextView yang menggunakan TextKit 2, gunakan laluan moden textLayoutManager. Gambaran keseluruhan TextKit Apple yang terkini membezakannya daripada layoutManager lama, dan panduan pemindahannya menerangkan bahawa mengakses sifat lama itu boleh mencetuskan pertukaran keserasian sehala kepada TextKit 1 bagi tika tersebut. Menukar enjin teks tidak diperlukan untuk memperuntukkan lajur adik-beradik. Gambaran keseluruhan TextKit Apple, Perkara baharu dalam TextKit dan paparan teks
Semak hasil pada had tetingkap
Jalankan contoh dan periksa keadaan berikut sebelum menggunakan corak ini pada antara muka yang lebih besar:
- Lebarkan tetingkap: lajur keterangan patut berkembang sementara bingkai label dan status mengekalkan lebarnya.
- Kecilkan hingga lebar minimum yang disokong: keterangan yang lebih panjang patut membalut dan menambah ketinggian baris.
- Matikan dan hidupkan
Tunjukkan keterangan lebih panjang: keterangan pendek patut kekal sejajar dengan lajur yang sama. - Gantikan status dengan teks sintetik yang lebih panjang: tentukan sama ada hendak membesarkan, membalut atau menyusun semula medan itu.
- Kurangkan ketinggian yang tersedia: pastikan semua baris masih boleh dicapai.
Untuk melihat lapisan yang menerima ruang, tambahkan sempadan buat sementara waktu betul-betul sebelum dan selepas bingkai fleksibel keterangan. Sempadan dalam menunjukkan sempadan teks; sempadan luar menunjukkan lajur yang diperuntukkan. Apple mengesyorkan sempadan berwarna sebagai cara praktikal untuk mendiagnosis saiz tindanan dan padding. Panduan kepada susun atur dalam SwiftUI
Pastikan dasar saiz dinyatakan dengan jelas apabila antara muka berkembang: peruntukkan lebar apabila penjajaran memerlukannya, berikan kandungan berubah-ubah kawasan fleksibel yang ditetapkan, dan tentukan kelakuan setiap medan pada lebar minimum. Dengan dasar dan belanjawan lebar itu, anda boleh mengubah label atau menambah kandungan tanpa meneka pengubah suai yang patut menerima keutamaan lebih tinggi.
Sumber
- Panduan kepada susun atur dalam SwiftUI — Apple
- frame(width:height:alignment:) — Apple
- frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:) — Apple
- fixedSize(horizontal:vertical:) — Apple
- layoutPriority(_:) — Apple
- WindowResizability — Apple
- contentMinSize — Apple
- Opaque and Boxed Protocol Types — Swift.org
- Spacer — Apple
- lineLimit(_:) — Apple
- ViewThatFits — Apple
- NSViewRepresentable — Apple
- sizeThatFits(_:nsView:context:) — Apple
- ProposedViewSize — Apple
- setContentCompressionResistancePriority(_:for:) — Apple
- TextKit — Apple
- What’s new in TextKit and text views — Apple