Untuk menjadikan ruang kosong dalam baris SwiftUI boleh diklik pada Mac, luaskan kandungan baris supaya memenuhi lebar yang tersedia dan gunakan bentuk kandungan segi empat tepat. Bagi baris yang melaksanakan tindakan, letakkan kedua-dua pengubah dalam label Button.
Tutorial ini membina aplikasi macOS kecil yang barisnya mengandungi bentuk dan teks sintetik. Mengklik bentuk, labelnya atau ruang kosong di sebelahnya akan menjalankan tindakan baris yang sama. Ruang di luar baris kekal di luar sasaran tindakan itu.
Mengapa teks memberi respons tetapi ruang kosong tidak?
Susun atur dan pengujian sasaran menjawab soalan yang berbeza. Bingkai menentukan cara paparan menggunakan ruang yang dicadangkan kepadanya; bentuk kandungan mentakrifkan kawasan yang digunakan untuk pengujian sasaran. Apple mendokumentasikan kedua-duanya secara berasingan dalam pengubah bingkai fleksibelnya dan pengubah bentuk kandungannya.
Sebagai contoh, baris mungkin kelihatan lebar kerana bekasnya memenuhi tetingkap, sedangkan interaksi hanya dikaitkan dengan paparan teks yang pendek. Begitu juga, menambah ruang susun atur kosong tidak secara jelas menetapkan bahawa seluruh baris perlu terlibat dalam pengujian sasaran. Penyelesaian praktikalnya ialah menetapkan sempadan baris yang dimaksudkan terlebih dahulu, kemudian memberikan kawasan itu bentuk interaksi.
Gunakan .frame(maxWidth: .infinity, alignment: .leading) supaya label boleh berkembang apabila induknya mencadangkan lebar tambahan. Kemudian gunakan .contentShape(.interaction, Rectangle()) pada label yang telah dikembangkan itu. Apple mentakrifkan interaction jenis bentuk kandungan khusus untuk pengujian sasaran dan kebolehcapaian.
Ini tidak menjadikan baris selebar tak terhingga. Bingkai itu masih tertakluk pada cadangan susun atur daripada induknya. Induk yang sempit menghasilkan baris yang sempit, dan bentuk kandungan tidak dapat menyediakan ruang susun atur yang tiada. Gabungan ini memenuhi dua keperluan: label yang cukup lebar dan kawasan pengujian sasaran yang ditetapkan secara jelas.
Bina contoh butang baris yang lengkap
Cipta projek aplikasi macOS dalam Xcode menggunakan SwiftUI dan Swift. Tetapkan sasaran penggunaan kepada macOS 12 atau lebih baharu untuk lebihan beban bentuk kandungan .interaction yang jelas, yang disenaraikan oleh Apple sebagai tersedia mulai macOS 12. Gantikan deklarasi aplikasi dan paparan kandungan yang dijana dengan program satu fail di bawah; kekalkan hanya satu deklarasi aplikasi @main. Rujuk dokumentasi lebihan beban bentuk kandungan Apple untuk maklumat ketersediaan.
Contoh ini menggunakan Button kerana setiap baris memulakan tindakan. Apple mengesyorkan butang untuk elemen antara muka yang melaksanakan tindakan dan secara jelas menyokong paparan sewenang-wenangnya sebagai label butang. Dokumentasi gerak isyarat ketiknya juga mengesyorkan butang tersuai apabila kawalan berasaskan gerak isyarat berfungsi sama seperti butang.
import SwiftUI
@main
struct ClickableRowsApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct SampleItem: Identifiable {
let id: Int
let title: String
let color: Color
}
struct ContentView: View {
private let items = [
SampleItem(id: 1, title: "Blue square", color: .blue),
SampleItem(id: 2, title: "Orange square", color: .orange),
SampleItem(id: 3, title: "Purple square", color: .purple)
]
@State private var lastActivated = "None"
@State private var activationCount = 0
var body: some View {
VStack(alignment: .leading, spacing: 12) {
Text("Choose a shape")
.font(.headline)
ScrollView {
VStack(spacing: 8) {
ForEach(items) { item in
Button {
lastActivated = item.title
activationCount += 1
} label: {
HStack(spacing: 12) {
Rectangle()
.fill(item.color)
.frame(width: 24, height: 24)
Text(item.title)
}
.padding(.horizontal, 12)
.padding(.vertical, 10)
.frame(maxWidth: .infinity,
alignment: .leading)
.contentShape(.interaction, Rectangle())
}
.buttonStyle(.plain)
.background(Color.gray.opacity(0.12))
}
}
}
Text("Last activated: \(lastActivated)")
Text("Activations: \(activationCount)")
}
.padding(16)
.frame(minWidth: 360, minHeight: 280)
}
}
Semua item dan keadaan interaksi kekal dalam memori. Setiap item mempunyai identiti integer tetap, selaras dengan protokol Identifiable Swift, yang mewakili identiti stabil. Paparan induk memiliki keadaan pengaktifan, mengikut panduan Apple supaya State setempat dirahsiakan dalam paparan yang perlu memilikinya.
Jalankan aplikasi dan klik kawasan kosong di sebelah kanan mana-mana tajuk. Kiraan pengaktifan sepatutnya meningkat sekali dan status sepatutnya menyebut nama baris itu. Latar belakang kelabu menunjukkan kawasan baris yang dimaksudkan semasa pemeriksaan ini; bentuk kandungan yang dinyatakan secara jelas mentakrifkan kawasan interaksi.
Program ini telah diperiksa berdasarkan dokumentasi API yang diperoleh, tetapi tidak dikompil atau dijalankan di sini kerana rantaian alat Swift tidak tersedia. Sahkan tingkah laku penunjuk dan papan kekuncinya dalam sasaran macOS anda sebelum mengintegrasikannya.
Di manakah bingkai, padding dan bentuk kandungan patut diletakkan?
Dalam contoh ini, susunannya disengajakan: bina kandungan label, tambahkan padding dalamannya, luaskan label itu, kemudian tetapkan bentuk interaksi di atas kawasan tersebut. Semua operasi ini berlaku di dalam closure label butang. Apple mendokumentasikan bahawa susunan pengubah penting.
Meletakkan padding di dalam label yang dibentuk ini memasukkan kawasan berpadding itu ke dalam sasaran yang dimaksudkan. Meletakkan padding di luar butang pula mewujudkan ruang susun atur di sekelilingnya; jangan anggap ruang itu sebahagian daripada label interaktif butang. Begitu juga, meluaskan bekas luar sahaja tidak menetapkan geometri label yang sama seperti meluaskan kandungan di dalam butang.
Pengubah .buttonStyle(.plain) memastikan contoh ini ringkas dari segi rupa. Apple menerangkan gaya butang plain sebagai tidak berhias ketika tidak aktif, dengan kemungkinan kesan apabila ditekan, difokuskan atau didayakan. Ini pilihan penggayaan, bukan pengganti untuk menetapkan lebar dan bentuk kandungan label.
Bagi sasaran penggunaan yang lebih awal daripada macOS 12, gantikan .contentShape(.interaction, Rectangle()) dengan .contentShape(Rectangle()). Apple mendokumentasikan lebihan beban lama sebagai mentakrifkan bentuk pengujian sasaran dan menyenaraikan ketersediaannya mulai macOS 10.15. Penggantian ini mengubah keperluan API bentuk kandungan; semak API lain dalam aplikasi anda secara berasingan.
Patutkah baris menggunakan butang, pemilihan senarai atau gerak isyarat?
Pilih interaksi berdasarkan maksud klik pada baris. Menjadikan ruang kosong boleh memberi respons sepatutnya mengekalkan maksud itu dan pemilikan kawalan dalam baris.
| Tingkah laku yang dilihat pembaca | Titik permulaan yang sesuai | Batasan yang perlu dikekalkan |
|---|---|---|
| Seluruh baris melaksanakan satu tindakan | Button dengan label yang dikembangkan dan dibentuk |
Kekalkan satu pemilik tindakan untuk baris itu |
| Baris mewakili pilihan semasa | List dengan binding pilihan |
Biarkan senarai mengurus tingkah laku pilihan |
| Paparan tersuai memerlukan gerak isyarat klik yang berasingan | Paparan berbentuk dengan onTapGesture |
Kaitkan gerak isyarat pada kawasan yang dimaksudkan |
| Baris mengandungi beberapa kawalan bebas | Kawalan adik-beradik yang berasingan | Berikan sasaran tersendiri kepada setiap kawalan |
Untuk pemilihan senarai, gunakan model pilihan bekas sebelum menambah pengendali klik seluruh baris. Dokumentasi List Apple menerangkan binding kepada pengecam item pilihan untuk pemilihan tunggal dan set pengecam untuk pemilihan berbilang. Butang yang melaksanakan tindakan dan baris senarai yang menjadi pilihan ialah dua keperluan interaksi yang berbeza.
Gerak isyarat tetap sesuai apabila anda memang memerlukan pengecaman gerak isyarat pada paparan tersuai. Gunakan urutan geometri yang sama—padding dan bingkai, kemudian bentuk kandungan—sebelum melampirkan onTapGesture. Apple mendokumentasikan parameternya, count, sebagai bilangan ketikan atau klik yang diperlukan. Bentuk kandungan menyediakan kawasan sasaran; ia tidak menyediakan tindakan dengan sendirinya. Lihat onTapGesture(count:perform:).
Jika baris turut mengandungi butang atau suis yang berasingan, kekalkannya di luar label butang utama. Struktur yang berguna ialah tindanan mendatar yang mengandungi butang utama yang boleh dikembangkan dan kawalan berasingan di hujung. Ruang kosong pada label utama adalah milik tindakannya; kawalan di hujung memiliki kawasannya sendiri. Elakkan meletakkan kawalan interaktif bertingkat di dalam butang yang merangkumi seluruh baris.
Jangan tambah pengubah keutamaan gerak isyarat semata-mata untuk membaiki sasaran ruang kosong. Apple mendokumentasikan highPriorityGesture sebagai pengubah keutamaan, manakala simultaneousGesture membolehkan gerak isyarat diproses bersama. Operasi itu mengubah hubungan antara gerak isyarat dan boleh menjejaskan interaksi paparan turunan; operasi tersebut tidak menetapkan geometri baris yang tiada.
Diagnosis baris yang masih terlepas klik
Ikuti urutan ini pada versi terkecil baris anda. Urutan ini membezakan masalah saiz daripada masalah bentuk sasaran dan masalah paparan bertindih.
- Periksa sempadan sebenar label. Tambahkan
.border(Color.orange)buat sementara waktu sejurus selepas pengubah bingkai label. Jika sempadannya berakhir di sebelah teks, periksa cadangan lebar induk dan sebarang kekangan lebar tetap. - Periksa kedudukan pengubah. Pastikan bentuk kandungan meliputi label yang telah dikembangkan itu, termasuk padding yang ingin dijadikan boleh diklik.
- Periksa pemilik interaksi. Gunakan tindakan butang untuk baris butang. Buang gerak isyarat ketik baris yang berlebihan semasa mengasingkan masalah.
- Periksa hiasan yang bertindih. Periksa lapisan tindihan dan paparan adik-beradik di atas baris. Bagi hiasan yang tidak sepatutnya menerima input, pertimbangkan
.allowsHitTesting(false)pada hiasan itu sahaja. - Pulihkan kawalan lain satu demi satu. Uji kawasan setiap kawalan selepas memulihkannya, kemudian uji ruang kosong yang selebihnya.
Apple mendokumentasikan allowsHitTesting(_:) sebagai penentu sama ada sesuatu paparan mengambil bahagian dalam operasi pengujian sasaran. Menggunakannya pada seluruh baris akan mengeluarkan baris itu daripada penyertaan, jadi sasarkan paparan hiasan tertentu apabila itulah tingkah laku yang dimaksudkan.
Gunakan beberapa lokasi klik yang berbeza untuk mengesahkan hasilnya. Jadual ini menerangkan tingkah laku yang dijangka bagi program yang diberikan, bukannya hasil ujian yang diukur.
| Lokasi klik | Hasil yang dijangka |
|---|---|
| Petak berwarna atau tajuk baris | Aktifkan baris itu sekali |
| Ruang kosong di sebelah kanan, di dalam baris kelabu | Aktifkan baris itu sekali |
| Padding dalaman di atas atau di bawah tajuk | Aktifkan baris itu sekali |
| Jurang antara baris | Tiada pengaktifan baris |
| Padding luar atau kawasan kosong di bawah baris | Tiada pengaktifan baris |
Ubah saiz tetingkap dan ulangi pemeriksaan ruang kosong. Sahkan juga fokus papan kekunci dan pengaktifan menggunakan tetapan navigasi papan kekunci Mac anda. Pemeriksaan ini membantu memastikan komponen akhir berfungsi seperti kawalan yang dimaksudkan, bukan sekadar memberi respons kepada penunjuk.
Bilakah pengujian sasaran AppKit penting?
Untuk baris SwiftUI biasa, mulakan dengan API susun atur, bentuk kandungan dan kawalan SwiftUI. AppKit menjadi relevan apabila aplikasi anda menyertakan paparan asli tersuai atau paparan terbenam yang mengubah sasaran peristiwa.
Apple mendokumentasikan NSView.hitTest(_:) sebagai kaedah untuk mencari turunan terjauh yang mengandungi sesuatu titik. Tetingkap menggunakannya terutamanya untuk menentukan paparan yang menerima peristiwa tekan tetikus. Titik inputnya dinyatakan dalam sistem koordinat paparan supernya, dan Apple mengatakan bahawa panggilan langsung jarang diperlukan.
Jika anda menyelenggara paparan AppKit tersuai, periksa sempadan dan penggantian pengujian sasarannya pada sempadan itu. Bentuk kandungan SwiftUI bukan arahan untuk memintas pemilikan peristiwa paparan asli yang berasingan. Kekalkan pembetulan dalam hierarki paparan yang bertanggungjawab menerima klik itu.
Untuk baris dalam tutorial ini, cara yang disokong adalah mudah: biarkan label butang memenuhi lebar baris yang dimaksudkan, tetapkan bentuk interaksi segi empat tepatnya dan kekalkan kawalan lain di kawasan masing-masing. Ini menjadikan ruang kosong yang berguna boleh diklik sambil mengekalkan interaksi lain dalam tetingkap.
Sumber
- contentShape(_:eoFill:) — Apple
- contentShape(::eoFill:) — Apple
- interaction — Apple
- frame(minWidth:idealWidth:maxWidth:minHeight:idealHeight:maxHeight:alignment:) — Apple
- Button — Apple
- plain — Apple
- padding(::) — Apple
- Identifiable — Apple
- State — Apple
- List — Apple
- onTapGesture(count:perform:) — Apple
- highPriorityGesture(_:including:) — Apple
- simultaneousGesture(_:including:) — Apple
- allowsHitTesting(_:) — Apple
- hitTest(_:) — Apple