React Native Dark Mod Entegrasyonu

Son yıllarda popüler olan ve gittikçe popülerleşmeye devam eden, kullanıcıların gözdesi olan dark mode ile uyumlu uygulama sayısı oldukça az. Ancak unutmayın ki küçük detaylar sizi her zaman rakiplerinizin önüne geçirir. Bu sebepten dolayı bu yazımda React Native Dark Mod entegrasyonunu anlatacağım.

1. Ön hazırlık

İlk olarak aşağıdaki komutu terminal üzerinde çalıştırarak darkmode adında yeni bir React Native Projesi oluşturalım.

npx react-native init darkmode

Daha sonra proje dizini içerisine girelim. Oluşturduğumuz uygulamanın sistem ayarlarını okuyarak karanlık modun devrede olup olmadığını bize iletecek olan React Native Dark Mod modülünü aşağıdaki komut ile kuralım.

npm install react-native-dark-mode --save

Modülü kurduktan sonra IOS platformu için yapmamız gereken işlem proje dizinindeki ios klasörü içinde iken terminale pod install komutunu yazmak. Bu aşamadan sonra React Native Dark Mod IOS platformunda sorunsuz çalışacaktır. Android için ise yapmamız gereken proje içindeki android/app/src/main dizini altındaki AndroidManifest.xml dosyasında şu değişikliği yapmak:

- android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
+ android:configChanges="keyboard|keyboardHidden|orientation|screenSize|uiMode"

Bu değişikliği yaptıktan sonra Android Studio üzerinde tekrar build almayı unutmayın. Şuanda uygulamamız aşağıdaki resimdeki gibi React Native’in default arayüzüne ve kodlarına sahip.

2. Basit Template Oluşturalım

Şimdi proje dizini içerisindeki App.js’i aşağıdaki gibi değiştirerek basit bir template hazırlayalım.

import React, { Component } from 'react';
import { View, Text, StyleSheet, StatusBar } from 'react-native';

export default class App extends Component{
  render(){
    return(
      <View style={{flex: 1}}>
        <StatusBar backgroundColor={"red"}/>
        <View style={styles.HeroSection}>
          <Text style={styles.HeroTitle}>React Native Dark Mode</Text>
          <Text style={styles.HeroSubtitle}>bestofprogramming.com</Text>
        </View>
        <View style={styles.Content}>
          
        </View>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  HeroSection: {
    flex: 4, 
    backgroundColor:'red',
    justifyContent:'center', 
    alignItems:'center'
  },
  HeroTitle: {
    fontSize: 25, 
    fontWeight:'bold', 
    color:'white', 
    textAlign:'center'
  },
  HeroSubtitle: {
    fontSize: 20, 
    color:'white', 
    textAlign:'center'
  },
  Content: {
    flex: 6, 
    backgroundColor:'white', 
    alignItems:'center', 
    justifyContent:'center'
  }
})

Bu kodları ekledikten sonra aşağıdaki gibi bir ekranla karşılaşmanız gerekir



3. Dark Mode

Template’i hazırladıktan sonra kütüphaneyi import edelim.

import { initialMode } from 'react-native-dark-mode'

initialMode uygulamanın ilk açılışta hangi renk teması ile açıldığını döndürüyor. Döndürdüğü değer “light” veya “dark”. React Native’in componentDidMount fonksiyonu o component çağırıldığında çalışan ilk fonsiyondur. Dolayısıyla bu fonksiyonu şu anki yapımıza ekleyip uygulama açıldığı zaman hangi renk temasıyla açıldığını kontrol edebiliriz. Bunun için kodda şöyle bir değişiklik yapalım

import React, { Component } from 'react'; 
import { View, Text, StyleSheet, StatusBar } from 'react-native'; 
import { initialMode } from 'react-native-dark-mode'

export default class App extends Component{
  componentDidMount(){
    console.log("App started with "+initialMode+" theme")
  }
  render(){ 
    return( 
      <View style={{flex: 1}}> 
        <StatusBar backgroundColor={"red"}/> 
        <View style={styles.HeroSection}> 
          <Text style={styles.HeroTitle}>React Native Dark Mode</Text> 
          <Text style={styles.HeroSubtitle}>bestofprogramming.com</Text> 
        </View> 
        <View style={styles.Content}>

        </View> 
      </View> 
    ) 
  } 
} 

const styles = StyleSheet.create({ 
  HeroSection: { 
    flex: 4, 
    backgroundColor:'red', 
    justifyContent:'center', 
    alignItems:'center' 
  }, 
  HeroTitle: { 
    fontSize: 25, 
    fontWeight:'bold', 
    color:'white', 
    textAlign:'center' 
  }, 
  HeroSubtitle: { 
    fontSize: 20, 
    color:'white', 
    textAlign:'center' 
  }, 
  Content: { 
    flex: 6, 
    backgroundColor:'white', 
    alignItems:'center', 
    justifyContent:'center' 
  } 
})

Böylelikle uygulamaya girdiğimiz zaman konsola bir mesaj bastırıp uygulama başlangıçta hangi renk temasıyla açılmış görebiliriz. Uygulamayı çalıştırdığınız zaman şöyle bir log alacaksınız

Renk temasını uygulama başında alabiliyoruz ancak bu ne kadar sağlıklı bir fikir tartışılır. Kullanıcı uygulamaya girdikten sonra cihazın renk temasını değiştirirse ne olacak biliyor musunuz ? Hemen cevap vereyim; hiçbir şey 😀

Bu sorunun çözümü için kullandığımız modülün içinde eventEmitter mevcut. eventEmitter sayesinde tema değişikliğini anlık olarak algılayıp uygulamanın buna göre tepki vermesini sağlayabiliriz. Hemen import satırını şu şekilde değiştirelim:

- import { initialMode } from 'react-native-dark-mode'
+ import { initialMode, eventEmitter } from 'react-native-dark-mode'

Daha sonra uygulama açıldığında başlayacak bir eventListener tanımlıyoruz.

componentDidMount(){
    eventEmitter.on('currentModeChanged', theme => {
      console.log("Theme switched to: "+theme)
    })
  }

Bu kod parçasıyla birlikte tema değişimlerinde konsola geçerli renk temasını yazdırıyoruz. Şimdi uygulamanın dark mod temasındaki stillerini tanımlayalım. Stillerimi şu şekilde değiştiriyorum:

const styles = StyleSheet.create({
  HeroSection: {
    flex: 4, 
    backgroundColor:'red',
    justifyContent:'center', 
    alignItems:'center'
  },
  HeroSectionDark: {
    flex: 4, 
    backgroundColor:'#283593',
    justifyContent:'center', 
    alignItems:'center'
  },
  HeroTitle: {
    fontSize: 25, 
    fontWeight:'bold', 
    color:'white', 
    textAlign:'center'
  },
  HeroSubtitle: {
    fontSize: 20, 
    color:'white', 
    textAlign:'center'
  },
  Content: {
    flex: 6, 
    backgroundColor:'#F0F0F0', 
    alignItems:'center', 
    justifyContent:'center'
  },
  ContentDark: {
    flex: 6, 
    backgroundColor:'#37474F', 
    alignItems:'center', 
    justifyContent:'center'
  },
  StatusText: {
    fontSize: 25,
    color:'black',
    fontWeight:'bold'
  },
  StatusTextDark: {
    fontSize: 25,
    color:'white',
    fontWeight:'bold'
  }
})

Şimdi ise logları kaldırıp sistem temasını state içinde tutalım. state içinde tutmamızın sebebi ise biliyorsunuz ki react native’de uygulamanın refresh edilebilmesi için state içinde herhangi bir şeyin değişmesi gerek. State içinde tutmazsak ne kadar değiştirsek değiştirelim uygulama aynı şekilde kalmaya devam edecektir. state içinde appTheme adında bir değişken oluşturup değerini initialMode olarak ayarlıyorum ki uygulama açıldığı zaman hangi renk temasıyla açıldıysa o tema appTheme’in default değeri olsun. Renk teması değişiminde ise EventListener’da state’in içinde yer alan appTheme’i tekrar set edeceğiz. Kodumuzu aşağıdaki gibi düzenliyoruz:

import React, { Component } from 'react'; 
import { View, Text, StyleSheet, StatusBar } from 'react-native'; 
import { initialMode, eventEmitter } from 'react-native-dark-mode'

export default class App extends Component{
  state = {appTheme: initialMode}
  componentDidMount(){
    eventEmitter.on('currentModeChanged', theme => {
      this.setState({appTheme: theme})
    })
  }
  render(){ 
    return( 
      <View style={{flex: 1}}> 
        <StatusBar backgroundColor={"red"}/> 
        <View style={styles.HeroSection}> 
          <Text style={styles.HeroTitle}>React Native Dark Mode</Text> 
          <Text style={styles.HeroSubtitle}>bestofprogramming.com</Text> 
        </View> 
        <View style={styles.Content}>

        </View> 
      </View> 
    ) 
  } 
} 

const styles = StyleSheet.create({ 
  HeroSection: { 
    flex: 4, 
    backgroundColor:'red', 
    justifyContent:'center', 
    alignItems:'center' 
  }, 
  HeroTitle: { 
    fontSize: 25, 
    fontWeight:'bold', 
    color:'white', 
    textAlign:'center' 
  }, 
  HeroSubtitle: { 
    fontSize: 20, 
    color:'white', 
    textAlign:'center' 
  }, 
  Content: { 
    flex: 6, 
    backgroundColor:'white', 
    alignItems:'center', 
    justifyContent:'center' 
  } 
})

Korkmanıza gerek yok, şu anda renk temasını değiştirsek de uygulamanın görünüşünde bir değişiklik olmuyor veya hiçbir şey loglanmıyor ancak arkaplanda her şey olması gerektiği gibi çalışıyor. Şimdi ise uygulamanın renk temasını değiştirme adıma geçelim. İlk olarak uzun uzun this.state.appTheme yazmak kodun çok karışık gözükmesine neden olacak. Bunun için theme adında bir kısaltma ekliyorum:

 render(){
+   let theme = this.state.appTheme
    return(
    ......

Ardından inline if statement ile eğer uygulama temasını değiştiriyorum. Örnek vermek gerekirse

<View style={theme=="light"?styles.HeroSection:styles.HeroSectionDark}>

.........
</View>

Burada View’in stilini şu şekilde belirliyorum; eğer theme light ise HeroSection style’ını uygula, eğer theme light değil ise HeroSectionDark stilini uygula. Aynı mantıkla diğer elementleri de değiştirelim. Bu değişiklik sonucunda aşağıdaki gibi bir kod ortaya çıkacak:

import React, { Component } from 'react';
import { View, Text, StyleSheet, StatusBar } from 'react-native';
import { initialMode, eventEmitter } from 'react-native-dark-mode'

export default class App extends Component{
  state = {appTheme: initialMode}
  componentDidMount(){
    eventEmitter.on('currentModeChanged', theme => {
      this.setState({appTheme: theme})
    })
  }
  render(){
    let theme = this.state.appTheme
    return(
      <View style={{flex: 1}}>
        <StatusBar backgroundColor={theme=="light"?"red":"#283593"}/>
        <View style={theme=="light"?styles.HeroSection:styles.HeroSectionDark}>
          <Text style={styles.HeroTitle}>React Native Dark Mode</Text>
          <Text style={styles.HeroSubtitle}>bestofprogramming.com</Text>
        </View>
        <View style={theme=="light"?styles.Content:styles.ContentDark}>
          <Text style={theme=="light"?styles.StatusText:styles.StatusTextDark}>{theme} theme active</Text>
        </View>
      </View>
    )
  }
}
const styles = StyleSheet.create({
  HeroSection: {
    flex: 4, 
    backgroundColor:'red',
    justifyContent:'center', 
    alignItems:'center'
  },
  HeroSectionDark: {
    flex: 4, 
    backgroundColor:'#283593',
    justifyContent:'center', 
    alignItems:'center'
  },
  HeroTitle: {
    fontSize: 25, 
    fontWeight:'bold', 
    color:'white', 
    textAlign:'center'
  },
  HeroSubtitle: {
    fontSize: 20, 
    color:'white', 
    textAlign:'center'
  },
  Content: {
    flex: 6, 
    backgroundColor:'#F0F0F0', 
    alignItems:'center', 
    justifyContent:'center'
  },
  ContentDark: {
    flex: 6, 
    backgroundColor:'#37474F', 
    alignItems:'center', 
    justifyContent:'center'
  },
  StatusText: {
    fontSize: 25,
    color:'black',
    fontWeight:'bold'
  },
  StatusTextDark: {
    fontSize: 25,
    color:'white',
    fontWeight:'bold'
  }
})

Bu aşamadan sonra geriye kalan tek şey test etmek, Buyrun test edelim 🙂

 

Aklınıza takılan bir şey olduysa mutlaka yorumlarda belirtin, elimden geldiğinde yardımcı olmaya çalışacağım




Written By

Uğur Demirel

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir