Layout
Resizable
A box which children can be resized along either the horizontal or vertical axis.
1class ResizableExample extends StatelessWidget {2 @override3 Widget build(BuildContext context) => DecoratedBox(4 decoration: BoxDecoration(5 border: .all(color: context.theme.colors.border),6 borderRadius: .circular(8),7 ),8 child: FResizable(9 axis: .vertical,10 crossAxisExtent: 300,11 children: [12 .region(13 initialExtent: 250,14 minExtent: 100,15 builder: (_, data, _) =>16 Label(data: data, icon: FIcons.sunrise, label: 'Morning'),17 ),18 .region(19 initialExtent: 100,20 minExtent: 100,21 builder: (_, data, _) =>22 Label(data: data, icon: FIcons.sun, label: 'Afternoon'),23 ),24 .region(25 initialExtent: 250,26 minExtent: 100,27 builder: (_, data, _) =>28 Label(data: data, icon: FIcons.sunset, label: 'Evening'),29 ),30 ],31 ),32 );33}3435class Label extends StatelessWidget {36 static final format = DateFormat.jm();37 final FResizableRegionData data;38 final IconData icon;39 final String label;40 const Label({41 required this.data,42 required this.icon,43 required this.label,44 super.key,45 });46 @override47 Widget build(BuildContext context) {48 final FThemeData(:colors, :typography) = context.theme;49 final start = DateTime.fromMillisecondsSinceEpoch(50 (data.offsetPercentage.min * Duration.millisecondsPerDay).round(),51 isUtc: true,52 );53 final end = DateTime.fromMillisecondsSinceEpoch(54 (data.offsetPercentage.max * Duration.millisecondsPerDay).round(),55 isUtc: true,56 );57 return Align(58 child: Column(59 mainAxisAlignment: .center,60 children: [61 Row(62 mainAxisSize: .min,63 mainAxisAlignment: .center,64 children: [65 Icon(icon, size: 15, color: colors.foreground),66 const SizedBox(width: 3),67 Text(68 label,69 style: typography.sm.copyWith(color: colors.foreground),70 ),71 ],72 ),73 const SizedBox(height: 5),74 Text(75 '${format.format(start)} - ${format.format(end)}',76 style: typography.sm.copyWith(color: colors.foreground),77 ),78 ],79 ),80 );81 }82}83CLI
To generate and customize this style:
dart run forui style create resizableUsage
FResizable(...)
1FResizable(2 style: const .inherit(),3 axis: .vertical,4 divider: .dividerWithThumb,5 children: [6 FResizableRegion(7 initialExtent: 200,8 builder: (context, data, child) => child!,9 ),10 FResizableRegion(11 initialExtent: 200,12 minExtent: 100,13 builder: (context, data, child) => child!,14 ),15 ],16)FResizableRegion(...)
1FResizableRegion(2 initialExtent: 200,3 minExtent: 100,4 builder: (context, data, child) => child!,5 child: const Placeholder(),6)Examples
Without Cascading
1class NoCascadingResizableExample extends StatelessWidget {2 @override3 Widget build(BuildContext context) => DecoratedBox(4 decoration: BoxDecoration(5 border: .all(color: context.theme.colors.border),6 borderRadius: .circular(8),7 ),8 child: FResizable(9 control: const .managed(),10 axis: .vertical,11 crossAxisExtent: 300,12 children: [13 .region(14 initialExtent: 200,15 minExtent: 100,16 builder: (_, data, _) =>17 Label(data: data, icon: FIcons.sunrise, label: 'Morning'),18 ),19 .region(20 initialExtent: 200,21 minExtent: 100,22 builder: (_, data, _) =>23 Label(data: data, icon: FIcons.sun, label: 'Afternoon'),24 ),25 .region(26 initialExtent: 200,27 minExtent: 100,28 builder: (_, data, _) =>29 Label(data: data, icon: FIcons.sunset, label: 'Evening'),30 ),31 ],32 ),33 );34}3536class Label extends StatelessWidget {37 static final format = DateFormat.jm();38 final FResizableRegionData data;39 final IconData icon;40 final String label;41 const Label({42 required this.data,43 required this.icon,44 required this.label,45 super.key,46 });47 @override48 Widget build(BuildContext context) {49 final FThemeData(:colors, :typography) = context.theme;50 final start = DateTime.fromMillisecondsSinceEpoch(51 (data.offsetPercentage.min * Duration.millisecondsPerDay).round(),52 isUtc: true,53 );54 final end = DateTime.fromMillisecondsSinceEpoch(55 (data.offsetPercentage.max * Duration.millisecondsPerDay).round(),56 isUtc: true,57 );58 return Align(59 child: Column(60 mainAxisAlignment: .center,61 children: [62 Row(63 mainAxisSize: .min,64 mainAxisAlignment: .center,65 children: [66 Icon(icon, size: 15, color: colors.foreground),67 const SizedBox(width: 3),68 Text(69 label,70 style: typography.sm.copyWith(color: colors.foreground),71 ),72 ],73 ),74 const SizedBox(height: 5),75 Text(76 '${format.format(start)} - ${format.format(end)}',77 style: typography.sm.copyWith(color: colors.foreground),78 ),79 ],80 ),81 );82 }83}84Horizontal
1@override2Widget build(BuildContext context) => DecoratedBox(3 decoration: BoxDecoration(4 border: .all(color: context.theme.colors.border),5 borderRadius: .circular(8),6 ),7 child: FResizable(8 axis: .horizontal,9 crossAxisExtent: 300,10 children: [11 .region(12 initialExtent: 100,13 minExtent: 100,14 builder: (context, data, _) =>15 Align(child: Text('Sidebar', style: context.theme.typography.sm)),16 ),17 .region(18 initialExtent: 300,19 minExtent: 100,20 builder: (context, data, _) =>21 Align(child: Text('Content', style: context.theme.typography.sm)),22 ),23 ],24 ),25);26Divider with No Thumb
1@override2Widget build(BuildContext context) => DecoratedBox(3 decoration: BoxDecoration(4 border: .all(color: context.theme.colors.border),5 borderRadius: .circular(8),6 ),7 child: FResizable(8 axis: .horizontal,9 divider: .divider,10 crossAxisExtent: 300,11 children: [12 .region(13 initialExtent: 100,14 minExtent: 100,15 builder: (context, data, _) =>16 Align(child: Text('Sidebar', style: context.theme.typography.sm)),17 ),18 .region(19 initialExtent: 300,20 minExtent: 100,21 builder: (context, data, _) =>22 Align(child: Text('Content', style: context.theme.typography.sm)),23 ),24 ],25 ),26);27Without Divider
1@override2Widget build(BuildContext context) => DecoratedBox(3 decoration: BoxDecoration(4 border: .all(color: context.theme.colors.border),5 borderRadius: .circular(8),6 ),7 child: FResizable(8 axis: .horizontal,9 divider: .none,10 crossAxisExtent: 300,11 children: [12 .region(13 initialExtent: 100,14 minExtent: 100,15 builder: (context, data, _) =>16 Align(child: Text('Sidebar', style: context.theme.typography.sm)),17 ),18 .region(19 initialExtent: 300,20 minExtent: 100,21 builder: (context, data, _) =>22 Align(child: Text('Content', style: context.theme.typography.sm)),23 ),24 ],25 ),26);27