• Stars
    star
    315
  • Rank 132,951 (Top 3 %)
  • Language
    Dart
  • License
    Apache License 2.0
  • Created over 4 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Easiest way to add support for light and dark theme in your flutter app.

adaptive_theme

Adaptive Theme

Easiest way to add support for light and dark theme in your Flutter app. It allows to manually set light or dark theme and also lets you define themes based on the system. It also persists the theme modes changes across app restarts.

Build Tests Codecov Pub Version

Demo: Adaptive Theme

Index

Getting Started

add following dependency to your pubspec.yaml

dependencies:
  adaptive_theme: <latest_version>

Initialization

You need to wrap your MaterialApp with AdaptiveTheme in order to apply themes.

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return AdaptiveTheme(
      light: ThemeData(
        brightness: Brightness.light,
        primarySwatch: Colors.red,
        accentColor: Colors.amber,
      ),
      dark: ThemeData(
        brightness: Brightness.dark,
        primarySwatch: Colors.red,
        accentColor: Colors.amber,
      ),
      initial: AdaptiveThemeMode.light,
      builder: (theme, darkTheme) => MaterialApp(
        title: 'Adaptive Theme Demo',
        theme: theme,
        darkTheme: darkTheme,
        home: MyHomePage(),
      ),
    );
  }
}

Changing Theme Mode

Now that you have initialized your app as mentioned above. It's very easy and straight forward to change your theme modes: light to dark, dark to light or to system default.

// sets theme mode to dark
AdaptiveTheme.of(context).setDark();

// sets theme mode to light
AdaptiveTheme.of(context).setLight();

// sets theme mode to system default
AdaptiveTheme.of(context).setSystem();

Toggle Theme Mode

AdaptiveTheme allows you to toggle between light, dark and system theme the easiest way possible.

AdaptiveTheme.of(context).toggleThemeMode();

Changing Themes

If you want to change the theme entirely like change all the colors to some other color swatch, then you can use setTheme method.

AdaptiveTheme.of(context).setTheme(
  light: ThemeData(
    brightness: Brightness.light,
    primarySwatch: Colors.purple,
    accentColor: Colors.amber,
  ),
  dark: ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.purple,
    accentColor: Colors.amber,
  ),
);

Reset Theme

AdaptiveTheme is smart enough to keep your default themes handy that you provided at the time of initialization. You can fallback to those default themes in a very easy way.

AdaptiveTheme.of(context).reset();

This will reset your theme as well as theme mode to the initial values provided at the time of initialization.

Set Default Theme

AdaptiveTheme persists theme mode changes across app restarts and uses the default themes to set theme modes(light/dark) on. You can change this behavior if you want to set a different theme as default theme other then the one provided at the time of initialization.

This comes handy when you're fetching themes remotely on app starts and setting theme as current theme.

Doing so is quit easy. You would set a new theme normally as you do by calling setTheme method but this time, with a flag isDefault set to true.

This is only useful when you might want to reset to default theme at some point.

AdaptiveTheme.of(context).setTheme(
  light: ThemeData(
    brightness: Brightness.light,
    primarySwatch: Colors.blue,
    accentColor: Colors.amber,
  ),
  dark: ThemeData(
    brightness: Brightness.dark,
    primarySwatch: Colors.blue,
    accentColor: Colors.amber,
  ),
  isDefault: true,
);

Get ThemeMode at App Start

When you change your theme, next app run won't be able to pick the most recent theme directly before rendering with default theme first time. This is because at time of initialization, we cannot run async code to get previous theme mode. However it can be avoided if you make your main() method async and load previous theme mode asynchronously. Below example shows how it can be done.

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  final savedThemeMode = await AdaptiveTheme.getThemeMode();
  runApp(MyApp(savedThemeMode: savedThemeMode));
}
AdaptiveTheme(
  light: lightTheme,
  dark: darkTheme,
  initial: savedThemeMode ?? AdaptiveThemeMode.light,
  builder: (theme, darkTheme) => MaterialApp(
    title: 'Adaptive Theme Demo',
    theme: theme,
    darkTheme: darkTheme,
    home: MyHomePage(),
  ),
)

Notice that I passed the retrieved theme mode to my material app so that I can use it while initializing the default theme. This helps avoiding theme change flickering on app startup.

Listen to the theme mode changes

You can listen to the changes in the theme mode via a ValueNotifier. This can be useful when designing theme settings screen or developing ui to show theme status.

AdaptiveTheme.of(context).modeChangeNotifier.addListener(() {
  // do your thing.
});

Or you can utilize it to react on UI with

ValueListenableBuilder(
  valueListenable: AdaptiveTheme.of(context).modeChangeNotifier,
  builder: (_, mode, child) {
    // update your UI
    return Container();
  },
);

Ceveats

Non-Persist theme changes

This is only useful in scenarios where you load your themes dynamically from network in the splash screen or some initial screens of the app. Please note that AdaptiveTheme does not persist the themes, it only persists the theme modes(light/dark/system). Any changes made to the provided themes won't be persisted and you will have to do the same changes at the time of the initialization if you want them to apply every time app is opened. e.g changing the accent color.

Using SharedPreferences

This package uses shared_preferences plugin internally to persist theme mode changes. If your app uses shared_preferences which might be the case all the time, clearing your shared_preferences at the time of logging out or signing out might clear these preferences too. Be careful not to clear these preferences if you want it to be persisted.

/// Do not remove this key from preferences
AdaptiveTheme.prefKey

You can use above key to exclude it while clearing the all the preferences.

Or you can call AdaptiveTheme.persist() method after clearing the preferences to make it persistable again as shown below.

final prefs = await SharedPreferences.getInstance();
await pref.clear();
AdaptiveTheme.persist();

Using CupertinoTheme

Wrap your CupertinoApp with CupertinoAdaptiveTheme in order to apply themes.

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return CupertinoAdaptiveTheme(
      light: CupertinoThemeData(
        brightness: Brightness.light,
      ),
      dark: CupertinoThemeData(
        brightness: Brightness.dark,
      ),
      initial: AdaptiveThemeMode.light,
      builder: (theme) => CupertinoApp(
        title: 'Adaptive Theme Demo',
        theme: theme,
        darkTheme: darkTheme,
        home: MyHomePage(),
      ),
    );
  }
}

Changing Cupertino Theme

// sets dark theme
CupertinoAdaptiveTheme.of(context).setDark();

// sets light theme
CupertinoAdaptiveTheme.of(context).setLight();

// sets system default theme
CupertinoAdaptiveTheme.of(context).setSystem();

Contribution

You are most welcome to contribute to this project!

Please have a look at Contributing Guidelines, before contributing and proposing a change.

Liked Adaptive Theme?

Show some love and support by starring the repository.

Or You can

Buy Me A Coffee

License

Copyright © 2020 Birju Vachhani

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

More Repositories

1

locus-android

An Awesome Kotlin Location library to retrieve location merely in 3 lines of code
Kotlin
328
star
2

spider

A small dart library to generate Assets dart code from assets folder.
Dart
163
star
3

target_mate

A companion app for Toggl track to track & manage your working hours to achieve your monthly goals.
Dart
65
star
4

screwdriver

A dart package aiming to provide useful extensions and helper functions to ease and speed up development.
Dart
20
star
5

expanding_flex_cards

A Flutter project that expands a card when clicked and collapses others.
Dart
17
star
6

pluto

A minimal new tab for Chrome/Edge.
Dart
17
star
7

bext

A kotlin extensions library to remove boilerplate code using Kotlin DSL. See wiki for more examples...
Kotlin
17
star
8

freedom

Freedom is an Android library to handle runtime permissions in easiest way.
Kotlin
16
star
9

gitmoji-android-live-templates

Awesome Android Studio Live Templates to decorate your git commit messages
15
star
10

gradle-utils

A small utility for gradle dependency management that saves a lot of precious time of developer wasted on finding required dependencies for Android libraries.
Kotlin
8
star
11

revix-android

Kotlin
7
star
12

login-mvvm-final-code

Kotlin
7
star
13

gradle_properties

A dart package allowing to work with Gradle properties files.
Dart
6
star
14

flutter-vs-jetpack-compose-ui

Kotlin
6
star
15

android-studio-settings

All about Android Studio settings that I use.
6
star
16

flutter_screwdriver

A flutter package aiming to provide useful extensions and helper functions to ease and speed up development.
Dart
5
star
17

char_animated_text

A char animated text that shows random characters before showing actual ones when hovered.
Dart
5
star
18

flutter_not_paid

Client did not pay? Add opacity to the body tag and decrease it every day until their site completely fades away. Set a due date and customize the number of days you offer them until the website is fully vanished.
Dart
5
star
19

gradle-kotlin-dsl-demo

An example of Gradle Kotlin DSL scripts for Android Project.
Kotlin
4
star
20

kiosk-demo-android

Shows how to use device policies manager to enable kiosk(lockdown) mode in Android
Kotlin
4
star
21

adbwifi-cli

A small cli app built using node to connect android devices wirelessly for easy development.
JavaScript
3
star
22

Socio

Social Integrations made easy.
Kotlin
3
star
23

awesome-animations-android

Java
2
star
24

vector-animations-android

Kotlin
2
star
25

login-mvvm-starter

Kotlin
2
star
26

birjuvachhani

2
star
27

retrofit-demo

Java
2
star
28

ndk-secure-keys-android

CMake
2
star
29

flutter_animated

A showcase of animated widgets.
Dart
2
star
30

qlocktwo

An intriguing clock that features a unique grid of 110 letter to display the time.
Dart
2
star
31

cursor_trail

A pictures stack that follow your cursor.
Dart
1
star
32

android-studio-settings-test

Dart
1
star
33

python-practicals

Basic Python practicals to begin with python
Python
1
star
34

spider-plugin

Kotlin
1
star
35

cursor_blob

A background gradient blob that follows your cursor. Inspired by poppr.be
Dart
1
star
36

bottom-dialog-android

Kotlin
1
star
37

login-sample-ktor

Kotlin
1
star