Search code examples
flutterdartsharedpreferencesflutter-provider

trying to do color picker in flutter


I was trying to do a Color Picker for my app in flutter...

i installed the Mtaerial Color Picker package from pub dev...

then i tried to make a Provider like i made for my Dark Mode...

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

class ThemeProvider with ChangeNotifier {
  ThemeData _selectedTheme;
  int primaryValue;

  static Color secondaryColor;

  ThemeProvider({
    bool isDarkMode,
    int primaryValue,
  }) {
    this._selectedTheme = isDarkMode ? dark : light;
    this.primaryValue = colorValue;
  }
  static int colorValue;

  ThemeData light = ThemeData.light().copyWith(
    primaryColor: Color(colorValue) ?? Colors.teal[700],
  );
  ThemeData dark = ThemeData.dark().copyWith();

  void changeColor(int value) async {
    SharedPreferences prefs = await SharedPreferences.getInstance();

    colorValue = value;
    primaryValue = colorValue;
    print(colorValue);
    prefs.setInt('PrimaryColor', primaryValue);
    notifyListeners();
  }

  void swapTheme() async {
    SharedPreferences prefs = await SharedPreferences.getInstance();
    if (_selectedTheme == dark) {
      _selectedTheme = light;
      prefs.setBool('isDarkTheme', false);
      print(prefs.getBool('isDarkTheme'));
    } else {
      _selectedTheme = dark;
      prefs.setBool('isDarkTheme', true);
      print(prefs.getBool('isDarkTheme'));
    }
    notifyListeners();
  }

  ThemeData get getTheme => _selectedTheme;
}

the swapTheme() is for my dark Mode and the change Color it is For my problem i get the Color int from my picker like that:

  MaterialColorPicker(
        circleSize: 50,
      selectedColor:
              _selectedColor ?? Colors.teal[700],
        onColorChange: (Color color) {
       setState(() {
           _selectedColor = color;
                        String primaryColorString =
                           _selectedColor.toString();
                        String valueString = primaryColorString
                       .split('(0x')[1]
                           .split(')')[0];
                  int value =
                int.parse(valueString, radix: 16);
             themeProvider.changeColor(value);
          });
         },
        ),

and when i choose a color it just activate the change color function where it should rebuild my app because i am using provider in my main.dart thats how my Dark Mode is working

return runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(
          create: (BuildContext context) => ThemeProvider(
            isDarkMode: prefs.getBool('isDarkTheme') ?? false,
            primaryValue: prefs.getInt('PrimaryColor') ?? 4293467747,
          ),
        ),
      ],
      child: MyApp(),
    ),
  );
}
return Consumer<ThemeProvider>(
      builder: (context, themeProvider, _) {
        return MaterialApp(
          debugShowCheckedModeBanner: false,
          title: 'Flutter Demo',
          theme: themeProvider.getTheme,

tho its giving me This Error

The method '&' was called on null.

Receiver: null Tried calling:

&(4294967295)

and this too

Bad state: Tried to read a provider that threw during the creation of its value.

The exception occurred during the creation of type ThemeProvider.


Solution

  • okay so it should be done this way this is my darkMode changer the theme one :

    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    class DarkModeProvider with ChangeNotifier {
      ThemeData _selectedTheme;
    
      DarkModeProvider({
        bool isDarkMode,
      }) {
        this._selectedTheme = isDarkMode ? dark : light;
      }
      ThemeData light = ThemeData.light();
      ThemeData dark = ThemeData.dark();
    
      void swapDarkMode() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        if (_selectedTheme == dark) {
          _selectedTheme = light;
          prefs.setBool('isDarkMode', false);
        } else {
          _selectedTheme = dark;
          prefs.setBool('isDarkMode', true);
        }
        notifyListeners();
      }
    
      ThemeData get getTheme => _selectedTheme;
    }
    

    my color changer file:

    import 'package:flutter/material.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    
    class ColorChanger with ChangeNotifier {
      int primary;
      int secondary;
      ColorChanger({
        this.primary,
        this.secondary,
      });
      void changePrimaryColor(int prim) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        primary = prim;
        prefs.setInt('Primary', primary);
        notifyListeners();
      }
    
      void changeSecondaryColor(int second) async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        secondary = second;
        prefs.setInt('Secondary', secondary);
        notifyListeners();
      }
    
      int get getPrimColor => primary;
      int get getSecondColor => secondary;
    }
    

    where i change both is my setting page you put the widgets in any page...

    import 'package:flutter/material.dart';
    import 'package:provider/provider.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:flutter_material_color_picker/flutter_material_color_picker.dart';
    
    import '../providers/color_provider.dart';
    import '../providers/dark_mode_provider.dart';
    
    class SettingsScreen extends StatefulWidget {
      static const routeName = '/settings';
      @override
      _SettingsScreenState createState() => _SettingsScreenState();
    }
    
    class _SettingsScreenState extends State<SettingsScreen> {
      bool _darkValue = false;
    
      Color _selectedPrimaryColor;
      Color _selectedSecondaryColor;
    
      _onBackPressed() {
        Navigator.of(context).pushReplacementNamed('/home');
      }
    
      getSharedPrefs() async {
        SharedPreferences prefs = await SharedPreferences.getInstance();
        var value = prefs.getBool('isDarkMode') ?? false;
        if (value == false) {
          setState(() {
            _darkValue = false;
          });
        } else {
          setState(() {
            _darkValue = true;
          });
        }
      }
    
      @override
      void initState() {
        super.initState();
        getSharedPrefs();
      }
    
      @override
      Widget build(BuildContext context) {
        DarkModeProvider darkModeProvider = Provider.of<DarkModeProvider>(
          context,
          listen: false,
        );
        ColorChanger colorChanger = Provider.of<ColorChanger>(
          context,
          listen: false,
        );
        return WillPopScope(
          onWillPop: () {
            return _onBackPressed();
          },
          child: Scaffold(
            appBar: AppBar(
              leading: IconButton(
                icon: Icon(Icons.arrow_back),
                onPressed: () {
                  _onBackPressed();
                },
              ),
            ),
            body: Container(
              margin: EdgeInsets.symmetric(
                horizontal: 20,
                vertical: 5,
              ),
              child: Column(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Flexible(
                        child: Container(
                          child: Text(
                            'Dark Mode',
                            style: TextStyle(
                              fontSize: 20,
                            ),
                          ),
                        ),
                      ),
                      Switch(
                          value: _darkValue,
                          onChanged: (toggle) {
                            darkModeProvider.swapDarkMode();
                            getSharedPrefs();
                          }),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Flexible(
                        child: Container(
                          child: Text(
                            'Primary Colors',
                            style: TextStyle(
                              fontSize: 20,
                            ),
                          ),
                        ),
                      ),
                      TextButton(
                        onPressed: () {
                          return showDialog(
                            context: context,
                            builder: (BuildContext context) {
                              return AlertDialog(
                                actions: <Widget>[
                                  IconButton(
                                    onPressed: () {
                                      Navigator.of(context).pop(true);
                                    },
                                    icon: Icon(Icons.check),
                                  ),
                                ],
                                content: SingleChildScrollView(
                                  child: Container(
                                    height:
                                        MediaQuery.of(context).size.height * 0.35,
                                    child: MaterialColorPicker(
                                      circleSize: 50,
                                      selectedColor:
                                          Color(colorChanger.getPrimColor) ??
                                              Colors.teal[700],
                                      onColorChange: (Color color) {
                                        setState(() {
                                          _selectedPrimaryColor = color;
                                          colorChanger.changePrimaryColor(
                                              _selectedPrimaryColor.value);
                                        });
                                      },
                                    ),
                                  ),
                                ),
                              );
                            },
                          );
                        },
                        child: CircleAvatar(
                          child: Icon(
                            Icons.color_lens,
                            color: Colors.white54,
                          ),
                          backgroundColor:
                              Color(colorChanger.getPrimColor) ?? Colors.teal[700],
                        ),
                      ),
                    ],
                  ),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Flexible(
                        child: Container(
                          child: Text(
                            'Secondary Colors',
                            style: TextStyle(
                              fontSize: 20,
                            ),
                          ),
                        ),
                      ),
                      TextButton(
                        onPressed: () {
                          return showDialog(
                            context: context,
                            builder: (BuildContext context) {
                              return AlertDialog(
                                actions: <Widget>[
                                  IconButton(
                                    onPressed: () {
                                      Navigator.of(context).pop(true);
                                    },
                                    icon: Icon(Icons.check),
                                  ),
                                ],
                                content: SingleChildScrollView(
                                  child: Container(
                                    height:
                                        MediaQuery.of(context).size.height * 0.35,
                                    child: MaterialColorPicker(
                                      circleSize: 50,
                                      selectedColor:
                                          Color(colorChanger.getSecondColor) ??
                                              Colors.amber,
                                      onColorChange: (Color color) {
                                        setState(() {
                                          _selectedSecondaryColor = color;
                                          colorChanger.changeSecondaryColor(
                                              _selectedSecondaryColor.value);
                                        });
                                      },
                                    ),
                                  ),
                                ),
                              );
                            },
                          );
                        },
                        child: CircleAvatar(
                          child: Icon(
                            Icons.color_lens,
                            color: Colors.white54,
                          ),
                          backgroundColor:
                              Color(colorChanger.getSecondColor) ?? Colors.amber,
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }
    

    here i used shared prefs.. so i can see my switch button functioning with the shared prefs

    and here how you can use the both provider in the Themedata in the main dart:

    import 'package:flutter/material.dart';
    import 'package:flutter/services.dart';
    import 'package:provider/provider.dart';
    import 'package:shared_preferences/shared_preferences.dart';
    import 'package:todo/providers/task_provider.dart';
    import 'package:todo/screens/add_task_screen.dart';
    
    import './screens/settings_screen.dart';
    import './providers/color_provider.dart';
    import './providers/dark_mode_provider.dart';
    import './screens/home_screen.dart';
    
    void main() async {
      WidgetsFlutterBinding.ensureInitialized();
      SharedPreferences prefs = await SharedPreferences.getInstance();
      return runApp(
        MultiProvider(
          providers: [
            ChangeNotifierProvider(
              create: (BuildContext context) => TaskProvider(),
            ),
            ChangeNotifierProvider(
              create: (BuildContext context) => DarkModeProvider(
                isDarkMode: prefs.getBool('isDarkTheme') ?? false,
              ),
            ),
            ChangeNotifierProvider(
              create: (BuildContext context) => ColorChanger(
                primary: prefs.getInt('Primary') ?? Colors.teal[700].value,
                secondary: prefs.getInt('Secondary') ?? Colors.amber.value,
              ),
            ),
          ],
          child: MyApp(),
        ),
      );
    }
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @override
      Widget build(BuildContext context) {
        SystemChrome.setPreferredOrientations([
          DeviceOrientation.portraitUp,
        ]);
        return Consumer2<DarkModeProvider, ColorChanger>(
            builder: (context, darkmode, colorChanger, _) {
          return MaterialApp(
            debugShowCheckedModeBanner: false,
            title: 'Flutter Demo',
            theme: darkmode.getTheme.copyWith(
              primaryColor: Color(colorChanger.getPrimColor),
              accentColor: Color(colorChanger.getSecondColor),
            ),
            home: HomeScreen(),
            routes: {
              HomeScreen.routeName: (context) => HomeScreen(),
              SettingsScreen.routeName: (context) => SettingsScreen(),
              AddTaskScreen.routeNamed: (context) => AddTaskScreen(),
            },
          );
        });
      }
    }
    

    i guess its helpful i used it in my app..

    thank you guys..