Neomorfisme menggunakan SwiftUI. Bagian 2: Apa yang dapat dilakukan dengan aksesibilitas?

Halo semuanya! Untuk mengantisipasi dimulainya kursus lanjutan "Pengembang iOS", kami menerbitkan terjemahan dari bagian kedua artikel tentang neomorfisme menggunakan SwiftUI ( baca bagian pertama ).





Tema gelap


Sebelum kita mulai memahami bagaimana kita dapat meningkatkan ketersediaan neomorfisme, mari kita lihat bagaimana kita dapat bekerja dengan efeknya untuk menciptakan gaya menarik lainnya.

Pertama tambahkan dua warna lagi ke ekstensi Colorsehingga kami memiliki beberapa nilai konstan:

static let darkStart = Color(red: 50 / 255, green: 60 / 255, blue: 65 / 255)
static let darkEnd = Color(red: 25 / 255, green: 25 / 255, blue: 30 / 255)

Kita dapat menggunakannya sebagai latar belakang untuk ContentViewmenggantikan yang sudah ada Color.white, seperti yang ditunjukkan di sini:

var body: some View {
    ZStack {
        LinearGradient(Color.darkStart, Color.darkEnd)

Kami SimpleButtonStylesekarang terlihat tidak pada tempatnya, karena memaksakan gaya yang cerah pada latar belakang yang gelap. Jadi, kita akan membuat gaya gelap baru yang berfungsi lebih baik di sini, tapi kali ini kita akan membaginya menjadi dua bagian: tampilan latar belakang yang bisa kita gunakan di mana saja, dan gaya tombol yang membungkusnya dengan padding dan pengubah contentShape. Ini akan memberi kami lebih banyak fleksibilitas, seperti yang akan Anda lihat nanti.

Tampilan latar belakang baru yang akan kita tambahkan akan memungkinkan kita menentukan bentuk apa pun untuk efek visual kita, jadi kita tidak lagi terikat pada lingkaran. Ini juga akan melacak apakah akan mencek efek cembung kami (dalam atau luar), tergantung pada properti isHighlightedyang dapat kita ubah dari luar.

Kita akan mulai dengan yang paling sederhana, menggunakan pendekatan bayangan flip yang dimodifikasi untuk mendapatkan efek cekung. Tambahkan struktur ini:

struct DarkBackground<S: Shape>: View {
    var isHighlighted: Bool
    var shape: S

    var body: some View {
        ZStack {
            if isHighlighted {
                shape
                    .fill(Color.darkEnd)
                    .shadow(color: Color.darkStart, radius: 10, x: 5, y: 5)
                    .shadow(color: Color.darkEnd, radius: 10, x: -5, y: -5)

            } else {
                shape
                    .fill(Color.darkEnd)
                    .shadow(color: Color.darkStart, radius: 10, x: -10, y: -10)
                    .shadow(color: Color.darkEnd, radius: 10, x: 10, y: 10)
            }
        }
    }
}

Modifikasi adalah bahwa ketika tombol ditekan, ukuran bayangan berkurang - kami menggunakan jarak 5 poin, bukan 10.

Kemudian kita dapat membungkusnya dengan bantuan DarkButtonStylepadding dan contentShape, seperti yang ditunjukkan di sini:

struct DarkButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .padding(30)
            .contentShape(Circle())
            .background(
                DarkBackground(isHighlighted: configuration.isPressed, shape: Circle())
            )
    }
}

Akhirnya, kita bisa menerapkan ini pada tombol kita ContentViewdengan mengubahnya ButtonStyle():

.buttonStyle(DarkButtonStyle())

Mari kita lihat apa yang terjadi - walaupun kita tidak memiliki banyak kode, saya pikir hasilnya terlihat cukup baik.



Beberapa eksperimen


Sekarang adalah waktu untuk bereksperimen dengan efeknya, karena itu akan membantu Anda lebih memahami apa yang secara spesifik mampu dilakukan oleh SwiftUI.

Sebagai contoh, kita dapat membuat tombol cembung halus dengan menambahkan gradien linier dan membaliknya ketika ditekan:

if isHighlighted {
    shape
        .fill(LinearGradient(Color.darkEnd, Color.darkStart))
        .shadow(color: Color.darkStart, radius: 10, x: 5, y: 5)
        .shadow(color: Color.darkEnd, radius: 10, x: -5, y: -5)

} else {
    shape
        .fill(LinearGradient(Color.darkStart, Color.darkEnd))
        .shadow(color: Color.darkStart, radius: 10, x: -10, y: -10)
        .shadow(color: Color.darkEnd, radius: 10, x: 10, y: 10)
}

Jika Anda menjalankan ini, Anda akan melihat bahwa tombol dengan lancar menjulang ke atas dan ke bawah saat ditekan dan dilepaskan. Saya pikir animasi adalah sedikit mengganggu, jadi saya sarankan nonaktifkan dengan menambahkan pengubah ini untuk metode makeBody()dari DarkButtonStyle, setelah pengubah hadir di sana background():

.animation(nil)



Efek tombol bantalan ini menarik, tetapi jika Anda berencana untuk menggunakannya, saya akan menyarankan Anda untuk mencoba tiga perubahan berikut untuk membuat tombol lebih menonjol.

Pertama, terlepas dari kenyataan bahwa ini bertentangan dengan prinsip kontras rendah desain neomorfik, saya akan mengganti ikon abu-abu dengan yang putih untuk membuatnya menonjol. Jadi, ContentViewAnda perlu yang berikut ini:

Image(systemName: "heart.fill")
    .foregroundColor(.white)

Kedua, jika Anda menambahkan overlay untuk tombol dalam keadaan ditekan, ini tidak hanya akan membuatnya lebih mirip tombol fisik nyata yang ditekan secara merata, tetapi juga akan membantu membedakan keadaan yang ditekan dari yang tidak ditekan.

Untuk melaksanakan ini, Anda perlu untuk memasukkan modifikator overlay()setelah fill()ketika isHighlighteditu benar, seperti di sini:

if isHighlighted {
    shape
        .fill(LinearGradient(Color.darkEnd, Color.darkStart))
        .overlay(shape.stroke(LinearGradient(Color.darkStart, Color.darkEnd), lineWidth: 4))
        .shadow(color: Color.darkStart, radius: 10, x: 5, y: 5)
        .shadow(color: Color.darkEnd, radius: 10, x: -5, y: -5)



Untuk mendapatkan tampilan yang lebih tajam, Anda dapat menghapus dua pengubah shadow()untuk kondisi penekanan yang berfokus pada overlay.

Ketiga, Anda juga dapat menambahkan overlay ke kondisi tidak tertekan, hanya untuk menandai bahwa itu adalah tombol. Taruh segera setelah itu fill(), seperti:

} else {
    shape
        .fill(LinearGradient(Color.darkStart, Color.darkEnd))
        .overlay(shape.stroke(Color.darkEnd, lineWidth: 4))
        .shadow(color: Color.darkStart, radius: 10, x: -10, y: -10)
        .shadow(color: Color.darkEnd, radius: 10, x: 10, y: 10)
}



Menambahkan Switch Style


Salah satu keuntungan memisahkan gaya tombol dari gaya latar belakang non-morfik adalah bahwa sekarang kita dapat menambahkan gaya sakelar menggunakan efek yang sama. Ini berarti membuat struktur ToggleStyleyang sesuai dengan protokol baru yang serupa dengan ButtonStyle, kecuali bahwa:

  1. Kita perlu membaca configuration.isOnuntuk menentukan apakah saklar menyala.
  2. Kita perlu menyediakan tombol untuk menangani tindakan switching, atau setidaknya sesuatu seperti onTapGesture()atau sesuatu seperti itu.

Tambahkan struktur ini ke proyek Anda:

struct DarkToggleStyle: ToggleStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        Button(action: {
            configuration.isOn.toggle()
        }) {
            configuration.label
                .padding(30)
                .contentShape(Circle())
        }
        .background(
            DarkBackground(isHighlighted: configuration.isOn, shape: Circle())
        )
    }
}

Kami ingin memasukkan salah satunya ContentViewsehingga Anda dapat mengujinya sendiri, jadi mulailah dengan menambahkan properti ini:

@State private var isToggled = false

Kemudian bungkus tombol yang ada VStackdengan spasi sama dengan 40 dan letakkan di bawah ini:

Toggle(isOn: $isToggled) {
    Image(systemName: "heart.fill")
        .foregroundColor(.white)
}
.toggleStyle(DarkToggleStyle())

Struktur Anda ContentViewakan terlihat seperti ini:

struct ContentView: View {
    @State private var isToggled = false

    var body: some View {
        ZStack {
            LinearGradient(Color.darkStart, Color.darkEnd)

            VStack(spacing: 40) {
                Button(action: {
                    print("Button tapped")
                }) {
                    Image(systemName: "heart.fill")
                        .foregroundColor(.white)
                }
                .buttonStyle(DarkButtonStyle())

                Toggle(isOn: $isToggled) {
                    Image(systemName: "heart.fill")
                        .foregroundColor(.white)
                }
                .toggleStyle(DarkToggleStyle())
            }
        }
        .edgesIgnoringSafeArea(.all)
    }
}

Dan itu saja - kami menerapkan desain neomorfik bersama di dua tempat!

Peningkatan aksesibilitas


Kami memiliki cukup waktu untuk bermain dengan berbagai gaya neomorfik, tetapi sekarang saya ingin memikirkan masalah desain ini: kurangnya kontras yang ekstrim berarti bahwa tombol dan kontrol penting lainnya tidak cukup untuk menonjol dari lingkungan mereka, yang membuatnya sulit untuk menggunakan aplikasi kami untuk orang dengan visi yang tidak sempurna.

Ini adalah momen di mana saya mengamati beberapa kesalahpahaman, jadi saya ingin mengatakan beberapa hal sebelumnya:

  1. Ya, saya mengerti bahwa tombol Apple standar terlihat seperti teks biru dan karena itu tidak menyerupai tombol yang akrab, setidaknya pada pandangan pertama, tetapi mereka memiliki rasio kontras yang tinggi.
  2. ยซ , , ยป โ€” โ€” ยซ ยป, , , - .
  3. - SwiftUI, , VoiceOver Apple.

Anda telah melihat bagaimana kami mengubah ikon abu-abu menjadi putih untuk mendapatkan peningkatan kontras instan, tetapi tombol dan sakelar masih membutuhkan lebih banyak kontras jika Anda ingin membuatnya lebih mudah diakses.

Jadi, kita akan mempertimbangkan perubahan apa yang bisa kita lakukan sehingga elemen-elemennya benar-benar menonjol.

Pertama, saya ingin Anda menambahkan dua warna baru ke ekstensi kami:

static let lightStart = Color(red: 60 / 255, green: 160 / 255, blue: 240 / 255)
static let lightEnd = Color(red: 30 / 255, green: 80 / 255, blue: 120 / 255)

Kedua, duplikat yang sudah ada DarkBackgrounddan beri nama salinan ColorfulBackground. Kami akan menghadapinya sebentar lagi, tetapi sekali lagi, pertama-tama kita perlu melakukan beberapa persiapan.

Ketiga, duplikat gaya gelap tombol dan beralih, ganti nama mereka menjadi ColorfulButtonStyledan ColorfulToggleStyle, dan kemudian buat mereka menggunakan yang baru ColorfulBackgroundsebagai latar belakang.

Jadi mereka akan terlihat seperti ini:

struct ColorfulButtonStyle: ButtonStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
            .padding(30)
            .contentShape(Circle())
            .background(
                ColorfulBackground(isHighlighted: configuration.isPressed, shape: Circle())
            )
            .animation(nil)
    }
}

struct ColorfulToggleStyle: ToggleStyle {
    func makeBody(configuration: Self.Configuration) -> some View {
        Button(action: {
            configuration.isOn.toggle()
        }) {
            configuration.label
                .padding(30)
                .contentShape(Circle())
        }
        .background(
            ColorfulBackground(isHighlighted: configuration.isOn, shape: Circle())
        )
    }
}

Dan akhirnya, edit tombol dan beralih ContentViewuntuk menggunakan gaya baru:

Button(action: {
    print("Button tapped")
}) {
    Image(systemName: "heart.fill")
        .foregroundColor(.white)
}
.buttonStyle(ColorfulButtonStyle())

Toggle(isOn: $isToggled) {
    Image(systemName: "heart.fill")
        .foregroundColor(.white)
}
.toggleStyle(ColorfulToggleStyle())

Anda dapat menjalankan aplikasi jika Anda mau, tetapi itu tidak masuk akal - sebenarnya belum berubah.

Untuk menghadirkan versi kehidupan kita yang penuh warna, kita akan mengubah modifikator fill()dan overlay()untuk kondisi yang ditekan dan tidak tertekan. Jadi, ketika isHighlightedbenar, ubah darkStartkeduanya darkEndmenjadi lightStartdan lightEnd, seperti ini:

if isHighlighted {
    shape
        .fill(LinearGradient(Color.lightEnd, Color.lightStart))
        .overlay(shape.stroke(LinearGradient(Color.lightStart, Color.lightEnd), lineWidth: 4))
        .shadow(color: Color.darkStart, radius: 10, x: 5, y: 5)
        .shadow(color: Color.darkEnd, radius: 10, x: -5, y: -5)

Jika Anda menjalankan aplikasi lagi, Anda akan melihat bahwa itu telah meningkat secara signifikan: keadaan yang ditekan sekarang memiliki warna biru cerah, sehingga menjadi jelas ketika tombol ditekan dan sakelar aktif. Tapi kita bisa melakukan sesuatu yang lain - kita bisa menambahkan warna yang sama di sekitar tombol ketika tidak ditekan, membantu menarik perhatian padanya.



Untuk melakukan ini, ubah status overlay()tidak stres yang ada menjadi ini:

.overlay(shape.stroke(LinearGradient(Color.lightStart, Color.lightEnd), lineWidth: 4))


Jadi, gaya tombol yang sudah selesai akan terlihat seperti ini:

ZStack {
    if isHighlighted {
        shape
            .fill(LinearGradient(Color.lightEnd, Color.lightStart))
            .overlay(shape.stroke(LinearGradient(Color.lightStart, Color.lightEnd), lineWidth: 4))
            .shadow(color: Color.darkStart, radius: 10, x: 5, y: 5)
            .shadow(color: Color.darkEnd, radius: 10, x: -5, y: -5)
    } else {
        shape
            .fill(LinearGradient(Color.darkStart, Color.darkEnd))
            .overlay(shape.stroke(LinearGradient(Color.lightStart, Color.lightEnd), lineWidth: 4))
            .shadow(color: Color.darkStart, radius: 10, x: -10, y: -10)
            .shadow(color: Color.darkEnd, radius: 10, x: 10, y: 10)
    }
}

Sekarang jalankan aplikasi lagi, dan Anda akan melihat bahwa cincin biru telah muncul di sekitar tombol dan switch, dan ketika diklik itu diisi dengan biru - itu jauh lebih mudah diakses.



Kesimpulan


Dalam praktiknya, Anda tidak akan memiliki beberapa gaya tombol yang berbeda dalam satu proyek, setidaknya jika Anda tidak suka membuat sakit kepala untuk pengguna Anda. Tetapi ini adalah ruang yang menarik untuk bereksperimen, dan saya harap Anda menangkap ide artikel saya ini, karena Anda dapat menciptakan efek yang sangat indah tanpa merobek punggung Anda.

Saya telah berulang kali mengatakan bahwa Anda harus selalu memantau ketersediaan aplikasi Anda, dan itu berarti lebih dari sekadar memastikan VoiceOver berfungsi dengan antarmuka pengguna Anda. Pastikan tombol Anda terlihat interaktif, pastikan label dan ikon teks Anda memiliki rasio kontras yang cukup dengan latar belakang (setidaknya 4,5: 1, tetapi cenderung 7: 1), dan pastikan area yang dapat diklik Anda nyaman dan besar (setidaknya 44x44 piksel).

Dan demi Tuhan, gunakan desain neomorfik untuk bereksperimen dan memperluas pengetahuan Anda tentang SwiftUI, tetapi jangan pernah lupa bahwa jika Anda mengorbankan kegunaan untuk tren desain mode baru, Anda tidak memenangkan apa pun.

Dapatkan kode sumber lengkap untuk proyek ini bisa di GitHub w

Baca bagian pertama.



Pelajari lebih lanjut tentang kursus.



All Articles