Bangun Kontrol Tersegmentasi SwiftUI yang Dapat Disesuaikan – Beragampengetahuan
Pada tahun 2022, akan ada lebih dari 4,5 juta aplikasi dan game di App Store. Banyaknya pilihan menjadikannya penting bagi aplikasi untuk menawarkan pengalaman baru yang segar atau menemukan cara lain untuk menonjol.
Membuat antarmuka yang unik dapat membantu menjadikan aplikasi lebih menarik dan sangat membantu dalam meningkatkan perolehan dan retensi pengguna. Menyesuaikan tampilan default kontrol atau membuat tab unik atau pengalih tema gelap/terang dapat membantu menjadikan aplikasi lebih menarik.
Dalam tutorial ini, kita akan mengeksplorasi cara membuat kontrol tersegmentasi yang dapat disesuaikan di SwiftUI. Pertama, kita akan menjelajahi skenario ini dengan membahas cara menggunakan SwiftUI Picker dengan gaya tersegmentasi. Kemudian, kita akan mengeksplorasi keterbatasannya. Akhirnya, kami akan membuat pemilih kami sendiri untuk penyesuaian dan penggunaan yang mudah.
Lompat ke depan:
Contents
prasyarat
Untuk mengikuti panduan ini, Anda harus memiliki yang berikut:
- Pengetahuan kerja tentang pengembangan iOS dan Swift
- Pengalaman membuat antarmuka pengguna dengan SwiftUI
mulai
Untuk mempelajari tentang proyek showcase SwiftUI Picker ini, lihat kode sumber terbuka di GitHub. Jika Anda ingin melompat langsung ke bagian tertentu, Anda dapat melihat berbagai cabang Git. Setiap bagian dari artikel ini memiliki cabang tertentu.
Berikut adalah penjelasan singkat tentang beberapa file penting yang harus Anda ketahui:
- Domain: mendefinisikan objek logika bisnis, dalam hal ini,
enumstruktur; Anda tidak perlu mengubah apa pun di direktori ini - Ekstensi: Berisi beberapa ekstensi praktis untuk artikel ini; Anda tidak perlu mengubah apa pun di direktori ini
- UI: Menyimpan semua komponen yang dapat digunakan kembali dalam proyek.Dalam hal ini berisi PickerPlus, picker yang dapat disesuaikan yang akan kita buat dalam tutorial ini
PickerLimitations.swift,StyledPicker.swift,DefaultPickerExamples.swift: Tampilan SwiftUI akan membantu memvisualisasikan teori yang dijelaskan dalam artikel ini
Menggunakan pemilih SwiftUI
Sebelum kita mulai membuat tampilan komponen kustom, mari kita lihat lebih dekat cara kerja Picker default SwiftUI. Ini akan membantu kami lebih memahami cara membuat tampilan yang mendukung banyak konfigurasi.
SwiftUI Picker adalah kontrol untuk memilih dari serangkaian nilai yang saling eksklusif. Mari kita lihat beberapa contoh Picker: sederhana, kompleks, dan tersegmentasi.
Buat pemilih sederhana
Tampilan ini juga memiliki sejumlah besar penginisialisasi untuk kita pilih.ini init(_:selection:content:) Penginisialisasi adalah pilihan yang baik untuk Picker sederhana. Kami menggunakan ini saat kami ingin pengguna dapat memilih dari daftar opsi.
Misalkan kita memiliki daftar opsi transportasi (misalnya sepeda, mobil, pesawat, atau roket) dan kita ingin pengguna memilih preferensi mereka.Membuka DefaultPickerExamples.swift file dan rekatkan kode berikut pada baris 19 untuk digunakan init(_:selection:content:) Penginisialisasi:
//swift
Text("SwiftUI Picker: Simple")
Picker("Types of Vehicles", selection: $selectedItem) {
ForEach(Vehicles.allCases) { vehicle in
Text(vehicle.rawValue.capitalized)
}
}
.padding()
Berikut pratinjau kodenya, menggunakan kanvas pratinjau SwiftUI Xcode:

Ini adalah cara yang sangat sederhana untuk menampilkan menu dropdown. Kami juga dapat memilih pendekatan yang berbeda untuk mendukung skenario yang lebih kompleks. Mari kita lihat contoh lain.
Bangun pemilih yang kompleks
Katakanlah kita memiliki beberapa kendaraan dan ingin menampilkannya di Picker sehingga pengguna dapat memilih daftar jenis kendaraan yang ingin dipilih.
Salin kode berikut dan tempel di baris 27:
//swift
Text("SwiftUI Picker: Complex")
Picker("Owned Vehicles", sources: $ownedVehicles, selection: \.vehicle) {
ForEach(Vehicles.allCases) { vehicle in
Text(vehicle.rawValue.capitalized)
}
}
.padding()
Sekarang, jika kita melihat pratinjau, kita akan melihat sesuatu seperti ini:

Bangun pemilih tersegmentasi
Kita dapat menggunakan pickerStyle untuk menentukan bagaimana Picker ditampilkan (menu, wheel, segmented, DLL. ).Untuk contoh ini, kita akan memilih segmented. Silakan tambahkan kode ini ke DefaultPickerExamples Pada baris 35:
//swift
Text("SwiftUI Picker: Segmented")
Picker("Types of Vehicles - Segmented", selection: $selectedItem) {
ForEach(Vehicles.allCases) { vehicle in
Text(vehicle.rawValue.capitalized)
}
}
.pickerStyle(.segmented)
.padding()
Kanvas pratinjau akan menampilkan sesuatu seperti ini:

ini ViewModifier Memungkinkan kita menyetel gaya berdasarkan konteks seputar kontrol.Untuk artikel ini, kami akan fokus .segmented gaya dan jelajahi keterbatasannya.
Pahami keterbatasan SwiftUI Picker
Gunakan pemilih default SwiftUI dengan .segmented gaya mungkin merupakan pilihan yang nyaman, tetapi ada beberapa batasan yang harus diperhatikan. Pemilih default tidak dapat menampilkan lebih dari satu baris teks atau menampilkan item vertikal. Selain itu, menata Picker default tidak ramah SwiftUI.
batas tampilan
ini UISegmentedControl adalah dasar dari setiap Picker .segmented gaya, dan begitu juga dibatasi oleh itu. Misalnya, jika kami mencoba menyetel item khusus dengan ketinggian berbeda, Pemilih default tidak akan menampilkannya dengan benar.
Untuk melihat bagaimana pemilih default menangani item vertikal, buka file PickerLimitations.swift file dan tempel kode berikut menggantikan TODO di baris 15:
//swift
Text("SwiftUI Picker: Vertical Items")
Picker("Types of Vehicles", selection: $selectedItem) {
ForEach(Vehicles.allCases) { vehicle in
VStack {
Text(vehicle.rawValue.capitalized)
vehicle.indicatorImage
.resizable()
.frame(width: 24, height: 24)
.scaledToFit()
}
}
}
.pickerStyle(.segmented)
.padding()
// TODO: Uncomment the following line after applying custom styles to `Picker`
// StyledPicker()
Sekarang, lihat pratinjaunya, seharusnya terlihat seperti ini:

secara default, UISegmentedControl Menentukan ketinggian tampilan.Masalah lainnya adalah pemilih disejajarkan pada saat yang bersamaan Text Dan Image sebagai pilihan.Sehingga tampilan tidak berperilaku seperti yang diharapkan saat setiap tampilan dipilih Text atau Image terkandung dalam.
kendala gaya
Masalah lain dengan pemilih default SwiftUI adalah opsi gaya sangat terbatas.kita dapat mencoba untuk menambahkan ViewModifiers ke Picker, tetapi pengaruhnya kecil pada Tampilan.Cara paling andal untuk menata pemilih adalah dengan menggunakan UIAppearance Mengatur gaya pemilih default.Sulit untuk memahami kode yang diperlukan untuk memodifikasi Picker karena Anda mungkin akan menggabungkan keduanya UIAppearance Dan ViewModifierdalam aplikasi Anda.
Membuka StyledPicker.swift Arsipkan dan lihat pratinjau; Anda akan melihat yang berikut:

Meskipun dikonfigurasi accentColor Di pemilih, pratinjau tidak menunjukkan bukti visual warna apa pun. Ini karena Picker default tidak menggunakan banyak sistem warna bawaan SwiftUI.
Untuk mengubah gaya Picker, kita harus menimpa UISegmentedControl.Kita bisa menambahkan penginisialisasi StyledPicker Seperti ini:
//swift
init() {
// Sets the background color of the Picker
UISegmentedControl.appearance().backgroundColor = .red.withAlphaComponent(0.15)
// Disappears the divider
UISegmentedControl.appearance().setDividerImage(UIImage(), forLeftSegmentState: .normal, rightSegmentState: .normal, barMetrics: .default)
// Changes the color for the selected item
UISegmentedControl.appearance().selectedSegmentTintColor = .red
// Changes the text color for the selected item
UISegmentedControl.appearance().setTitleTextAttributes([.foregroundColor: UIColor.white], for: .selected)
}
Berikut pratinjau yang menampilkan gaya baru Picker:

Ini bukan pendekatan yang paling intuitif karena kami sedang membuat Picker menggunakan SwiftUI. Kode yang ditambahkan umum di aplikasi yang menggunakan UIKit, bukan SwiftUI, yang membuat sintaksnya sedikit membingungkan.
Juga, ada batasan untuk apa yang dapat kami sesuaikan. Kontrol juga memiliki bayangannya sendiri di atas latar belakang, memberikan tampilan yang tidak akurat. Ini menghasilkan warna latar belakang yang lebih gelap.
Buka sekarang PickerLimitations.swift Komit file lagi dan batalkan komentar pada baris 32. Anda akan melihat sesuatu seperti ini:

penampilan tertutup UISegmentedControl akan mengesampingkan tampilan layar untuk semua pemilih – bukan hanya satu. Ini tidak ideal karena gayanya tidak disesuaikan untuk tampilan yang kita terapkan. Perilaku seperti ini rawan kesalahan dan membatasi kemampuan kita untuk memperpanjang kode kita. Itu juga dapat menyebabkan pengalaman pengembang yang buruk.
Buat pemilih yang dapat disesuaikan
Sekarang setelah kita memiliki gagasan yang jelas tentang masalah dan batasan dari SwiftUI Picker, mari kita atasi beberapa di antaranya dengan membuat pemilih yang dapat disesuaikan sendiri—kita akan menyebutnya PickerPlus.
Ayo mulai!
Membuka PickerPlus.swift file dan ganti TODO pada baris 4 dengan kode berikut:
//swift
public let sources: [Data]
public let selection: Data?
private let itemBuilder: (Data) -> Content
// TODO: Add default background
// TODO: Add borders and corner radius.
// TODO: Add support for custom indicators
public init(
_ sources: [Data],
selection: Data?,
@ViewBuilder itemBuilder: @escaping (Data) -> Content
) {
self.sources = sources
self.selection = selection
self.itemBuilder = itemBuilder
}
Mirip dengan penginisialisasi untuk pemilih default, kami memiliki tiga properti berbeda PickerPlus:
sources: Susunan data yang akan diulangi oleh PickerPlusselection: item nullable yang seharusnya dimilikisources; Ini membantu untuk menentukan indeks apa yang saat ini dipilih saat merancang dan memposisikan indikatoritemBuilder: Fungsi yang digunakan untuk membuat Tampilan yang sesuai dengan setiap item di dalamnyaPickerPlus; Itu dapat mendukung konfigurasi yang berbeda
Sekarang ganti TODO pada baris 29 dengan yang berikut:
//swift
HStack(spacing: 0) {
ForEach(sources, id: \.self) { item in
itemBuilder(item)
}
}
Di sini kami sedang membangun tampilan yang diperlukan untuk menampilkan opsi yang tersedia di pemilih.Ini dilakukan dengan iterasi sources dan gunakan itemBuilder.
Mari tambahkan contoh visualisasi PickerPlus Lihat aksinya. Ganti TODO pada baris 50 dengan yang berikut:
//swift
Text("Using an enum")
PickerPlus(
Vehicles.allCases,
selection: selectedItem
) { item in
Text(item.rawValue.capitalized)
.font(Font.footnote.weight(.medium))
.foregroundColor(selectedItem == item ? .white : nil)
.padding(.vertical, 8)
.padding(.horizontal, 8)
.frame(maxWidth: .infinity)
.multilineTextAlignment(.center)
.onTapGesture {
withAnimation(.easeInOut(duration: 0.150)) {
selectedItem = item
}
}
}
.accentColor(.green)
.padding()
Di bawah ini adalah pratinjau PickerPlus. Pengguna dapat memilih item apa pun dan melihat perubahan pratinjau:

Terapkan latar belakang default
teks yang digunakan untuk setiap opsi di atas PickerPlus pratinjau memiliki beberapa gaya, tetapi opsi yang dipilih tidak terlihat. Mari perbaiki ini dengan menambahkan latar belakang.
Ganti todo pada baris 8 dengan kode berikut:
//swift
@State private var backgroundColor: Color = Color.black.opacity(0.05)
func pickerBackgroundColor(_ color: Color) -> PickerPlus {
var view = self
view._backgroundColor = State(initialValue: color)
return view
}
Sekarang, lewati ke baris 40 dan ubah ke baris berikut:
//swift
.background(
RoundedRectangle(cornerRadius: 6.0)
.fill(backgroundColor)
)
Sekarang, jika Anda melihat kembali pratinjau, Anda akan melihat sesuatu seperti ini:

Dukungan untuk jari-jari sudut dan batas
Selanjutnya, mari tambahkan beberapa jari-jari sudut dan batas pendukung ke tampilan pemetik khusus kita; ini akan memungkinkan lebih banyak gaya untuk kita PickerPlus.
Pertama ganti todo di baris 16 dengan yang berikut:
//swift
@State private var cornerRadius: CGFloat?
func cornerRadius(_ cornerRadius: CGFloat) -> PickerPlus {
var view = self
view._cornerRadius = State(initialValue: cornerRadius)
return view
}
@State private var borderColor: Color?
func borderColor(_ borderColor: Color) -> PickerPlus {
var view = self
view._borderColor = State(initialValue: borderColor)
return view
}
@State private var borderWidth: CGFloat?
func borderWidth(_ borderWidth: CGFloat) -> PickerPlus {
var view = self
view._borderWidth = State(initialValue: borderWidth)
return view
}
Ini akan mengaktifkan fungsionalitas modifikasi baru untuk kita PickerPlus. Sekarang kita perlu mengubah RoundedRectangle Opsi batas dan radius sudut didukung saat menggambar latar belakang.
Mengubah .background Tambahkan baris berikut ke baris 62:
//swift
.background(
RoundedRectangle(cornerRadius: cornerRadius ?? 6.0)
.fill(
backgroundColor,
strokeBorder: borderColor ?? Color.clear,
lineWidth: borderWidth ?? .zero
)
)
Menggunakan kode ini, kami mengaktifkan PickerPlus Mendukung warna batas khusus, lebar batas, dan radius sudut.Kami juga menentukan nilai default cornerRadius 6pt, mirip dengan default yang disediakan oleh SwiftUI Picker.
Sekarang lihat pratinjau dan Anda akan melihat pengaturan default cornerRadius Diterapkan ke latar belakang. Coba pratinjau dan tambahkan batas dan latar belakang khusus ke dalamnya. Berikut pratinjau yang menunjukkan tampilannya:

Tambahkan tampilan metrik
Sejauh ini, kami PickerPlus Terlihat bagus, tetapi ada satu bagian penting yang hilang: indikator pemilihan. Jika kami ingin menyempurnakan pengaturan default yang tersedia untuk SwiftUI Picker, tampilan ini harus memenuhi persyaratan berikut:
- Menganimasikan posisi saat pemilihan berubah
- Periksa dan terapkan warna aksen
- Dukungan untuk implementasi khusus
Untuk mendukung persyaratan ini, mari perbarui todo pada baris 40 dengan kode berikut:
//swift
private var customIndicator: AnyView? = nil
public init(
_ sources: [Data],
selection: Data?,
indicatorBuilder: @escaping () -> some View,
@ViewBuilder itemBuilder: @escaping (Data) -> Content
) {
self.sources = sources
self.selection = selection
self.itemBuilder = itemBuilder
self.customIndicator = AnyView(indicatorBuilder())
}
Di sini kami menambahkan a indicator — Ini akan memungkinkan kami untuk mendukung indikator khusus. Faktanya, penginisialisasi khusus mengaktifkan dukungan untuk ini.itu membungkus indicatorBuilder Dan AnyView Dan memungkinkan kita untuk membangun indikator apapun yang kita inginkan.
Sekarang, mari ubah todo pada baris 66 dengan kode berikut:
//swift
if let selection = selection, let selectedIdx = sources.firstIndex(of: selection) {
if let customIndicator = customIndicator {
customIndicator
} else {
GeometryReader { geo in
RoundedRectangle(cornerRadius: cornerRadius ?? 6.0)
.foregroundColor(.accentColor)
.padding(EdgeInsets(top: borderWidth ?? 2, leading: borderWidth ?? 2, bottom: borderWidth ?? 2, trailing: borderWidth ?? 2))
.frame(width: geo.size.width / CGFloat(sources.count))
.shadow(color: .black.opacity(0.1), radius: 2, x: 1, y: 1)
.animation(.spring().speed(1.5))
.offset(x: geo.size.width / CGFloat(sources.count) * CGFloat(selectedIdx), y: 0)
}.frame(height: 32)
}
}
Dengan menggunakan kode ini, kami:
- periksa apakah
selectiondiatur dan menegaskan bahwa itu milik proyeksourcesDengan cara ini kita hanya merender indikator saat dibutuhkan, yang juga merupakan kondisi default di Picker - menentukan apakah
PickerPlusharus merendercustomIndicatoratau implementasi default - Tambahkan implementasi default yang menganimasikan posisinya dan memeriksa arus
.accentColor
Terakhir, mari tambahkan contoh untuk ditampilkan indicatorBuilder Bangun metrik khusus.ganti kode di <body> dari PreviewPickerPlus dengan konten sebagai berikut:
//swift
VStack {
Text("Custom Picker: Vintage Style")
PickerPlus(
Vehicles.allCases,
selection: selectedItem
) { item in
Text(item.rawValue.capitalized)
.font(Font.footnote.weight(.medium))
.foregroundColor(selectedItem == item ? .white : nil)
.padding(.vertical, 8)
.padding(.horizontal, 8)
.frame(maxWidth: .infinity)
.multilineTextAlignment(.center)
.onTapGesture {
withAnimation(.easeInOut(duration: 0.150)) {
selectedItem = item
}
}
}
.pickerBackgroundColor(.blue.opacity(0.15))
.cornerRadius(0)
.borderWidth(1)
.borderColor(.blue)
.accentColor(.blue)
.padding()
Text("Custom Picker: Vertical Items")
PickerPlus(
Vehicles.allCases,
selection: selectedItem,
indicatorBuilder: {
GeometryReader { geo in
Rectangle()
.foregroundColor(.white)
.cornerRadius(6.0)
.padding(1)
.frame(width: geo.size.width / CGFloat(Vehicles.allCases.count))
.shadow(color: .black.opacity(0.1), radius: 2, x: 1, y: 1)
.animation(.spring().speed(1.5))
.offset(x: geo.size.width / CGFloat(Vehicles.allCases.count) * CGFloat(Vehicles.allCases.firstIndex(of: selectedItem!)!), y: 0)
}.frame(height: 64)
}
) { item in
VerticalItem(
item: item,
isSelected: selectedItem == item
)
.padding(.vertical, 8)
.onTapGesture {
withAnimation(.easeInOut(duration: 0.150)) {
selectedItem = item
}
}
}
.padding()
}
Berikut pratinjau yang menunjukkan tampilan metrik:

Dan, itu satu paket!
Saya harap Anda menikmati tutorial ini dan memperoleh pemahaman yang lebih baik tentang cara menggunakan SwiftUI untuk membuat kontrol tersegmentasi yang dapat disesuaikan untuk aplikasi iOS Anda. Jika Anda memiliki pertanyaan atau komentar, jangan ragu untuk meninggalkannya di bagian komentar di bawah.
Artikel Membangun Kontrol Tersegmentasi yang Dapat Disesuaikan untuk SwiftUI muncul pertama kali di Blog beragampengetahuan.
Dari Blog beragampengetahuan https://ift.tt/GfgPmJb
Hasilkan $200 seminggu
dengan lebih banyak membaca
rencana pengembangan website
metode pengembangan website
jelaskan beberapa rencana untuk pengembangan website, proses pengembangan website, kekuatan dan kelemahan bisnis pengembangan website
, jasa pengembangan website, tahap pengembangan website, biaya pengembangan website
#Bangun #Kontrol #Tersegmentasi #SwiftUI #yang #Dapat #Disesuaikan