paint-brush
SwiftUI için Temel Bir Kılavuz: Özel Değiştiricilerle Yeniden Kullanılabilir Kullanıcı Arayüzüile@nemi
1,615 okumalar
1,615 okumalar

SwiftUI için Temel Bir Kılavuz: Özel Değiştiricilerle Yeniden Kullanılabilir Kullanıcı Arayüzü

ile Nemi Shah9m2023/04/28
Read on Terminal Reader
Read this story w/o Javascript

Çok uzun; Okumak

SwiftUI'daki Özel ViewModifiers, tüm görünümlerinize uygulanabilecek yeniden şekillendirilebilir stiller oluşturmanıza olanak tanır. Bu makalede, kullanıcı arayüzü oluşturmayı çok daha kolay hale getirmek için bu özelliğin nasıl kullanılabileceğine dair örnekleri ele alacağız. Bu makalenin amacı Swift kullanıcı arayüzünde özel değiştiriciler ve stiller oluşturmanın farklı yollarından bazılarını ele almaktır.
featured image - SwiftUI için Temel Bir Kılavuz: Özel Değiştiricilerle Yeniden Kullanılabilir Kullanıcı Arayüzü
Nemi Shah HackerNoon profile picture
0-item
1-item

Ö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:

  • Resim: Bir miktar köşe yarıçapına sahip standart bir resim bileşeni
  • Metinler: Bir başlığımız ve gövde metnimiz var
  • Düğme: Tam genişlikte bir düğme

Düz SwiftUI kodu

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) } }


Bu yaklaşımla ilgili birkaç sorun var:

  • 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:

  • Ekran kapsayıcısı: Ekranın kendisinde evrensel dolgu vardır, bu isteğe bağlıdır ancak tüm ekranların evrensel bir stile sahip olmasını tercih ederim
  • Köşe yarıçapı
  • Başlık ve gövde metinleri
  • Tam genişlik: Öğelerin üst öğelerinin genişliğini doldurabilmesi gerekir (yukarıdaki örnekteki düğme ve resim)
  • Düğme stili
  • Görüntü ölçekleme

Özel Görünüm Değiştiriciler

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) } }


Şimdi kodu doğrudan stil vermek yerine bunları kullanacak şekilde dönüştürelim:


 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)