Yazılar

React Native’de Açık ve Koyu Tema Kullanımı: Detaylı Rehber
Yazılım 5 dk.

React Native’de Açık ve Koyu Tema Kullanımı: Detaylı Rehber

Cep telefonlarda ve tabletlerde sistemin temasını koyu veya açık olarak belirlenebiliyor. Mobil uygulamalarda da eğer renk belirtilmediği sürece sistemin temasından etkilenir. Örneğin react native uygulamasında text'e ait stillendirme yapılırken eğer color verilmediyse; Sistemin teması koyu ise beyaz, sistemin teması açık ise siyah olarak gelir. Burada buna yönelik ayarlamalar yapılmadığı takdirde uygulamada tasarımsal sorunlar çıkması olasıdır. Bugün sizlere React Native mobil uygulama geliştirirken bunu nasıl kolay bir şekilde yapacağımızı basit kodlar üzerinden anlatmaya çalışıcam. Uygulama ilk açıldığında seçilen bir tema olmadığı için sistemin temasını alacaktır. Eğer uygulamamız üzerinden seçildiyse ona göre aksiyon almasını anlatmaya çalışacağız. 

İlk olarak uygulamaya başlarken renkler üzerinden gideceğiz. Burada renkler için theme.js dosyası oluşturacağız. Renklerin kullanımını direk yazmak yerine bu dosyadaki renklerin çağrılması gerekmektedir. Burada renk tonlarına göre isimlendirme yapılır. yapılan listenin tam tersi olarakta koyu tema için ayarlamalar yapılır. Bunun yapılmasının amacı eğer açık tema ise ve colors.primary_50 yani  #fdf4e6 burasını otomatik olarak alacak eğer koyu tema ise #2a1501 renk kodunu alacaktır. hem açık hemde koyu tema ayrışımını bu şekilde yapacaktır. Birde açık-koyu tema fark etmeksizin kullanılacak renkleri de commonColors  kısmında tanımlayarak bunu light ve dark objelerine dahil ettik.

theme.js

const commonColors = {
    opacity_primary: `rgba(56, 58, 66, 0.44)`,
    black: `#000000`,
    white: `#ffffff`,
    transparent: `transparent`,
    secondary: `#333333`,
    lightGray: `#979797`,

}


export const COLORS = {

    light: {
        primary_50: `#fdf4e6`,
        primary_100: `#fbe8cd`,
        primary_200: `#f5cf9c`,
        primary_300: `#ecb566`,
        primary_400: `#d8902d`,
        primary_500: `#a16207`,
        primary_600: `#8b5106`,
        primary_700: `#733f05`,
        primary_800: `#5c3204`,
        primary_900: `#422202`,
        primary_950: `#2a1501`,

        ...commonColors

    },

    dark: {
        primary_50: `#2a1501`,
        primary_100: `#422202`,
        primary_200: `#5c3204`,
        primary_300: `#733f05`,
        primary_400: `#8b5106`,
        primary_500: `#a16207`,
        primary_600: `#d8902d`,
        primary_700: `#ecb566`,
        primary_800: `#f5cf9c`,
        primary_900: `#fbe8cd`,
        primary_950: `#fdf4e6`,

        ...commonColors
    },


};

const appTheme = {COLORS};

export default appTheme;

 

Temanın rengi ve renkleri tüm ekranlara tek tek eklemek yerine her yerden erişebilmek için context yapısı kurulması gerekiyordu. ThemeContext.js dosyasında ilk olarak eğer daha önce uygulama içinde uygulama teması belirlendiyse onu kullan yok ilk defa açılıyorsa yada uygulama içinde daha önce seçilmediyse cihazın teması neyse onu kullanacak şekilde tasarlandı. Uygulamaya ait temayu tutmak için AsyncStorage yani cihazın belleğine themeMode  key'i ile kaydettik. uygulamanın teması setTheme  fonskiyonu ile değiştirilmektedir. burada bunu useEffect içinde tutarak değiştiği takdirde tekrardan render edilmesini sağlar. 30. satırda da görüldüğü gibi değiştiği takdirde cihazın belleğini de güncelleme işlemi yapılıp kaydedilmektedir.

ThemContext.js

import React, { createContext, useContext, useEffect, useState } from `react`;
import { Appearance } from `react-native`;
import {COLORS as colors}  from "../../constants";
import AsyncStorage from `@react-native-async-storage/async-storage`;

const ThemeContext = createContext();

export const THEME_MODES = {
  LIGHT: `light`,
  DARK: `dark`,
  SYSTEM: `system`
};

export const ThemeProvider = ({ children }) => {
  const [themeMode, setThemeMode] = useState(THEME_MODES.SYSTEM);
  const [systemColorScheme, setSystemColorScheme] = useState(
    Appearance.getColorScheme() || `light`
  );

  useEffect(() => {
    (async () => {
      const savedTheme = await AsyncStorage.getItem(`themeMode`);
      if (savedTheme) {
        setThemeMode(savedTheme);
      }
    })();
  }, []);

  useEffect(() => {
    AsyncStorage.setItem(`themeMode`, themeMode);
  }, [themeMode]);

  useEffect(() => {
    const subscription = Appearance.addChangeListener(({ colorScheme }) => {
      setSystemColorScheme(colorScheme || `light`);
    });

    return () => subscription?.remove();
  }, []);

  const getActiveTheme = () => {
    if (themeMode === THEME_MODES.SYSTEM) {
      return systemColorScheme;
    }
    return themeMode;
  };

  const activeTheme = getActiveTheme();
  const isDark = activeTheme === `dark`;

  const currentColors = {
    ...colors.light,
    ...colors[activeTheme]
  };

  const contextValue = {
    themeMode,
    activeTheme,
    isDark,
    systemColorScheme,

    colors: currentColors,

    setTheme: setThemeMode,
    toggleTheme: () => {
      setThemeMode(current =>
        current === THEME_MODES.LIGHT
          ? THEME_MODES.DARK
          : THEME_MODES.LIGHT
      );
    },
    setSystemTheme: () => setThemeMode(THEME_MODES.SYSTEM)
  };

  return (
    
      {children}
    
  );
};

export const useTheme = () => {
  const context = useContext(ThemeContext);
  return context;
};

export const useThemeColors = () => {
  const { colors } = useTheme();
  return colors;
};

 

Tema için context yapısı hazırlandıktan sonra, App.js ' içinde nasıl sarmaladığımızı görebilirsiniz. En dış katmanda bulunarak screenlerin erişilmesi sağlanmıştır.

  • const { isDark } = useTheme();  buradaki tanım ile uygulamanın teması belirlenip ve state içinde tututlur.
  • const colors = useThemeColors(); burada ise renklere erişebilmek için bu şekilde tanımlanır. color çağrıldığında kendisi uygulamanın temasına göre light veya dark altındaki değerlerin okunması sağlanır.

App.js

import React from `react`;
import {DarkTheme, NavigationContainer} from `@react-navigation/native`;
import StackNavigation from `./navigation`;
import {LogBox} from `react-native`;
import {DefaultTheme, PaperProvider} from `react-native-paper`;
import {ThemeProvider ,useTheme, useThemeColors} from "./screens/context/ThemeContext";



const AppContent = () => {
    const { isDark } = useTheme();
    const colors = useThemeColors();


    const CustomLightTheme = {
        ...DefaultTheme,
        colors: {
            ...DefaultTheme.colors,
            background: colors.neutrals_50,
        },
    };


    const CustomDarkTheme = {
        ...DarkTheme,
        colors: {
            ...DarkTheme.colors,
            background: colors.neutrals_950,
        },
    };
    return (
        
            
                
            
        
    )
}

const App = () => {
  console.warn = () => {};
  LogBox.ignoreAllLogs(true);

    return (
        
            
        
    );



};

export default App;

 Aşağıda uygulama içinde tema değiştiği takdirde context üzerinden ilgili config ayarları yapılır. ve uygulama teması değiştirilmesi gerçekleşir.

  setTheme(value ? THEME_MODES.DARK : THEME_MODES.LIGHT)}
   value={isDark}
   styleContainer={{ alignSelf: `center` }}
   size={8}
                   />

 

Aşağıda da style dosyalarının çağrılımı gösterilmektedir. colors nasıl çağrıldığı görülmetkedir. colors ilgili style dosyalarına parametre ile gönderilerek ilgili dosyada colors temanın türünü göre ilgili rengin seçilmesi sağlanır.

  const colors = useThemeColors();
  const styles = createStyles(colors);

 

Aşağıda örnekte olduğu gibi colors style dosyasına parametre olarak gönderilir. Bu şekilde colors değerleri temanın türüne göre açık tema için ayrı koyu tema için ayrı renk kodları ayarlanmış olur.

styles.js

import { StyleSheet} from `react-native`;


const createStyles = (colors) => StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: colors.primary_500,
  },

});

export default createStyles;

 

Uygulama genel olarak bu şekilde ayarlanmıştır. React native üzerinde açık ve koyu tema göstermeye çalıştım. Aklınıza takılan soru varsa iletişime geçebilirsiniz.

İletişim

Bana ulaşmak için aşağıdaki formu kullanabilirsiniz. Sorularınızı, önerilerinizi veya işbirliği taleplerinizi iletmekten memnuniyet duyarım.

contactLoading
{{ contactErrorMessage }}
{{ contactSentMessage }}
İletişime Geçin

Her türlü soru ve talebiniz için benimle iletişime geçebilirsiniz.