How to customize a date picker

2020-03-15 23:53发布

问题:

I’m using the showDatePicker() method to display a date picker in my flutter application. How do I customize the colors of the date picker?

Here is my theme's code:

class CustomTheme extends Theme {
  /*
   * Colors:
   *    Primary Blue: #335C81 (51, 92, 129)
   *    Light Blue:   #74B3CE (116, 179, 206)
   *    Yellow:       #FCA311 (252, 163, 17)
   *    Red:          #E15554 (255, 85, 84)
   *    Green:        #3BB273 (59, 178, 115)
   */

  static int _fullAlpha = 255;
  static Color blueDark =  new Color.fromARGB(_fullAlpha, 51, 92, 129);
  static Color blueLight = new Color.fromARGB(_fullAlpha, 116, 179, 206);
  static Color yellow =    new Color.fromARGB(_fullAlpha, 252, 163, 17);
  static Color red =       new Color.fromARGB(_fullAlpha, 255, 85, 84);
  static Color green =     new Color.fromARGB(_fullAlpha, 59, 178, 115);

  static Color activeIconColor = yellow;


  CustomTheme(Widget child): super(
    child: child,
    data: new ThemeData(
      primaryColor: blueDark,
      accentColor: yellow,
      cardColor: blueLight,
      backgroundColor: blueDark,
      highlightColor: red,
      splashColor: green
    )
  );
}

Here is my code for wrapping the page in the theme:

  @override
  Widget build(BuildContext context) {
    [...]
    return new CustomTheme(
      new Scaffold(
        [...]
      )
    );
  }

回答1:

I assume that you want to customize the date picker differently from your main theme. Normally, date picker follow your main theme.

If so, wrap the button that triggers the action in a Builder inside a Theme. For example, here's a FAB that pops up an orange date picker (in a light material app theme), inheriting the rest from the main theme.

  floatingActionButton: new Theme(
    data: Theme.of(context).copyWith(
          primaryColor: Colors.amber,
        ),
    child: new Builder(
      builder: (context) => new FloatingActionButton(
            child: new Icon(Icons.date_range),
            onPressed: () => showDatePicker(
                  context: context,
                  initialDate: new DateTime.now(),
                  firstDate:
                      new DateTime.now().subtract(new Duration(days: 30)),
                  lastDate: new DateTime.now().add(new Duration(days: 30)),
                ),
          ),
    ),
  ),

Check the source code of date_picker.dart to see which parts of the Theme affect different aspects of the date picker.

If you just want the picker to follow the main theme, here's a working example

import 'package:flutter/material.dart';

class PickerThemeDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(title: const Text('Picker theme demo')),
      body: new Container(),
      floatingActionButton: new FloatingActionButton(
        child: new Icon(Icons.date_range),
        onPressed: () => showDatePicker(
              context: context,
              initialDate: new DateTime.now(),
              firstDate: new DateTime.now().subtract(new Duration(days: 30)),
              lastDate: new DateTime.now().add(new Duration(days: 30)),
            ),
      ),
    );
  }
}

Color hexToColor(int rgb) => new Color(0xFF000000 + rgb);

class CustomTheme extends Theme {
  //Primary Blue: #335C81 (51, 92, 129)
  //Light Blue:   #74B3CE (116, 179, 206)
  //Yellow:       #FCA311 (252, 163, 17)
  //Red:          #E15554 (255, 85, 84)
  //Green:        #3BB273 (59, 178, 115)

  static Color blueDark = hexToColor(0x335C81);
  static Color blueLight = hexToColor(0x74B3CE);
  static Color yellow = hexToColor(0xFCA311);
  static Color red = hexToColor(0xE15554);
  static Color green = hexToColor(0x3BB273);

  CustomTheme(Widget child)
      : super(
          child: child,
          data: new ThemeData(
            primaryColor: blueDark,
            accentColor: yellow,
            cardColor: blueLight,
            backgroundColor: blueDark,
            highlightColor: red,
            splashColor: green,
          ),
        );
}

void main() {
  runApp(
    new MaterialApp(
      home: new CustomTheme(new PickerThemeDemo()),
    ),
  );
}

If you want to apply the theme to the whole app, it can be added most concisely (without the need for the CustomTheme class) to the Material app:

Color hexToColor(int rgb) => new Color(0xFF000000 + rgb);

void main() {
  runApp(
    new MaterialApp(
      theme: new ThemeData(
        brightness: Brightness.light,
        primaryColor: hexToColor(0x335C81),
        accentColor: hexToColor(0xFCA311),
        splashColor: hexToColor(0x3BB273),
      ),
      home: new PickerThemeDemo(),
    ),
  );
} 


回答2:

There is builder parameter available with showDatePicker() method.

try this:

const MaterialColor buttonTextColor = const MaterialColor(
  0xFF4A5BF6,
  const <int, Color>{
    50: const Color(0xFF4A5BF6),
    100: const Color(0xFF4A5BF6),
    200: const Color(0xFF4A5BF6),
    300: const Color(0xFF4A5BF6),
    400: const Color(0xFF4A5BF6),
    500: const Color(0xFF4A5BF6),
    600: const Color(0xFF4A5BF6),
    700: const Color(0xFF4A5BF6),
    800: const Color(0xFF4A5BF6),
    900: const Color(0xFF4A5BF6),
  },
);

showDatePicker(
  context: context,
  initialDate: DateTime.now(),
  firstDate: DateTime(2018),
  lastDate: DateTime(2030),
  builder: (BuildContext context, Widget child) {
    return Theme(
        data: ThemeData.light().copyWith(
          primarySwatch: buttonTextColor,//OK/Cancel button text color
          primaryColor: const Color(0xFF4A5BF6),//Head background
          accentColor: const Color(0xFF4A5BF6)//selection color
          //dialogBackgroundColor: Colors.white,//Background color
           ),     
          child: child,
    );
  },
);

and you will get something like this:



回答3:

If you only want to change the theme data for the datePicker you need to wrap the widget responsible for showing the datePicker inside a Builder widget and ultimately wrap it all inside a Theme widget as shown below:

PS: But at the time I was writing this answer, the text color ("OK/CANCEL") was not accepted. It is a issue in the flutter framework. 19623 is the issue.

Widget dateOfBirth(String hintText){

    return Theme(
      data: Theme.of(context).copyWith(
        primaryColor: Color(0xFFFF3661), //color of the main banner
        accentColor: Color(0xFFFF3661), //color of circle indicating the selected date
        buttonTheme: ButtonThemeData(
          textTheme: ButtonTextTheme.accent //color of the text in the button "OK/CANCEL"
        ),
      ),
      child: Builder(              // This widget is required for the theme to be applied
        builder: (context){
          return GestureDetector(
            onTap: () async {

              DateTime initialDate = DateTime(DateTime.now().year - 17,DateTime.now().month,DateTime.now().day);

              final picked = await showDatePicker(
                context: context,
                initialDate: initialDate,
                firstDate: DateTime(DateTime.now().year - 100,DateTime.now().month,DateTime.now().day),
                lastDate: DateTime(DateTime.now().year - 17,DateTime.now().month,DateTime.now().day),
              );

              if(picked != null && picked != dobSelected){
                setState(() {
                  dobSelected = picked; // dobSelected is variable to store the selected value
                });
              }

              return picked;
            },
            child: Padding(        //You can use any other widget here
              padding: const EdgeInsets.symmetric(horizontal: 40.0),
              child: Container(
                  height: 55,
                  width: MediaQuery.of(context).size.width,
                  alignment: Alignment.centerLeft,
                  decoration: BoxDecoration(
                    borderRadius: BorderRadius.all(Radius.circular(3)),
                    color: Color(0xFFF2F2F2),
                  ),
                  padding: const EdgeInsets.symmetric(horizontal: 13),
                  child: dobSelected == null?Text('Date Of Birth',style: TextStyle(color: widget.isLender?Color(0xFF8B8B8B):Color(0xFFB3B1B1),fontSize: 15),):Text(DateFormat('yyyy-MM-dd').format(dobSelected))
              ),
            ),
          );
        },
      ),
    );
  }

Output

Hope this helps!!!



回答4:

The above answers are working except for the Ok/Cancel buttons. Just adding this in case somebody needs help on customizing it. It is a combination of colorScheme and buttonTheme.

showTimePicker(
  context: context,
  initialTime: TimeOfDay(hour: hour, minute: minute),
  builder: (BuildContext context, Widget child) {
    return Theme(
      data: ThemeData.light().copyWith(
          primaryColor: const Color(0xFF8CE7F1),
          accentColor: const Color(0xFF8CE7F1),
          colorScheme: ColorScheme.light(primary: const Color(0xFF8CE7F1)),
          buttonTheme: ButtonThemeData(
            textTheme: ButtonTextTheme.primary
          ),
      ),
      child: child,
    );
  },
);


标签: dart flutter