ex_widget.dart 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. import 'package:flutter/gestures.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/semantics.dart';
  4. import 'package:shared/utils/ext_dart.dart';
  5. /// 手势 tap
  6. typedef GestureOnTapChangeCallback = void Function<T>(T val);
  7. //点击防抖类型
  8. enum ClickType { none, throttle, debounce }
  9. extension WidgetPaddingX on Widget {
  10. Widget paddingAll(double padding) =>
  11. Padding(padding: EdgeInsets.all(padding), child: this);
  12. Widget paddingSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
  13. Padding(
  14. padding:
  15. EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
  16. child: this);
  17. Widget paddingOnly({
  18. double left = 0.0,
  19. double top = 0.0,
  20. double right = 0.0,
  21. double bottom = 0.0,
  22. }) =>
  23. Padding(
  24. padding: EdgeInsets.only(
  25. top: top, left: left, right: right, bottom: bottom),
  26. child: this);
  27. Widget get paddingZero => Padding(padding: EdgeInsets.zero, child: this);
  28. }
  29. /// Add margin property to widget
  30. extension WidgetMarginX on Widget {
  31. Widget marginAll(double margin) =>
  32. Container(margin: EdgeInsets.all(margin), child: this);
  33. Widget marginSymmetric({double horizontal = 0.0, double vertical = 0.0}) =>
  34. Container(
  35. margin:
  36. EdgeInsets.symmetric(horizontal: horizontal, vertical: vertical),
  37. child: this);
  38. Widget marginOnly({
  39. double left = 0.0,
  40. double top = 0.0,
  41. double right = 0.0,
  42. double bottom = 0.0,
  43. }) =>
  44. Container(
  45. margin: EdgeInsets.only(
  46. top: top, left: left, right: right, bottom: bottom),
  47. child: this);
  48. Widget get marginZero => Container(margin: EdgeInsets.zero, child: this);
  49. }
  50. /// 扩展 Widget
  51. extension ExWidget on Widget {
  52. /// 对齐
  53. Widget align(
  54. AlignmentGeometry alignment, {
  55. Key? key,
  56. }) =>
  57. Align(
  58. key: key,
  59. alignment: alignment,
  60. child: this,
  61. );
  62. /// 对齐 中间
  63. Widget alignCenter() => align(Alignment.center);
  64. /// 对齐 左边
  65. Widget alignLeft() => align(Alignment.centerLeft);
  66. /// 对齐 右边
  67. Widget alignRight() => align(Alignment.centerRight);
  68. /// 对齐 顶部
  69. Widget alignTop() => align(Alignment.topCenter);
  70. /// 对齐 底部
  71. Widget alignBottom() => align(Alignment.bottomCenter);
  72. // 比例布局
  73. Widget aspectRatio({
  74. Key? key,
  75. required double aspectRatio,
  76. }) =>
  77. AspectRatio(
  78. key: key,
  79. aspectRatio: aspectRatio,
  80. child: this,
  81. );
  82. /// 背景颜色
  83. Widget backgroundColor(
  84. Color? color, {
  85. Key? key,
  86. }) =>
  87. DecoratedBox(
  88. key: key,
  89. child: this,
  90. decoration: BoxDecoration(color: color),
  91. );
  92. /// 背景图片
  93. Widget backgroundImage(
  94. DecorationImage image, {
  95. Key? key,
  96. }) =>
  97. DecoratedBox(
  98. key: key,
  99. child: this,
  100. decoration: BoxDecoration(image: image),
  101. );
  102. /// 边框
  103. Widget border({
  104. Key? key,
  105. double? all,
  106. double? left,
  107. double? right,
  108. double? top,
  109. double? bottom,
  110. Color color = const Color(0xFF000000),
  111. BorderStyle style = BorderStyle.solid,
  112. }) {
  113. BoxDecoration decoration = BoxDecoration(
  114. border: Border(
  115. left: (left ?? all) == null ? BorderSide.none : BorderSide(color: color, width: left ?? all ?? 0, style: style),
  116. right: (right ?? all) == null ? BorderSide.none : BorderSide(color: color, width: right ?? all ?? 0, style: style),
  117. top: (top ?? all) == null ? BorderSide.none : BorderSide(color: color, width: top ?? all ?? 0, style: style),
  118. bottom: (bottom ?? all) == null ? BorderSide.none : BorderSide(color: color, width: bottom ?? all ?? 0, style: style),
  119. ),
  120. );
  121. return DecoratedBox(
  122. key: key,
  123. child: this,
  124. decoration: decoration,
  125. );
  126. }
  127. /// 圆角
  128. Widget borderRadius({
  129. Key? key,
  130. double? all,
  131. double? topLeft,
  132. double? topRight,
  133. double? bottomLeft,
  134. double? bottomRight,
  135. }) {
  136. BoxDecoration decoration = BoxDecoration(
  137. borderRadius: BorderRadius.only(
  138. topLeft: Radius.circular(topLeft ?? all ?? 0.0),
  139. topRight: Radius.circular(topRight ?? all ?? 0.0),
  140. bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
  141. bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
  142. ),
  143. );
  144. return DecoratedBox(
  145. key: key,
  146. child: this,
  147. decoration: decoration,
  148. );
  149. }
  150. /// 阴影
  151. Widget boxShadow({
  152. Key? key,
  153. Color color = const Color(0xFF000000),
  154. Offset offset = Offset.zero,
  155. double blurRadius = 0.0,
  156. double spreadRadius = 0.0,
  157. }) {
  158. BoxDecoration decoration = BoxDecoration(
  159. boxShadow: [
  160. BoxShadow(
  161. color: color,
  162. blurRadius: blurRadius,
  163. spreadRadius: spreadRadius,
  164. offset: offset,
  165. ),
  166. ],
  167. );
  168. return DecoratedBox(
  169. key: key,
  170. child: this,
  171. decoration: decoration,
  172. );
  173. }
  174. /// 卡片
  175. Widget card({
  176. Key? key,
  177. Color? color,
  178. double? elevation,
  179. ShapeBorder? shape,
  180. bool borderOnForeground = true,
  181. EdgeInsetsGeometry? margin,
  182. Clip? clipBehavior,
  183. bool semanticContainer = true,
  184. }) =>
  185. Card(
  186. key: key,
  187. color: color,
  188. elevation: elevation,
  189. shape: shape,
  190. borderOnForeground: borderOnForeground,
  191. margin: margin,
  192. clipBehavior: clipBehavior,
  193. semanticContainer: semanticContainer,
  194. child: this,
  195. );
  196. // 居中
  197. Widget center({
  198. Key? key,
  199. double? widthFactor,
  200. double? heightFactor,
  201. }) =>
  202. Center(
  203. key: key,
  204. widthFactor: widthFactor,
  205. heightFactor: heightFactor,
  206. child: this,
  207. );
  208. /// 裁剪 oval
  209. Widget clipOval({Key? key}) => ClipOval(
  210. key: key,
  211. child: this,
  212. );
  213. /// 裁剪 rect
  214. Widget clipRect({
  215. Key? key,
  216. CustomClipper<Rect>? clipper,
  217. Clip clipBehavior = Clip.hardEdge,
  218. }) =>
  219. ClipRect(
  220. key: key,
  221. clipper: clipper,
  222. clipBehavior: clipBehavior,
  223. child: this,
  224. );
  225. /// 裁剪圆角
  226. Widget clipRRect({
  227. Key? key,
  228. double? all,
  229. double? topLeft,
  230. double? topRight,
  231. double? bottomLeft,
  232. double? bottomRight,
  233. CustomClipper<RRect>? clipper,
  234. Clip clipBehavior = Clip.antiAlias,
  235. }) =>
  236. ClipRRect(
  237. key: key,
  238. child: this,
  239. clipper: clipper,
  240. clipBehavior: clipBehavior,
  241. borderRadius: BorderRadius.only(
  242. topLeft: Radius.circular(topLeft ?? all ?? 0.0),
  243. topRight: Radius.circular(topRight ?? all ?? 0.0),
  244. bottomLeft: Radius.circular(bottomLeft ?? all ?? 0.0),
  245. bottomRight: Radius.circular(bottomRight ?? all ?? 0.0),
  246. ),
  247. );
  248. /// 约束
  249. Widget constrained({
  250. Key? key,
  251. double? width,
  252. double? height,
  253. double minWidth = 0.0,
  254. double maxWidth = double.infinity,
  255. double minHeight = 0.0,
  256. double maxHeight = double.infinity,
  257. }) {
  258. BoxConstraints constraints = BoxConstraints(
  259. minWidth: minWidth,
  260. maxWidth: maxWidth,
  261. minHeight: minHeight,
  262. maxHeight: maxHeight,
  263. );
  264. constraints = (width != null || height != null) ? constraints.tighten(width: width, height: height) : constraints;
  265. return ConstrainedBox(
  266. key: key,
  267. child: this,
  268. constraints: constraints,
  269. );
  270. }
  271. /// 盒子装饰器
  272. Widget decorated({
  273. Key? key,
  274. Color? color,
  275. DecorationImage? image,
  276. BoxBorder? border,
  277. BorderRadius? borderRadius,
  278. List<BoxShadow>? boxShadow,
  279. Gradient? gradient,
  280. BlendMode? backgroundBlendMode,
  281. BoxShape shape = BoxShape.rectangle,
  282. DecorationPosition position = DecorationPosition.background,
  283. }) {
  284. BoxDecoration decoration = BoxDecoration(
  285. color: color,
  286. image: image,
  287. border: border,
  288. borderRadius: borderRadius,
  289. boxShadow: boxShadow,
  290. gradient: gradient,
  291. backgroundBlendMode: backgroundBlendMode,
  292. shape: shape,
  293. );
  294. return DecoratedBox(
  295. key: key,
  296. child: this,
  297. decoration: decoration,
  298. position: position,
  299. );
  300. }
  301. /// elevation
  302. Widget elevation(
  303. double elevation, {
  304. Key? key,
  305. BorderRadiusGeometry borderRadius = BorderRadius.zero,
  306. Color shadowColor = const Color(0xFF000000),
  307. }) =>
  308. Material(
  309. key: key,
  310. child: this,
  311. color: Colors.transparent,
  312. elevation: elevation,
  313. borderRadius: borderRadius,
  314. shadowColor: shadowColor,
  315. );
  316. /// expanded 撑满,用于线性布局
  317. Widget expanded({
  318. Key? key,
  319. int flex = 1,
  320. }) =>
  321. Expanded(
  322. key: key,
  323. child: this,
  324. flex: flex,
  325. );
  326. /// 调整子控件大小与位置
  327. Widget fittedBox({
  328. Key? key,
  329. BoxFit fit = BoxFit.contain,
  330. AlignmentGeometry alignment = Alignment.center,
  331. }) =>
  332. FittedBox(
  333. key: key,
  334. fit: fit,
  335. alignment: alignment,
  336. child: this,
  337. );
  338. /// 弹性布局 flexible,用于线性布局
  339. Widget flexible({
  340. Key? key,
  341. int flex = 1,
  342. FlexFit fit = FlexFit.loose,
  343. }) =>
  344. Flexible(
  345. key: key,
  346. child: this,
  347. flex: flex,
  348. fit: fit,
  349. );
  350. Widget fractionallySizedBox({
  351. Key? key,
  352. AlignmentGeometry alignment = Alignment.center,
  353. double? widthFactor,
  354. double? heightFactor,
  355. }) =>
  356. FractionallySizedBox(
  357. key: key,
  358. alignment: alignment,
  359. widthFactor: widthFactor,
  360. heightFactor: heightFactor,
  361. child: this,
  362. );
  363. /// 手势
  364. Widget gestures({
  365. Key? key,
  366. GestureOnTapChangeCallback? onTapChange,
  367. GestureTapDownCallback? onTapDown,
  368. GestureTapUpCallback? onTapUp,
  369. GestureTapCallback? onTap,
  370. GestureTapCancelCallback? onTapCancel,
  371. GestureTapDownCallback? onSecondaryTapDown,
  372. GestureTapUpCallback? onSecondaryTapUp,
  373. GestureTapCancelCallback? onSecondaryTapCancel,
  374. GestureTapCallback? onDoubleTap,
  375. GestureLongPressCallback? onLongPress,
  376. GestureLongPressStartCallback? onLongPressStart,
  377. GestureLongPressMoveUpdateCallback? onLongPressMoveUpdate,
  378. GestureLongPressUpCallback? onLongPressUp,
  379. GestureLongPressEndCallback? onLongPressEnd,
  380. GestureDragDownCallback? onVerticalDragDown,
  381. GestureDragStartCallback? onVerticalDragStart,
  382. GestureDragUpdateCallback? onVerticalDragUpdate,
  383. GestureDragEndCallback? onVerticalDragEnd,
  384. GestureDragCancelCallback? onVerticalDragCancel,
  385. GestureDragDownCallback? onHorizontalDragDown,
  386. GestureDragStartCallback? onHorizontalDragStart,
  387. GestureDragUpdateCallback? onHorizontalDragUpdate,
  388. GestureDragEndCallback? onHorizontalDragEnd,
  389. GestureDragCancelCallback? onHorizontalDragCancel,
  390. GestureDragDownCallback? onPanDown,
  391. GestureDragStartCallback? onPanStart,
  392. GestureDragUpdateCallback? onPanUpdate,
  393. GestureDragEndCallback? onPanEnd,
  394. GestureDragCancelCallback? onPanCancel,
  395. GestureScaleStartCallback? onScaleStart,
  396. GestureScaleUpdateCallback? onScaleUpdate,
  397. GestureScaleEndCallback? onScaleEnd,
  398. GestureForcePressStartCallback? onForcePressStart,
  399. GestureForcePressPeakCallback? onForcePressPeak,
  400. GestureForcePressUpdateCallback? onForcePressUpdate,
  401. GestureForcePressEndCallback? onForcePressEnd,
  402. HitTestBehavior? behavior,
  403. bool excludeFromSemantics = false,
  404. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  405. }) =>
  406. GestureDetector(
  407. key: key,
  408. onTapDown: (TapDownDetails tapDownDetails) {
  409. if (onTapDown != null) onTapDown(tapDownDetails);
  410. if (onTapChange != null) onTapChange(true);
  411. },
  412. onTapCancel: () {
  413. if (onTapCancel != null) onTapCancel();
  414. if (onTapChange != null) onTapChange(false);
  415. },
  416. onTap: () {
  417. if (onTap != null) onTap();
  418. if (onTapChange != null) onTapChange(false);
  419. },
  420. onTapUp: onTapUp,
  421. onDoubleTap: onDoubleTap,
  422. onLongPress: onLongPress,
  423. onLongPressStart: onLongPressStart,
  424. onLongPressEnd: onLongPressEnd,
  425. onLongPressMoveUpdate: onLongPressMoveUpdate,
  426. onLongPressUp: onLongPressUp,
  427. onVerticalDragStart: onVerticalDragStart,
  428. onVerticalDragEnd: onVerticalDragEnd,
  429. onVerticalDragDown: onVerticalDragDown,
  430. onVerticalDragCancel: onVerticalDragCancel,
  431. onVerticalDragUpdate: onVerticalDragUpdate,
  432. onHorizontalDragStart: onHorizontalDragStart,
  433. onHorizontalDragEnd: onHorizontalDragEnd,
  434. onHorizontalDragCancel: onHorizontalDragCancel,
  435. onHorizontalDragUpdate: onHorizontalDragUpdate,
  436. onHorizontalDragDown: onHorizontalDragDown,
  437. onForcePressStart: onForcePressStart,
  438. onForcePressEnd: onForcePressEnd,
  439. onForcePressPeak: onForcePressPeak,
  440. onForcePressUpdate: onForcePressUpdate,
  441. onPanStart: onPanStart,
  442. onPanEnd: onPanEnd,
  443. onPanCancel: onPanCancel,
  444. onPanDown: onPanDown,
  445. onPanUpdate: onPanUpdate,
  446. onScaleStart: onScaleStart,
  447. onScaleEnd: onScaleEnd,
  448. onScaleUpdate: onScaleUpdate,
  449. behavior: behavior ?? HitTestBehavior.opaque,
  450. excludeFromSemantics: excludeFromSemantics,
  451. dragStartBehavior: dragStartBehavior,
  452. child: this,
  453. );
  454. /// 手势
  455. Widget onTap(
  456. GestureTapCallback onTap, {
  457. Key? key,
  458. HitTestBehavior? behavior,
  459. ClickType type = ClickType.none,
  460. int milliseconds = 500,
  461. bool excludeFromSemantics = false,
  462. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  463. double padding = 0, // 通过 padding 参数控制点击范围的扩展
  464. }) =>
  465. GestureDetector(
  466. key: key,
  467. onTap: type == ClickType.debounce
  468. ? onTap.debounce(milliseconds)
  469. : type == ClickType.throttle
  470. ? onTap.throttle(milliseconds)
  471. : onTap,
  472. behavior: behavior ?? HitTestBehavior.opaque,
  473. excludeFromSemantics: excludeFromSemantics,
  474. dragStartBehavior: dragStartBehavior,
  475. child: Padding(
  476. padding: EdgeInsets.all(padding), // 通过 Padding 扩大点击区域
  477. child: this,
  478. ),
  479. );
  480. /// 长按手势
  481. Widget onLongPress(
  482. GestureTapCallback onLongPress, {
  483. Key? key,
  484. HitTestBehavior? behavior,
  485. bool excludeFromSemantics = false,
  486. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  487. }) =>
  488. GestureDetector(
  489. key: key,
  490. onLongPress: onLongPress,
  491. behavior: behavior ?? HitTestBehavior.opaque,
  492. excludeFromSemantics: excludeFromSemantics,
  493. dragStartBehavior: dragStartBehavior,
  494. child: this,
  495. );
  496. /// 约束 高度
  497. Widget height(
  498. double height, {
  499. Key? key,
  500. }) =>
  501. ConstrainedBox(
  502. key: key,
  503. child: this,
  504. constraints: BoxConstraints.tightFor(height: height),
  505. );
  506. /// 限制盒子 最大宽高
  507. Widget limitedBox({
  508. Key? key,
  509. double maxWidth = double.infinity,
  510. double maxHeight = double.infinity,
  511. }) =>
  512. LimitedBox(
  513. key: key,
  514. maxWidth: maxWidth,
  515. maxHeight: maxHeight,
  516. child: this,
  517. );
  518. /// 偏移
  519. Widget offstage({
  520. Key? key,
  521. bool offstage = true,
  522. }) =>
  523. Offstage(
  524. key: key,
  525. offstage: offstage,
  526. child: this,
  527. );
  528. /// 透明度
  529. Widget opacity(
  530. double opacity, {
  531. Key? key,
  532. bool alwaysIncludeSemantics = false,
  533. }) =>
  534. Opacity(
  535. key: key,
  536. opacity: opacity,
  537. alwaysIncludeSemantics: alwaysIncludeSemantics,
  538. child: this,
  539. );
  540. /// 溢出
  541. Widget overflow({
  542. Key? key,
  543. AlignmentGeometry alignment = Alignment.center,
  544. double? minWidth,
  545. double? maxWidth,
  546. double? minHeight,
  547. double? maxHeight,
  548. }) =>
  549. OverflowBox(
  550. key: key,
  551. alignment: alignment,
  552. minWidth: minWidth,
  553. maxWidth: minWidth,
  554. minHeight: minHeight,
  555. maxHeight: maxHeight,
  556. child: this,
  557. );
  558. /// 内间距
  559. Widget padding({
  560. Key? key,
  561. EdgeInsetsGeometry? value,
  562. double? all,
  563. double? horizontal,
  564. double? vertical,
  565. double? top,
  566. double? bottom,
  567. double? left,
  568. double? right,
  569. }) =>
  570. Padding(
  571. key: key,
  572. padding: value ??
  573. EdgeInsets.only(
  574. top: top ?? vertical ?? all ?? 0.0,
  575. bottom: bottom ?? vertical ?? all ?? 0.0,
  576. left: left ?? horizontal ?? all ?? 0.0,
  577. right: right ?? horizontal ?? all ?? 0.0,
  578. ),
  579. child: this,
  580. );
  581. /// 内间距 下
  582. Widget paddingBottom(double val) => padding(bottom: val);
  583. /// 内间距 横向
  584. Widget paddingHorizontal(double val) => padding(horizontal: val);
  585. /// 内间距 左
  586. Widget paddingLeft(double val) => padding(left: val);
  587. /// 内间距 右
  588. Widget paddingRight(double val) => padding(right: val);
  589. /// 内间距 上
  590. Widget paddingTop(double val) => padding(top: val);
  591. /// 内间距 纵向
  592. Widget paddingVertical(double val) => padding(vertical: val);
  593. /// stack布局 位置
  594. Widget positioned({
  595. Key? key,
  596. double? left,
  597. double? top,
  598. double? right,
  599. double? bottom,
  600. double? width,
  601. double? height,
  602. }) =>
  603. Positioned(
  604. key: key,
  605. child: this,
  606. left: left,
  607. top: top,
  608. right: right,
  609. bottom: bottom,
  610. width: width,
  611. height: height,
  612. );
  613. /// 涟漪
  614. Widget ripple({
  615. Key? key,
  616. Color? bgColor,
  617. Color? focusColor,
  618. Color? hoverColor,
  619. Color? highlightColor,
  620. Color? splashColor,
  621. InteractiveInkFeatureFactory? splashFactory,
  622. double? radius,
  623. ShapeBorder? customBorder,
  624. bool enableFeedback = true,
  625. bool excludeFromSemantics = false,
  626. FocusNode? focusNode,
  627. bool canRequestFocus = true,
  628. bool autoFocus = false,
  629. bool enable = true,
  630. }) =>
  631. enable
  632. ? Builder(
  633. key: key,
  634. builder: (BuildContext context) {
  635. GestureDetector? gestures = context.findAncestorWidgetOfExactType<GestureDetector>();
  636. return Material(
  637. color: bgColor ?? Colors.transparent,
  638. child: InkWell(
  639. focusColor: focusColor,
  640. hoverColor: hoverColor,
  641. highlightColor: highlightColor,
  642. splashColor: splashColor,
  643. splashFactory: splashFactory,
  644. radius: radius,
  645. customBorder: customBorder,
  646. enableFeedback: enableFeedback,
  647. excludeFromSemantics: excludeFromSemantics,
  648. focusNode: focusNode,
  649. canRequestFocus: canRequestFocus,
  650. autofocus: autoFocus,
  651. onTap: gestures?.onTap,
  652. child: this,
  653. ),
  654. );
  655. },
  656. )
  657. : Builder(
  658. key: key,
  659. builder: (context) => this,
  660. );
  661. // 刘海屏 特殊屏幕 留白
  662. Widget safeArea({
  663. Key? key,
  664. bool top = true,
  665. bool bottom = true,
  666. bool left = true,
  667. bool right = true,
  668. }) =>
  669. SafeArea(
  670. key: key,
  671. top: top,
  672. bottom: bottom,
  673. left: left,
  674. right: right,
  675. child: this,
  676. );
  677. /// 比例缩放
  678. Widget scale({
  679. Key? key,
  680. double? all,
  681. double? x,
  682. double? y,
  683. Offset? origin,
  684. AlignmentGeometry alignment = Alignment.center,
  685. bool transformHitTests = true,
  686. }) =>
  687. Transform(
  688. key: key,
  689. transform: Matrix4.diagonal3Values(x ?? all ?? 0, y ?? all ?? 0, 1.0),
  690. alignment: alignment,
  691. child: this,
  692. origin: origin,
  693. transformHitTests: transformHitTests,
  694. );
  695. /// 滚动视图
  696. Widget scrollable({
  697. Key? key,
  698. Axis scrollDirection = Axis.vertical,
  699. bool reverse = false,
  700. bool? primary,
  701. ScrollPhysics? physics,
  702. ScrollController? controller,
  703. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  704. EdgeInsetsGeometry? padding,
  705. }) =>
  706. SingleChildScrollView(
  707. key: key,
  708. child: this,
  709. scrollDirection: scrollDirection,
  710. reverse: reverse,
  711. primary: primary,
  712. physics: physics,
  713. controller: controller,
  714. dragStartBehavior: dragStartBehavior,
  715. padding: padding,
  716. );
  717. /// 语义调试
  718. /// MaterialApp.showSemanticsDebugger: true,
  719. Widget semanticsLabel(
  720. String label, {
  721. Key? key,
  722. }) =>
  723. Semantics.fromProperties(
  724. key: key,
  725. properties: SemanticsProperties(label: label),
  726. child: this,
  727. );
  728. /// 约束 宽高
  729. Widget tight({
  730. double? width,
  731. double? height,
  732. Key? key,
  733. }) =>
  734. ConstrainedBox(
  735. key: key,
  736. child: this,
  737. constraints: BoxConstraints.tightFor(width: width, height: height),
  738. );
  739. /// transforms Matrix4
  740. Widget transform({
  741. Key? key,
  742. required Matrix4 transform,
  743. Offset? origin,
  744. AlignmentGeometry? alignment,
  745. bool transformHitTests = true,
  746. }) =>
  747. Transform(
  748. key: key,
  749. transform: transform,
  750. alignment: alignment,
  751. origin: origin,
  752. transformHitTests: transformHitTests,
  753. child: this,
  754. );
  755. /// translate 变化位置
  756. Widget translate({
  757. Key? key,
  758. required Offset offset,
  759. bool transformHitTests = true,
  760. }) =>
  761. Transform.translate(
  762. key: key,
  763. offset: offset,
  764. transformHitTests: transformHitTests,
  765. child: this,
  766. );
  767. /// 约束 宽度
  768. Widget width(
  769. double width, {
  770. Key? key,
  771. }) =>
  772. ConstrainedBox(
  773. key: key,
  774. child: this,
  775. constraints: BoxConstraints.tightFor(width: width),
  776. );
  777. }