当前位置:   article > 正文

flutter自定义组件_flutter 自定义组件

flutter 自定义组件

 分享一个大佬的自定义组件demo。

更多demo请移步github:

https://github.com/shang1219178163/flutter_templet_projecicon-default.png?t=M5H6https://github.com/shang1219178163/flutter_templet_projec

数量计步器 NumberStepper

  1. //...
  2. NumberStepper(
  3. minValue: 1,
  4. maxValue: 1000,
  5. stepValue: 100,
  6. iconSize: 60,
  7. value: 1000,
  8. color: Colors.blue,
  9. style: NumberStepperStyle.system,
  10. block: (value){
  11. DDLog(value);
  12. },
  13. ),
  14. SizedBox(height: 20,),
  15. NumberStepper(
  16. minValue: 1,
  17. maxValue: 1000,
  18. stepValue: 100,
  19. iconSize: 40,
  20. value: 1000,
  21. color: Colors.blue,
  22. style: NumberStepperStyle.outlined,
  23. block: (value){
  24. DDLog(value);
  25. },
  26. ),
  27. //...

NumberStepper.dart

如果打不开,这里是源码:

  1. //
  2. // NumberStepper.dart
  3. // flutter_templet_project
  4. //
  5. // Created by shang on 6/13/21 6:23 AM.
  6. // Copyright © 6/13/21 shang. All rights reserved.
  7. //
  8. // ignore: must_be_immutable
  9. import 'package:flutter/cupertino.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:flutter_templet_project/extensions/ddlog.dart';
  12. enum NumberStepperStyle {
  13. system,
  14. outlined,
  15. textfield,
  16. }
  17. ///自定义数值增减 Stepper
  18. class NumberStepper extends StatefulWidget {
  19. NumberStepper({
  20. required this.minValue,
  21. required this.maxValue,
  22. required this.stepValue,
  23. this.iconSize = 24,
  24. required this.value,
  25. this.color = Colors.blue,
  26. this.style = NumberStepperStyle.system,
  27. this.radius = 5.0,
  28. this.wraps = true,
  29. required this.block,
  30. });
  31. final int minValue;
  32. final int maxValue;
  33. final int stepValue;
  34. final double iconSize;
  35. int value;
  36. final bool wraps;
  37. final Color color;
  38. final NumberStepperStyle style;
  39. final double radius;
  40. void Function(int value) block;
  41. @override
  42. _NumberStepperState createState() => _NumberStepperState();
  43. }
  44. class _NumberStepperState extends State<NumberStepper> {
  45. // 控制器
  46. final _textController = TextEditingController();
  47. // 焦点
  48. final focusNode1 = FocusNode();
  49. @override
  50. void initState() {
  51. // TODO: implement initState
  52. _textController.text = "${widget.value}";
  53. ddlog(_textController.text);
  54. super.initState();
  55. }
  56. @override
  57. Widget build(BuildContext context) {
  58. // return buildOther(context);
  59. switch (widget.style) {
  60. case NumberStepperStyle.outlined:
  61. return buildOutlinedStyle(context);
  62. break;
  63. case NumberStepperStyle.textfield:
  64. return buildTexfieldStyle(context);
  65. default:
  66. break;
  67. }
  68. return buildSystemStyle(context);
  69. }
  70. Widget buildSystemStyle(BuildContext context) {
  71. return Row(
  72. mainAxisAlignment: MainAxisAlignment.center,
  73. children: [
  74. Container(
  75. width: widget.iconSize,
  76. height: widget.iconSize,
  77. decoration: BoxDecoration(
  78. color: widget.color,
  79. borderRadius: BorderRadius.circular(widget.radius),
  80. border: Border.all(color: widget.color, width: 1), // 边色与边宽度
  81. ),
  82. child: IconButton(
  83. icon: Icon(Icons.remove, size: widget.iconSize),
  84. // iconSize: widget.iconSize,
  85. padding: EdgeInsets.zero,
  86. color: Colors.white,
  87. onPressed: () {
  88. go(-widget.stepValue);
  89. },
  90. ),
  91. ),
  92. Container(
  93. width: widget.value.toString().length*18*widget.iconSize/30,
  94. // width: widget.iconSize + 20,
  95. child: Text('${widget.value}',
  96. style: TextStyle(
  97. fontSize: widget.iconSize * 0.8,
  98. ),
  99. textAlign: TextAlign.center,
  100. ),
  101. ),
  102. Container(
  103. width: widget.iconSize,
  104. height: widget.iconSize,
  105. decoration: BoxDecoration(
  106. color: widget.color,
  107. borderRadius: BorderRadius.circular(widget.radius),
  108. border: Border.all(color: widget.color, width: 1), // 边色与边宽度
  109. ),
  110. child: IconButton(
  111. icon: Icon(Icons.add, size: widget.iconSize,),
  112. // iconSize: widget.iconSize,
  113. padding: EdgeInsets.zero,
  114. color: Colors.white,
  115. onPressed: () {
  116. setState(() {
  117. go(widget.stepValue);
  118. });
  119. },
  120. ),
  121. ),
  122. ],
  123. );
  124. }
  125. Widget buildOutlinedStyle(BuildContext context) {
  126. return Row(
  127. mainAxisAlignment: MainAxisAlignment.center,
  128. children: [
  129. Container(
  130. width: widget.iconSize,
  131. height: widget.iconSize,
  132. // color: Theme.of(context).primaryColor,
  133. decoration: BoxDecoration(
  134. color: Colors.white,
  135. borderRadius: BorderRadius.circular(widget.radius),
  136. border: Border.all(color: widget.color, width: 1), // 边色与边宽度
  137. ),
  138. child: IconButton(
  139. icon: Icon(Icons.remove, size: widget.iconSize),
  140. // iconSize: widget.iconSize,
  141. padding: EdgeInsets.zero,
  142. color: widget.color,
  143. onPressed: () {
  144. go(-widget.stepValue);
  145. },
  146. ),
  147. ),
  148. Container(
  149. width: widget.value.toString().length*18*widget.iconSize/30,
  150. // width: widget.iconSize + 20,
  151. child: Text('${widget.value}',
  152. style: TextStyle(
  153. fontSize: widget.iconSize * 0.8,
  154. ),
  155. textAlign: TextAlign.center,
  156. ),
  157. ),
  158. Container(
  159. width: widget.iconSize,
  160. height: widget.iconSize,
  161. // color: Theme.of(context).primaryColor,
  162. decoration: BoxDecoration(
  163. color: Colors.white,
  164. borderRadius: BorderRadius.circular(widget.radius),
  165. border: Border.all(color: widget.color, width: 1), // 边色与边宽度
  166. ),
  167. child: IconButton(
  168. icon: Icon(Icons.add, size: widget.iconSize),
  169. // iconSize: widget.iconSize,
  170. padding: EdgeInsets.zero,
  171. color: widget.color,
  172. onPressed: () {
  173. setState(() {
  174. go(widget.stepValue);
  175. });
  176. },
  177. ),
  178. ),
  179. ],
  180. );
  181. }
  182. Widget buildTexfieldStyle(BuildContext context) {
  183. return Row(
  184. mainAxisAlignment: MainAxisAlignment.center,
  185. children: [
  186. Expanded(
  187. child: TextField(
  188. enableInteractiveSelection: false,
  189. toolbarOptions: ToolbarOptions(
  190. copy:false,
  191. paste: false,
  192. cut: false,
  193. selectAll: false,
  194. //by default all are disabled 'false'
  195. ),
  196. controller: _textController,
  197. decoration: InputDecoration(
  198. // labelText: "请输入内容",//输入框内无文字时提示内容,有内容时会自动浮在内容上方
  199. // helperText: "随便输入文字或数字", //输入框底部辅助性说明文字
  200. prefixIcon:IconButton(
  201. icon: Icon(
  202. Icons.remove,
  203. size: widget.iconSize,
  204. ),
  205. onPressed: (){
  206. // go(-widget.stepValue);
  207. setState(() {
  208. go(-widget.stepValue);
  209. _textController.text = "${widget.value}";
  210. });
  211. },
  212. ),
  213. border: OutlineInputBorder(
  214. borderRadius: BorderRadius.circular(4.0) //圆角大小
  215. ),
  216. suffixIcon: IconButton(
  217. icon: Icon(
  218. Icons.add,
  219. size: widget.iconSize,
  220. ),
  221. onPressed: (){
  222. // go(widget.stepValue);
  223. setState(() {
  224. // FocusScope.of(context).requestFocus(FocusNode());
  225. go(widget.stepValue);
  226. _textController.text = "${widget.value}";
  227. });
  228. },
  229. ),
  230. contentPadding: const EdgeInsets.only(bottom:8)
  231. ),
  232. keyboardType: TextInputType.number,
  233. ),
  234. ),
  235. ],
  236. );
  237. }
  238. void go(int stepValue) {
  239. setState(() {
  240. if (stepValue < 0 && (widget.value == widget.minValue || widget.value + stepValue < widget.minValue)) {
  241. ddlog("it's minValue!");
  242. if (widget.wraps) widget.value = widget.maxValue;
  243. widget.block(widget.value);
  244. return;
  245. }
  246. if (stepValue > 0 && (widget.value == widget.maxValue || widget.value + stepValue > widget.maxValue)) {
  247. ddlog("it's maxValue!");
  248. if (widget.wraps) widget.value = widget.minValue;
  249. widget.block(widget.value);
  250. return;
  251. }
  252. widget.value += stepValue;
  253. });
  254. widget.block(widget.value);
  255. }
  256. }

LineSegmentControl / 线条指示器分段组件

  1. //...
  2. SizedBox(height: 15),
  3. buildLineSegmentControl(null, lineColor: Colors.blue),
  4. SizedBox(height: 15),
  5. buildLineSegmentControl(Colors.white, lineColor: Colors.blue),
  6. SizedBox(height: 15),
  7. buildLineSegmentControl(Colors.black87, lineColor: Colors.white),
  8. //...

  1. Widget buildLineSegmentControl(Color? backgroundColor, {required Color lineColor}) {
  2. final Map<int, Widget> children = const <int, Widget>{
  3. 0: Text("Item 111", style: TextStyle(fontSize: 15), textAlign: TextAlign.center,),
  4. 1: Text("Item 222", style: TextStyle(fontSize: 15), textAlign: TextAlign.center,),
  5. 2: Text("Item 333", style: TextStyle(fontSize: 15), textAlign: TextAlign.center,),
  6. };
  7. if (backgroundColor != null) {
  8. return LineSegmentControl(
  9. groupValue: groupValue,
  10. children: children,
  11. backgroundColor: backgroundColor,
  12. lineColor: lineColor,
  13. onValueChanged: (i){
  14. setState(() {
  15. groupValue = int.parse("$i");
  16. });
  17. DDLog(groupValue);
  18. },
  19. );
  20. }
  21. return LineSegmentControl(
  22. groupValue: groupValue,
  23. children: children,
  24. // backgroundColor: backgroundColor,
  25. lineColor: lineColor,
  26. onValueChanged: (i){
  27. setState(() {
  28. groupValue = int.parse("$i");
  29. });
  30. DDLog(groupValue);
  31. },
  32. );
  33. }

  1. //
  2. // LineSegmentWidget.dart
  3. // fluttertemplet
  4. //
  5. // Created by shang on 6/14/21 8:47 AM.
  6. // Copyright © 6/14/21 shang. All rights reserved.
  7. //
  8. import 'dart:ui';
  9. import 'package:flutter/cupertino.dart';
  10. import 'package:flutter/material.dart';
  11. import 'package:flutter/widgets.dart';
  12. import 'package:fluttertemplet/dartExpand/DDLog.dart';
  13. enum LineSegmentStyle {
  14. top,
  15. bottom,
  16. }
  17. ///线条指示器分段组件
  18. class LineSegmentControl<T> extends StatefulWidget {
  19. final Map<T, Widget> children;
  20. T? groupValue;
  21. final EdgeInsetsGeometry padding;
  22. final EdgeInsetsGeometry margin;
  23. final LineSegmentStyle style;
  24. final Color? backgroundColor;
  25. final Color lineColor;
  26. final double height;
  27. final Radius radius;
  28. void Function(T value) onValueChanged;
  29. LineSegmentControl({
  30. Key? key,
  31. required this.children,
  32. required this.groupValue,
  33. this.style = LineSegmentStyle.bottom,
  34. this.backgroundColor = CupertinoColors.tertiarySystemFill,
  35. this.lineColor = Colors.blue,
  36. this.height = 36,
  37. this.padding = const EdgeInsets.symmetric(horizontal: 0),
  38. this.margin = const EdgeInsets.symmetric(horizontal: 15),
  39. this.radius = const Radius.circular(4),
  40. required this.onValueChanged,
  41. }) : super(key: key);
  42. @override
  43. _LineSegmentControlState createState() => _LineSegmentControlState();
  44. }
  45. class _LineSegmentControlState extends State<LineSegmentControl> {
  46. @override
  47. Widget build(BuildContext context) {
  48. double screenWidth = MediaQuery.of(context).size.width;
  49. double contentWidth = screenWidth - widget.margin.horizontal - widget.padding.horizontal;
  50. double itemWidth = contentWidth / widget.children.values.length;
  51. return Container(
  52. margin: widget.margin,
  53. padding: widget.padding,
  54. decoration: BoxDecoration(
  55. color: widget.backgroundColor,
  56. borderRadius: BorderRadius.all(widget.radius),
  57. ),
  58. child: Stack(
  59. children: [
  60. Row(
  61. children: widget.children.values.map((e) => Column(
  62. crossAxisAlignment: CrossAxisAlignment.center,
  63. mainAxisSize: MainAxisSize.min,
  64. children: <Widget>[
  65. Container(
  66. height: widget.height,
  67. width: itemWidth,
  68. child: TextButton(
  69. child: e,
  70. onPressed: (){
  71. DDLog(e);
  72. setState(() {
  73. widget.groupValue = widget.children.values.toList().indexOf(e);
  74. });
  75. widget.onValueChanged(widget.groupValue);
  76. },
  77. ),
  78. ),
  79. ],
  80. ),
  81. ).toList(),
  82. ),
  83. AnimatedPositioned(
  84. duration: Duration(milliseconds: 200),
  85. top: widget.style == LineSegmentStyle.top ? 0 : widget.height - 2,
  86. left: widget.groupValue*itemWidth,
  87. child: Container(
  88. height: 2,
  89. width: itemWidth,
  90. color: widget.lineColor,
  91. // decoration: BoxDecoration(
  92. // borderRadius: BorderRadius.circular(4),
  93. // color: widget.lineColor,
  94. // ),
  95. ),
  96. ),
  97. ],
  98. ),
  99. );
  100. }
  101. }

LineSegmentControl.dart

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/307838
推荐阅读
相关标签
  

闽ICP备14008679号