feat : button , outlined button
fab button , fab outlined button , input , pagination widget's
This commit is contained in:
155
lib/presentation/common/app_fonts.dart
Normal file
155
lib/presentation/common/app_fonts.dart
Normal file
@@ -0,0 +1,155 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AppFonts {
|
||||
AppFonts._(); // Private constructor to prevent instantiation
|
||||
|
||||
// --- Font Families ---
|
||||
static const String yekan = 'yekan';
|
||||
|
||||
// --- Font Weights ---
|
||||
static const FontWeight regular = FontWeight.w400;
|
||||
static const FontWeight bold = FontWeight.w600;
|
||||
static const double _height = 1.20;
|
||||
|
||||
static const TextStyle yekan61Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 61,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan49Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 48,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan39Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 39,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan31Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 31,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan25Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 25,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan24Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 24,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan20Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 20,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan16Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 16,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan13Regular = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 13,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan10Regular = TextStyle(
|
||||
// Rounded from 10.24
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 10,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan61Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 61,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan49Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 48,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan39Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 39,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan31Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 31,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan25Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 25,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan24Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 24,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan20Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 20,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan16Bold = TextStyle(
|
||||
// Base size bold
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 16,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan13Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 13,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan10Bold = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: bold, // Use bold weight
|
||||
fontSize: 10,
|
||||
height: _height,
|
||||
);
|
||||
}
|
||||
24
lib/presentation/common/assets.dart
Normal file
24
lib/presentation/common/assets.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
///This file is automatically generated. DO NOT EDIT, all your changes would be lost.
|
||||
class Assets {
|
||||
Assets._();
|
||||
|
||||
static const String iconsAdd = 'assets/icons/add.svg';
|
||||
static const String iconsArrowLeft = 'assets/icons/arrow_left.svg';
|
||||
static const String iconsArrowRight = 'assets/icons/arrow_right.svg';
|
||||
static const String iconsDownload = 'assets/icons/download.svg';
|
||||
static const String iconsEdit = 'assets/icons/edit.svg';
|
||||
static const String iconsFilter = 'assets/icons/filter.svg';
|
||||
static const String iconsScan = 'assets/icons/scan.svg';
|
||||
static const String iconsTrash = 'assets/icons/trash.svg';
|
||||
static const String imagesInnerSplash = 'assets/images/inner_splash.webp';
|
||||
static const String imagesOutterSplash = 'assets/images/outter_splash.webp';
|
||||
static const String vecAddSvg = 'assets/vec/add.svg.vec';
|
||||
static const String vecArrowLeftSvg = 'assets/vec/arrow_left.svg.vec';
|
||||
static const String vecArrowRightSvg = 'assets/vec/arrow_right.svg.vec';
|
||||
static const String vecDownloadSvg = 'assets/vec/download.svg.vec';
|
||||
static const String vecEditSvg = 'assets/vec/edit.svg.vec';
|
||||
static const String vecFilterSvg = 'assets/vec/filter.svg.vec';
|
||||
static const String vecScanSvg = 'assets/vec/scan.svg.vec';
|
||||
static const String vecTrashSvg = 'assets/vec/trash.svg.vec';
|
||||
|
||||
}
|
||||
24
lib/presentation/utils/color_utils.dart
Normal file
24
lib/presentation/utils/color_utils.dart
Normal file
@@ -0,0 +1,24 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
extension ColorUtils on Color {
|
||||
Color _darken([double amount = 0.1]) {
|
||||
assert(amount >= 0 && amount <= 1, 'مقدار تیرگی باید بین 0 و 1 باشد');
|
||||
final hslColor = HSLColor.fromColor(this);
|
||||
final newLightness = (hslColor.lightness - amount).clamp(0.0, 1.0);
|
||||
final hslDarkerColor = hslColor.withLightness(newLightness);
|
||||
return hslDarkerColor.toColor();
|
||||
}
|
||||
|
||||
get disabledColor{
|
||||
return withAlpha(38);
|
||||
}
|
||||
|
||||
get hoverColor{
|
||||
return _darken(0.5);
|
||||
}
|
||||
|
||||
get pressedColor{
|
||||
return _darken(0.10);
|
||||
}
|
||||
|
||||
}
|
||||
58
lib/presentation/widget/buttons/elevated.dart
Normal file
58
lib/presentation/widget/buttons/elevated.dart
Normal file
@@ -0,0 +1,58 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
|
||||
class RElevated extends StatefulWidget {
|
||||
RElevated({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.onPressed,
|
||||
foregroundColor,
|
||||
backgroundColor,
|
||||
disabledBackgroundColor,
|
||||
disabledForegroundColor,
|
||||
radius,
|
||||
textStyle,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final VoidCallback? onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
Color? disabledForegroundColor;
|
||||
Color? disabledBackgroundColor;
|
||||
double? radius;
|
||||
TextStyle? textStyle;
|
||||
|
||||
@override
|
||||
State<RElevated> createState() => _RElevatedState();
|
||||
}
|
||||
|
||||
class _RElevatedState extends State<RElevated> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {});
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: widget.backgroundColor ?? AppColor.blueNormal,
|
||||
foregroundColor: widget.foregroundColor ?? Colors.white,
|
||||
disabledBackgroundColor:
|
||||
widget.disabledBackgroundColor ?? AppColor.blueNormal.withAlpha(38),
|
||||
disabledForegroundColor: widget.disabledForegroundColor ?? Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||
),
|
||||
fixedSize: Size(widget.width, widget.height),
|
||||
padding: EdgeInsets.zero,
|
||||
textStyle: widget.textStyle ?? AppFonts.yekan24Regular,
|
||||
),
|
||||
child: Text(widget.text),
|
||||
);
|
||||
}
|
||||
}
|
||||
232
lib/presentation/widget/buttons/fab.dart
Normal file
232
lib/presentation/widget/buttons/fab.dart
Normal file
@@ -0,0 +1,232 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/assets.dart';
|
||||
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/vec_widget.dart';
|
||||
|
||||
class RFab extends StatefulWidget {
|
||||
|
||||
|
||||
final VoidCallback? onPressed;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
Color? disabledForegroundColor;
|
||||
Color? disabledBackgroundColor;
|
||||
double? radius;
|
||||
ShapeBorder? shapeBorder;
|
||||
Widget? icon;
|
||||
|
||||
@override
|
||||
State<RFab> createState() => _RFabState();
|
||||
|
||||
//region Add
|
||||
RFab.smallAdd({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecAddSvg),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.add({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecAddSvg),
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Edit
|
||||
RFab.smallEdit({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecEditSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.edit({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecEditSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region delete
|
||||
RFab.smallDelete({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecTrashSvg),
|
||||
backgroundColor: AppColor.redNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.delete({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecTrashSvg),
|
||||
backgroundColor: AppColor.redNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region action
|
||||
RFab.smallAction({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecScanSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.action({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecScanSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region filter
|
||||
RFab.smallFilter({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecFilterSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.filter({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecFilterSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region download
|
||||
RFab.smallDownload({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecDownloadSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.download({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecDownloadSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Excel
|
||||
RFab.smallExcel({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecDownloadSvg),
|
||||
backgroundColor: AppColor.greenDark,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.excel({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecDownloadSvg),
|
||||
backgroundColor: AppColor.greenDark,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Back
|
||||
RFab.smallBack({required VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecArrowLeftSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
RFab.back({required VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
onPressed: onPressed,
|
||||
icon: vecWidget(Assets.vecArrowLeftSvg),
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
key: key,
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region General
|
||||
RFab.small({
|
||||
required this.onPressed,
|
||||
required this.icon,
|
||||
required this.backgroundColor,
|
||||
super.key,
|
||||
}) : radius = 40.0,
|
||||
foregroundColor = Colors.white;
|
||||
|
||||
RFab({
|
||||
required this.onPressed,
|
||||
required this.icon,
|
||||
required this.backgroundColor,
|
||||
super.key,
|
||||
}) : radius = 56.0,
|
||||
foregroundColor = Colors.white;
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
||||
class _RFabState extends State<RFab> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ElevatedButton(
|
||||
onPressed: widget.onPressed,
|
||||
style: ButtonStyle(
|
||||
side: WidgetStateProperty.all(BorderSide.none),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return widget.backgroundColor?.pressedColor ??
|
||||
AppColor.blueNormalActive;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor?.hoverColor ??
|
||||
AppColor.blueNormalHover;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor?.disabledColor ??
|
||||
AppColor.blueNormal.disabledColor;
|
||||
}
|
||||
return widget.backgroundColor ?? AppColor.blueNormal;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return widget.foregroundColor?.disabledColor;
|
||||
}
|
||||
return widget.foregroundColor;
|
||||
}),
|
||||
|
||||
shape: WidgetStatePropertyAll(
|
||||
CircleBorder(side: BorderSide(width: 1, color: Colors.transparent)),
|
||||
),
|
||||
fixedSize: WidgetStatePropertyAll(
|
||||
Size(widget.radius ?? 56, widget.radius ?? 56),
|
||||
),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
),
|
||||
child: widget.icon,
|
||||
);
|
||||
}
|
||||
}
|
||||
605
lib/presentation/widget/buttons/fab_outlined.dart
Normal file
605
lib/presentation/widget/buttons/fab_outlined.dart
Normal file
@@ -0,0 +1,605 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/assets.dart';
|
||||
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/vec_widget.dart';
|
||||
|
||||
class RFabOutlined extends StatefulWidget {
|
||||
final Widget icon;
|
||||
VoidCallback? onPressed;
|
||||
final Color backgroundColor;
|
||||
final Color? borderColor;
|
||||
final double? radius;
|
||||
OutlinedBorder? shapeBorder;
|
||||
|
||||
@override
|
||||
State<RFabOutlined> createState() => _RFabOutlinedState();
|
||||
|
||||
//region General
|
||||
RFabOutlined({
|
||||
required this.icon,
|
||||
required this.onPressed,
|
||||
required this.backgroundColor,
|
||||
required this.borderColor,
|
||||
this.radius = 56.0,
|
||||
super.key,
|
||||
}) : shapeBorder = CircleBorder(
|
||||
side: BorderSide(color: borderColor ?? Colors.transparent),
|
||||
);
|
||||
|
||||
RFabOutlined.noBorder({
|
||||
required this.icon,
|
||||
required this.onPressed,
|
||||
required this.backgroundColor,
|
||||
super.key,
|
||||
}) : borderColor = Colors.transparent,
|
||||
radius = 56.0,
|
||||
shapeBorder = CircleBorder(
|
||||
side: BorderSide(color: Colors.transparent, width: 1),
|
||||
);
|
||||
|
||||
RFabOutlined.small({
|
||||
required this.icon,
|
||||
required this.onPressed,
|
||||
required this.backgroundColor,
|
||||
required this.borderColor,
|
||||
super.key,
|
||||
}) : radius = 40.0,
|
||||
shapeBorder = CircleBorder(
|
||||
side: BorderSide(color: borderColor ?? Colors.transparent, width: 1),
|
||||
);
|
||||
|
||||
RFabOutlined.smallNoBorder({
|
||||
required this.icon,
|
||||
required this.onPressed,
|
||||
required this.backgroundColor,
|
||||
super.key,
|
||||
}) : borderColor = Colors.transparent,
|
||||
radius = 40.0,
|
||||
shapeBorder = CircleBorder(
|
||||
side: BorderSide(color: Colors.transparent, width: 1),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Add
|
||||
RFabOutlined.smallAdd({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
borderColor: AppColor.greenNormal,
|
||||
icon: vecWidget2(
|
||||
Assets.vecAddSvg,
|
||||
|
||||
color: AppColor.greenNormal,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallAddNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecAddSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenNormal
|
||||
: AppColor.greenNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.add({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
borderColor: AppColor.greenNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecAddSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenNormal
|
||||
: AppColor.greenNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.addNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecAddSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenNormal
|
||||
: AppColor.greenNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Edit
|
||||
RFabOutlined.smallEdit({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecEditSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallEditNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecEditSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.edit({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecEditSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.editNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecEditSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Delete
|
||||
RFabOutlined.smallDelete({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.redNormal,
|
||||
borderColor: AppColor.redNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecTrashSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.redNormal
|
||||
: AppColor.redNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallDeleteNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.redNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecTrashSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.redNormal
|
||||
: AppColor.redNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.delete({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.redNormal,
|
||||
borderColor: AppColor.redNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecTrashSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.redNormal
|
||||
: AppColor.redNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.deleteNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.redNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecTrashSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.redNormal
|
||||
: AppColor.redNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Action
|
||||
RFabOutlined.smallAction({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecScanSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallActionNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecScanSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.action({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecScanSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.actionNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecScanSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Filter
|
||||
RFabOutlined.smallFilter({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecFilterSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallFilterNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecFilterSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.filter({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecFilterSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.filterNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecFilterSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Download
|
||||
RFabOutlined.smallDownload({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallDownloadNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.download({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.downloadNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Excel
|
||||
RFabOutlined.smallExcel({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenDark,
|
||||
borderColor: AppColor.greenDark,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallExcelNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenDark,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.excel({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenDark,
|
||||
borderColor: AppColor.greenDark,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.excelNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.greenDark,
|
||||
icon: vecWidget(
|
||||
Assets.vecDownloadSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.greenDark
|
||||
: AppColor.greenDark.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
|
||||
//region Back
|
||||
RFabOutlined.smallBack({VoidCallback? onPressed, Key? key})
|
||||
: this.small(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecArrowLeftSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.smallBackNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.smallNoBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecArrowLeftSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.back({VoidCallback? onPressed, Key? key})
|
||||
: this(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
borderColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecArrowLeftSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
RFabOutlined.backNoBorder({VoidCallback? onPressed, Key? key})
|
||||
: this.noBorder(
|
||||
key: key,
|
||||
onPressed: onPressed,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
icon: vecWidget(
|
||||
Assets.vecArrowLeftSvg,
|
||||
color:
|
||||
onPressed != null
|
||||
? AppColor.blueNormal
|
||||
: AppColor.blueNormal.disabledColor,
|
||||
),
|
||||
);
|
||||
|
||||
//endregion
|
||||
}
|
||||
|
||||
class _RFabOutlinedState extends State<RFabOutlined> {
|
||||
bool isOnPressed =false;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OutlinedButton(
|
||||
onPressed:widget.onPressed ,
|
||||
style: ButtonStyle(
|
||||
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||
if (states.contains(WidgetState.disabled)) {
|
||||
return BorderSide(
|
||||
color:
|
||||
widget.borderColor?.disabledColor ??
|
||||
AppColor.blueNormal.disabledColor,
|
||||
width: 2,
|
||||
);
|
||||
}
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal,
|
||||
width: 2,
|
||||
);
|
||||
}),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return widget.backgroundColor;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor.hoverColor ??
|
||||
AppColor.blueNormal.hoverColor;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor.disabledColor ??
|
||||
AppColor.blueNormal.disabledColor;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor.disabledColor ??
|
||||
AppColor.blueNormal.disabledColor;
|
||||
}
|
||||
return widget.backgroundColor;
|
||||
}),
|
||||
|
||||
shape: WidgetStatePropertyAll(widget.shapeBorder),
|
||||
fixedSize: WidgetStatePropertyAll(
|
||||
Size(widget.radius ?? 56, widget.radius ?? 56),
|
||||
),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
),
|
||||
child: widget.icon
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
101
lib/presentation/widget/buttons/outline_elevated.dart
Normal file
101
lib/presentation/widget/buttons/outline_elevated.dart
Normal file
@@ -0,0 +1,101 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
import 'package:rasadyar_app/presentation/utils/color_utils.dart';
|
||||
|
||||
class ROutlinedElevated extends StatefulWidget {
|
||||
ROutlinedElevated({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.onPressed,
|
||||
this.foregroundColor,
|
||||
this.backgroundColor,
|
||||
this.borderColor,
|
||||
this.disabledBackgroundColor,
|
||||
this.pressedBackgroundColor,
|
||||
this.radius,
|
||||
this.textStyle,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final VoidCallback? onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
|
||||
Color? borderColor;
|
||||
|
||||
Color? disabledBackgroundColor;
|
||||
Color? pressedBackgroundColor;
|
||||
double? radius;
|
||||
TextStyle? textStyle;
|
||||
|
||||
@override
|
||||
State<ROutlinedElevated> createState() => _ROutlinedElevatedState();
|
||||
}
|
||||
|
||||
class _ROutlinedElevatedState extends State<ROutlinedElevated> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return OutlinedButton(
|
||||
onPressed: widget.onPressed,
|
||||
style: ButtonStyle(
|
||||
side: WidgetStateProperty.resolveWith<BorderSide?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal,
|
||||
width: 2,
|
||||
);
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal.withAlpha(38),
|
||||
width: 2,
|
||||
);
|
||||
}
|
||||
return BorderSide(
|
||||
color: widget.borderColor ?? AppColor.blueNormal,
|
||||
width: 2,
|
||||
);
|
||||
}),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
if (widget.pressedBackgroundColor != null) {
|
||||
return widget.pressedBackgroundColor;
|
||||
}
|
||||
return widget.backgroundColor?.pressedColor ?? AppColor.blueNormal;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor?.hoverColor ??
|
||||
AppColor.blueNormal.hoverColor;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.backgroundColor?.disabledColor ?? Colors.transparent;
|
||||
}
|
||||
return widget.backgroundColor;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return AppColor.blueNormal.withAlpha(38);
|
||||
}
|
||||
return AppColor.blueNormal;
|
||||
}),
|
||||
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||
),
|
||||
),
|
||||
fixedSize: WidgetStatePropertyAll(Size(widget.width, widget.height)),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStatePropertyAll(
|
||||
widget.textStyle ??
|
||||
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
child: Text(widget.text),
|
||||
);
|
||||
}
|
||||
}
|
||||
77
lib/presentation/widget/buttons/text_button.dart
Normal file
77
lib/presentation/widget/buttons/text_button.dart
Normal file
@@ -0,0 +1,77 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
|
||||
class RTextButton extends StatefulWidget {
|
||||
RTextButton({
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.onPressed,
|
||||
foregroundColor,
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
disabledBackgroundColor,
|
||||
radius,
|
||||
textStyle,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
});
|
||||
|
||||
final String text;
|
||||
final VoidCallback? onPressed;
|
||||
final double width;
|
||||
final double height;
|
||||
Color? foregroundColor;
|
||||
Color? backgroundColor;
|
||||
Color? borderColor;
|
||||
|
||||
Color? disabledBackgroundColor;
|
||||
double? radius;
|
||||
TextStyle? textStyle;
|
||||
|
||||
@override
|
||||
State<RTextButton> createState() => _RTextButtonState();
|
||||
}
|
||||
|
||||
class _RTextButtonState extends State<RTextButton> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextButton(
|
||||
style: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide.none),
|
||||
backgroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return widget.backgroundColor ?? AppColor.blueNormal;
|
||||
} else if (states.contains(WidgetState.hovered)) {
|
||||
return widget.backgroundColor?.withAlpha(38) ?? AppColor.blueNormal.withAlpha(38);
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return widget.disabledBackgroundColor ?? Colors.transparent;
|
||||
}
|
||||
return Colors.transparent;
|
||||
}),
|
||||
foregroundColor: WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
} else if (states.contains(WidgetState.disabled)) {
|
||||
return AppColor.blueNormal.withAlpha(38);
|
||||
}
|
||||
return AppColor.blueNormal;
|
||||
}),
|
||||
|
||||
shape: WidgetStatePropertyAll(
|
||||
RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(widget.radius ?? 8),
|
||||
),
|
||||
),
|
||||
fixedSize: WidgetStatePropertyAll(Size(widget.width, widget.height)),
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStatePropertyAll(
|
||||
widget.textStyle ??
|
||||
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
onPressed:widget.onPressed,
|
||||
child: Text(widget.text),
|
||||
);
|
||||
}
|
||||
}
|
||||
216
lib/presentation/widget/inputs/r_input.dart
Normal file
216
lib/presentation/widget/inputs/r_input.dart
Normal file
@@ -0,0 +1,216 @@
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
@immutable
|
||||
class RTextField extends StatefulWidget {
|
||||
RTextField(
|
||||
{super.key,
|
||||
this.maxLines,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.isForNumber = false,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.validator,
|
||||
this.readonly = false,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.radius,
|
||||
this.filled,
|
||||
this.enabled,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.label}) {
|
||||
filled = filled ?? false;
|
||||
obscure = false;
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.grey.shade300),
|
||||
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||
}
|
||||
|
||||
RTextField.noBorder(
|
||||
{super.key,
|
||||
this.maxLines,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.radius,
|
||||
this.validator,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.isForNumber = false,
|
||||
this.readonly = false,
|
||||
this.label,
|
||||
this.filled,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.enabled}) {
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||
obscure = false;
|
||||
filled = filled ?? true;
|
||||
}
|
||||
|
||||
RTextField.password(
|
||||
{super.key,
|
||||
this.maxLines = 1,
|
||||
this.maxLength,
|
||||
this.hintText,
|
||||
this.padding,
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.keyboardType,
|
||||
this.showCounter = false,
|
||||
this.isDense,
|
||||
this.initText,
|
||||
this.style,
|
||||
this.hintStyle,
|
||||
this.suffixIcon,
|
||||
this.prefixIcon,
|
||||
this.radius,
|
||||
this.validator,
|
||||
this.boxConstraints,
|
||||
this.minLines,
|
||||
this.isForNumber = false,
|
||||
this.readonly = false,
|
||||
this.label,
|
||||
this.filled,
|
||||
this.errorStyle,
|
||||
this.labelStyle,
|
||||
this.enabled}) {
|
||||
_inputBorder = OutlineInputBorder(
|
||||
borderSide: BorderSide.none,
|
||||
borderRadius: BorderRadius.circular(radius ?? 16));
|
||||
filled = filled ?? true;
|
||||
obscure = true;
|
||||
_isPassword = true;
|
||||
prefixIcon = prefixIcon ?? const Icon(CupertinoIcons.person);
|
||||
}
|
||||
|
||||
final int? maxLines;
|
||||
final int? minLines;
|
||||
final int? maxLength;
|
||||
final String? hintText;
|
||||
final String? label;
|
||||
final EdgeInsets? padding;
|
||||
final TextStyle? style;
|
||||
final TextStyle? errorStyle;
|
||||
final TextStyle? hintStyle;
|
||||
final TextStyle? labelStyle;
|
||||
final bool showCounter;
|
||||
final bool? isDense;
|
||||
final bool? isForNumber;
|
||||
final bool readonly;
|
||||
bool? obscure;
|
||||
final bool? enabled;
|
||||
final double? radius;
|
||||
final TextInputType? keyboardType;
|
||||
final Function(String)? onChanged;
|
||||
final Function(String)? onSubmitted;
|
||||
final FormFieldValidator? validator;
|
||||
final String? initText;
|
||||
Widget? suffixIcon;
|
||||
Widget? prefixIcon;
|
||||
bool? filled;
|
||||
bool _isPassword = false;
|
||||
|
||||
final BoxConstraints? boxConstraints;
|
||||
late final InputBorder? _inputBorder;
|
||||
|
||||
@override
|
||||
State<RTextField> createState() => _RTextFieldState();
|
||||
}
|
||||
|
||||
class _RTextFieldState extends State<RTextField> {
|
||||
final TextEditingController _controller = TextEditingController();
|
||||
bool? obscure;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
if (widget.initText != null) {
|
||||
_controller.text = widget.initText!;
|
||||
}
|
||||
obscure = widget.obscure;
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant RTextField oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
if (widget.initText != oldWidget.initText) {
|
||||
_controller.text = widget.initText ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: widget.padding ?? const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: TextFormField(
|
||||
controller: _controller,
|
||||
readOnly: widget.readonly,
|
||||
minLines: widget.minLines,
|
||||
maxLines: widget.maxLines,
|
||||
onChanged: widget.onChanged,
|
||||
validator: widget.validator,
|
||||
enabled: widget.enabled,
|
||||
obscureText: obscure ?? false,
|
||||
onTapOutside: (event) {
|
||||
FocusScope.of(context).unfocus();
|
||||
},
|
||||
onFieldSubmitted: widget.onSubmitted,
|
||||
maxLength: widget.maxLength,
|
||||
textDirection: TextDirection.rtl,
|
||||
style: widget.style ,
|
||||
keyboardType: widget.keyboardType,
|
||||
decoration: InputDecoration(
|
||||
errorStyle: widget.errorStyle,
|
||||
errorMaxLines: 1,
|
||||
isDense: widget.isDense,
|
||||
suffixIcon: widget.suffixIcon ??
|
||||
(widget._isPassword
|
||||
? IconButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
obscure = !obscure!;
|
||||
});
|
||||
},
|
||||
icon: Icon(!obscure!
|
||||
? CupertinoIcons.eye_slash
|
||||
: CupertinoIcons.eye))
|
||||
: null),
|
||||
suffixIconConstraints: widget.boxConstraints,
|
||||
prefixIcon: widget.prefixIcon,
|
||||
prefixIconConstraints: widget.boxConstraints,
|
||||
hintText: widget.hintText,
|
||||
labelText: widget.label,
|
||||
labelStyle: widget.labelStyle,
|
||||
filled: widget.filled,
|
||||
counter: widget.showCounter ? null : const SizedBox(),
|
||||
hintStyle: widget.hintStyle,
|
||||
enabledBorder: widget._inputBorder,
|
||||
focusedBorder: widget._inputBorder,
|
||||
border: widget._inputBorder),
|
||||
));
|
||||
}
|
||||
}
|
||||
255
lib/presentation/widget/pagination/pagination_from_until.dart
Normal file
255
lib/presentation/widget/pagination/pagination_from_until.dart
Normal file
@@ -0,0 +1,255 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
|
||||
class PaginationFromUntil extends StatefulWidget {
|
||||
const PaginationFromUntil({super.key});
|
||||
|
||||
@override
|
||||
State<PaginationFromUntil> createState() => _PaginationFromUntilState();
|
||||
}
|
||||
|
||||
class _PaginationFromUntilState extends State<PaginationFromUntil> {
|
||||
int current = 1;
|
||||
int total = 10;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: 164,
|
||||
height: 47,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
color: const Color(0xFFEAEFFF),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(50)),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
FloatingActionButton.small(
|
||||
onPressed: () {
|
||||
if(current>1){
|
||||
setState(() {
|
||||
current--;
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
shape: CircleBorder(),
|
||||
elevation: 0,
|
||||
backgroundColor: Colors.white,
|
||||
child: Icon(CupertinoIcons.arrow_left, color: AppColor.blueNormal),
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
'$current از $total',
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.rtl,
|
||||
style: AppFonts.yekan16Regular.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
),
|
||||
FloatingActionButton.small(
|
||||
|
||||
onPressed:() {
|
||||
if (current < total) {
|
||||
setState(() {
|
||||
current++;
|
||||
});
|
||||
}
|
||||
},
|
||||
shape: CircleBorder(),
|
||||
elevation: 0,
|
||||
backgroundColor: AppColor.blueNormal,
|
||||
child: Icon(CupertinoIcons.arrow_right, color: Colors.white),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Stack buildStack() {
|
||||
return Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 4,
|
||||
top: 4,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 40,
|
||||
top: 40,
|
||||
child: Container(
|
||||
transform:
|
||||
Matrix4.identity()
|
||||
..translate(0.0, 0.0)
|
||||
..rotateZ(-3.14),
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
color:
|
||||
Colors.white /* Secondary */,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color:
|
||||
Colors
|
||||
.white /* Secondary */,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(50),
|
||||
),
|
||||
),
|
||||
child: Stack(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
top: 8,
|
||||
child: Container(width: 24, height: 24, child: Stack()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 120,
|
||||
top: 3,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 40,
|
||||
top: 40,
|
||||
child: Container(
|
||||
transform:
|
||||
Matrix4.identity()
|
||||
..translate(0.0, 0.0)
|
||||
..rotateZ(-3.14),
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: 0,
|
||||
top: 0,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: ShapeDecoration(
|
||||
color: const Color(
|
||||
0xFF2D5FFF,
|
||||
) /* Primary */,
|
||||
shape: RoundedRectangleBorder(
|
||||
side: BorderSide(
|
||||
width: 1,
|
||||
color: const Color(
|
||||
0xFF2D5FFF,
|
||||
) /* Primary */,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(50),
|
||||
),
|
||||
),
|
||||
child: Stack(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 8,
|
||||
top: 8,
|
||||
child: Container(width: 24, height: 24, child: Stack()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned(
|
||||
left: 63,
|
||||
top: 9,
|
||||
child: Text(
|
||||
'1 از 17',
|
||||
style: TextStyle(
|
||||
color: const Color(0xFF2D5FFF) /* Primary */,
|
||||
fontSize: 16,
|
||||
fontFamily: 'IRANYekanFN',
|
||||
fontWeight: FontWeight.w400,
|
||||
height: 1.75,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
78
lib/presentation/widget/pagination/show_more.dart
Normal file
78
lib/presentation/widget/pagination/show_more.dart
Normal file
@@ -0,0 +1,78 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
|
||||
class RShowMore extends StatefulWidget {
|
||||
const RShowMore({super.key});
|
||||
|
||||
@override
|
||||
State<RShowMore> createState() => _RShowMoreState();
|
||||
}
|
||||
|
||||
class _RShowMoreState extends State<RShowMore>
|
||||
with SingleTickerProviderStateMixin {
|
||||
bool _toggled = false;
|
||||
late final AnimationController _controller;
|
||||
late final Animation<double> _iconRotation;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 500),
|
||||
);
|
||||
_iconRotation = Tween<double>(
|
||||
begin: 0,
|
||||
end: 0.50,
|
||||
) // 90 degrees (quarter turn)
|
||||
.animate(CurvedAnimation(parent: _controller, curve: Curves.easeInOut));
|
||||
}
|
||||
|
||||
void _toggle() {
|
||||
setState(() => _toggled = !_toggled);
|
||||
_toggled ? _controller.forward() : _controller.reverse();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GestureDetector(
|
||||
onTap: _toggle,
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
spacing: 8,
|
||||
children: [
|
||||
RotationTransition(
|
||||
turns: _iconRotation,
|
||||
child: const Icon(CupertinoIcons.chevron_down, size: 12,color:AppColor.blueNormal ,),
|
||||
),
|
||||
|
||||
AnimatedSwitcher(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
transitionBuilder:
|
||||
(child, animation) =>
|
||||
FadeTransition(opacity: animation, child: child),
|
||||
child: Text(
|
||||
_toggled ? 'کمتر' : 'مشاهده بیشتر',
|
||||
key: ValueKey(_toggled),
|
||||
style: AppFonts.yekan10Regular.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 50,)
|
||||
],
|
||||
|
||||
|
||||
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
784
lib/presentation/widget/tabs/new_tab.dart
Normal file
784
lib/presentation/widget/tabs/new_tab.dart
Normal file
@@ -0,0 +1,784 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
/// @docImport 'switch.dart';
|
||||
library;
|
||||
|
||||
import 'dart:collection';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
// Minimum padding from edges of the segmented control to edges of
|
||||
// encompassing widget.
|
||||
const EdgeInsetsGeometry _kHorizontalItemPadding = EdgeInsets.symmetric(
|
||||
horizontal: 16.0,
|
||||
);
|
||||
|
||||
// Minimum height of the segmented control.
|
||||
const double _kMinSegmentedControlHeight = 28.0;
|
||||
|
||||
// The default color used for the text of the disabled segment.
|
||||
const Color _kDisableTextColor = Color.fromARGB(115, 122, 122, 122);
|
||||
|
||||
// The duration of the fade animation used to transition when a new widget
|
||||
// is selected.
|
||||
const Duration _kFadeDuration = Duration(milliseconds: 165);
|
||||
|
||||
class NewCupertinoSegmentedControl<T extends Object> extends StatefulWidget {
|
||||
/// Creates an iOS-style segmented control bar.
|
||||
///
|
||||
/// The [children] argument must be an ordered [Map] such as a
|
||||
/// [LinkedHashMap]. Further, the length of the [children] list must be
|
||||
/// greater than one.
|
||||
///
|
||||
/// Each widget value in the map of [children] must have an associated key
|
||||
/// that uniquely identifies this widget. This key is what will be returned
|
||||
/// in the [onValueChanged] callback when a new value from the [children] map
|
||||
/// is selected.
|
||||
///
|
||||
/// The [groupValue] is the currently selected value for the segmented control.
|
||||
/// If no [groupValue] is provided, or the [groupValue] is null, no widget will
|
||||
/// appear as selected. The [groupValue] must be either null or one of the keys
|
||||
/// in the [children] map.
|
||||
NewCupertinoSegmentedControl({
|
||||
super.key,
|
||||
required this.children,
|
||||
required this.onValueChanged,
|
||||
this.groupValue,
|
||||
this.unselectedColor,
|
||||
this.selectedColor,
|
||||
this.borderColor,
|
||||
this.pressedColor,
|
||||
this.disabledColor,
|
||||
this.disabledTextColor,
|
||||
this.padding,
|
||||
this.disabledChildren = const <Never>{},
|
||||
}) : assert(children.length >= 2),
|
||||
assert(
|
||||
groupValue == null ||
|
||||
children.keys.any((T child) => child == groupValue),
|
||||
'The groupValue must be either null or one of the keys in the children map.',
|
||||
);
|
||||
|
||||
/// The identifying keys and corresponding widget values in the
|
||||
/// segmented control.
|
||||
///
|
||||
/// The map must have more than one entry.
|
||||
/// This attribute must be an ordered [Map] such as a [LinkedHashMap].
|
||||
final Map<T, Widget> children;
|
||||
|
||||
/// The identifier of the widget that is currently selected.
|
||||
///
|
||||
/// This must be one of the keys in the [Map] of [children].
|
||||
/// If this attribute is null, no widget will be initially selected.
|
||||
final T? groupValue;
|
||||
|
||||
/// The callback that is called when a new option is tapped.
|
||||
///
|
||||
/// The segmented control passes the newly selected widget's associated key
|
||||
/// to the callback but does not actually change state until the parent
|
||||
/// widget rebuilds the segmented control with the new [groupValue].
|
||||
final ValueChanged<T> onValueChanged;
|
||||
|
||||
/// The color used to fill the backgrounds of unselected widgets and as the
|
||||
/// text color of the selected widget.
|
||||
///
|
||||
/// Defaults to [CupertinoTheme]'s `primaryContrastingColor` if null.
|
||||
final Color? unselectedColor;
|
||||
|
||||
/// The color used to fill the background of the selected widget and as the text
|
||||
/// color of unselected widgets.
|
||||
///
|
||||
/// Defaults to [CupertinoTheme]'s `primaryColor` if null.
|
||||
final Color? selectedColor;
|
||||
|
||||
/// The color used as the border around each widget.
|
||||
///
|
||||
/// Defaults to [CupertinoTheme]'s `primaryColor` if null.
|
||||
final Color? borderColor;
|
||||
|
||||
/// The color used to fill the background of the widget the user is
|
||||
/// temporarily interacting with through a long press or drag.
|
||||
///
|
||||
/// Defaults to the selectedColor at 20% opacity if null.
|
||||
final Color? pressedColor;
|
||||
|
||||
/// The color used to fill the background of the segment when it is disabled.
|
||||
///
|
||||
/// If null, this color will be 50% opacity of the [selectedColor] when
|
||||
/// the segment is selected. If the segment is unselected, this color will be
|
||||
/// set to [unselectedColor].
|
||||
final Color? disabledColor;
|
||||
|
||||
/// The color used for the text of the segment when it is disabled.
|
||||
final Color? disabledTextColor;
|
||||
|
||||
/// The CupertinoSegmentedControl will be placed inside this padding.
|
||||
///
|
||||
/// Defaults to EdgeInsets.symmetric(horizontal: 16.0)
|
||||
final EdgeInsetsGeometry? padding;
|
||||
|
||||
/// The set of identifying keys that correspond to the segments that should be disabled.
|
||||
///
|
||||
/// All segments are enabled by default.
|
||||
final Set<T> disabledChildren;
|
||||
|
||||
@override
|
||||
State<NewCupertinoSegmentedControl<T>> createState() =>
|
||||
_SegmentedControlState<T>();
|
||||
}
|
||||
|
||||
class _SegmentedControlState<T extends Object>
|
||||
extends State<NewCupertinoSegmentedControl<T>>
|
||||
with TickerProviderStateMixin<NewCupertinoSegmentedControl<T>> {
|
||||
T? _pressedKey;
|
||||
|
||||
final List<AnimationController> _selectionControllers =
|
||||
<AnimationController>[];
|
||||
final List<ColorTween> _childTweens = <ColorTween>[];
|
||||
|
||||
late ColorTween _forwardBackgroundColorTween;
|
||||
late ColorTween _reverseBackgroundColorTween;
|
||||
late ColorTween _textColorTween;
|
||||
|
||||
Color? _selectedColor;
|
||||
Color? _unselectedColor;
|
||||
Color? _borderColor;
|
||||
Color? _pressedColor;
|
||||
Color? _selectedDisabledColor;
|
||||
Color? _unselectedDisabledColor;
|
||||
Color? _disabledTextColor;
|
||||
|
||||
AnimationController createAnimationController() {
|
||||
return AnimationController(duration: _kFadeDuration, vsync: this)
|
||||
..addListener(() {
|
||||
setState(() {
|
||||
// State of background/text colors has changed
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool _updateColors() {
|
||||
assert(mounted, 'This should only be called after didUpdateDependencies');
|
||||
bool changed = false;
|
||||
final Color disabledTextColor =
|
||||
widget.disabledTextColor ?? _kDisableTextColor;
|
||||
if (_disabledTextColor != disabledTextColor) {
|
||||
changed = true;
|
||||
_disabledTextColor = disabledTextColor;
|
||||
}
|
||||
final Color selectedColor =
|
||||
widget.selectedColor ?? CupertinoTheme.of(context).primaryColor;
|
||||
if (_selectedColor != selectedColor) {
|
||||
changed = true;
|
||||
_selectedColor = selectedColor;
|
||||
}
|
||||
final Color unselectedColor =
|
||||
widget.unselectedColor ??
|
||||
CupertinoTheme.of(context).primaryContrastingColor;
|
||||
if (_unselectedColor != unselectedColor) {
|
||||
changed = true;
|
||||
_unselectedColor = unselectedColor;
|
||||
}
|
||||
final Color selectedDisabledColor =
|
||||
widget.disabledColor ?? selectedColor.withOpacity(0.5);
|
||||
final Color unselectedDisabledColor =
|
||||
widget.disabledColor ?? unselectedColor;
|
||||
if (_selectedDisabledColor != selectedDisabledColor ||
|
||||
_unselectedDisabledColor != unselectedDisabledColor) {
|
||||
changed = true;
|
||||
_selectedDisabledColor = selectedDisabledColor;
|
||||
_unselectedDisabledColor = unselectedDisabledColor;
|
||||
}
|
||||
final Color borderColor =
|
||||
widget.borderColor ?? CupertinoTheme.of(context).primaryColor;
|
||||
if (_borderColor != borderColor) {
|
||||
changed = true;
|
||||
_borderColor = borderColor;
|
||||
}
|
||||
final Color pressedColor =
|
||||
widget.pressedColor ??
|
||||
CupertinoTheme.of(context).primaryColor.withOpacity(0.2);
|
||||
if (_pressedColor != pressedColor) {
|
||||
changed = true;
|
||||
_pressedColor = pressedColor;
|
||||
}
|
||||
|
||||
_forwardBackgroundColorTween = ColorTween(
|
||||
begin: _pressedColor,
|
||||
end: _selectedColor,
|
||||
);
|
||||
_reverseBackgroundColorTween = ColorTween(
|
||||
begin: _unselectedColor,
|
||||
end: _selectedColor,
|
||||
);
|
||||
_textColorTween = ColorTween(begin: _selectedColor, end: _unselectedColor);
|
||||
return changed;
|
||||
}
|
||||
|
||||
void _updateAnimationControllers() {
|
||||
assert(mounted, 'This should only be called after didUpdateDependencies');
|
||||
for (final AnimationController controller in _selectionControllers) {
|
||||
controller.dispose();
|
||||
}
|
||||
_selectionControllers.clear();
|
||||
_childTweens.clear();
|
||||
|
||||
for (final T key in widget.children.keys) {
|
||||
final AnimationController animationController =
|
||||
createAnimationController();
|
||||
if (widget.groupValue == key) {
|
||||
_childTweens.add(_reverseBackgroundColorTween);
|
||||
animationController.value = 1.0;
|
||||
} else {
|
||||
_childTweens.add(_forwardBackgroundColorTween);
|
||||
}
|
||||
_selectionControllers.add(animationController);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
|
||||
if (_updateColors()) {
|
||||
_updateAnimationControllers();
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(NewCupertinoSegmentedControl<T> oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (_updateColors() ||
|
||||
oldWidget.children.length != widget.children.length) {
|
||||
_updateAnimationControllers();
|
||||
}
|
||||
|
||||
if (oldWidget.groupValue != widget.groupValue) {
|
||||
int index = 0;
|
||||
for (final T key in widget.children.keys) {
|
||||
if (widget.groupValue == key) {
|
||||
_childTweens[index] = _forwardBackgroundColorTween;
|
||||
_selectionControllers[index].forward();
|
||||
} else {
|
||||
_childTweens[index] = _reverseBackgroundColorTween;
|
||||
_selectionControllers[index].reverse();
|
||||
}
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (final AnimationController animationController
|
||||
in _selectionControllers) {
|
||||
animationController.dispose();
|
||||
}
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onTapDown(T currentKey) {
|
||||
if (_pressedKey == null && currentKey != widget.groupValue) {
|
||||
setState(() {
|
||||
_pressedKey = currentKey;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _onTapCancel() {
|
||||
setState(() {
|
||||
_pressedKey = null;
|
||||
});
|
||||
}
|
||||
|
||||
void _onTap(T currentKey) {
|
||||
if (currentKey != _pressedKey) {
|
||||
return;
|
||||
}
|
||||
if (!widget.disabledChildren.contains(currentKey)) {
|
||||
if (currentKey != widget.groupValue) {
|
||||
widget.onValueChanged(currentKey);
|
||||
}
|
||||
}
|
||||
_pressedKey = null;
|
||||
}
|
||||
|
||||
Color? getTextColor(int index, T currentKey) {
|
||||
if (widget.disabledChildren.contains(currentKey)) {
|
||||
return _disabledTextColor;
|
||||
}
|
||||
if (_selectionControllers[index].isAnimating) {
|
||||
return _textColorTween.evaluate(_selectionControllers[index]);
|
||||
}
|
||||
if (widget.groupValue == currentKey) {
|
||||
return _unselectedColor;
|
||||
}
|
||||
return _selectedColor;
|
||||
}
|
||||
|
||||
Color? getBackgroundColor(int index, T currentKey) {
|
||||
if (widget.disabledChildren.contains(currentKey)) {
|
||||
return widget.groupValue == currentKey
|
||||
? _selectedDisabledColor
|
||||
: _unselectedDisabledColor;
|
||||
}
|
||||
if (_selectionControllers[index].isAnimating) {
|
||||
return _childTweens[index].evaluate(_selectionControllers[index]);
|
||||
}
|
||||
if (widget.groupValue == currentKey) {
|
||||
return _selectedColor;
|
||||
}
|
||||
if (_pressedKey == currentKey) {
|
||||
return _pressedColor;
|
||||
}
|
||||
return _unselectedColor;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<Widget> gestureChildren = <Widget>[];
|
||||
final List<Color> backgroundColors = <Color>[];
|
||||
int index = 0;
|
||||
int? selectedIndex;
|
||||
int? pressedIndex;
|
||||
for (final T currentKey in widget.children.keys) {
|
||||
selectedIndex = (widget.groupValue == currentKey) ? index : selectedIndex;
|
||||
pressedIndex = (_pressedKey == currentKey) ? index : pressedIndex;
|
||||
|
||||
final TextStyle textStyle = DefaultTextStyle.of(
|
||||
context,
|
||||
).style.copyWith(color: getTextColor(index, currentKey));
|
||||
final IconThemeData iconTheme = IconThemeData(
|
||||
color: getTextColor(index, currentKey),
|
||||
);
|
||||
|
||||
Widget child = Center(child: widget.children[currentKey]);
|
||||
|
||||
child = MouseRegion(
|
||||
cursor: kIsWeb ? SystemMouseCursors.click : MouseCursor.defer,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTapDown:
|
||||
widget.disabledChildren.contains(currentKey)
|
||||
? null
|
||||
: (TapDownDetails event) {
|
||||
_onTapDown(currentKey);
|
||||
},
|
||||
onTapCancel:
|
||||
widget.disabledChildren.contains(currentKey)
|
||||
? null
|
||||
: _onTapCancel,
|
||||
onTap: () {
|
||||
_onTap(currentKey);
|
||||
},
|
||||
child: IconTheme(
|
||||
data: iconTheme,
|
||||
child: DefaultTextStyle(
|
||||
style: textStyle,
|
||||
child: Semantics(
|
||||
button: true,
|
||||
inMutuallyExclusiveGroup: true,
|
||||
selected: widget.groupValue == currentKey,
|
||||
child: child,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
backgroundColors.add(getBackgroundColor(index, currentKey)!);
|
||||
gestureChildren.add(child);
|
||||
index += 1;
|
||||
}
|
||||
|
||||
final Widget box = _SegmentedControlRenderWidget<T>(
|
||||
selectedIndex: selectedIndex,
|
||||
pressedIndex: pressedIndex,
|
||||
backgroundColors: backgroundColors,
|
||||
borderColor: _borderColor!,
|
||||
children: gestureChildren,
|
||||
);
|
||||
|
||||
return Padding(
|
||||
padding: widget.padding ?? _kHorizontalItemPadding,
|
||||
child: UnconstrainedBox(constrainedAxis: Axis.horizontal, child: box),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SegmentedControlRenderWidget<T> extends MultiChildRenderObjectWidget {
|
||||
const _SegmentedControlRenderWidget({
|
||||
super.key,
|
||||
super.children,
|
||||
required this.selectedIndex,
|
||||
required this.pressedIndex,
|
||||
required this.backgroundColors,
|
||||
required this.borderColor,
|
||||
});
|
||||
|
||||
final int? selectedIndex;
|
||||
final int? pressedIndex;
|
||||
final List<Color> backgroundColors;
|
||||
final Color borderColor;
|
||||
|
||||
@override
|
||||
RenderObject createRenderObject(BuildContext context) {
|
||||
return _RenderSegmentedControl<T>(
|
||||
textDirection: Directionality.of(context),
|
||||
selectedIndex: selectedIndex,
|
||||
pressedIndex: pressedIndex,
|
||||
backgroundColors: backgroundColors,
|
||||
borderColor: borderColor,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void updateRenderObject(
|
||||
BuildContext context,
|
||||
_RenderSegmentedControl<T> renderObject,
|
||||
) {
|
||||
renderObject
|
||||
..textDirection = Directionality.of(context)
|
||||
..selectedIndex = selectedIndex
|
||||
..pressedIndex = pressedIndex
|
||||
..backgroundColors = backgroundColors
|
||||
..borderColor = borderColor;
|
||||
}
|
||||
}
|
||||
|
||||
class _SegmentedControlContainerBoxParentData
|
||||
extends ContainerBoxParentData<RenderBox> {
|
||||
RRect? surroundingRect;
|
||||
}
|
||||
|
||||
typedef _NextChild = RenderBox? Function(RenderBox child);
|
||||
|
||||
class _RenderSegmentedControl<T> extends RenderBox
|
||||
with
|
||||
ContainerRenderObjectMixin<
|
||||
RenderBox,
|
||||
ContainerBoxParentData<RenderBox>
|
||||
>,
|
||||
RenderBoxContainerDefaultsMixin<
|
||||
RenderBox,
|
||||
ContainerBoxParentData<RenderBox>
|
||||
> {
|
||||
_RenderSegmentedControl({
|
||||
required int? selectedIndex,
|
||||
required int? pressedIndex,
|
||||
required TextDirection textDirection,
|
||||
required List<Color> backgroundColors,
|
||||
required Color borderColor,
|
||||
}) : _textDirection = textDirection,
|
||||
_selectedIndex = selectedIndex,
|
||||
_pressedIndex = pressedIndex,
|
||||
_backgroundColors = backgroundColors,
|
||||
_borderColor = borderColor;
|
||||
|
||||
int? get selectedIndex => _selectedIndex;
|
||||
int? _selectedIndex;
|
||||
|
||||
set selectedIndex(int? value) {
|
||||
if (_selectedIndex == value) {
|
||||
return;
|
||||
}
|
||||
_selectedIndex = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
int? get pressedIndex => _pressedIndex;
|
||||
int? _pressedIndex;
|
||||
|
||||
set pressedIndex(int? value) {
|
||||
if (_pressedIndex == value) {
|
||||
return;
|
||||
}
|
||||
_pressedIndex = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
TextDirection get textDirection => _textDirection;
|
||||
TextDirection _textDirection;
|
||||
|
||||
set textDirection(TextDirection value) {
|
||||
if (_textDirection == value) {
|
||||
return;
|
||||
}
|
||||
_textDirection = value;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
List<Color> get backgroundColors => _backgroundColors;
|
||||
List<Color> _backgroundColors;
|
||||
|
||||
set backgroundColors(List<Color> value) {
|
||||
if (_backgroundColors == value) {
|
||||
return;
|
||||
}
|
||||
_backgroundColors = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
Color get borderColor => _borderColor;
|
||||
Color _borderColor;
|
||||
|
||||
set borderColor(Color value) {
|
||||
if (_borderColor == value) {
|
||||
return;
|
||||
}
|
||||
_borderColor = value;
|
||||
markNeedsPaint();
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicWidth(double height) {
|
||||
RenderBox? child = firstChild;
|
||||
double minWidth = 0.0;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
final double childWidth = child.getMinIntrinsicWidth(height);
|
||||
minWidth = math.max(minWidth, childWidth);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
return minWidth * childCount;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicWidth(double height) {
|
||||
RenderBox? child = firstChild;
|
||||
double maxWidth = 0.0;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
final double childWidth = child.getMaxIntrinsicWidth(height);
|
||||
maxWidth = math.max(maxWidth, childWidth);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
return maxWidth * childCount;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMinIntrinsicHeight(double width) {
|
||||
RenderBox? child = firstChild;
|
||||
double minHeight = 0.0;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
final double childHeight = child.getMinIntrinsicHeight(width);
|
||||
minHeight = math.max(minHeight, childHeight);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
return minHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
double computeMaxIntrinsicHeight(double width) {
|
||||
RenderBox? child = firstChild;
|
||||
double maxHeight = 0.0;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
final double childHeight = child.getMaxIntrinsicHeight(width);
|
||||
maxHeight = math.max(maxHeight, childHeight);
|
||||
child = childParentData.nextSibling;
|
||||
}
|
||||
return maxHeight;
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDistanceToActualBaseline(TextBaseline baseline) {
|
||||
return defaultComputeDistanceToHighestActualBaseline(baseline);
|
||||
}
|
||||
|
||||
@override
|
||||
void setupParentData(RenderBox child) {
|
||||
if (child.parentData is! _SegmentedControlContainerBoxParentData) {
|
||||
child.parentData = _SegmentedControlContainerBoxParentData();
|
||||
}
|
||||
}
|
||||
|
||||
void _layoutRects(
|
||||
_NextChild nextChild,
|
||||
RenderBox? leftChild,
|
||||
RenderBox? rightChild,
|
||||
) {
|
||||
RenderBox? child = leftChild;
|
||||
double start = 0.0;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
final Offset childOffset = Offset(start, 0.0);
|
||||
childParentData.offset = childOffset;
|
||||
final Rect childRect = Rect.fromLTWH(
|
||||
start,
|
||||
0.0,
|
||||
child.size.width,
|
||||
child.size.height,
|
||||
);
|
||||
final RRect rChildRect;
|
||||
if (child == leftChild) {
|
||||
rChildRect = RRect.fromRectAndCorners(
|
||||
childRect,
|
||||
topLeft: const Radius.circular(10.0),
|
||||
bottomLeft: const Radius.circular(10.0),
|
||||
);
|
||||
} else if (child == rightChild) {
|
||||
rChildRect = RRect.fromRectAndCorners(
|
||||
childRect,
|
||||
topRight: const Radius.circular(10.0),
|
||||
bottomRight: const Radius.circular(10.0),
|
||||
);
|
||||
} else {
|
||||
rChildRect = RRect.fromRectAndCorners(childRect);
|
||||
}
|
||||
childParentData.surroundingRect = rChildRect;
|
||||
start += child.size.width;
|
||||
child = nextChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
Size _calculateChildSize(BoxConstraints constraints) {
|
||||
double maxHeight = _kMinSegmentedControlHeight;
|
||||
double childWidth = constraints.minWidth / childCount;
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
childWidth = math.max(
|
||||
childWidth,
|
||||
child.getMaxIntrinsicWidth(double.infinity),
|
||||
);
|
||||
child = childAfter(child);
|
||||
}
|
||||
childWidth = math.min(childWidth, constraints.maxWidth / childCount);
|
||||
child = firstChild;
|
||||
while (child != null) {
|
||||
final double boxHeight = child.getMaxIntrinsicHeight(childWidth);
|
||||
maxHeight = math.max(maxHeight, boxHeight);
|
||||
child = childAfter(child);
|
||||
}
|
||||
return Size(childWidth, maxHeight);
|
||||
}
|
||||
|
||||
Size _computeOverallSizeFromChildSize(Size childSize) {
|
||||
return constraints.constrain(
|
||||
Size(childSize.width * childCount, childSize.height),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
double? computeDryBaseline(
|
||||
covariant BoxConstraints constraints,
|
||||
TextBaseline baseline,
|
||||
) {
|
||||
final Size childSize = _calculateChildSize(constraints);
|
||||
final BoxConstraints childConstraints = BoxConstraints.tight(childSize);
|
||||
|
||||
BaselineOffset baselineOffset = BaselineOffset.noBaseline;
|
||||
for (
|
||||
RenderBox? child = firstChild;
|
||||
child != null;
|
||||
child = childAfter(child)
|
||||
) {
|
||||
baselineOffset = baselineOffset.minOf(
|
||||
BaselineOffset(child.getDryBaseline(childConstraints, baseline)),
|
||||
);
|
||||
}
|
||||
return baselineOffset.offset;
|
||||
}
|
||||
|
||||
@override
|
||||
Size computeDryLayout(BoxConstraints constraints) {
|
||||
final Size childSize = _calculateChildSize(constraints);
|
||||
return _computeOverallSizeFromChildSize(childSize);
|
||||
}
|
||||
|
||||
@override
|
||||
void performLayout() {
|
||||
final BoxConstraints constraints = this.constraints;
|
||||
final Size childSize = _calculateChildSize(constraints);
|
||||
|
||||
final BoxConstraints childConstraints = BoxConstraints.tightFor(
|
||||
width: childSize.width,
|
||||
height: childSize.height,
|
||||
);
|
||||
|
||||
RenderBox? child = firstChild;
|
||||
while (child != null) {
|
||||
child.layout(childConstraints, parentUsesSize: true);
|
||||
child = childAfter(child);
|
||||
}
|
||||
|
||||
switch (textDirection) {
|
||||
case TextDirection.rtl:
|
||||
_layoutRects(childBefore, lastChild, firstChild);
|
||||
case TextDirection.ltr:
|
||||
_layoutRects(childAfter, firstChild, lastChild);
|
||||
}
|
||||
|
||||
size = _computeOverallSizeFromChildSize(childSize);
|
||||
}
|
||||
|
||||
@override
|
||||
void paint(PaintingContext context, Offset offset) {
|
||||
RenderBox? child = firstChild;
|
||||
int index = 0;
|
||||
while (child != null) {
|
||||
_paintChild(context, offset, child, index);
|
||||
child = childAfter(child);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void _paintChild(
|
||||
PaintingContext context,
|
||||
Offset offset,
|
||||
RenderBox child,
|
||||
int childIndex,
|
||||
) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
|
||||
context.canvas.drawRRect(
|
||||
childParentData.surroundingRect!.shift(offset),
|
||||
Paint()
|
||||
..color = backgroundColors[childIndex]
|
||||
..style = PaintingStyle.fill,
|
||||
);
|
||||
context.canvas.drawRRect(
|
||||
childParentData.surroundingRect!.shift(offset),
|
||||
Paint()
|
||||
..color = borderColor
|
||||
..strokeWidth = 1.0
|
||||
..style = PaintingStyle.stroke,
|
||||
);
|
||||
|
||||
context.paintChild(child, childParentData.offset + offset);
|
||||
}
|
||||
|
||||
@override
|
||||
bool hitTestChildren(BoxHitTestResult result, {required Offset position}) {
|
||||
RenderBox? child = lastChild;
|
||||
while (child != null) {
|
||||
final _SegmentedControlContainerBoxParentData childParentData =
|
||||
child.parentData! as _SegmentedControlContainerBoxParentData;
|
||||
if (childParentData.surroundingRect!.contains(position)) {
|
||||
return result.addWithPaintOffset(
|
||||
offset: childParentData.offset,
|
||||
position: position,
|
||||
hitTest: (BoxHitTestResult result, Offset localOffset) {
|
||||
assert(localOffset == position - childParentData.offset);
|
||||
return child!.hitTest(result, position: localOffset);
|
||||
},
|
||||
);
|
||||
}
|
||||
child = childParentData.previousSibling;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
115
lib/presentation/widget/tabs/tab.dart
Normal file
115
lib/presentation/widget/tabs/tab.dart
Normal file
@@ -0,0 +1,115 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_color.dart';
|
||||
import 'package:rasadyar_app/presentation/common/app_fonts.dart';
|
||||
|
||||
import 'new_tab.dart';
|
||||
|
||||
class CupertinoSegmentedControlDemo extends StatefulWidget {
|
||||
const CupertinoSegmentedControlDemo({super.key});
|
||||
|
||||
@override
|
||||
State<CupertinoSegmentedControlDemo> createState() =>
|
||||
_CupertinoSegmentedControlDemoState();
|
||||
}
|
||||
|
||||
class _CupertinoSegmentedControlDemoState
|
||||
extends State<CupertinoSegmentedControlDemo> {
|
||||
int _selectedSegment = 0;
|
||||
|
||||
// The data for the segments
|
||||
final Map<int, Widget> _segments = const {
|
||||
0: Text('Segment 1'),
|
||||
1: Text('Segment 2'),
|
||||
2: Text('Segment 3'),
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
CupertinoSlidingSegmentedControl<int>(
|
||||
children: _segments,
|
||||
groupValue: _selectedSegment,
|
||||
|
||||
onValueChanged: (int? value) {
|
||||
setState(() {
|
||||
_selectedSegment = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Selected Segment: ${_selectedSegment + 1}',
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CupertinoSegmentedControlDemo2 extends StatefulWidget {
|
||||
const CupertinoSegmentedControlDemo2({super.key});
|
||||
|
||||
@override
|
||||
State<CupertinoSegmentedControlDemo2> createState() =>
|
||||
_CupertinoSegmentedControlDemoState2();
|
||||
}
|
||||
|
||||
class _CupertinoSegmentedControlDemoState2
|
||||
extends State<CupertinoSegmentedControlDemo2> {
|
||||
int _selectedSegment = 0;
|
||||
|
||||
// The data for the segments
|
||||
final Map<int, Widget> _segments = {
|
||||
0:Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(50)
|
||||
),
|
||||
child: Text('لاشه', style: AppFonts.yekan13Regular),
|
||||
),
|
||||
1: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(50)
|
||||
),
|
||||
child: Text('زنده', style: AppFonts.yekan13Regular),
|
||||
),
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
NewCupertinoSegmentedControl<int>(
|
||||
padding: EdgeInsetsDirectional.symmetric(
|
||||
horizontal: 20,
|
||||
vertical: 10,
|
||||
),
|
||||
children: _segments,
|
||||
groupValue: _selectedSegment,
|
||||
selectedColor: AppColor.blueNormal,
|
||||
unselectedColor: Colors.white,
|
||||
borderColor: Colors.grey.shade300,
|
||||
onValueChanged: (int value) {
|
||||
setState(() {
|
||||
_selectedSegment = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Selected Segment: ${_selectedSegment + 1}',
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
47
lib/presentation/widget/vec_widget.dart
Normal file
47
lib/presentation/widget/vec_widget.dart
Normal file
@@ -0,0 +1,47 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:vector_graphics/vector_graphics.dart';
|
||||
|
||||
SvgPicture vecWidget(
|
||||
String assets, {
|
||||
double? width,
|
||||
double? height,
|
||||
BoxFit? fit,
|
||||
Color? color,
|
||||
}) {
|
||||
return SvgPicture(
|
||||
AssetBytesLoader(assets),
|
||||
width: width,
|
||||
height: height,
|
||||
fit: fit ?? BoxFit.contain,
|
||||
colorFilter:
|
||||
color != null ? ColorFilter.mode(color, BlendMode.srcIn) : null,
|
||||
);
|
||||
}
|
||||
Widget vecWidget2(
|
||||
String assets, {
|
||||
double? width,
|
||||
double? height,
|
||||
BoxFit? fit,
|
||||
Color? color,
|
||||
}) {
|
||||
final resolvedColor = WidgetStateProperty.resolveWith<Color?>((states) {
|
||||
if (states.contains(WidgetState.pressed)) {
|
||||
return Colors.white;
|
||||
}
|
||||
return color;
|
||||
}).resolve({}); // You can pass actual states if needed
|
||||
|
||||
return IconTheme(
|
||||
data: IconThemeData(color: resolvedColor),
|
||||
child: SvgPicture(
|
||||
AssetBytesLoader(assets),
|
||||
width: width,
|
||||
height: height,
|
||||
fit: fit ?? BoxFit.contain,
|
||||
colorFilter: resolvedColor != null
|
||||
? ColorFilter.mode(resolvedColor, BlendMode.srcIn)
|
||||
: null,
|
||||
),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user