diff --git a/README.md b/README.md index 69c889d..d6e93a2 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,32 @@ +# Custom Animated Container + + + + + + + + + + +
Custom Animated Container
+ +# Wide Expansion Panel + + + + + + + + + + +
Wide Expansion Panel
+ # Circular Progress @@ -98,6 +124,38 @@
+# Custom Text Field + + + + + + + + + + + + + +
Custom Text Field GIF Custom Text Field PNG
+ +# Info Message Panel + + + + + + + + + + + + + +
Info Message Panel GIFInfo Message Panel PNG
+ # FacePile diff --git a/github/gifs/animatedContainer/animatedContainer.gif b/github/gifs/animatedContainer/animatedContainer.gif new file mode 100644 index 0000000..dd412e6 Binary files /dev/null and b/github/gifs/animatedContainer/animatedContainer.gif differ diff --git a/github/gifs/custom_text_field/custom_text_field.gif b/github/gifs/custom_text_field/custom_text_field.gif new file mode 100644 index 0000000..9932f03 Binary files /dev/null and b/github/gifs/custom_text_field/custom_text_field.gif differ diff --git a/github/gifs/info_message_panel/info_message_panel.gif b/github/gifs/info_message_panel/info_message_panel.gif new file mode 100644 index 0000000..f11d138 Binary files /dev/null and b/github/gifs/info_message_panel/info_message_panel.gif differ diff --git a/github/gifs/wideExpansionPanel/wideExpansionPanel.gif b/github/gifs/wideExpansionPanel/wideExpansionPanel.gif new file mode 100644 index 0000000..49ea4b2 Binary files /dev/null and b/github/gifs/wideExpansionPanel/wideExpansionPanel.gif differ diff --git a/github/images/info_message_panel/info_message_panel.png b/github/images/info_message_panel/info_message_panel.png new file mode 100644 index 0000000..b9b1607 Binary files /dev/null and b/github/images/info_message_panel/info_message_panel.png differ diff --git a/github/images/text_field/custom_text_field.png b/github/images/text_field/custom_text_field.png new file mode 100644 index 0000000..26c0fbd Binary files /dev/null and b/github/images/text_field/custom_text_field.png differ diff --git a/lib/atomic/custom_animated/example_animated.dart b/lib/atomic/custom_animated/example_animated.dart new file mode 100644 index 0000000..417e424 --- /dev/null +++ b/lib/atomic/custom_animated/example_animated.dart @@ -0,0 +1,43 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/custom_animated/item_card_widget.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; + +class CustomAnimated extends StatefulWidget { + const CustomAnimated({Key? key}) : super(key: key); + + @override + State createState() => _CustomAnimatedState(); +} + +class _CustomAnimatedState extends State { + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: ColorConstants.white, + appBar: AppBar(title: const Text('İşlerim')), + body: Column( + children: [ + ItemCardWidget( + buttons: [ + ItemCardButton(buttonText: 'İşi Tamamla', onPressed: () {}), + ItemCardButton( + buttonText: 'Detay', + isPrimary: false, + onPressed: () {}, + backgroundColor: ColorConstants.steelGray), + ], + cardLines: const [ + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + CardLine(title: 'Title', value: 'Value', index: 0), + ], + ), + ], + ), + ); + } +} diff --git a/lib/atomic/custom_animated/item_card_widget.dart b/lib/atomic/custom_animated/item_card_widget.dart new file mode 100644 index 0000000..582ca51 --- /dev/null +++ b/lib/atomic/custom_animated/item_card_widget.dart @@ -0,0 +1,244 @@ +// ignore_for_file: must_be_immutable, library_private_types_in_public_api + +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/large_button.dart/custom_large_button.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; +import 'package:ready_to_use_widgets/core/init/extensions/context_extension.dart'; + + +class ItemCardWidget extends StatefulWidget { + final int minShowItemCount; + final List cardLines; + final Duration animationDuration; + final Curve animationCurve = Curves.easeInOutCubic; + final List buttons; + bool isExpanded; + + ItemCardWidget( + {Key? key, + this.isExpanded = false, + this.minShowItemCount = 3, + required this.cardLines, + this.animationDuration = const Duration(milliseconds: 180), + required this.buttons}) + : super(key: key); + + @override + _ItemCardWidgetState createState() => _ItemCardWidgetState(); +} + +class _ItemCardWidgetState extends State + with SingleTickerProviderStateMixin { + late AnimationController _animationController; + late Animation _animation; + + @override + void initState() { + super.initState(); + + _animationController = AnimationController( + vsync: this, + duration: widget.animationDuration, + lowerBound: 0, + upperBound: 180); + _animation = CurvedAnimation( + parent: _animationController, + curve: widget.animationCurve, + reverseCurve: widget.animationCurve); + } + + @override + void dispose() { + _animationController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 15.0, vertical: 10.0), + child: Material( + elevation: 4, + color: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + child: AnimatedBuilder( + animation: _animation, + builder: (context, child) => Container( + padding: const EdgeInsets.only(top: 10), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(10), + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + buildCardLines(), + Column( + children: [ + buttonGroup(widget.buttons), + buildExpandButton(), + ], + ) + ], + )), + )), + ); + } + + AnimatedCrossFade buildCardLines() { + return AnimatedCrossFade( + firstCurve: widget.animationCurve, + secondCurve: widget.animationCurve, + sizeCurve: widget.animationCurve, + firstChild: buildCardLinesColumn(), + secondChild: buildCardLinesColumn(), + crossFadeState: widget.isExpanded + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + duration: widget.animationDuration); + } + + AnimatedBuilder buildExpandButton() { + return AnimatedBuilder( + animation: _animation, + builder: (context, child) => ClipOval( + child: Material( + color: Colors.white, + child: InkWell( + onTap: () { + if (widget.isExpanded) { + _animationController.reverse(); + widget.isExpanded = false; + } else { + _animationController.forward(); + widget.isExpanded = true; + } + }, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Transform.rotate( + origin: const Offset(0.5, 0.5), + angle: _animationController.value * pi / 180, + child: const Icon(Icons.keyboard_arrow_down_outlined, + color: Colors.black), + ), + ), + ), + ), + ), + ); + } + + Column buildCardLinesColumn() { + return Column( + mainAxisSize: MainAxisSize.min, + children: widget.isExpanded + ? widget.cardLines + : widget.cardLines.sublist( + 0, + (widget.minShowItemCount < widget.cardLines.length + ? widget.minShowItemCount + : widget.cardLines.length)), + ); + } + + Widget buttonGroup(List buttons) { + List widgetList = []; + buttons.forEach((element) { + widgetList.add( + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 4.0), + child: element, + )), + ); + }); + + return Container( + padding: const EdgeInsets.only( + top: 4, + left: 16, + right: 16, + ), + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: widgetList), + ); + } +} + +class ItemCardButton extends StatelessWidget { + final Color? backgroundColor; + final bool isPrimary; + final String? buttonText; + final VoidCallback? onPressed; + + const ItemCardButton({ + Key? key, + this.isPrimary = true, + this.buttonText, + this.onPressed, + this.backgroundColor, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return LargeButton( + text: buttonText.toString(), + style: context.appTheme().itemCardWidgetTextStyle, + backgroundColor: isPrimary ? ColorConstants.blueGray : backgroundColor, + isOutlined: true, + onPressed: onPressed, + ); + } +} + +class CardLine extends StatelessWidget { + const CardLine({ + Key? key, + required this.title, + required this.value, + required this.index, + }) : super(key: key); + + final String title; + final String value; + final int index; + + final _listBottomLeftTextStyle = const TextStyle( + fontWeight: FontWeight.bold, fontSize: 14, color: Colors.black); + final _listBottomRightTextStyle = + const TextStyle(fontSize: 14, color: Colors.black); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.only( + top: 4, + left: 16, + right: 16, + ), + child: Row( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: _listBottomLeftTextStyle, + ), + SizedBox( + // width: MediaQuery.of(context).size.width*0.4, + child: Text( + value, + style: _listBottomRightTextStyle, + textAlign: TextAlign.right, + ), + ) + ], + ), + ); + } +} diff --git a/lib/atomic/custom_text_field/custom_text_field.dart b/lib/atomic/custom_text_field/custom_text_field.dart new file mode 100644 index 0000000..bfc56cc --- /dev/null +++ b/lib/atomic/custom_text_field/custom_text_field.dart @@ -0,0 +1,144 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; +import 'package:ready_to_use_widgets/core/init/extensions/context_extension.dart'; + +class CustomTextField extends StatefulWidget { + const CustomTextField({ + Key? key, + required this.context, + this.headerText = '', + this.isOutlined = false, + this.borderColor = ColorConstants.steelGray, + this.showBorder = false, + this.headerTextStyle, + this.prefixIcon, + this.inputFormatters, + this.controller, + this.keyboardType, + this.hintText, + this.validator, + this.onSaved, + this.textAlign, + this.suffixIcon, + this.autoValidateMode, + this.obscureText, + this.hintTextStyle, + this.errorTextStyle, + this.topPadding, + this.enabled = true, + this.focusNode, + this.textStyle, + this.initialValue, + }) : super(key: key); + + final bool showBorder; + final BuildContext context; + final String headerText; + final TextStyle? headerTextStyle; + final bool? isOutlined; + final Color? borderColor; + final Widget? prefixIcon; + final List? inputFormatters; + final TextEditingController? controller; + final TextInputType? keyboardType; + final String? hintText; + final FormFieldValidator? validator; + final FormFieldSetter? onSaved; + final TextAlign? textAlign; + final Widget? suffixIcon; + final AutovalidateMode? autoValidateMode; + final bool? obscureText; + final TextStyle? hintTextStyle; + final TextStyle? errorTextStyle; + final double? topPadding; + final bool enabled; + final FocusNode? focusNode; + final TextStyle? textStyle; + final String? initialValue; + + @override + State createState() => _CustomTextFieldState(); +} + +class _CustomTextFieldState extends State { + bool _isVisible = false; + + void changeVisibility() { + setState(() { + _isVisible = !_isVisible; + }); + } + + @override + Widget build(BuildContext context) { + return Container( + padding: EdgeInsets.only( + top: widget.topPadding ?? context.dynamicHeight(0.015)), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: EdgeInsets.only(bottom: context.dynamicHeight(0.007)), + child: Text( + widget.headerText, + style: widget.headerTextStyle ?? + context.appTheme().textFieldHeaderTextStyle, + ), + ), + SizedBox( + child: TextFormField( + focusNode: widget.focusNode, + initialValue: widget.initialValue, + enabled: widget.enabled, + validator: widget.validator, + style: widget.textStyle ?? + context.appTheme().textFieldHeaderTextStyle, + textAlign: widget.textAlign ?? TextAlign.start, + controller: widget.controller, + inputFormatters: widget.inputFormatters, + keyboardType: widget.keyboardType, + obscureText: widget.obscureText ?? false, + autovalidateMode: AutovalidateMode.disabled, + decoration: InputDecoration( + disabledBorder: widget.showBorder + ? OutlineInputBorder( + borderSide: + BorderSide(color: widget.borderColor!, width: 1)) + : const OutlineInputBorder( + borderSide: BorderSide( + color: ColorConstants.steelGray, width: 1)), + hintText: widget.hintText, + hintStyle: widget.hintTextStyle ?? + context.appTheme().textFieldHeaderTextStyle, + errorStyle: widget.errorTextStyle ?? + context.appTheme().textFieldHeaderTextStyle, + prefixIcon: widget.prefixIcon, + suffixIcon: widget.suffixIcon, + enabledBorder: widget.showBorder + ? OutlineInputBorder( + borderSide: + BorderSide(color: widget.borderColor!, width: 1)) + : const OutlineInputBorder( + borderSide: BorderSide( + color: ColorConstants.steelGray, width: 1)), + focusColor: ColorConstants.steelGray, + focusedBorder: const OutlineInputBorder( + borderSide: BorderSide(color: ColorConstants.steelGray)), + border: const OutlineInputBorder(), + filled: true, + fillColor: ((widget.isOutlined ?? false) && + widget.borderColor == null) + ? ColorConstants.steelGray + : (widget.isOutlined ?? false) && + widget.borderColor != null + ? widget.borderColor + : ColorConstants.white), + onSaved: widget.onSaved, + ), + ), + ], + ), + ); + } +} diff --git a/lib/atomic/custom_text_field/custom_text_field_example.dart b/lib/atomic/custom_text_field/custom_text_field_example.dart new file mode 100644 index 0000000..2710ee9 --- /dev/null +++ b/lib/atomic/custom_text_field/custom_text_field_example.dart @@ -0,0 +1,70 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/large_button.dart/custom_large_button.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; +import 'package:ready_to_use_widgets/core/init/extensions/context_extension.dart'; +import 'package:ready_to_use_widgets/atomic/custom_text_field/custom_text_field.dart'; + +class TextFieldExample extends StatelessWidget { + const TextFieldExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Custom Text Field Example'), + backgroundColor: ColorConstants.blueGray), + body: Padding( + padding: const EdgeInsets.all(16.0), + child: Column(children: [ + buildEmailTextField(context), + buildPasswordTextField(context), + buildDoubleLargeButton(context) + ]), + ), + ); + } + + Widget buildEmailTextField(BuildContext context) { + return CustomTextField( + context: context, + headerText: 'Email', + headerTextStyle: context.appTheme().textFieldHeaderTextStyle, + suffixIcon: const Icon(Icons.email), + ); + } + + Widget buildPasswordTextField(BuildContext context) { + return CustomTextField( + context: context, + suffixIcon: const Icon(Icons.admin_panel_settings_rounded), + headerText: 'Password', + headerTextStyle: context.appTheme().textFieldHeaderTextStyle, + obscureText: true, + topPadding: context.dynamicHeight(0.03), + ); + } + + Widget buildDoubleLargeButton(BuildContext context) { + return Padding( + padding: EdgeInsets.only(top: context.dynamicHeight(0.03)), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + LargeButton( + text: 'Giriş Yap', + onPressed: () {}, + style: context.appTheme().itemCardWidgetTextStyle, + backgroundColor: ColorConstants.blueGray, + isOutlined: true, + ), + LargeButton( + text: 'Kayıt Ol', + onPressed: () {}, + backgroundColor: ColorConstants.blueGray, + isOutlined: true, + style: context.appTheme().itemCardWidgetTextStyle, + ) + ], + )); + } +} diff --git a/lib/atomic/info_message_panel/info_message_panel_example.dart b/lib/atomic/info_message_panel/info_message_panel_example.dart new file mode 100644 index 0000000..3331d30 --- /dev/null +++ b/lib/atomic/info_message_panel/info_message_panel_example.dart @@ -0,0 +1,32 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/info_message_panel/info_message_panel_widget.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; + +class InfoMessagePanelExample extends StatelessWidget { + const InfoMessagePanelExample({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + body: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + InfoMessagePanel( + borderColor: ColorConstants.casablanca, + icon: const Icon(Icons.info), + isClosable: true, + message: + 'Installation: If an anti-virus application scan is running, programs may not install and an error message appears.', + messageWidget: Column( + children: const [], + ), + elevation: 1, + ) + ], + ), + ), + ); + } +} diff --git a/lib/atomic/info_message_panel/info_message_panel_widget.dart b/lib/atomic/info_message_panel/info_message_panel_widget.dart new file mode 100644 index 0000000..11ad9b1 --- /dev/null +++ b/lib/atomic/info_message_panel/info_message_panel_widget.dart @@ -0,0 +1,139 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; +import 'package:ready_to_use_widgets/core/init/extensions/context_extension.dart'; + +class InfoMessagePanel extends StatefulWidget { + final String message; + final dynamic icon; + final bool? isClosable; + final double? elevation; + final Widget? messageWidget; + final bool? showBorder; + final Color? borderColor; + final bool? showIcon; + + const InfoMessagePanel({ + Key? key, + required this.message, + this.icon, + this.isClosable = false, + this.elevation = 0, + this.messageWidget, + this.showBorder = true, + this.borderColor, + this.showIcon = true, + }) : super(key: key); + + @override + _InfoMessagePanelState createState() => _InfoMessagePanelState(); +} + +class _InfoMessagePanelState extends State { + bool _show = true; + Duration animationDuration = const Duration(milliseconds: 400); + + @override + Widget build(BuildContext context) { + return AnimatedCrossFade( + duration: animationDuration, + sizeCurve: Curves.easeInOutQuart, + firstCurve: Curves.easeInOutQuart, + secondCurve: Curves.easeInOutQuart, + crossFadeState: + _show ? CrossFadeState.showSecond : CrossFadeState.showFirst, + firstChild: Container(), + secondChild: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Stack( + children: [ + Padding( + padding: + EdgeInsets.symmetric(vertical: context.dynamicHeight(0.01)), + child: Material( + color: ColorConstants.transparent, + elevation: widget.elevation!, + borderRadius: BorderRadius.circular(10), + child: Container( + decoration: BoxDecoration( + color: ColorConstants.transparent, + borderRadius: BorderRadius.circular(10), + border: ((widget.showBorder ?? false) == false) + ? null + : Border.all( + color: widget.borderColor ?? + ((widget.icon != null && widget is Icon + ? (widget.icon.color ?? + ColorConstants.mercury) + : ColorConstants.mercury)) + .withAlpha(80), + style: BorderStyle.solid, + )), + child: Padding( + padding: const EdgeInsets.all(12.0), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + !widget.showIcon! + ? Container() + : Padding( + padding: const EdgeInsets.all(8.0), + child: widget.icon ?? + const Icon( + Icons.info, + color: ColorConstants.casablanca, + ), + ), + Expanded( + child: widget.message == null + ? widget.messageWidget! + : Text( + widget.message, + softWrap: true, + style: context + .appTheme() + .infoMessagePanelTextStyle, + ), + ), + ], + ), + ), + ), + ), + ), + widget.isClosable == false + ? Container() + : Positioned( + top: 8, + right: 8, + child: ClipOval( + child: Material( + color: ColorConstants.errorColor, // Button color + child: InkWell( + splashColor: + ColorConstants.primaryColor, // Splash color + onTap: () { + setState(() { + _show = false; + }); + }, + child: const Padding( + padding: EdgeInsets.all(3.0), + child: Icon( + Icons.close_outlined, + color: ColorConstants.secondaryColor, + size: 16, + ), + ), + ), + ), + ), + ) + ], + ), + ], + ), + ); + } +} diff --git a/lib/atomic/large_button.dart/custom_large_button.dart b/lib/atomic/large_button.dart/custom_large_button.dart new file mode 100644 index 0000000..5d5811f --- /dev/null +++ b/lib/atomic/large_button.dart/custom_large_button.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; + +class LargeButton extends StatelessWidget { + final String text; + final TextStyle? style; + final Color? backgroundColor; + final double radius; + final bool isOutlined; + final VoidCallback? onPressed; + final double borderWidth; + final Color? borderColor; + const LargeButton({ + Key? key, + required this.text, + this.style, + this.backgroundColor, + this.radius = 8, + this.isOutlined = false, + this.onPressed, + this.borderWidth = 0.8, + this.borderColor, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return OutlinedButton( + onPressed: onPressed, + style: OutlinedButton.styleFrom( + side: BorderSide( + width: onPressed == null ? 0 : borderWidth, + color: (isOutlined && borderColor == null + ? ColorConstants.white + : isOutlined && borderColor != null + ? borderColor + : ColorConstants.steelGray)!), + backgroundColor: isOutlined ? backgroundColor : ColorConstants.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(radius), + ), + ), + child: Text( + text, + style: style, + ), + ); + } +} diff --git a/lib/atomic/wide_expansion_panel/wide_expansion_panel.dart b/lib/atomic/wide_expansion_panel/wide_expansion_panel.dart new file mode 100644 index 0000000..5312144 --- /dev/null +++ b/lib/atomic/wide_expansion_panel/wide_expansion_panel.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; + +ExpansionPanel wideExpansionPanel( + {required Widget body, + bool isExpanded = false, + List? header, + List? subHeader}) { + header = [ + ElevatedButton( + style: ButtonStyle( + backgroundColor: + MaterialStateProperty.all(ColorConstants.steelGray), + shape: MaterialStateProperty.all( + RoundedRectangleBorder( + borderRadius: BorderRadius.circular(15.0), + ))), + onPressed: () {}, + child: const Text('Stokta', + style: TextStyle(color: ColorConstants.white))), + Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + Text( + 'Grup Kodu', + style: TextStyle(fontWeight: FontWeight.w600), + ), + Text('20203896') + ], + ), + ), + Padding( + padding: const EdgeInsets.only(right: 10.0), + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: const [ + Text('Sipariş Adedi', style: TextStyle(fontWeight: FontWeight.w600)), + Text('500000000') + ], + ), + ), + ]; + + subHeader = [ + Column( + children: const [ + Text( + 'Üretimde', + style: TextStyle(fontWeight: FontWeight.w600), + ), + Text('20203896') + ], + ), + Column( + children: const [ + Text( + 'Stokta', + style: TextStyle(fontWeight: FontWeight.w600), + ), + Text('20203896') + ], + ), + Column( + children: const [ + Text( + 'Toplam', + style: TextStyle(fontWeight: FontWeight.w600), + ), + Text('20203896') + ], + ), + ]; + + return ExpansionPanel( + canTapOnHeader: true, + isExpanded: isExpanded, + headerBuilder: (context, isExpanded) { + return Padding( + padding: const EdgeInsets.only(left: 10.0, top: 10.0, bottom: 10.0), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + alignment: WrapAlignment.spaceEvenly, + direction: Axis.horizontal, + spacing: 18.0, + ), + ); + }, + body: body); +} diff --git a/lib/atomic/wide_expansion_panel/wide_expansion_panel_example.dart b/lib/atomic/wide_expansion_panel/wide_expansion_panel_example.dart new file mode 100644 index 0000000..a2ec755 --- /dev/null +++ b/lib/atomic/wide_expansion_panel/wide_expansion_panel_example.dart @@ -0,0 +1,29 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/wide_expansion_panel/wide_expansion_panel_list.dart'; + +class WideExpansionPanel extends StatelessWidget { + const WideExpansionPanel({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(), + body: Column( + children: [ + WideExpansionPanelList( + kontrolText: 'Kontrol', + durumText: 'Durum', + isAdiText: 'İş Adı', + isIdText: 'İş ID', + revizyonText: 'Revizyon', + urunKoduText: 'Ürün Kodu', + data: [ + Data(expandedValue: 'expandedValue', headerValue: 'headerValue') + ], + key: null, + ), + ], + ), + ); + } +} diff --git a/lib/atomic/wide_expansion_panel/wide_expansion_panel_list.dart b/lib/atomic/wide_expansion_panel/wide_expansion_panel_list.dart new file mode 100644 index 0000000..733c0a3 --- /dev/null +++ b/lib/atomic/wide_expansion_panel/wide_expansion_panel_list.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; +import 'package:ready_to_use_widgets/atomic/wide_expansion_panel/wide_expansion_panel.dart'; +import 'package:ready_to_use_widgets/core/init/extensions/context_extension.dart'; + +class WideExpansionPanelList extends StatefulWidget { + final List data; + final String? kontrolText; + final String? durumText; + final String? urunKoduText; + final String? isAdiText; + final String? isIdText; + final String? revizyonText; + const WideExpansionPanelList( + {Key? key, + required this.data, + this.kontrolText, + this.durumText, + this.urunKoduText, + this.isAdiText, + this.isIdText, + this.revizyonText}) + : super(key: key); + + @override + State createState() => _WideExpansionPanelListState(); +} + +class _WideExpansionPanelListState extends State { + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(10.0), + child: Material( + elevation: 4, + borderRadius: BorderRadius.circular(10.0), + child: ClipRRect( + borderRadius: BorderRadius.circular(10.0), + child: ExpansionPanelList( + expansionCallback: (panelIndex, isExpanded) { + setState(() { + widget.data[panelIndex].isExpanded = !isExpanded; + }); + }, + children: widget.data.map((dynamic item) { + return wideExpansionPanel( + body: buildDataTable(), isExpanded: item.isExpanded); + }).toList(), + ), + ), + ), + ); + } + + buildDataTable() { + return SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: DataTable(columns: [ + DataColumn( + label: Text(widget.kontrolText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + DataColumn( + label: Text(widget.durumText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + DataColumn( + label: Text(widget.urunKoduText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + DataColumn( + label: Text(widget.isAdiText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + DataColumn( + label: Text(widget.isIdText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + DataColumn( + label: Text(widget.revizyonText.toString(), + style: context.appTheme().wideExpansionPanelTextStyle), + ), + ], rows: [ + buildDataRow(), + buildDataRow(), + buildDataRow(), + ]), + ); + } + + DataRow buildDataRow() { + return DataRow( + cells: [ + DataCell(Checkbox( + value: false, + onChanged: (value) {}, + )), + const DataCell(Text('Stokta')), + const DataCell(Text('4564564564')), + const DataCell(Text('GIDA REGULASYON_SOGUTUCU')), + const DataCell(Text('5247')), + const DataCell(Text('50')), + ], + ); + } +} + +class Data { + Data({ + required this.expandedValue, + required this.headerValue, + this.isExpanded = false, + }); + + String expandedValue; + String headerValue; + bool isExpanded; +} diff --git a/lib/core/init/constants/color_constant.dart b/lib/core/init/constants/color_constant.dart index f404dac..fd1d68e 100644 --- a/lib/core/init/constants/color_constant.dart +++ b/lib/core/init/constants/color_constant.dart @@ -12,4 +12,14 @@ class ColorConstants { static const Color pomegranate = Color(0xFFE91E63); static const Color dodgerBlue = Color(0xFF2196F3); static const Color fruitSalad = Color(0xFF4CAF50); + static const Color blueGray = Color(0xFF607D8B); + static const Color steelGray = Color(0xFF201E2A); + static const Color transparent = Colors.transparent; + static const Color mercury = Color(0xffE8E8E8); + static const Color casablanca = Color(0xFFF8B23E); + static const Color errorColor = Color(0xffFBC670); //Color(0xffbb2d3b); + static const Color secondaryColor = Colors.white; + static const Color primaryColor = Color(0xffFBC670); + static const Color scarpaFlow = Color(0xFF56565C); + } diff --git a/lib/core/init/extensions/context_extension.dart b/lib/core/init/extensions/context_extension.dart new file mode 100644 index 0000000..78f8fd3 --- /dev/null +++ b/lib/core/init/extensions/context_extension.dart @@ -0,0 +1,9 @@ +import 'package:flutter/cupertino.dart'; +import 'package:ready_to_use_widgets/core/init/theme/base/base_theme.dart'; +import '../theme/viewmodel/theme_viewmodel.dart'; + +extension ContextExtension on BuildContext { + double dynamicHeight(double value) => MediaQuery.of(this).size.height * value; + double dynamicWidth(double value) => MediaQuery.of(this).size.width * value; + BaseTheme appTheme() => ThemeViewModel.theme!; +} diff --git a/lib/core/init/theme/base/base_theme.dart b/lib/core/init/theme/base/base_theme.dart index 8e0db86..ad730ca 100644 --- a/lib/core/init/theme/base/base_theme.dart +++ b/lib/core/init/theme/base/base_theme.dart @@ -2,6 +2,8 @@ import 'package:flutter/material.dart'; abstract class BaseTheme { ThemeData get themeData; - - TextStyle get customSnackBar; + TextStyle get itemCardWidgetTextStyle; + TextStyle get wideExpansionPanelTextStyle; + TextStyle get textFieldHeaderTextStyle; + TextStyle get infoMessagePanelTextStyle; } diff --git a/lib/core/init/theme/dark_theme.dart b/lib/core/init/theme/dark_theme.dart index 3540001..3332570 100644 --- a/lib/core/init/theme/dark_theme.dart +++ b/lib/core/init/theme/dark_theme.dart @@ -16,5 +16,14 @@ class DarkTheme extends BaseTheme { ThemeData get themeData => throw UnimplementedError(); @override - TextStyle get customSnackBar => throw UnimplementedError(); + TextStyle get itemCardWidgetTextStyle => throw UnimplementedError(); + + @override + TextStyle get wideExpansionPanelTextStyle => throw UnimplementedError(); + + @override + TextStyle get textFieldHeaderTextStyle => throw UnimplementedError(); + + @override + TextStyle get infoMessagePanelTextStyle => throw UnimplementedError(); } diff --git a/lib/core/init/theme/light_theme.dart b/lib/core/init/theme/light_theme.dart index b668e31..fe977ba 100644 --- a/lib/core/init/theme/light_theme.dart +++ b/lib/core/init/theme/light_theme.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:google_fonts/google_fonts.dart'; -import 'package:ready_to_use_widgets/atomic/beauty_textfield/beauty_textfield.dart'; import 'package:ready_to_use_widgets/core/init/constants/color_constant.dart'; import 'package:ready_to_use_widgets/core/init/theme/base/base_theme.dart'; @@ -21,11 +20,31 @@ class LightTheme extends BaseTheme { // Örnek olarak yapılmıştır. @override - TextStyle get customSnackBar => GoogleFonts.ubuntu( + TextStyle get itemCardWidgetTextStyle => GoogleFonts.ubuntu( textStyle: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, - color: ColorConstants.dodgerBlue, - ), + color: ColorConstants.white, + fontSize: 14, + fontWeight: FontWeight.w600), + ); + @override + TextStyle get wideExpansionPanelTextStyle => GoogleFonts.ubuntu( + textStyle: const TextStyle( + color: ColorConstants.black, + fontSize: 14, + fontStyle: FontStyle.italic, + fontWeight: FontWeight.bold), + ); + + @override + TextStyle get textFieldHeaderTextStyle => GoogleFonts.ubuntu( + fontSize: 12, + fontWeight: FontWeight.bold, + color: ColorConstants.steelGray, + ); + @override + TextStyle get infoMessagePanelTextStyle => GoogleFonts.ubuntu( + fontSize: 14, + fontWeight: FontWeight.w500, + color: ColorConstants.scarpaFlow, ); } diff --git a/lib/main.dart b/lib/main.dart index efc0380..f6d2f92 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,15 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:internet_connection_checker/internet_connection_checker.dart'; - +import 'package:ready_to_use_widgets/atomic/info_message_panel/info_message_panel_example.dart'; import 'package:ready_to_use_widgets/view/future_navigate.dart'; - import 'package:ready_to_use_widgets/atomic/glow_image/example_glow_image.dart'; import 'package:ready_to_use_widgets/atomic/rating_bar/extension/rating_bar_icon_extension.dart'; import 'package:ready_to_use_widgets/atomic/rating_bar/rating_bar.dart'; import 'atomic/button/asynchronous_button.dart'; import 'atomic/dropdown/example_custom_dropdown.dart'; import 'atomic/text/animated_cross_text.dart'; + import 'feature/network_connection/cubit/network_cubit.dart'; void main() => runApp(const AppBlocProvider()); @@ -60,6 +60,7 @@ class _MyAppState extends State { @override Widget build(BuildContext context) { - return const MaterialApp(title: 'Material App', home: FutureNavigateView()); + return const MaterialApp( + title: 'Material App', home: InfoMessagePanelExample()); } }