Flutter에서 지속적인 다크 모드 구현

6293 단어
현재 UI/UX 디자인의 현대적 요소는 앱 내에서 다크 모드와 라이트 모드 사이를 전환할 수 있는 기능의 구현입니다. 다행스럽게도 Flutter 개발자에게는 DART에서도 이를 구현할 수 있습니다. 우리 앱에서는 전화 테마에 의존하지 않고 토글 버튼을 사용합니다. 또한 테마를 유지하기를 원하므로 앱 전체 테마에 provider package을 사용하고 테마를 유지하려면 shared preferences을 사용합니다.
프로젝트의 소스 코드를 찾을 수 있습니다here.
먼저 이를 시연하기 위해 간단한 UI를 생성합니다. 시연 목적으로 핀테크 샘플 앱 프런트엔드로 이동했습니다.

import 'package:darkmode/home/homepage.dart';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';


void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
          return MaterialApp(
            title: 'Flutter Demo',
            home: HomePage(),
          );

  }
}


둘째, 시각적 테마를 정의할 수 있는 ThemeData를 이용하여 밝은 테마와 어두운 테마를 정의할 수 있는 클래스를 생성한다. 또한 iconTheme, appBarTheme 및 textTheme와 같은 ThemeData 내의 다양한 속성을 전달합니다.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
ThemeData lightThemeData(BuildContext context) {
  return ThemeData.light().copyWith(
      visualDensity: VisualDensity.adaptivePlatformDensity,
      scaffoldBackgroundColor: Colors.white,
      appBarTheme: appBarTheme,
      iconTheme:const IconThemeData(color: Colors.black),

     textTheme: Theme.of(context).textTheme.apply(bodyColor: Colors.black));
}

ThemeData darkThemeData(BuildContext context) {
  return ThemeData.dark().copyWith(
      visualDensity: VisualDensity.adaptivePlatformDensity,
      scaffoldBackgroundColor:const Color(0xFF1D1D35),
      appBarTheme: appBarTheme,
      iconTheme:const IconThemeData(color: Colors.white),

      textTheme: Theme.of(context).textTheme.apply(bodyColor: Colors.white));
}

const appBarTheme = AppBarTheme(centerTitle: false, elevation: 0);


셋째, Provider packageshared preferences package을 추가합니다. 제공자 패키지를 사용하여 앱 전체 테마 전환을 활성화하고 공유 기본 설정 패키지를 사용하여 지속된 테마 세부 정보를 저장하므로 앱을 종료하고 열 때 다시 올라가면 테마가 지속됩니다.

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:shared_preferences/shared_preferences.dart';


class ThemeProvider extends ChangeNotifier {
 final String key = "theme";
 late SharedPreferences _prefs;
 late bool _darkTheme;

  bool get  darkTheme => _darkTheme;

  ThemeProvider() {
    _darkTheme = true;
    _loadFromPrefs();
  }

  toggleTheme() {
    _darkTheme = !_darkTheme;
    _saveToPrefs();
    notifyListeners();
  }

  _initPrefs() async {
    // if(_prefs == null)
      _prefs = await SharedPreferences.getInstance();
  }

  _loadFromPrefs() async {
    await _initPrefs();
    _darkTheme = _prefs.getBool(key) ?? true;
    notifyListeners();
  }

  _saveToPrefs()async {
    await _initPrefs();
    _prefs.setBool(key, _darkTheme);
  }
}


이 작업을 완료하면 main.dart의 Materialapp으로 돌아가서 ChangeNotifier.notifyListeners가 호출될 때마다 자손의 ChangeNotifier 위젯을 수신하고 종속 항목을 다시 빌드하는 ChangeNotifierProvider 위젯으로 MaterialApp 위젯을 래핑합니다. 우리는 또한 우리를 위해 provider.of를 호출하고 테마의 변경 사항을 수신하여 필요할 때마다 다시 빌드하는 Consumer 위젯으로 MaterialApp 위젯을 래핑합니다.

import 'package:darkmode/home/homepage.dart';
import 'package:darkmode/provider/theme_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await SystemChrome.setPreferredOrientations([
    DeviceOrientation.portraitUp,
    DeviceOrientation.portraitDown,
  ]);
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
        create: (_) => ThemeProvider(),
        child: Consumer<ThemeProvider>(
            builder: (context, ThemeProvider notifier, child) {
          return MaterialApp(
            title: 'Flutter Demo',
            theme: notifier.darkTheme
                ? darkThemeData(context)
                : lightThemeData(context),
            debugShowCheckedModeBanner: false,
            home: HomePage(),
          );
        }));
  }
}


이제 밝은 모드와 어두운 모드 사이를 전환할 수 있는 스위치 버튼을 만듭니다. 전환 버튼을 소비자 위젯으로 래핑하여 ThemeProvider의 변경 사항을 수신합니다.

import 'package:darkmode/provider/theme_provider.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';


class ChangeThemeButtonWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Consumer<ThemeProvider>(
      builder: (context, notifier, child) => Switch.adaptive(
        value: notifier.darkTheme,
        onChanged: (val) {
          notifier.toggleTheme();
          //bool value of switch which is true or false
        },
        activeTrackColor: Colors.green[100],
        inactiveTrackColor: Colors.green[300],
      ),
    );
  }
}


소스 코드를 찾을 수 있는 어두운 모드와 밝은 모드 사이의 전환을 시연하는 쉬운 방법으로 핀테크 프런트엔드를 만들었습니다here.
결과는 다음과 같습니다.


읽어주셔서 감사합니다. Flutter 개발에 관한 더 많은 기사를 기대해 주세요.

좋은 웹페이지 즐겨찾기