tx_design 0.2.26 copy "tx_design: ^0.2.26" to clipboard
tx_design: ^0.2.26 copied to clipboard

A custom component library that contains some basic UI components and provides theme configuration.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:tx_design/localizations.dart';
import 'package:tx_design/tx_design.dart';

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

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  ThemeMode _themeMode = ThemeMode.light;

  @override
  Widget build(BuildContext context) {
    const shape = RoundedRectangleBorder(
      borderRadius: BorderRadius.all(Radius.circular(6.0)),
    );

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        disabledColor: const Color(0xFFBBBBBB),
        hoverColor: const Color(0x0FE94F50),
        focusColor: const Color(0x24E94F50),
        splashColor: const Color(0x1CE94F50),
        highlightColor: const Color(0x20E94F50),
        colorScheme: ColorScheme.fromSeed(
          seedColor: const Color(0xFFEA4545),
          error: const Color(0xFFE94F50),
          primary: const Color(0xFFEA4545),
        ),
        listTileTheme: const ListTileThemeData(
          selectedTileColor: Color(0x1AE94F50),
          shape: shape,
        ),
        brightness: Brightness.light,
        extensions: const [
          SpacingThemeData(),
          RadiusThemeData(),
          TxCellThemeData(),
          TxTileThemeData(),
        ],
        bottomSheetTheme: const BottomSheetThemeData(
          backgroundColor: Color(0xFFF9F9F9),
          surfaceTintColor: Color(0xFFF9F9F9),
        ),
        useMaterial3: true,
        textTheme: const TextTheme(
          bodyLarge: TextStyle(fontSize: 16.0, color: Color(0xFF666666)),
        ),
        inputDecorationTheme: const InputDecorationTheme(
          outlineBorder: BorderSide(color: Color(0x1A000000)),
          iconColor: Color(0x40000000),
          prefixIconColor: Color(0xFFB1B7CC),
          suffixIconColor: Color(0x40000000),
          fillColor: Color(0x80FFFFFF),
          filled: true,
        ),
        expansionTileTheme: const ExpansionTileThemeData(
          collapsedShape: shape,
          shape: shape,
        ),
      ),
      themeMode: _themeMode,
      darkTheme: ThemeData(
        colorSchemeSeed: Colors.purple,
        brightness: Brightness.dark,
        extensions: const [
          SpacingThemeData(),
          RadiusThemeData(),
          TxCellThemeData(),
        ],
        useMaterial3: true,
      ),
      locale: const Locale('zh', 'CN'),
      supportedLocales: const [Locale('en', 'US'), Locale('zh', 'CN')],
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
        TxLocalizations.delegate,
      ],
      home: MyHomePage(
        title: 'HomePage',
        changeTheme: () {
          setState(() {
            if (_themeMode == ThemeMode.dark) {
              _themeMode = ThemeMode.light;
            } else {
              _themeMode = ThemeMode.dark;
            }
          });
        },
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title, required this.changeTheme});

  final String title;

  final VoidCallback changeTheme;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Tx Design')),
      body: Form(key: _formKey, child: const FormView()),
      bottomNavigationBar: Padding(
        padding: const EdgeInsets.all(12.0),
        child: ElevatedButton(
          onPressed: () => _formKey.currentState!.validate(),
          child: const Text('验证'),
        ),
      ),
    );
  }
}

class FormView extends StatefulWidget {
  const FormView({super.key});

  static const List<String> sources = ['选项1', '选项2', '选项3'];
  static const List<(String, String)> sources1 = [
    ('选项1', '值1'),
    ('选项2', '值2'),
    ('选项3', '值3'),
  ];
  static const sources2 = [
    {'id': '1'},
    {'id': '11', 'pid': '1'},
    {'id': '12', 'pid': '1'},
    {'id': '111', 'pid': '11'},
    {'id': '112', 'pid': '11'},
    {'id': '121', 'pid': '12'},
    {'id': '122', 'pid': '12'},
    {'id': '2'},
    {'id': '21', 'pid': '2'},
    {'id': '22', 'pid': '2'},
    {'id': '211', 'pid': '21'},
    {'id': '212', 'pid': '21'},
    {'id': '221', 'pid': '22'},
    {'id': '222', 'pid': '22'},
  ];

  @override
  State<FormView> createState() => _FormViewState();
}

class _FormViewState extends State<FormView> {
  final Map form = {'text': 'text'};

  @override
  Widget build(BuildContext context) {
    // return ListTile(
    //   tileColor: Colors.blue,
    //   title: const Text('测试'),
    //   subtitle: const Text('测试'),
    //   // visualDensity: VisualDensity.compact,
    // );
    return SingleChildScrollView(
      padding: const EdgeInsets.symmetric(horizontal: 12.0),
      child: Column(
        children: [
          TxCascadePickerFormField.fromMapList(
            labelText: '级联选择',
            source: FormView.sources2,
            labelKey: 'id',
            onChanged: (val) => form['cascadeValue'] = val,
            initialData: form['cascadeValue'],
            required: true,
            // disabledWhen: (data) => data['id'] == '111',
            // parentCheckable: false,
            // subtitleBuilder: (context, data) => Text(data['id']),
            // showSearchField: false,
            // placeholder: const Center(child: Text('暂无数据')),
            // itemBuilder: (context, data, selected, onChanged) {
            //   return RadioListTile(
            //     value: data,
            //     groupValue: selected,
            //     onChanged: onChanged,
            //     title: Text(data['id']),
            //   );
            // },
            // bordered: true,
            // decoration: InputDecoration(filled: true),
          ),
          TxMultiCascadePickerFormField.fromMapList(
            labelText: '级联多选',
            source: FormView.sources2,
            labelKey: 'id',
            onChanged: (val) => form['cascadeMultiValue'] = val,
            initialData: form['cascadeMultiValue'],
            required: true,
            disabledWhen: (data) => data['id'] == '111',
            parentCheckable: false,
            linkage: false,
            minCount: 1,
            maxCount: 3,
            // bordered: true,
            // decoration: InputDecoration(filled: true),
          ),
          TxTextFormField(
            initialValue: form['text'],
            labelText: '文字输入',
            onChanged: (val) => form['text'] = val,
            required: true,
          ),
          TxPickerFormField(
            labelText: '单项选择',
            source: FormView.sources,
            labelMapper: (val) => val,
            valueMapper: (val) => val,
            onChanged: (val) => form['pickerValue'] = val,
            initialValue: form['pickerValue'],
            required: true,
            clearable: true,
            subtitleBuilder: (context, data) => Text(data),
            disabledWhen: (data) => data == '选项1',
            showSearchField: true,
            placeholder: const Center(child: Text('暂无数据')),
            // itemBuilder: (context, data, selected, onChanged) {
            //   return RadioListTile(
            //     value: data,
            //     groupValue: selected,
            //     onChanged: onChanged,
            //     title: Text(data),
            //   );
            // },
            // readOnly: true,
          ),
          TxDatePickerFormField(
            labelText: '日期选择器',
            onChanged: (date) => form['date'] = date,
            initialDate: form['date'],
            format: 'yyyy/MM/dd',
            titleText: '日期选择器',
            required: true,
            validator: (date) {
              if (date!.isBefore(DateTime.now())) {
                return '请选择大于今日的日期';
              }
              return null;
            },
          ),
          TxDatetimePickerFormField(
            labelText: '日期时间选择器',
            maximumDate: DateTime.now().add(const Duration(days: 10)),
            onChanged: (date) => form['datetime'] = date,
            initialDatetime: form['datetime'],
            titleText: '日期时间选择器',
            required: true,
            validator: (date) {
              if (date!.isBefore(DateTime.now())) {
                return '请选择大于今日的日期';
              }
              return null;
            },
          ),
          TxDateRangePickerFormField(
            labelText: '日期区间选择',
            minimumDate: DateTime(2024),
            maximumDate: DateTime(2025),
            onChanged: (date) => form['dateRange'] = date,
            initialDateRange: form['dateRange'],
            helpText: '请选择本年时间',
            required: true,
          ),
          TxDatetimeRangePickerFormField(
            labelText: '日期时间区间选择',
            minimumDate: DateTime(2024),
            maximumDate: DateTime(2025),
            onChanged: (date) => form['datetimeRange'] = date,
            initialDatetimeRange: form['datetimeRange'],
            helpText: '请选择本年时间',
            required: true,
          ),
          TxTimeRangePickerFormField(
            labelText: '时间段选择',
            minimumTime: const TimeOfDay(hour: 10, minute: 5),
            maximumTime: const TimeOfDay(hour: 20, minute: 5),
            onChanged: (date) => form['timeRange'] = date,
            initialTimeRange: form['timeRange'],
            helpText: '请选择时间',
            required: true,
          ),
          TxDropdownFormField(
            labelText: '下拉选择',
            source: FormView.sources,
            labelMapper: (val) => val,
            onChanged: (val) => form['dropdown'] = val,
            initialValue: form['dropdown'],
            required: true,
          ),
          TxMonthPickerFormField(
            labelText: '月份选择',
            minimumMonth: DateTime(2020),
            onChanged: (month) => form['month'] = month,
            maximumYear: DateTime.now().year + 2,
            initialMonth: form['month'],
            titleText: '月份选择',
            required: true,
          ),
          TxMultiPickerFormField<String, String>(
            source: FormView.sources,
            labelMapper: (val) => val,
            labelText: '多项选择',
            minCount: 1,
            maxCount: 2,
            required: true,
            onChanged: (val) => form['multiPickerValue'] = val,
            initialData: form['multiPickerValue'],
          ),
          TxNumberFormField(
            onChanged: (val) => form['number'] = val,
            initialValue: form['number'],
            labelText: '数字输入',
            required: true,
            minValue: 12,
            maxValue: 100,
            stepped: true,
          ),
          TxRadioFormField<String, String>(
            source: FormView.sources,
            initialValue: form['radioValue'],
            labelText: 'Radio 单选',
            required: true,
            onChanged: (val) => form['radioValue'] = val,
            labelMapper: (val) => val,
          ),
          TxChipFormField<String, String>(
            onChanged: (val) => form['chipValue'] = val,
            initialData: form['chipValue'],
            source: FormView.sources,
            labelMapper: (val) => val,
            labelText: 'Chip 选择',
            // required: true,
            minCount: 1,
            maxCount: 2,
            required: true,
          ),
          TxSwitchFormField(
            onChanged: (val) => form['switchValue'] = val,
            initialValue: form['switchValue'],
            labelText: 'Switch 开关',
            required: true,
          ),
          TxArrayFormField<String>.builder(
            itemBuilder: (field, index, data, actions) => ListTile(
              title: TxTextFormField(
                initialValue: data,
                onChanged: (val) => field.value![index] = val ?? '',
              ),
              trailing: actions == null
                  ? null
                  : Row(
                      mainAxisSize: MainAxisSize.min,
                      children: actions,
                    ),
            ),
            defaultValue: (index) => '',
            labelText: '自增组件',
            onChanged: (val) => form['autoIncrement'] = val,
            initialValue: form['autoIncrement'],
            limit: 3,
            required: true,
          ),
          TxTimePickerFormField(
            labelText: '时间选择',
            minimumTime: const TimeOfDay(hour: 6, minute: 0),
            maximumTime: const TimeOfDay(hour: 18, minute: 0),
            onChanged: (time) => form['time'] = time,
            initialTime: form['time'],
            titleText: '时间选择',
            required: true,
          ),
          TxYearPickerFormField(
            labelText: '年份选择',
            minimumYear: 2000,
            onChanged: (year) => form['year'] = year,
            maximumYear: 2023,
            initialYear: form['year'],
            titleText: '年份选择',
            required: true,
          ),
        ],
      ),
    );
  }
}
2
likes
90
points
14
downloads

Publisher

unverified uploader

Weekly Downloads

A custom component library that contains some basic UI components and provides theme configuration.

Homepage
Repository (GitHub)
View/report issues

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

equatable, flutter

More

Packages that depend on tx_design