Özel görünüm değiştiriciler oluşturma yeteneği SwiftUI'da güçlü bir özelliktir. Bu makalede, bu özelliğin kullanıcı arayüzü oluşturmayı çok daha kolay hale getirmek için nasıl kullanılabileceğine dair örnekleri ele alacağız. SwiftUI'daki ViewModifiers'a ve özel görünümlerin nasıl oluşturulacağına aşina değilseniz, bunlar hakkında buradan bilgi alabilirsiniz.
Bu makalenin amacı, SwiftUI'da özel değiştiriciler ve stiller oluşturmanın farklı yollarından bazılarını ve bunların temiz ve tutarlı bir nihai çıktı elde ederken kullanıcı arayüzü oluşturmayı daha bildirimsel hale getirmek için nasıl kullanılabileceğini ele almaktır.
Oluşturmak istediğimiz son kullanıcı arayüzü şudur:
Ekrandaki tüm bileşenleri tek tek ele alalım:
Bu ekranı herhangi bir değiştirici olmadan oluşturursanız kod şuna benzer:
struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .resizable() .aspectRatio(contentMode: .fill) .frame(minWidth: 0, maxWidth: .infinity) .frame(height: 220) .cornerRadius(12) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) Spacer() Button(action: { }) { Text("Label") .font(.system(size: 14, weight: .medium)) } .frame(minWidth: 0, maxWidth: .infinity) .padding(.horizontal, 10) .padding(.vertical, 12) .background(Color.blue) .foregroundColor(Color.white) .cornerRadius(12) } .padding(.all, 16) } }
Bazı öğelerin stilinin (örneğin başlık ve ayrıntı metinleri) kopyalanması gerekir
Yaygın stillerden bazılarında (eleman dolgusu, köşe yarıçapı vb.) değişikliklerin birden fazla yerde yapılması gerekir
Artık bu sorunu UIKit yöntemiyle özel görünümler oluşturarak çözebilirsiniz, ancak ben bu yaklaşımın hayranı değilim çünkü yerleşik Görünümlerden uzaklaşmayı içeriyordu ve yeni ekip üyelerinin katılımını daha sürtünmeli hale getiriyor. Daha kolay bir yol, stillerin kendisi yerine uygulanabilecek bazı evrensel görünüm değiştiricileri tanımlamak olacaktır.
İhtiyacımız olan ortak stili inceleyelim:
Köşe yarıçapıyla başlayalım:
struct CommonCornerRadius: ViewModifier { func body(content: Content) -> some View { content .cornerRadius(12) } }
Bu oldukça basittir; elemanlar için evrensel bir köşe yarıçapı uygulamamıza olanak tanır. Bu, özel Görünümler oluşturmaya veya kod tabanında birden fazla değişiklik yapmaya gerek kalmadan uygulama stillerini genel olarak değiştirmeyi kolaylaştırır.
struct FullWidthModifier: ViewModifier { func body(content: Content) -> some View { content .frame(minWidth: 0, maxWidth: .infinity) } }
Bu, tam genişlikli görünümlerin uygulanmasını kolaylaştırır; artık .frame
manuel olarak eklemeye gerek kalmaz!
struct TitleTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("titleTextColor")) .font(.system(size: 20, weight: .bold)) } } struct BodyTextModifier: ViewModifier { func body(content: Content) -> some View { content .foregroundColor(Color("bodyTextColor")) .font(.system(size: 14, weight: .medium)) } }
Bu, ortak metin stiline olanak tanır; normalde özel Metin bileşenleri veya yardımcı program işlevleri oluşturur ve kod aracılığıyla kullanıcı arayüzü bileşenleri eklersiniz.
extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }
Pekala, anladınız… bu özel bir görünüm değiştirici değil, basit bir uzantı. Bunun nedeni, ViewModifiers'ın genel Görünümlere uygulanması ve resizable
gibi bazı işlevlerin yalnızca görüntüler için geçerli olması, uzantıların ve özel değiştiricilerin bir kombinasyonunun kullanılması bu sorunu çözmeye yardımcı olmasıdır.
struct FullWidthButtonStyle: ButtonStyle { func makeBody(configuration: Configuration) -> some View { configuration.label .fullWidth() .foregroundColor(Color.white) .font(.system(size: 14, weight: .medium)) .padding(.horizontal, 10) .padding(.vertical, 12) .background(configuration.isPressed ? Color.blue.opacity(0.2) : Color.blue) } } struct FullWidthButton: ViewModifier { func body(content: Content) -> some View { content .buttonStyle(FullWidthButtonStyle()) } }
Son olarak, bu düğme içindir; aynı etkiyi elde etmek için basitçe bir ViewModifier oluşturabilecek olsak da, dokunulduğunda düğmenin görünümünün değişmeyeceğini unutmayın. Bunun nedeni, bir düğme üzerinde .background
ayarının, düğmeyi hem dokunulan hem de dokunulmayan durumlarda bu arka planı kullanmaya zorlamasıdır. ButtonStyle
basılıp basılmamasına bağlı olarak düğmenin opaklığını değiştirmemizi sağlar.
Kolaylık olsun diye şu değiştiricileri kullanan uzantılar yapmayı seviyorum:
extension View { func commonCornerRadius() -> some View { modifier(CommonCornerRadius()) } func fullWidth() -> some View { modifier(FullWidthModifier()) } func title() -> some View { modifier(TitleTextModifier()) } func body() -> some View { modifier(BodyTextModifier()) } func fullWidthButton() -> some View { modifier(FullWidthButton()) } } extension Image { func aspectFill() -> some View { self .resizable() .aspectRatio(contentMode: .fill) } }
struct ContentView: View { var body: some View { VStack (alignment: .leading) { Image("feature") .aspectFill() .fullWidth() .frame(height: 220) .commonCornerRadius() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI are the best!") .title() .padding(.bottom, 12) Text("Custom ViewModifiers in SwiftUI let you create resuable styles that can be applied to all your views") .body() Spacer() Button(action: { }) { Text("Awesome") } .fullWidthButton() .commonCornerRadius() } .padding(.all, 16) } }
Çok daha temiz! Şimdi ilk bakışta bu, stilleri manuel olarak ayarlamaktan daha fazla kod ve çaba gibi geliyor, ancak uzun vadede bu çok fazla çaba tasarrufu sağlayacaktır. Kişisel olarak bu yaklaşım aynı zamanda uygulamanızın stilinin, görünüm bazında stillendirme yerine genel değiştiricilere daha fazla güvenerek daha tutarlı olmasını da teşvik eder.
Ve hepsi bu! Umarız bu, uygulamalarınızı daha hızlı ve daha kolay oluşturmanıza yardımcı olur; başka bir avantaj da, bu değiştiricilerin herhangi bir uygulamanıza bırakılabilmesi ve stil yönergelerine uyacak şekilde ayarlanabilmesidir. Ayrıca bunu daha da ileri götürmek için bir kütüphane üzerinde çalışıyorum, buradan kontrol edebilirsiniz (Not: Bunu yazarken kütüphane süper erken bir aşamadadır, depo boş :p ama bizi izlemeye devam edin)