PSD’den XAML’a Login Page Tasarımı (Xamarin Forms)
Merhaba, Biz programcılar genellikle business logic tarafında kaynaklar hazırlamayı çok severiz. Bunun içindir ki bu konuda hazırlanmış yığınlarca materyal bulabiliriz. Hepside işimize yarar ama coğunlukla design kısmı unutulur ve uzerinde yeterince kaynak bulamayız. Eğer HTML ve CSS bilginiz varsa, burada da BOX model tasarımının uygulandığını göreceksiniz. Eğer geçmişte web sayfası hazırlamışsanız kullanıcı arayüzü hazırlama konusundaki deneyiminiz burada da size faydalı olacaktır.
Tasarıma başlamadan önce sunu belirtmeliyim ki, izlediğim yol belkide çoğunuzun izlediği yoldan farkli olabilir bu sizi düşündürmesin. Programcılık dünyasinda bir problemin birden fazla çözümü olabilir ve ben sizin tercih etmediğiniz çözümü kullanıyor olabilirim.
Kullanmis olduğum dizaynları buradan indirebilirsiniz psd files. Bu yazıyı hazırlarken kullandığım Xamarin versiyonu 4.3 tür.
Bu yazımda IOS kısmından devamında ise Adroid tarafindan bahsedeceğim.
Öncelikle implement etmek istediğim dizayn resimde görünen dizayndir. Basit gibi görünebilir fakat icerisinde bilinmesi gereken değerli konseptler bulundurur.
Düşündüğüm şey en az sayıda layout kullanarak bu işi yapmak ve aynı zamanda az zaman harcamak. Sadece bir stacklayout kullanarak bu işi kapatabilecegimizi düsünebiliriz fakat bu fikrimiz controller’in arasındaki farklı boşluklar sebebiyle problemli olacaktır. Absolute Layout veya Relative layout kullanilabilir. Ama ben bu ikisinden mecbur kalmadıkca uzak duruyorum. Aşagidaki şekilde nasıl bir yol izleyeceğimi açıklamaya calıştım.
Resimde görünen yolu izlemeye çalısacağım.Grid’e ne gerek vardi diyebilirsiniz onunda cevabını sırası geldiğinde bulacaksınız. Yeni bir Xamarin.Forms projesi oluşturarak işe başlayalım.
Proje olustuktan sonra Forms Blank Content Page Xaml olusturalim. Ilk olarak Grid ekleyelim ve backgound color property’sini #323542 set edelim. 2X2 bir grid olacak. Row ve Column Definitions Property’lerinide resimdeki gibi ayarladıktan sonra uygulamamızı test edelim.
Çok güzel background color tam istediğimiz gibi.
Şimdi sıra kullanacağımız resimleri import etmeye. Photoshop kullanarak lazım olan resim dosyalarını export ettim ve kullanıma hazır hale geldi. PCL projemde Assets/Images klasörlerini oluşturup resim dosyalarını bunun içine import ettim. Import ettikten sonra bu resimlerin Built Action Property’sini Embedded Resource olarak set ederek projeme devam ettim. Eğer bu ayarı yapmaz iseniz resimleri göstermeniz zor olacaktır.
Assetlerimizide import ettikten sonra kaldığımız yerden devam edebiliriz. Şimdi 2 tane vertical stacklayout ekleyim bitanesinin x:Name’ini ContentStacklayout yapalım. Stacklayout Grid.Row, Grid.Column ve BackgroundColor ayarlarini resimdeki gibi yapalim, ve test edelim.
Şekildende görüldüğü gibi planımız gayet güzel işliyor. Fakat dikkat ettiğiniz gibi stacklayoutların arası ve sağ tarafında bir boşluk var. Bu boşluk Grid’imizin RowSpacing ve ColumnSpacing Property’isinden kaynaklanmaktadır. Bu değerler default olarak 6’dir. Bunlari 0 olarak ayarlayip tekrar test edelim.
Şimdi istediğimiz sonucu aldık. Şimdi sırasıyla Stacklayout, Label, BoxView(Horizontal line icin), Image controllerini ilk stacklayout’un icine koyalim. Gerekli olan property ayarlarını resimdeki gibi yapalım ve test edelim.
IOS tarafında test ettigim icin Label status bar’in altinda gorunuyor. Bu durum sadece Content Page kullanıldığında iOS tarafında olan bir ozellik. Bunu duzeltmek icin Stacklayout’umuzun Padding Property’isinin top padding’ini 20 ye ayarliyorum. Bunun için OnPlatform tag’inden yararlanıyorum.
Padding ayarlarını asağıdaki gibi yapıp test edelim.
Logo neden gelmedi diye soruyor olabilirsiniz. Bunu yapabilmek için custom bir XAML Markup extension yazmamız gerekiyor. Burada dikkat etmemiz gereken nokta bu extension dosyasinin PCL projesinin içinde oluşturmamız gerekiyor. PCL projemde MarkupExtensions adında klasor olusturup icine ImageSourceExtension diye bir class olusturuyorum. Bu class IMarkupExtension interface’ini inherit ediyor. Resimdeki gibi kodumuzu tamamlayıp test edelim.
Bu extension string olarak path alıp geriye image resource gonderiyor. Simdi LoginPage.xaml dosyasini update etmek kaldi. Oncelikle bu yazdigimiz extension’i kullanmak icin namespace eklememiz gerekiyor xaml dosyamiza.
Simdi artik bu extension’i kullanabiliriz.
Bu haliyle test edersek eger.
Harika logomuzda yüklendi. Simdi ImageSourceEntension Class’ina geri donelim. ContentProperty attribute’ünü “Source” olarak set etmişiz. Beki bu ne demek. Bu su demek XAML tarafinda daha az kod yazmak demek. XAML tarafinda bir elementin ContentProperty’sini ayarlarken o property ismini acik acik yazmamiza gerek yok. Simdi image tag’ina tekrar bakalim.
Logonun path’ini belirlerken kullandığım single qoute (‘) aslında gereksiz ama ben bakınca onun bir bütün olduğunu anlamak için böyle yapıyorum. Image source oluştururken su yolu izlememiz gerekecek: Source = Assembly + Folder Structure nokta “.” notasyonu kullanarak. Nokta demek 1 level asagi demek. Simdi sıra ilk stacklayout’umuzun olçülerini design ile eşleştirmek.
Resimdeki değişiklikleri yaptıktan sonra test edelim.
Neredeyse tamam olmak üzere. Şu anda status bar siyah bunu beyaz yapmanın birkaç yolu var ben en kolayıma geleni seçiyorum. IOS projesi içindeki plist dosyasını update ediyorum. Aşağıda nasıl yaptığımı goreceksiniz.
Key toggle butonuna tıklarsanız bu şekilde görürsünüz. UIStatusBarStyle ve UIViewControllerBasedStatusBarAppearance keylerini ayarlayıp test edelim.
Şimdi birinci stacklayout bitti diyebiliriz. Asıl iş ikinci stacklayoutun içinde aslında. Şimdi sırasıyla 2 Stacklayout ve bunların içlerinede gerekli olan controlleri koyalım.
Ilk denememiz bu şekilde ve bi test edip sonucu görelim.
Custom Renderer ve Effects kullanma zamanı geldi. Öncelikle Entry’lerimiz için custom class oluşturalım ki her Entry aynı şekilde render edilmesin. PCL projemde CustomControls diye bir klasör oluşturacağım, ve bunun içine bütün custom controllerimi koyacağım. LoginPageEntry adında bir Class olusturacağım ve bunu Entry Class’ından inherit edeceğim. Bu class public olmak zorunda, ancak böyle olursa IOS ve Android projelerinin içinde referans alabilirim.
LoginPageEntry’i oluşturduktan sonra XAML tarafına gidip bütün Entry’lerimizi bununla değiştirelim. Bunu yapabilmek için oncelikle XAML’imiza namespace eklememiz gerekiyor.
Bu işlemden sonra birkez daha test edelim. Sonuc aynı değişmedi. Daha yapmamız gerekenler var. Bu değişikleri yapmadan önce biraz daha iyilestirelim sayfamızı. Öncelikle Grid’imizin Padding olarak 30 değerini veriyoruz.
Entry ve Button’un HeightRequest değerlerini 50 olarak değiştiriyoruz.
Şimdi test edip son duruma bakalım.
Asağıdaki değişiklikleri yaptıktan sonra tekrar test edelim.
Şu ana kadar iyi gidiyorduk ve XAML dışında hiç birsey kullanmadık. LoginPageEntry’lere baktığınız zaman eksik olan bazi seyler var. Entry frame’mimizin koşeleri oval değil, ve sol kısmında resim yok. Şimdi bunlari yapalım. Tekrar LoginPageEntry.cs dosyasina gidelim ve buradaki degişiklikleri yapalım. Öncelikle isimleri LeftImageSource ve CornerRadius olan 2 tane property ekleyelim. Daha sonra binding özelliğini kullanabilmemiz için isimleri LeftImageSourceProperty ve CornerRadiusProperty olan iki tane BindableProperty ekleyelim ve bu işlemi aşağıdaki şekilde tamamlayalım.
Bunu da yaptiktan sonra Login sayfamıza geri dönebiliriz. Tanımlamış olduğumuz Property’leri Entry’lerimize ekleyelim.
Şimdi tekrar deneyelim. Son halinden farklı olmadığını göreceksiniz. Şimdi iOS projesine gidip custom renderer olusturacağız. Öncelikle CustomRenderers klasörünü iOS projesine ekliyorum. LoginPageEntryRenderer adında bir class oluşturup EntryRenderer class’ından inherit alıyoruz. ViewRenderer class’ındanda inherit alabilirsiniz fakat bu farklı bir implementation gerektirir. Ben EntryRenderer kullanacağım. Class’ımıza ExportRenderer Attribute’u assembly level veriyoruz ki compliation işlemi olduğunda compiler bu attribute’u görüp LoginPageEntry’sini LoginPageEntryRenderer kulllanarak render etsin. Custom renderer uzun bir konu ve bütün özelliklerini burada anlatmamız mümkün değil.
Biz burada sadece visual olarak değistirebilicegimiz özelliklerinden bahsedeceğiz. Sonucta grafik nasıl olusturulur onu inceliyoruz.
Bunu yapmak icin LoginPageRenderer class’ımız içinde
- void OnElementChanged(ElementChangedEventArgs<Entry> e)
- void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
Methodlarından faydalanağım.
Öncelikle OnElementChanged(ElementChangedEventArgs<Entry> e) methodunun içinde UITextfield’imiza corner radius özelliğini vereceğim. Bunun icin oncelikle Control Property’sinin null olmadığından emin olmam gerekiyor. Control Objesi initialize edildikten sonra bu method cağırılıyor o yüzden width ve height property’ilerinin set edilmiş olması garanti değildir. Bu yüzden UITextfield’imizin LeftView elementini OnElementPropertyChanged(object sender, PropertyChangedEventArgs e) methodu içinde yapacağım. Bu şekilde Width ve Height Property’lerinin set edilmiş olduğundan emin olabiliriz.
Biraz matematikten sonra gerekli değişiklikleri yaptık. Test edelim ve sonuca bakalım.
Buraya kadar iyi geldik. Simdi sağ alt köşedeki link veya label’a bakmanızı istiyorum. Alt çizgili olmadığını fark etmişsinizdir. Bunu yapmak icin renderer kullanabiliriz fakat bu seferde Effects kullanıp bununda nasıl kullanıldığını görelim. Aynı şekilde önce CustomEffects klasörü oluşturuyoruz. Ilk önce oluşturacağımız effect’i kullanabilmek için PCL projesinde RoutingEffect’ten inherit olmuş UnderlineEffect adında bir class oluşturuyoruz. Bu class kullanılacak effect’in platform specific implementation’ı getirmek için kullanılıyor.
PCL içerisindeki UnderlineEffect.cs
Simdi iOS projesine CustomEffects klasörü oluşturup içine UnderlineEffect Class’i oluşturalım. Asağıdaki koduda yazalım.
Şimdi tekrar XAML tarafina dönüp hazırladığımız effect’i ekleyelim. Önce namespace ekliyoruz.
Son olarak Label control’üne effect’i ekliyoruz.
Şimdi test edelim.
Harika 10 numara oldu. Şimdi gelelim neden 2X2 Grid kullandım. Cihazımızın rotation’ı değistirdiğimizde görünüyor ki buttonumuz gosterilmiyor.
Bu durumu düzeltmek için sayfanın SizeChanged eventine subscribe edeceğim bir method yardımıyla isteğim ayarlamaları yapacağım. Bununla beraber Grid’imizin x:Name’ ni MainGrid olarak ayarlamayı unutmayın ki code behind’en erişebilelim.
Bu methodun icinde oncelikle Portrait mi Landscape mi onun tespitini yapacağım. Bunun içinde Width ve Height property’ilerini kullanacağım. Width eğer Height’ten büyük ise Landscape aksi durumda ise Portrait olacaktır. Methodun tamamlanmış hali asağidaki gibidir.
Şimdi tekrar test edelim.
Sonuc harika. Galiba bitti bundan sonrasi business logic.
Bu yazimda faydalandigim ozellikler:
- Custom Renderers
- Effects
- Markup Extensions
- Embedded Resources
Son olarak
İşaretlediğim LayoutOptions değerleri sadece Stacklayout’un içindeki elementler için kullanılır. Bunun haricindeki yapılarda Expand ozelliği herhangi bir etki göstermez. Bu hatırlatmayı yaptıktan sonra yazıma şimdilik son verebilirim.
Tekrar gorusmek uzere 🙂
3 Yorum
You can post comments in this post.
Merhaba. Yazınıçok güzel.Çok faydalı oldu benim için. Yalnız İOS kısmı tamam ama Android de Custom Renderer kısmını anlatabilirseniz çok iyi olacak. ayrıcaLogoyu bir türlü gösteremedim. Sayfanın üst kısmına eklediğimiz xmlns:local=”clr-namespace:Deneme.CustomControls;assembly:Deneme” kısmını kabul etmiyor. Sonundaki assembly:Deneme kısmını çıkarınca kabul ediyor ama resim bir türlü görünmüyor. Bu konularda yardımcı olabilirsenizsevinirim. İYi çalışmalar.
Sertan Özcan 5 sene ago
Tekrarmerhaba. Logonun görünmesi problemini çözdüm. Shared proje idiprojem netstandart olarak tekrar yazınca Logo görünüyor fakat Android de customRenderers ta sorun oluyor. Control.Layer tanımlı değil. Yardımlarınız için teşekkürler.
Sertan Özcan 5 sene ago
Merhabalar.
Bu sayfanın bir benzerini yaptım. Entry lerin sol kısmındaki resimler çalışmadı. Ayrıca logoyu ana projeden aldıramadımbu yüzden tüm patformlara logoyu ekleyip çalıştırdım. Yine de genel olarak çalıştırmış oldum. Teşekkür ederim.
ORHAN SEZGİN 5 sene ago
Yorum Gönder