card_settings 0.1.14 copy "card_settings: ^0.1.14" to clipboard
card_settings: ^0.1.14 copied to clipboard

outdated

A flutter package for building card based settings forms. This includes a library of pre-built form field widgets.

example/lib/main.dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:card_settings/card_settings.dart';
import 'package:intl/intl.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Card Settings Example',
      home: PonyExample(),
      theme: ThemeData(
        accentColor: Colors.indigo[400], // background color of card headers
        cardColor: Colors.white, // background color of fields
        backgroundColor: Colors.indigo[100], // color outside the card
        primaryColor: Colors.teal, // color of page header
        buttonColor: Colors.lightBlueAccent[100], // background color of buttons
        textTheme: TextTheme(
          button:
              TextStyle(color: Colors.deepPurple[900]), // style of button text
          subhead: TextStyle(color: Colors.grey[800]), // style of input text
        ),
      ),
    );
  }
}

// example viewmodel for the form
class PonyModel {
  String name = 'Twilight Sparkle';
  String type = 'Unicorn';
  int age = 7;
  String coatColor = 'D19FE4';
  String maneColor = '273873';
  bool hasSpots = false;
  String spotColor = 'FF5198';
  String description =
      'An intelligent and dutiful scholar with an avid love of learning and skill in unicorn magic such as levitation, teleportation, and the creation of force fields.';
  double height = 3.5;
  int weight = 45;
  DateTime showDateTime = DateTime(2010, 10, 10, 20, 30);
  double ticketPrice = 65.99;
  int boxOfficePhone = 8005551212;
  String email = 'me@nowhere.org';
  String password = 'secret1';
}

class PonyExample extends StatefulWidget {
  @override
  _PonyExampleState createState() => _PonyExampleState();
}

class _PonyExampleState extends State<PonyExample> {
  final _ponyModel = PonyModel();

  bool _autoValidate = false;

  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
  final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();

  // control state only works if the field order never changes.
  // to support orientation changes, we assign a unique key to each field
  // if you only have one orientation, the _formKey is sufficient
  final GlobalKey<FormState> _nameKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _typeKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _ageKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _descriptionlKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _coatKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _maneKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _hasSpotsKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _spotKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _heightKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _weightKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _dateKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _timeKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _priceKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _phoneKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _emailKey = GlobalKey<FormState>();
  final GlobalKey<FormState> _passwordKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,
      backgroundColor: Theme.of(context).backgroundColor,
      appBar: AppBar(
          title: Text("My Little Pony"),
          actions: <Widget>[
            IconButton(
              icon: Icon(Icons.save),
              onPressed: _savePressed,
            ),
          ],
          leading: IconButton(
            icon: Icon(Icons.refresh),
            onPressed: _resetPressed,
          )),
      body: Form(
        key: _formKey,
        child: Theme(
          data: Theme.of(context).copyWith(
            primaryTextTheme: TextTheme(
              title:
                  TextStyle(color: Colors.lightBlue[50]), // style for headers
            ),
            inputDecorationTheme: InputDecorationTheme(
              labelStyle:
                  TextStyle(color: Colors.indigo[400]), // style for labels
            ),
          ),
          child: OrientationBuilder(
            builder: (context, orientation) {
              return (orientation == Orientation.portrait)
                  ? _buildPortraitLayout()
                  : _buildLandscapeLayout();
            },
          ),
        ),
      ),
    );
  }

  /* CARDSETTINGS FOR EACH LAYOUT */

  CardSettings _buildPortraitLayout() {
    return CardSettings(
      children: <Widget>[
        CardSettingsHeader(label: 'Bio'),
        _buildCardSettingsText_Name(_nameKey),
        _buildCardSettingsListPicker_Type(_typeKey),
        _buildCardSettingsNumberPicker(_ageKey),
        _buildCardSettingsParagraph(_descriptionlKey, 5),
        CardSettingsHeader(label: 'Colors'),
        _buildCardSettingsColorPicker_Coat(_coatKey),
        _buildCardSettingsColorPicker_Mane(_maneKey),
        _buildCardSettingsSwitch_Spots(_hasSpotsKey),
        _buildCardSettingsColorPicker_Spot(_spotKey),
        CardSettingsHeader(label: 'Size'),
        _buildCardSettingsDouble_Height(_heightKey),
        _buildCardSettingsInt_Weight(_weightKey),
        CardSettingsHeader(label: 'First Show'),
        _buildCardSettingsInstructions(),
        _buildCardSettingsDatePicker(_dateKey),
        _buildCardSettingsTimePicker(_timeKey),
        _buildCardSettingsCurrency(_priceKey),
        _buildCardSettingsPhone(_phoneKey),
        CardSettingsHeader(label: 'Security'),
        _buildCardSettingsEmail(_emailKey),
        _buildCardSettingsPassword(_passwordKey),
        CardSettingsHeader(label: 'Actions'),
        _buildCardSettingsButton_Save(),
        _buildCardSettingsButton_Reset(),
        Container(height: 4.0)
      ],
    );
  }

  CardSettings _buildLandscapeLayout() {
    return CardSettings(
      labelPadding: 12.0,
      children: <Widget>[
        CardSettingsHeader(label: 'Bio'),
        _buildCardSettingsText_Name(_nameKey),
        CardFieldLayout_FractionallySpaced(children: <Widget>[
          _buildCardSettingsListPicker_Type(_typeKey),
          _buildCardSettingsNumberPicker(_ageKey, labelAlign: TextAlign.right),
        ], widthFactors: <double>[
          0.7,
          0.3
        ]),
        _buildCardSettingsParagraph(_descriptionlKey, 3),
        // note, different order than portrait to show state mapping
        CardSettingsHeader(label: 'Security'),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsEmail(_emailKey),
          _buildCardSettingsPassword(_passwordKey),
        ]),
        CardSettingsHeader(label: 'Colors'),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsColorPicker_Coat(_coatKey),
          _buildCardSettingsColorPicker_Mane(_maneKey),
        ]),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsSwitch_Spots(_hasSpotsKey),
          _buildCardSettingsColorPicker_Spot(_spotKey),
        ]),
        CardSettingsHeader(label: 'Size'),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsDouble_Height(_heightKey),
          _buildCardSettingsInt_Weight(_weightKey),
        ]),
        CardSettingsHeader(label: 'First Show'),
        _buildCardSettingsInstructions(),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsDatePicker(_dateKey),
          _buildCardSettingsTimePicker(_timeKey),
        ]),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsCurrency(_priceKey),
          _buildCardSettingsPhone(_phoneKey),
        ]),
        CardSettingsHeader(label: 'Actions'),
        CardFieldLayout_EqualSpaced(children: <Widget>[
          _buildCardSettingsButton_Save(),
          _buildCardSettingsButton_Reset(),
          _buildCardSettingsButton_Close(),
        ]),
        Container(height: 4.0)
      ],
    );
  }

  /* BUILDERS FOR EACH FIELD */

  CardSettingsButton _buildCardSettingsButton_Close() {
    return CardSettingsButton(
      label: 'CLOSE',
      onPressed: _closePressed,
      backgroundColor: Colors.greenAccent,
    );
  }

  CardSettingsButton _buildCardSettingsButton_Reset() {
    return CardSettingsButton(
      label: 'RESET',
      onPressed: _resetPressed,
      backgroundColor: Colors.redAccent,
      textColor: Colors.white,
    );
  }

  CardSettingsButton _buildCardSettingsButton_Save() {
    return CardSettingsButton(
      label: 'SAVE',
      onPressed: _savePressed,
    );
  }

  CardSettingsPassword _buildCardSettingsPassword(Key key) {
    return CardSettingsPassword(
      key: key,
      icon: Icon(Icons.lock),
      initialValue: _ponyModel.password,
      validator: (value) {
        if (value == null) return 'Password is required.';
        if (value.length <= 6) return 'Must be more than 6 characters.';
        return null;
      },
      onSaved: (value) => _ponyModel.password = value,
      onChanged: (value) => _showSnackBar('Password', value),
    );
  }

  CardSettingsEmail _buildCardSettingsEmail(Key key) {
    return CardSettingsEmail(
      key: key,
      icon: Icon(Icons.person),
      initialValue: _ponyModel.email,
      validator: (value) {
        if (value == null || value.isEmpty) return 'Email is required.';
        if (!value.contains('@')) return "Email not formatted correctly.";
        return null;
      },
      onSaved: (value) => _ponyModel.email = value,
      onChanged: (value) => _showSnackBar('Email', value),
    );
  }

  CardSettingsPhone _buildCardSettingsPhone(Key key) {
    return CardSettingsPhone(
      key: key,
      label: 'Box Office',
      initialValue: _ponyModel.boxOfficePhone,
      validator: (value) {
        if (value != null && value.toString().length != 10)
          return 'Incomplete number';
        return null;
      },
      onSaved: (value) => _ponyModel.boxOfficePhone = value,
      onChanged: (value) => _showSnackBar('Box Office', value),
    );
  }

  CardSettingsCurrency _buildCardSettingsCurrency(Key key) {
    return CardSettingsCurrency(
      key: key,
      label: 'Ticket Price',
      initialValue: _ponyModel.ticketPrice,
      validator: (value) {
        if (value != null && value > 100) return 'No scalpers allowed!';
        return null;
      },
      onSaved: (value) => _ponyModel.ticketPrice = value,
      onChanged: (value) => _showSnackBar('Ticket Price', value),
    );
  }

  CardSettingsTimePicker _buildCardSettingsTimePicker(Key key) {
    return CardSettingsTimePicker(
      key: key,
      icon: Icon(Icons.access_time),
      label: 'Time',
      initialValue: TimeOfDay(
          hour: _ponyModel.showDateTime.hour,
          minute: _ponyModel.showDateTime.minute),
      onSaved: (value) => _ponyModel.showDateTime =
          updateJustTime(value, _ponyModel.showDateTime),
      onChanged: (value) => _showSnackBar('Show Time', value),
    );
  }

  CardSettingsDatePicker _buildCardSettingsDatePicker(Key key) {
    return CardSettingsDatePicker(
      key: key,
      icon: Icon(Icons.calendar_today),
      label: 'Date',
      initialValue: _ponyModel.showDateTime,
      onSaved: (value) => _ponyModel.showDateTime =
          updateJustDate(value, _ponyModel.showDateTime),
      onChanged: (value) => _showSnackBar('Show Date', value),
    );
  }

  CardSettingsInstructions _buildCardSettingsInstructions() {
    return CardSettingsInstructions(
      text: 'This is when this little horse got her big break',
    );
  }

  CardSettingsInt _buildCardSettingsInt_Weight(Key key) {
    return CardSettingsInt(
      key: key,
      label: 'Weight',
      unitLabel: 'lbs',
      initialValue: _ponyModel.weight,
      validator: (value) {
        if (value != null) {
          if (value > 70) return 'You won\'t fly at the weight.';
          if (value < 10) return 'Cmon, you are not a feather.';
        }
        return null;
      },
      onSaved: (value) => _ponyModel.weight = value,
      onChanged: (value) => _showSnackBar('Weight', value),
    );
  }

  CardSettingsDouble _buildCardSettingsDouble_Height(Key key) {
    return CardSettingsDouble(
      key: key,
      label: 'Height',
      unitLabel: 'feet',
      initialValue: _ponyModel.height,
      onSaved: (value) => _ponyModel.height = value,
      onChanged: (value) => _showSnackBar('Height', value),
    );
  }

  CardSettingsColorPicker _buildCardSettingsColorPicker_Spot(Key key) {
    return CardSettingsColorPicker(
      key: key,
      label: 'Spot',
      initialValue: intelligentCast<Color>(_ponyModel.spotColor),
      visible: _ponyModel.hasSpots,
      onSaved: (value) => _ponyModel.spotColor = colorToString(value),
      onChanged: (value) => _showSnackBar('Spot', value),
    );
  }

  CardSettingsSwitch _buildCardSettingsSwitch_Spots(Key key) {
    return CardSettingsSwitch(
      key: key,
      label: 'Has Spots?',
      initialValue: _ponyModel.hasSpots,
      onChanged: (value) {
        setState(() => _ponyModel.hasSpots = value);
        _showSnackBar('Has Spots?', value);
      },
      onSaved: (value) => _ponyModel.hasSpots = value,
    );
  }

  CardSettingsColorPicker _buildCardSettingsColorPicker_Mane(Key key) {
    return CardSettingsColorPicker(
      key: key,
      label: 'Mane',
      initialValue: intelligentCast<Color>(_ponyModel.maneColor),
      validator: (value) {
        if (value.computeLuminance() > .7) return 'This color is too light.';
        return null;
      },
      onSaved: (value) => _ponyModel.maneColor = colorToString(value),
      onChanged: (value) => _showSnackBar('Mane', value),
    );
  }

  CardSettingsColorPicker _buildCardSettingsColorPicker_Coat(Key key) {
    return CardSettingsColorPicker(
      key: key,
      label: 'Coat',
      initialValue: intelligentCast<Color>(_ponyModel.coatColor),
      validator: (value) {
        if (value.computeLuminance() < .3)
          return 'This color is not cheery enough.';
        return null;
      },
      onSaved: (value) => _ponyModel.coatColor = colorToString(value),
      onChanged: (value) => _showSnackBar('Coat', value),
    );
  }

  CardSettingsParagraph _buildCardSettingsParagraph(Key key, int lines) {
    return CardSettingsParagraph(
      key: key,
      label: 'Description',
      initialValue: _ponyModel.description,
      numberOfLines: lines,
      onSaved: (value) => _ponyModel.description = value,
      onChanged: (value) => _showSnackBar('Description', value),
    );
  }

  CardSettingsNumberPicker _buildCardSettingsNumberPicker(Key key,
      {TextAlign labelAlign}) {
    return CardSettingsNumberPicker(
      key: key,
      label: 'Age',
      labelAlign: labelAlign,
      initialValue: _ponyModel.age,
      min: 1,
      max: 30,
      validator: (value) {
        if (value == null) return 'Age is required.';
        if (value > 20) return 'No grown-ups allwed!';
        if (value < 3) return 'No Toddlers allowed!';
        return null;
      },
      onSaved: (value) => _ponyModel.age = value,
      onChanged: (value) => _showSnackBar('Age', value),
    );
  }

  CardSettingsListPicker _buildCardSettingsListPicker_Type(Key key) {
    return CardSettingsListPicker(
      key: key,
      label: 'Type',
      initialValue: _ponyModel.type,
      autovalidate: _autoValidate,
      options: <String>['Earth', 'Unicorn', 'Pegasi', 'Alicorn'],
      validator: (String value) {
        if (value == null || value.isEmpty) return 'You must pick a type.';
        return null;
      },
      onSaved: (value) => _ponyModel.type = value,
      onChanged: (value) => _showSnackBar('Type', value),
    );
  }

  CardSettingsText _buildCardSettingsText_Name(Key key) {
    return CardSettingsText(
      key: key,
      label: 'Name',
      initialValue: _ponyModel.name,
      requiredIndicator: Text('*', style: TextStyle(color: Colors.red)),
      autovalidate: _autoValidate,
      validator: (value) {
        if (value == null || value.isEmpty) return 'Name type is required.';
        return null;
      },
      onSaved: (value) => _ponyModel.name = value,
      onChanged: (value) => _showSnackBar('Name', value),
    );
  }

  /* EVENT HANDLERS */

  Future _savePressed() async {
    final form = _formKey.currentState;

    if (form.validate()) {
      form.save();
      _showResults();
    } else {
      setState(() => _autoValidate = true);
    }
  }

  void _resetPressed() {
    _formKey.currentState.reset();
  }

  void _closePressed() {
    // This is just a placeholder to have a third button
  }

  void _showSnackBar(String label, dynamic value) {
    _scaffoldKey.currentState.removeCurrentSnackBar();
    _scaffoldKey.currentState.showSnackBar(
      SnackBar(
        content: Text(label + ' = ' + value.toString()),
      ),
    );
  }

  void _showResults() {
    showDialog<String>(
      context: context,
      builder: (BuildContext context) {
        return AlertDialog(
          title: Text('Updated Results'),
          content: SingleChildScrollView(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                _buildResultsRow('Name', _ponyModel.name),
                _buildResultsRow('Type', _ponyModel.type),
                _buildResultsRow('Age', _ponyModel.age),
                Text(_ponyModel.description),
                _buildResultsRow('CoatColor', _ponyModel.coatColor),
                _buildResultsRow('ManeColor', _ponyModel.maneColor),
                _buildResultsRow('HasSpots', _ponyModel.hasSpots),
                _buildResultsRow('SpotColor', _ponyModel.spotColor),
                _buildResultsRow('Height', _ponyModel.height),
                _buildResultsRow('Weight', _ponyModel.weight),
                _buildResultsRow('ShowDate',
                    DateFormat.yMd().format(_ponyModel.showDateTime)),
                _buildResultsRow('ShowTime',
                    DateFormat.jm().format(_ponyModel.showDateTime)),
                _buildResultsRow('Phone', _ponyModel.boxOfficePhone),
                _buildResultsRow('Price', _ponyModel.ticketPrice),
              ],
            ),
          ),
          actions: <Widget>[
            FlatButton(
              child: Text("Close"),
              onPressed: () {
                Navigator.of(context).pop();
              },
            ),
          ],
        );
      },
    );
  }

  Widget _buildResultsRow(String name, dynamic value) {
    return Column(
      children: <Widget>[
        Row(
          children: <Widget>[
            Expanded(
              child: Text(
                '$name:',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
            ),
            Text(value.toString()),
          ],
        ),
        Container(height: 12.0),
      ],
    );
  }
}
238
likes
0
pub points
82%
popularity

Publisher

unverified uploader

A flutter package for building card based settings forms. This includes a library of pre-built form field widgets.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, flutter_colorpicker, flutter_masked_text, intl

More

Packages that depend on card_settings