Merhaba arkadaşlar,
mobilhanem.com üzerinden anlattığımız/yayınladığımız derslere bugün sizlere Android Dark Mode Kullanımını anlatan bir uygulama yapacağım.
Android 10 ( API Level 29 ) ile birlikte ortaya çıkan Android Dark Mode nedir, ne işe yarar öncelikle bunları anlatmakla başlayalım; Dark Mode kullanıcılara koyu bir arayüz ortamı sunmaktadır.
Android Dark Mode Avantajları
- Parlak ışığa duyarlı olan kullanıcılar için görünürlüğü artırır.
- Geç saatlerde görsel olarak kendini ayarlayabilen bir ortam kullanıcılara sunmuş olur.
- Güç kullanımını önemli ölçüde azaltabilir (cihazın ekran teknolojisine bağlı olarak)
Android 10 sürümlerinde Dark Mode aktifleştirmek için cihazın Sistem ayarlarından (Settings -> Display -> Theme) kısmından Dark mode aktifleştirebilirsiniz.
Dark mode da tema desteğini sağlayabilmemiz için res->values->styles.xml de bulunan uygulama temasını aşağıdaki şekilde yeni gelen DayNight tema desteğini ile kullanabiliriz.
<style name="AppTheme" parent="Theme.AppCompat.DayNight">
Uygulamamızda tema kullanıcı tarafından değiştirilmek istenebilir. Dark mode için;
Android 9 veya önceki sürümlerde çalışan cihazlarda önerilen tema seçenekleri aşağıdadır :
- Light
- Dark
- Set by Battery Saver
Android 10 ve daha üst sürümlerde çalışan cihazlarda ise önerilen tema seçenekleri:
- Light
- Dark
- System default
Bu seçeneklerin her biri doğrudan AppCompat.DayNight modlarından birine eşlenir peki nedir bu modlar gelin inceleyelim:
- Light : MODE_NIGHT_NO: Zamana bağlı kalmadan light mod kullanılmasını sağlar.
- Dark : MODE_NIGHT_YES: Zamana bağlı kalmadan dark mod kullanılmasını sağlar.
- Set by Battery Saver: MODE_NIGHT_AUTO_BATTERY: Sistemin pil tasarrufu etkinken, dark mod kullanılmasını sağlar aksi taktirde light mod kullanılır. Bu mod ile birlikte cihazın güç kullanılımın azalmasına yardımcı olunur.
- System default: MODE_NIGHT_FOLLOW_SYSTEM: Gece olup olmadığını belirlemek için sistemin gece modu ayarını kullanan mod.
Temayı değiştirmek için aşağıdaki kod bloğu kullanılır.
AppCompatDelegate.setDefaultNightMode()
örnek olarak; dark mode yapısını etkinleştirmek için aşağıdaki gibi methoda neyi set etmesini gerektiğini söylüyoruz.
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
Geçerli dark mode türünü alabilmek için aşağıdaki kod bloğunu kullanırız. Bu method bize integer bir değer döndürür.
AppCompatDelegate.getDefaultNightMode()
Dönen değerler aşağıdaki tiplere karşılık gelmektedir.
MODE_NIGHT_AUTO = 0
MODE_NIGHT_NO = 1
MODE_NIGHT_YES = 2
MODE_NIGHT_FOLLOW_SYSTEM = -1
MODE_NIGHT_UNSPECIFIED = -100
Android Dark Mode Klasör Yapısı
Dark mode yapısını uygulamaya yerleştirmek istediğimizde öncelikle dark mode yapısına göre klasörleme mantığını oturtmamız gerekmektedir. Örnek verecek olursak; uygulamamızda renk kodlarını tutabilmek için kullandığımız colors.xml klasörü normalde bir tane bulunmaktadır ama dark mode göre farklı renkler kullanmak istersek bir tane daha colors.xml oluşturmalıyız.
Android Studio da colors.xml klasör yapısı aşağıdaki gibi olacaktır. colors.xml ve colors.xml (night )
Bu şekilde yapı oluşturabilmek için Android Studio da görünüm olarak sol üst kısımda yer alan Project seçeneğini seçelim daha sonra res klasörüne sağ tıklayıp New -> Android Resource Directory tıkladıktan sonra Directory name kısmına values-night yazarak oluşturalım. Dark mode temasına uygun olarak artık klasöre sahibiz. Artık bu klasör altına dark mode yapısına göre oluşmasını istediğimiz dosyaları yaratabiliriz. ( colors.xml, styles.xml gibi )
örnek klasör yapısı:
Şimdi projemizi oluşturmaya başlayalım;
Öncelikle Dark Mode yapısını Application sınıfı üzerinden yönlendirmek istiyorum bu yüzden Application sınıfı ile ilgili işlemler yapmam gerecek. Aşağıdaki gibi InitApplication adını verdiğimiz bir sınıf oluşturuyoruz.
InitApplication.kt
package com.mobilhanem.darkmodeapp import android.app.Application import android.preference.PreferenceManager class InitApplication : Application() { val DARK_MODE = "DARK_MODE" var isDarkModeEnabled = false companion object { private var INSTANCE: InitApplication? = null val instance: InitApplication get() { if (INSTANCE == null) { INSTANCE = InitApplication() } return INSTANCE!! } } override fun onCreate() { super.onCreate() INSTANCE = this val mPrefs = PreferenceManager.getDefaultSharedPreferences(this) this.isDarkModeEnabled = mPrefs.getBoolean(DARK_MODE, false) } fun setIsDarkModeEnabled(isDarkModeEnabled: Boolean) { this.isDarkModeEnabled = isDarkModeEnabled val sharedPref = PreferenceManager.getDefaultSharedPreferences(this) val sharedEditor = sharedPref.edit() sharedEditor.putBoolean(DARK_MODE, isDarkModeEnabled) sharedEditor.apply() } }
Bu application sınıfını incelersek eğer; singleton bir sınıf yapısı kurduğumuzu göreceksiniz. Application sınıfı yaratıldığında shared preferences yapısından gelen değeri ilgili değişkene set ederiz. Bu değer true veya false olabilir. setIsDarkModeEnabled methodu da boolean bir değişken alır daha sonra o aldığı değişkeni ilgili değere set eder. Son olarak da Shared Preferences ile de cihaza o değeri kaydetmiş oluruz. Kaydedilen bu değeri kontrol ederek çeşitli işlemler yapacacağız.
DarkMode Android
Application sınıfını oluşturduktan sonra uygulamamızın ve bu sınıfın sorunsuz çalışabilmesi için AndroidManifest e aşağıdaki gibi android:name kullanarak sınıfımızı tanımlamamız gerekmektedir.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.mobilhanem.darkmodeapp"> <application android:name=".InitApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> </manifest>
Şimdi uygulamamızda kullanacağımız renk kodlarını oluşturalım aynı yukarıda anlattığım şekilde hem normal kullanılacak olan renk kodu dosyası hem de dark mode için kullanılacak olan renk dosyasına ihtiyacımız var.
night/colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="red">#ff5311</color> <color name="redDark">#ff2c11</color> <color name="darkmode_textColor">#D4AC0D</color> <color name="switchColor">#BC2F1D</color> </resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#3F51B5</color> <color name="colorPrimaryDark">#303F9F</color> <color name="colorAccent">#FF4081</color> <color name="red">#ff8200</color> <color name="redDark">#f77000</color> <color name="darkmode_textColor">#D4AC0D</color> <color name="switchColor">#911DEE</color> </resources>
Şimdi uygulamamızda kullanacağımız style dosyalarını oluşturalım aynı renk kodlarını oluştururken kullandığımız mantık burası içinde geçerli;
night/styles.xml
<resources> <style name="AppTheme" parent="Theme.AppCompat.DayNight"> <item name="colorPrimary">@color/red</item> <item name="colorPrimaryDark">@color/redDark</item> <item name="colorAccent">@color/colorAccent</item> <item name="android:textColorPrimary">@android:color/white</item> </style> <style name="CustomDialog" parent="Theme.AppCompat.DayNight.Dialog.Alert"/> <style name="CustomSwitch"> <item name="colorControlActivated">@color/switchColor</item> </style> </resources>
styles.xml
<resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <style name="CustomDialog" parent="Theme.AppCompat.Light.Dialog.Alert"/> </resources>
Şimdi uygulamamızda kullanacağımız resim dosyalarını oluşturalım aynı işlemler resim dosyaları içinde geçerli eğer dark mode için ayrı bir gösterim yapmak istiyorsak o resim dosyasınıda oluşturmamız gerekmektedir. Kaynak kodu indirip incelediğinizde konuyu daha iyi anlayacaksınız. Drawable klasörü için yapı aşağıdaki gibidir. mobilhanem_logo adını verdiğimiz resmi hem normal mod için hem dark mod için kullandığımızı görüyoruz. Bu resimlerin adı aynı olmak zorunda fakat içerikleri farklı olabilir.
Şimdi xml layout dosyasının görsel kısımlarını oluşturalım;
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_margin="@android:dimen/app_icon_size" android:text="Dark mode dersine hoşgeldiniz." android:textColor="@color/darkmode_textColor" android:textSize="18sp" /> <ImageView android:id="@+id/imageView" android:layout_width="250dp" android:layout_height="250dp" android:layout_centerInParent="true" android:src="@drawable/mobilhanem_logo" /> <TextView android:id="@+id/txtNightMode" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBaseline="@+id/switchCompat" android:layout_centerHorizontal="true" android:paddingRight="8dp" android:text="Gece Modu" android:textColor="@color/darkmode_textColor" /> <android.support.v7.widget.SwitchCompat android:id="@+id/switchCompat" android:layout_width="wrap_content" android:theme="@style/CustomSwitch" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="@android:dimen/app_icon_size" android:layout_toRightOf="@+id/txtNightMode" android:checked="false" android:textAppearance="?android:attr/textAppearanceMedium" /> <Button android:id="@+id/clickButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_above="@+id/imageView" android:layout_alignLeft="@+id/txtNightMode" android:layout_alignStart="@+id/txtNightMode" android:text="Tıkla" android:textColor="@color/darkmode_textColor" /> </RelativeLayout>
Bu layout a bağlı olan activity sınıfımızıda oluşturalım;
MainActivity.kt
package com.mobilhanem.darkmodeapp import android.os.Bundle import android.support.v7.app.AlertDialog import android.support.v7.app.AppCompatActivity import android.support.v7.app.AppCompatDelegate import android.support.v7.widget.SwitchCompat import android.widget.Button class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) if (InitApplication.instance.isDarkModeEnabled) { ThemeHelper.applyTheme(ThemeHelper.DARK_MODE) } else { ThemeHelper.applyTheme(ThemeHelper.LIGHT_MODE) } setContentView(R.layout.activity_main) val switchCompat = findViewById<SwitchCompat>(R.id.switchCompat) val button = findViewById<Button>(R.id.clickButton) button.setOnClickListener { AlertDialog.Builder(this, R.style.CustomDialog) .setTitle("Başlık") .setMessage("Mesaj") .show() } if (AppCompatDelegate.getDefaultNightMode() == AppCompatDelegate.MODE_NIGHT_YES) switchCompat.isChecked = true switchCompat.setOnCheckedChangeListener { buttonView, isChecked -> if (isChecked) { InitApplication.instance.setIsDarkModeEnabled(true) recreate() } else { InitApplication.instance.setIsDarkModeEnabled(false) recreate() } } } }
ThemeHelper adını verdiğimiz uygulama içinde hangi temanın kullanılacağına karar veren mekanizmayıda aşağıdaki gibi oluşturuyoruz.
ThemeHelper.kt
package com.mobilhanem.darkmodeapp import android.support.v7.app.AppCompatDelegate object ThemeHelper { const val LIGHT_MODE = "light" const val DARK_MODE = "dark" fun applyTheme(theme: String) { val mode = when (theme) { LIGHT_MODE -> AppCompatDelegate.MODE_NIGHT_NO DARK_MODE -> AppCompatDelegate.MODE_NIGHT_YES else -> { AppCompatDelegate.MODE_NIGHT_NO } } AppCompatDelegate.setDefaultNightMode(mode) } }
Yukarıdaki kod bloklarını incelersek; Application sınıfı üzerinden oluşturduğumuz değişken değerinin kontrol edildiğini göreceksiniz eğer o değer kayıtlı ise yani değişken true ise ThemeHelper üzerinden dark mode aktifleştirdiğimizi görüyoruz eğer değer kayıtlı değil ise yani değişken false ise ThemeHelper üzerinden light mode aktifleştirdiğimizi görüyoruz. SwitchCompat seçili ise Application sınıfı üzerinden ilgili methodu true göndererek çağırdığımızı görüyoruz. Eğer seçili değilse ilgili methoda false gönderiyoruz. Bu işlemlerden sonra tema değişeceği için ilgili sayfayı yenilememiz gerekmektedir işte bu yüzden recreate methodunu çağırıyoruz.
Uygulamamızı çalıştırdığımızda light mode için aşağıdaki ekran görüntüsünü elde edeceğiz.
Uygulamamızı çalıştırdığımızda dark mode için aşağıdaki ekran görüntüsünü elde edeceğiz.
Evet arkadaşlar Android Dark Mode Kullanımını temel bir proje yaparak sizlere anlatmaya çalıştım. Umarım herkese faydalı olmuştur kaynak kodu indirip çalıştırdığınızda konuyu daha iyi anlayacaksınızdır. İlerleyen derslerde Android 10 ile gelen yeni özelliklere değinmeye çalışacağım.
DarkMode Android
Tüm Android Ders, Proje ve Kaynak Kodlar için tıklayınız.
Mobilhanem.com üzerinden anlattığımız android uygulama geliştirme derslerine devam edeceğiz. Konu hakkında sorunuzu yorum alanından sorabilirsiniz. Konu dışı sorularınızı ve tüm yazılımsal sorularınızı sorucevap.mobilhanem.com sitemizden de sorabilirsiniz.
Bir dahaki dersimizde görüşmek dileğiyle..
3
Merhabalar, detaylar icin cok tesekkur ederim yalniz bir noktaya deginmek istedim. Application’i singleton pattern ile kullanmak dogru degil cunku zaten application 1 kere olusturulabiliyor. Singleton yapmadan herhangi bir yerden context uzerinden context.getApplication() seklinde ulasabilirsiniz.
Referans: https://developer.android.com/reference/android/app/Application.html
Merhaba, yapıcı eleştiriniz için teşekkür ederiz dikkate alacağız.
Sizce bu değerlendirme sonrasında kodlarınızda nasıl bşr değişim olur?