React Native를 사용한 iOS 다크 모드

소개



iOS 13에는 사용자가 시스템 전체의 밝은 테마 또는 어두운 테마 중에서 선택할 수 있는 기능인 다크 모드가 도입되었습니다. 그 당시 많은 사람들은 이것을 눈속임으로만 여겼습니다. 얼마 지나지 않아 Whatsapp, Facebook Messenger, Youtube 또는 Gmail은 iOS 앱의 밝은 버전과 어두운 버전을 모두 내놓았습니다.


더 버지의 이미지

여기에서 시작



앱을 디자인하기 전에 Apple Human Interface Guidelines을 읽어 보십시오. 디자인 세부 사항에 대해서는 다루지 않겠지만 here은 훌륭한 리소스입니다.

주요 내용:
  • iOS는 밝거나 어두운 모드에 자동으로 적응하는 동적 시스템 색상을 제공합니다.
  • 앱은 사람들이 설정에서 선택한 모양 모드를 준수해야 합니다.

  • 앱을 만들어 봅시다



    React Native CLI을 사용하여 새 응용 프로그램을 만들 것입니다. Github에서 최종 버전을 확인하거나 따라갈 수 있습니다.

    npx react-native init DarkModeExample
    


    App.js에서 생성된 코드를 제거하고 다음 코드로 바꾸십시오.

    import React from 'react';
    import {View, Text, StyleSheet} from 'react-native';
    
    const App = () => (
      <View style={styles.container}>
        <Text>Hello World</Text>
      </View>
    );
    
    const styles = StyleSheet.create({
      container: {
        justifyContent: 'center',
        alignItems: 'center',
        flex: 1,
      },
    });
    
    export default App;
    


    이제 앱을 사용자 정의할 준비가 되었습니다.

    1. 시작 화면



    시작 화면으로 사용자 지정을 시작하겠습니다. 이것은 응용 프로그램이 실행될 때 잠시 동안 나타나는 스플래시 화면입니다.

    Xcode에서 프로젝트를 엽니다.


    LaunchScreen.storyboard로 이동하여 보기의 배경색을 SystemBackground로 변경했는지 확인합니다. SystemBackground는 밝은 테마의 경우 순수한 흰색이고 어두운 테마의 경우 순수한 검정입니다. 또한 "DarkModeExample"텍스트의 색상을 시스템 주황색으로 변경했습니다.

    결과를 보려면 시뮬레이터에서 설정->개발자->모양으로 이동하여 어두운 모양과 밝은 모양 사이를 전환하고 앱을 엽니다. 선택한 항목에 따라 LaunchScreen이 적절하게 변경되어야 합니다.

    2. 로그인 화면 추가



    데모 목적으로 로그인 화면을 디자인합니다.
    많은 UI 키트와 라이브러리는 다크 모드가 iOS에 출시되기 전부터 테마 기능을 제공했습니다. 대부분은 React Context에 의존하여 이러한 종류의 기능을 제공합니다.

    React Native 0.63 도입PlatformColor . PlatformColor를 사용하면 기본 색상의 해당 문자열 값을 제공하여 대상 플랫폼의 기본 색상에 액세스할 수 있습니다.

    backgroundColor: PlatformColor('systemBackground')
    


    systemBackground는 기본 iOS 색상입니다. 그 이상으로 동적이므로 밝은 테마의 경우 값이 #fff이고 어두운 테마의 경우 #000입니다. 설정에서 사용자가 테마를 변경하면 색상이 자동으로 변경됩니다.

    이제 App.js 파일을 업데이트해 보겠습니다.

    import React from 'react';
    import {
      KeyboardAvoidingView,
      Platform,
      PlatformColor,
      Pressable,
      StyleSheet,
      Text,
      TextInput,
      View,
    } from 'react-native';
    
    const App = () => {
      return (
        <View style={styles.container}>
          <KeyboardAvoidingView
            style={styles.contentContainer}
            behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
            <View style={styles.form}>
              <TextInput
                paddingLeft={10}
                autoCapitalize="none"
                autoCorrect={false}
                keyboardType="email-address"
                placeholder="Email"
                placeholderTextColor={Platform.select({
                  ios: PlatformColor('secondaryLabel'),
                  android: 'white',
                })}
                style={styles.input}
              />
    
              <TextInput
                paddingLeft={10}
                secureTextEntry
                autoCapitalize="none"
                autoCorrect={false}
                placeholder="Password"
                placeholderTextColor={Platform.select({
                  ios: PlatformColor('secondaryLabel'),
                })}
                style={styles.input}
              />
    
              <View>
                <Pressable style={styles.loginButton}>
                  <Text style={styles.label}>Login</Text>
                </Pressable>
              </View>
            </View>
          </KeyboardAvoidingView>
        </View>
      );
    };
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        ...Platform.select({
          ios: {backgroundColor: PlatformColor('systemBackground')},
          default: {
            backgroundColor: '#000000ff',
          },
        }),
      },
      contentContainer: {
        flex: 1,
        maxHeight: '90%',
        flexDirection: 'column',
        justifyContent: 'space-evenly',
        alignItems: 'center',
        ...Platform.select({
          ios: {backgroundColor: PlatformColor('systemBackground')},
          default: {
            backgroundColor: '#000000ff',
          },
        }),
      },
      form: {
        width: '90%',
        justifyContent: 'space-between',
        borderRadius: 5,
      },
      input: {
        height: 40,
        marginTop: 10,
        fontWeight: '500',
        borderWidth: 0.3,
        borderRadius: 5,
        ...Platform.select({
          ios: {
            color: PlatformColor('labelColor'),
            backgroundColor: PlatformColor('tertiarySystemBackground'),
            borderColor: PlatformColor('separator'),
          },
          default: {
            backgroundColor: '#1c1c1eff',
            borderColor: '#54545899',
          },
        }),
      },
      loginButton: {
        width: '100%',
        justifyContent: 'center',
        borderRadius: 5,
        height: 40,
        marginTop: 40,
        ...Platform.select({
          ios: {backgroundColor: PlatformColor('systemBlue')},
          android: {backgroundColor: '#0a84ffff'},
          default: {
            backgroundColor: '#0a84ffff',
          },
        }),
      },
      label: {
        fontWeight: '600',
        color: 'white',
        width: '100%',
        fontSize: 20,
        textAlign: 'center',
      },
    });
    
    export default App;
    


    참고: 반응하지 않을 가능성이 있으며 모든 화면 크기에서 잘 보이지 않을 수 있습니다.

    밝은 테마와 어두운 테마 사이를 다시 전환하고 색상이 어떻게 자동으로 업데이트되는지 확인합니다.



    보시다시피 PlatformColor를 사용하여 다양한 iOS 기본 색상을 얻었습니다. 전체 목록을 확인하려면this .

    PlatformColor('systemBlue');
    


    이러한 색상은 iOS 13+에서만 사용할 수 있으므로 이전 버전의 iOS 또는 Android 플랫폼의 경우 대체 값을 제공해야 합니다. 이는 PlatformSelect를 사용하여 수행할 수 있습니다.

    ...Platform.select({
          ios: {backgroundColor: PlatformColor('systemBlue')},
          android: {backgroundColor: '#0a84ffff'},
          default: {
            backgroundColor: '#0a84ffff',
          },
        })
    


    3. 다이나믹 로고 추가



    로그인 화면에서 유일하게 누락된 부분은 일반적으로 이미지인 로고입니다. 로고가 흑백 배경 모두에서 잘 보이지 않을 가능성이 매우 높습니다. 이 문제를 해결하려면 로고에 밝은 버전과 어두운 버전이 필요합니다.

    먼저 다음과 같은 폴더 구조를 만듭니다.

    DarkModeExample
    │   
    │   
    │
    └───src
        └───assets
        │    │   logo_dark.png
        │    │   logo_light.png
        │    │ 
        └─── components
              │  LogoComponent.js
              │
    


    myGithub repository에서 이미지를 가져올 수 있습니다.

    이제 LogoComponent를 구현해 보겠습니다.

    import React from 'react';
    import {useColorScheme, Image} from 'react-native';
    
    const LogoComponent = (props) => {
      const colorScheme = useColorScheme();
    
      return colorScheme === 'dark' ? (
        <Image source={require('./../assets/logo_dark.png')} style={{...props}} />
      ) : (
        <Image source={require('./../assets/logo_light.png')} style={{...props}} />
      );
    };
    
    export default LogoComponent;
    


    보시다시피 React Native는 활성 색 구성표를 문자열로 반환하는 useColorScheme() 후크를 제공합니다. 이를 바탕으로 적절한 버전의 로고를 반환합니다.

    우리가 해야 할 일은 App.js에서 LogoComponent를 가져오고 양식 바로 위에 렌더링하는 것입니다.



    결론



    여기까지 왔군요! 고맙습니다! 이 시점에서 React Native 앱에 다크 모드를 구현할 수 있어야 합니다 🚀

    좋은 웹페이지 즐겨찾기