Dark Theme com React Navigation + Typescript + React Native Paper

27442 단어 reactnativetypescript
Nesse artigo você irá aprender는 React Native, React Navigation, React Native Paper 및 Typescript와 같은 구현 테마와 활용법을 적용하고 있습니다.

Você também pode ver esse tutorial em video e o repositório no Github .

Criando projeto React Native com Typescript



React Native는 Typescript와 함께 프로젝트를 진행하고 있으며, 가장 먼저 시작하고 있습니다.

npx react-native init NavigationTypescriptPaper --template react-native-template-typescript


Referência da documentação

Instalando 반응 탐색



Para instalar o React Navigation precisamos instalar os seguintes pacotes

yarn add @react-navigation/native react-native-screens react-native-safe-area-context


이 종속성은 사용자가 사용할 수 있는 정보를 탐색할 때 사용하지 않는 경우에만 사용할 수 있습니다. Para usarmos um Stack, precisamos instalar

yarn add @react-navigation/stack


Caso vocês esteja usando Mac, rode o comando

npx pod-install ios


E para Android, você precisa editar o arquivo MainActivity.java que fica em android/app/src/main/java/<nome do projeto>/MainActivity.java
import android.os.Bundle;
// ...

public class MainActivity extends ReactActivity {

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(null);
  }

  // ...
}


Referência da documentação

Instalando 리액트 네이티브 페이퍼



Para instalar o React Native Paper precisamos instalar os seguintes pacotes 설치

yarn add react-native-paper react-native-vector-icons


Referência da documentação

Caso você esteja usando Mac, edite sei PodFile e adicione o seguinte código

pod 'RNVectorIcons', :path => '../node_modules/react-native-vector-icons'


Android 사용자는 문서가 필요하지 않습니다android/app/build.gradle.

apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"


Referência da documentação

Criando 또는 ThemeContext 및 ThemeContextProvider



Primeiro iremos importar os temas tanto do React Navigation como do React Native Paper

import {
  DarkTheme as NavigationDarkTheme,
  DefaultTheme as NavigationDefaultTheme,
  NavigationContainer,
} from '@react-navigation/native';
import {
  DarkTheme as PaperDarkTheme,
  DefaultTheme as PaperDefaultTheme,
  Provider as PaperProvider,
} from 'react-native-paper';


E assim iremos dar um merge nos temas, criando um tema light com a junção dos dois temas default e um temas dark com a junção dos dois temas dark.

const lightTheme = {
  ...NavigationDefaultTheme,
  ...PaperDefaultTheme,
  colors: {
    ...NavigationDefaultTheme.colors,
    ...PaperDefaultTheme.colors,
  },
};

const darkTheme = {
  ...NavigationDarkTheme,
  ...PaperDarkTheme,
  colors: {
    ...NavigationDarkTheme.colors,
    ...PaperDarkTheme.colors,
  },
};


Assim teremos os dois temas definidos com os valores default dos dois pacotes e poderemos adicionar nossas próprias cores caso desejado.

Em seguida já podemos definir 2 tipos que usaremos sobre o nosso tema. O Primeiro é criar um tipo que definira o nosso tema, utilizando o typeof do lightTheme , assim caso adicionemos alguma configuração a mais no nosso tema, ele é refletido para o tipo.

export type Theme = typeof lightTheme;


E também definiremos os tipos de temas que teremos, que no caso serálightdark .

export type ThemeType = 'dark' | 'light';


Assim já podemos definir quais dados teremos nosso context가 없습니다. Passaremos o tema atual, assim como seu tipo, um booleano indicando se o tema é dark, para facilitar a comparação na hora de utilizar, uma função para alternar o valor do tema e outra para atualizar diretamente o tema caso seja necessário.

export interface ThemeContextValue {
  theme: Theme;
  themeType: ThemeType;
  isDarkTheme: boolean;
  toggleThemeType: () => void;
  setThemeType: React.Dispatch<React.SetStateAction<ThemeType>>;
}


E assim utilizaremosReact.createContext para criar o contexto e passaremos valores default para cara propriedade.

export const ThemeContext = React.createContext<ThemeContextValue>({
  theme: lightTheme,
  themeType: 'light',
  isDarkTheme: false,
  setThemeType: () => {},
  toggleThemeType: () => {},
});


Como vamos utilizar hooks, já podemos criar o nosso próprio hook que chamaremos de useTheme , simplesmente para facilitar a utilização desse contexto.

export const useTheme = () => useContext(ThemeContext);


컨텍스트를 구현하는 데 사용할 수 있는 항목은 구성 요소에 대한 정의ThemeContextProvider이며 소품과 관련된 인터페이스입니다.

export interface ThemeContextProviderProps {
  children: React.ReactNode;
}

export const ThemeContextProvider = ({children}: ThemeContextProviderProps) => {
    // ...
}


Dentro dele utilizaremos o useColorScheme para saber se o celular está no modo normal ou dark mode e passaremos esse valor para um useState onde armazenaremos o tipo do tema.

export const ThemeContextProvider = ({children}: ThemeContextProviderProps) => {
    const colorScheme = useColorScheme();
    const [themeType, setThemeType] = useState<ThemeType>(colorScheme || 'light');

    // ...
}


Criaremos uma simples função para alternar or tipo do tema.

export const ThemeContextProvider = ({children}: ThemeContextProviderProps) => {
    // ...

    const toggleThemeType = useCallback(() => {
      setThemeType(prev => (prev === 'dark' ? 'light' : 'dark'));
    }, []);

    // ...
}


E também definiremos isDarkTheme e o tema em si a ser utilizado

export const ThemeContextProvider = ({children}: ThemeContextProviderProps) => {
    // ...

    const isDarkTheme = useMemo(() => themeType === 'dark', [themeType]);
  const theme = useMemo(
    () => (isDarkTheme ? darkTheme : lightTheme),
    [isDarkTheme],
  );

    // ...
}


Agora que temos todos os valores do nosso context definidos, podemos renderizar o NavigationContainer eo PaperProvider para passar o tema e também nosso provider com os valores do context.

O componente complete ficaria da seguinte forma

export const ThemeContextProvider = ({children}: ThemeContextProviderProps) => {
  const colorScheme = useColorScheme();
  const [themeType, setThemeType] = useState<ThemeType>(colorScheme || 'light');

  const toggleThemeType = useCallback(() => {
    setThemeType(prev => (prev === 'dark' ? 'light' : 'dark'));
  }, []);

  const isDarkTheme = useMemo(() => themeType === 'dark', [themeType]);
  const theme = useMemo(
    () => (isDarkTheme ? darkTheme : lightTheme),
    [isDarkTheme],
  );

  return (
    <NavigationContainer theme={theme}>
      <PaperProvider theme={theme}>
        <ThemeContext.Provider
          value={{
            theme,
            themeType,
            isDarkTheme,
            setThemeType,
            toggleThemeType,
          }}>
          {children}
        </ThemeContext.Provider>
      </PaperProvider>
    </NavigationContainer>
  );
};


컨텍스트 및 테마 변경 활용



Em nosso App.tsx iremos renderizar o ThemeContextProvider e dentro dele utilizaremos um stack para a navegação através do createStackNavigator . Dentro desse stack teremos uma tela apenas para demonstrar que o tema está funcionando.

const TestScreen = () => {
    // ...
};

const Stack = createStackNavigator();

const App = () => {
  return (
    <ThemeContextProvider>
      <Stack.Navigator>
        <Stack.Screen name="Test" component={TestScreen} />
      </Stack.Navigator>
    </ThemeContextProvider>
  );
};


Dentro da nossa tela de teste, podemos utilizar o custom hook que criamos useTheme para pegar os valores do context e utilizarmos da forma que preferirmos.

const TestScreen = () => {
  const {toggleThemeType, themeType, isDarkTheme, theme} = useTheme();

  return (
    <View>
      <Button mode="contained" onPress={toggleThemeType}>
        Toggle Theme
      </Button>
      <Headline>{themeType}</Headline>
      <Headline>isDarkTheme: {`${isDarkTheme}`}</Headline>
      <Headline>Primary: {theme.colors.primary}</Headline>
    </View>
  );
};


Assim, apertando o botão podemos ver que o tema muda.

Podemos analisar também que se você colocar o celular no modo escuro, o aplicativo já inicia o tema como dark .

좋은 웹페이지 즐겨찾기