1080P Windows Phone'lar için uygulama geliştirirken dikkat edilmesi gerekenler.

0 dakikada yazıldı

43384 defa okundu

Düzenle

1080P çözünürlükteki Windows Phone'ların gelmesi ile beraber
uygulamalarda da ne gibi değişiklikler yapmak gerekiyor soruları akla
gelmeye başladı. Acaba bugüne kadar geliştirdiğimiz ve 720P için
optimize ettiğimiz uygulamalarda ne gibi değişiklikler yapmak gerekecek?
İşte bu yazıda bu sorunun cevabını vereceğiz.

"Phablet" adı 5" ve üstü büyüklükteki cihazları tanımlanırken
kullanılıyor. Buradaki karışıklıklardan biri aslında hem çözünürlüğün
hem de fiziksel olarak cihazın büyümesi ve maalesef API'lar 720P için
tasarlanmış uygulamaları kırmayacak şekilde tutulduğu için 1080P'yi
algılamanın tek yolu cihazın fiziksel büyüklüğüne bakmak oluyor. Yani,
720P'ye kadar çözünürlüğe bakarken sonrası için cihaz boyutuna bakmak
zorunda kalıyor. Yarın öbür gün 5"'den büyük ve 1080P çözünürlükten
düşük çözünürlüklü telefon çıkarsa ne yapacağız bilmiyorum :) Sanırım bu
seçenek hiç gerçekleşmeyeceği için hem Nokia hem Microsoft rahat
durumdalar.

[C#]

namespace resolutions_sample.Helpers
{
    public enum Resolutions { WVGAWXGAHD720pHD1080p };

    public static class ResolutionHelper
    {
        static private Size _size;

        private static bool IsWvga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 100;
            }
        }

        private static bool IsWxga
        {
            get
            {
                return App.Current.Host.Content.ScaleFactor == 160;
            }
        }

        private static bool Is720p
        {
            get
            {
                //ScaleFactor 1080P ve 720P'de aynı döndüğü için Is1080P'de 
                PhysicalScreenResolution'a bakmak zorundayız.

                return (App.Current.Host.Content.ScaleFactor == 150 && !Is1080p);
            }
        }

        private static bool Is1080p
        {
            get
            {
                if (_size.Width == 0)
                {
                    try
                    {
                        _size = (Size)DeviceExtendedProperties
                                    .GetValue("PhysicalScreenResolution");
                    }
                    catch (Exception)
                    {
                        _size.Width = 0;
                    }
                }
                return _size.Width == 1080;
            }
        }

        public static Resolutions CurrentResolution
        {
            get
            {
                if (IsWvgareturn Resolutions.WVGA;
                else if (IsWxgareturn Resolutions.WXGA;
                else if (Is720preturn Resolutions.HD720p;
                else if (Is1080preturn Resolutions.HD1080p;
                else throw new InvalidOperationException("Bilinmeyen Çözünürlük");
            }
        }
    }
}

Yukarıdaki Helper sınıfı çözünürlük tespiti için kullanabileceğiniz en
güncel yardımcı sınıf. Şu anda Windows Phone'da var olan tüm
çözünürlükleri tespit edebiliyor. Kod içerisinde de görebileceğiniz
üzere 1080P'ye gelene App.Current.Host.Content.ScaleFactor
kadar namespace'ini kullanıyoruz. 1080P'ye geldiğimizde maalesef
720P ile aynı ScaleFactor döndüğü için bu noktadan sonra detection
yapmak mümkün olmuyor. Bunun nedeni daha önce de bahsettiğim gibi var
olan uygulamaları kırmamak ve aslında uygulamaların aynen çalışmaya
devam etmesini sağlamak. İşletim sistemi kendi scaling'ini uygulayarak
işe devam ediyor. Fakat tabi ki istisnalar söz konusu olabilir.
Birincisi siz uygulamanızda scaling yerine yeni gelen pikselleri farklı
işler için kullanmak isteyebilirsiniz. İkincisi ise içeriğiniz scale
edilemeyen bitmap'lerden oluşuyor da olabilir. Bu her iki senaryoda da
1080P çözünürlüğü algılayıp ona göre aksyon almak anlamlı olacaktır.

1080P'yi algılamak için cihazın fiziksel ekran boyutuna bakmamız
gerekiyor. Bunun için de "PhysicalScreenResolution"'ı DeviceExtendedProperties'dan istiyoruz.
Buradan dönen çözünürlüğe göre artık kendi scalingimize karar
verebiliriz. Yukarıdaki kodu çalışan örnek bir uygulama ile Github'a da
attım.
Nitekim yazı
boyunca var olan tüm Helper'ları Github'daki örneklerde bulabilirsiniz.

Çözünürlüğü yakalamanın ötesinde gerçekten ekranın boyutunu da merak
edebilirsiniz. Bunun için Dpi bilgilerini alarak gerekli hesaplamaları
yapmak yeterli olacaktır. Böylece cihazın gerçek boyutunu da öğrenebilir
ve ona göre layout'unuzu nasıl düzenleyeceğinize karar verebilirsiniz.

[C#]

namespace resolutions_sample.Helpers
{
    class ScreenSizeHelper
    {
        static private double _screenSize = -1.0f;
        static private double _screenDpiX = 0.0f;
        static private double _screenDpiY = 0.0f;
        static private Size _resolution;
        
        static public double CurrentScreenSize
        {
            get
            {
                // Büyük ekranlı cihaz simülasyonu için emülatörde şimdilik 720P kullanılabilir.
                if (Microsoft.Devices.Environment.DeviceType == 
                                                   
Microsoft
.Devices.DeviceType.Emulator)
                {
                    _screenSize = (App.Current.Host.Content.ScaleFactor == 150? 6.0f : 0.0f;
                }

                if (_screenSize == -1.0f)
                {
                    try
                    {
                        _screenDpiX = (double)DeviceExtendedProperties.GetValue("RawDpiX");
                        _screenDpiY = (double)DeviceExtendedProperties.GetValue("RawDpiY");
                        _resolution = (Size)DeviceExtendedProperties
                                               
.
GetValue("PhysicalScreenResolution");

                        _screenSize =
                            Math.Sqrt(Math.Pow(_resolution.Width / _screenDpiX2+
                                      Math.Pow(_resolution.Height / _screenDpiY2));
                    }
                    catch (Exception e)
                    {
                        _screenSize = 0;
                    }
                }

                return _screenSize;
            }
        }
    }
}

Yukarıdaki Helper'ın bir öncekinden tek farkı RawDpiX ve RawDpiY özelliklerini de alarak ekran
boyutunu hesaplaması. Böylece hem istediğimiz gibi çözünürlük
biliglerine hem de cihazın boyutuna ulaşmış oluyoruz.

Resimlerde dikkat edilmesi gerekenler...

Nokia'ya soracak olursanız :) "1080P için tüm resimlerinizi düzenleyin
ve sadece onları kullanın" diyorlar. Zaten işletim sistemi daha düşük
çözünürlükte resim göstermek isterse rahatlıkla büyüğü ufaltıp
gösterebiliyor. Ama bu durum tabi ki özellikle düşük bellekli cihazların
koca koca resimlerle uğraşması anlamına gelecek ki bu da pek süper bir
manzara değil. Bu durumu engellemek için kullanabileceğiniz taktiklerden
biri BitmapImage nesnelerinizin DecodePixelWidth özelliğini
kullanmak.

[C#]

      //Büyük bir resmi düşük bellek kullanımı ile yüklemek.
      var bmp = new BitmapImage();

      //Decode işleminde kullanılacak yatay piksel sayısı.
      bmp.DecodePixelWidth = 100;

      bmp.UriSource = new Uri(@"Assets\AlignmentGrid.png"UriKind.Relative);
      IMG.Source = bmp;

Bu özelliği set ederek aslında Decode'in sonucunda almak istediğin
genişliği vermiş oluyorsunuz ve tüm resmi decode edip sonrasında resize
etmek yerine çok daha performanslı bir süreçten geçiyorsunuz. Ayrıca
bellek kullanımı da sadece göstereceğiniz Bitmap boyutunda oluyor
çünkü Image kontrolünde tüm resim gitmiyor.

Bir diğer seçenek de tabi ki çözünürlüğe göre ayrı ayrı resimler
yüklemek ama öyle bir iş yükünün altına girmek de pek mümkün gözükmüyor.
Yine de gelin şu ScaleFactor ve gerçek boyutlara bir göz atalım. Kafalar
biraz karışacak :)

768p (WXGA) bir cihazda 100px genişliğinde bir UI kontrolü 1.6x
ScaleFactor nedeniyle 160px olarak render edilir. Yani ekranda bu
şekilde gözükür. O nedenle 100px'lik bir Image kontrolüne aslında
160px'lik resim load etmeniz gerekir de tamamen net bir görüntü elde
edin. Diğer yandan 1080P cihazlarda ScaleFactor 1.5 olarak gelir ama :)
gerçek scaling 2.25 şeklinde gerçekleşir. Bu garip durum daha önce
bahsettiğimiz API'ların 720P gibi davranmalarından kaynaklanıyor. Yani
özetle 1080P bir cihazda 100px'lik kontrol ekrana 225px olarak yansır.
Eğer ki göstereceğiniz resimlerin çözünürlükten ve cihazdan bağımsız
olarak hep aynı büyüklükte gözükmesini isterseniz işiniz biraz daha zor.
768p ve 1080p cihazların mantıksal, yani UI kontrollerine verilen
boyutlarının arasındaki oranın 1.6/2.225=0.7111 olması gerekiyor ki her
iki cihazda da fiziksel olarak gösterilen öğeler bire bir aynı
büyüklükte olsun. 768p cihazdaki kontrol eğer 0.7111 oranın ufaltılırsa
1080p cihazda da aynı büyüklükte gözükecektir. Allah kolaylık versin :)

Splash Screen ne olacak?

Burada da Microsoft ve Nokia'nın tavsiyeleri birbirinden farklı :)
Projelerde hala 720p Splash Screen dosyasını göreceksiniz ve 1080P
cihazlarda söz konusu SplashScreen dosyaları resize edilecek. Bu tabi ki
hafif blur'lu Splash Screen'ler anlamına geliyor. Profil olarak
AppManifest dosyasına da 1080P'nin gelmediğini düşünürsek Microsoft
bakış açısı ile 1080P aslında developer'lara tamamen transparent
kalmalı. API'lar aynı ScaleFactor'ı döndürdüğü gibi Splash Screen de
aynı kalmalı. Ama diğer yandan Nokia'nın tavsiyesi için 720P JPEG
dosyasında 1080P çözünürlükte resmi çakmanız yönünde :) Doğal olarak
720P cihazlarda scale-down ile bu resimler düzgün şekilde gözükecek ve
1080P cihazlarda da herhangi bir scale-up olmadığı için o cihazlarda da
netlik korunacak. Aslına bakarsanız varsayılan ayarlarda Splash Screen
dosyaları 768x1280 şeklinde. Böyle bir splash screen maalesef ki 1080P
cihazlarda ekranın üstünde siyah bir boşluk / bant bırakcaktır. Karar
sizin.

Live Tile'larda birşeyler var mı?

Bir değişiklik yok :) Aslına bakarsanız 1080P cihazlarda Live Tile'lar
diğer çözünürlüklerden daha ufak gözüküyor. Bunun nedeni ise normalde
kolon olan Start Screen'in üç kolona çıkıyor olması. 1080P cihazlardaki
üç kolon nedeniyle kolon başına düşen genişlik 720P'deki iki kolonda
kolon başına düşenden daha düşük. O nedenle 1080P cihazlarda Live
Tile'lar daha ufalıyor :)

Daha çok bellek gerekirse?

1080P cihazlarla uğraşırken doğal olarak büyük resimler, büyük videolar
derken herşeyin büyüdüğünü göreceksiniz ve uygulamanızın bellek
kullanımı da otomatik olarak artacak. Bu durumda normal sınırlardaki
bellek limitleri canınızı sıkmaya başlayabilir. Bugün 1GB ve üstü
belleğe sahip telefonlarda XAML uygulamaları için 300MB limiti var.
Düşük bellekli telefonlarda ise bu limit 150MB'a düşüyor. Özellikle
1080P telefonlarda bu limitleri yükseltmek için AppManifest'te ek bir
talepte bulunabiliyorsunuz. (Dikkat bu özellikle WP8 Update 3 ile
geliyor)

[WMAppManifest.xml]

  <App xmlns="" ProductID="{476ed98e-af35-41b6-ba7e-6c1132242400}
" Title="resolutions_sample" RuntimeType="Silverlight" Version="1.0.0.0" 
Genre="apps.normal" Author="resolutions_sample author" Description="Sample description" 
Publisher="resolutions_sample" PublisherID="{6b07464a-f45a-40b4-9f9b-0c335cb1c38a}">
    <FunctionalCapabilities>
      <FunctionalCapability Name="ID_FUNCCAP_EXTEND_MEM"/>
    </FunctionalCapabilities>
    <IconPath IsRelative="true" IsResource="false">Assets\ApplicationIcon.png</IconPath>
    <Capabilities>
      <Capability Name="ID_CAP_NETWORKING"/>
      <Capability Name="ID_CAP_MEDIALIB_AUDIO"/>
      <Capability Name="ID_CAP_MEDIALIB_PLAYBACK"/>
      <Capability Name="ID_CAP_SENSORS"/>
      <Capability Name="ID_CAP_WEBBROWSERCOMPONENT"/>
    </Capabilities>

Yukarıdaki gibi "Capability" olarak ID_FUNCCAP_EXTEND_MEM özelliğini
isterseniz artık uygulamanızı daha yüksek bellek limitleri atanacak. 1GB
bellekli telefonlarda 380MB, 2GB bellekli telefonlarda ise 570MB hafıza
kullanabileceksiniz. 1GB altı telefonlar içinse limit 180MB'a çıkacak.
Ayrıca isterseniz ID_REQ_MEMORY_300 özelliğini de
"Requirement" olarak kullanarak uygulamanızın 1GB altı bellekli
telefonlara yüklenememesini de sağlayabilirsiniz. İnsanları
süründürmekten iyidir :)

Son olarak hatırlatiyim, yazıdaki herşey Github'da örnek bir
projede
var ;)
Görüşmek üzere.